diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 69d825e238..9c6619aa32 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -46,6 +46,9 @@ namespace clang { /// \brief The file managers we're importing to and from. FileManager &ToFileManager, &FromFileManager; + /// \brief Whether to perform a minimal import. + bool Minimal; + /// \brief Mapping from the already-imported types in the "from" context /// to the corresponding types in the "to" context. llvm::DenseMap ImportedTypes; @@ -71,11 +74,29 @@ namespace clang { NonEquivalentDeclSet NonEquivalentDecls; public: + /// \brief Create a new AST importer. + /// + /// \param ToContext The context we'll be importing into. + /// + /// \param ToFileManager The file manager we'll be importing into. + /// + /// \param FromContext The context we'll be importing from. + /// + /// \param FromFileManager The file manager we'll be importing into. + /// + /// \param MinimalImport If true, the importer will attempt to import + /// as little as it can, e.g., by importing declarations as forward + /// declarations that can be completed at a later point. ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, - ASTContext &FromContext, FileManager &FromFileManager); + ASTContext &FromContext, FileManager &FromFileManager, + bool MinimalImport); virtual ~ASTImporter(); + /// \brief Whether the importer will perform a minimal import, creating + /// to-be-completed forward declarations when possible. + bool isMinimalImport() const { return Minimal; } + /// \brief Import the given type from the "from" context into the "to" /// context. /// @@ -169,6 +190,12 @@ namespace clang { /// context. FileID Import(FileID); + /// \brief Import the definition of the given declaration, including all of + /// the declarations it contains. + /// + /// This routine is intended to be used + void ImportDefinition(Decl *From); + /// \brief Cope with a name conflict when importing a declaration into the /// given context. /// @@ -225,12 +252,13 @@ namespace clang { /// \brief Note that we have imported the "from" declaration by mapping it /// to the (potentially-newly-created) "to" declaration. /// - /// \returns \p To - Decl *Imported(Decl *From, Decl *To); + /// Subclasses can override this function to observe all of the \c From -> + /// \c To declaration mappings as they are imported. + virtual Decl *Imported(Decl *From, Decl *To); /// \brief Determine whether the given types are structurally /// equivalent. - bool IsStructurallyEquivalent(QualType From, QualType To); + bool IsStructurallyEquivalent(QualType From, QualType To); }; } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index eaab3d3e6c..315f4feca6 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -83,7 +83,7 @@ namespace { SourceLocation &Loc); void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); - void ImportDeclContext(DeclContext *FromDC); + void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); bool ImportDefinition(RecordDecl *From, RecordDecl *To); TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); @@ -1713,7 +1713,15 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, } } -void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC) { +void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { + if (Importer.isMinimalImport() && !ForceImport) { + if (DeclContext *ToDC = Importer.ImportContext(FromDC)) { + ToDC->setHasExternalLexicalStorage(); + ToDC->setHasExternalVisibleStorage(); + } + return; + } + for (DeclContext::decl_iterator From = FromDC->decls_begin(), FromEnd = FromDC->decls_end(); From != FromEnd; @@ -3897,9 +3905,12 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { } ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, - ASTContext &FromContext, FileManager &FromFileManager) + ASTContext &FromContext, FileManager &FromFileManager, + bool MinimalImport) : ToContext(ToContext), FromContext(FromContext), - ToFileManager(ToFileManager), FromFileManager(FromFileManager) { + ToFileManager(ToFileManager), FromFileManager(FromFileManager), + Minimal(MinimalImport) +{ ImportedDecls[FromContext.getTranslationUnitDecl()] = ToContext.getTranslationUnitDecl(); } @@ -4163,6 +4174,17 @@ FileID ASTImporter::Import(FileID FromID) { return ToID; } +void ASTImporter::ImportDefinition(Decl *From) { + Decl *To = Import(From); + if (!To) + return; + + if (DeclContext *FromDC = cast(From)) { + ASTNodeImporter Importer(*this); + Importer.ImportDeclContext(FromDC, true); + } +} + DeclarationName ASTImporter::Import(DeclarationName FromName) { if (!FromName) return DeclarationName(); diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index ec074415c1..3905b99b02 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -52,7 +52,8 @@ void ASTMergeAction::ExecuteAction() { ASTImporter Importer(CI.getASTContext(), CI.getFileManager(), Unit->getASTContext(), - Unit->getFileManager()); + Unit->getFileManager(), + /*MinimalImport=*/false); TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); for (DeclContext::decl_iterator D = TU->decls_begin(),