From: Douglas Gregor Date: Fri, 2 Dec 2011 23:42:12 +0000 (+0000) Subject: When we treat an #include or #import as a module import, create an X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=93ebfa6139bbca4d446c7343e3afc8e5ec777484;p=clang When we treat an #include or #import as a module import, create an implicit ImportDecl in the translation unit to record the presence of the import. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145727 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index d65da5d67b..8feab307ea 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -782,7 +782,8 @@ public: bool serialize(raw_ostream &OS); virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility) { + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) { // ASTUnit doesn't know how to load modules (not that this matters). return 0; } diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 21f8eeead3..b488cde6e6 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -642,7 +642,8 @@ public: /// } virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility); + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective); }; } // end namespace clang diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 0bd97b6bd4..b2fb722b94 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -48,10 +48,15 @@ public: /// \param Visibility The visibility provided for the names in the loaded /// module. /// + /// \param IsInclusionDirective Indicates that this module is being loaded + /// implicitly, due to the presence of an inclusion directive. Otherwise, + /// it is being loaded due to an import declaration. + /// /// \returns If successful, returns the loaded module. Otherwise, returns /// NULL to indicate that the module could not be loaded. virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility) = 0; + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) = 0; }; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 2f167eedd1..1ed149b68f 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2657,9 +2657,7 @@ ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, Module *Imported, SourceLocation EndLoc) { void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation)); - ImportDecl *Import - = new (Mem) ImportDecl(DC, ImportLoc, Imported, - ArrayRef(&EndLoc, 1)); + ImportDecl *Import = new (Mem) ImportDecl(DC, ImportLoc, Imported, EndLoc); Import->setImplicit(); return Import; } diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 746c00a361..6a060e036f 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -11,6 +11,7 @@ #include "clang/Sema/Sema.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -1070,7 +1071,8 @@ static void compileModule(CompilerInstance &ImportingInstance, Module *CompilerInstance::loadModule(SourceLocation ImportLoc, ModuleIdPath Path, - Module::NameVisibilityKind Visibility) { + Module::NameVisibilityKind Visibility, + bool IsInclusionDirective) { // If we've already handled this import, just return the cached result. // This one-element cache is important to eliminate redundant diagnostics // when both the preprocessor and parser see the same import declaration. @@ -1259,8 +1261,16 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, } // Make the named module visible. - if (Module) - ModuleManager->makeModuleVisible(Module, Visibility); + ModuleManager->makeModuleVisible(Module, Visibility); + + // If this module import was due to an inclusion directive, create an + // implicit import declaration to capture it in the AST. + if (IsInclusionDirective && hasASTContext()) { + TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); + TU->addDecl(ImportDecl::CreateImplicit(getASTContext(), TU, + ImportLoc, Module, + Path.back().second)); + } LastModuleImportLoc = ImportLoc; LastModuleImportResult = Module; diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 836d21b204..b44a0a2934 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1363,7 +1363,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, // If this was an #__include_macros directive, only make macros visible. Module::NameVisibilityKind Visibility = (IncludeKind == 3)? Module::MacrosVisible : Module::AllVisible; - TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility); + TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility, + /*IsIncludeDirective=*/true); return; } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 6cf34e226a..dea7efc765 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -599,7 +599,8 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { // If we have a non-empty module path, load the named module. if (!ModuleImportPath.empty()) (void)TheModuleLoader.loadModule(ModuleImportLoc, ModuleImportPath, - Module::MacrosVisible); + Module::MacrosVisible, + /*IsIncludeDirective=*/false); } void Preprocessor::AddCommentHandler(CommentHandler *Handler) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 01c7906e80..fdb2cf5d96 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9893,7 +9893,8 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path) { Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, - Module::AllVisible); + Module::AllVisible, + /*IsIncludeDirective=*/false); if (!Mod) return true;