diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/Module.h | 20 | ||||
-rw-r--r-- | clang/include/clang/Frontend/ASTUnit.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Frontend/CompilerInstance.h | 3 | ||||
-rw-r--r-- | clang/include/clang/Lex/ModuleLoader.h | 9 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 10 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 32 |
10 files changed, 89 insertions, 13 deletions
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index 4f5280738fa..4eaa1be2915 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -58,17 +58,33 @@ public: /// \brief Whether this is an explicit submodule. bool IsExplicit; + /// \brief Describes the visibility of the various names within a + /// particular module. + enum NameVisibilityKind { + /// \brief All of the names in this module are hidden. + /// + Hidden, + /// \brief Only the macro names in this module are visible. + MacrosVisible, + /// \brief All of the names in this module are visible. + AllVisible + }; + + ///\ brief The visibility of names within this particular module. + NameVisibilityKind NameVisibility; + /// \brief Construct a top-level module. explicit Module(StringRef Name, SourceLocation DefinitionLoc, bool IsFramework) : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0), - IsFramework(IsFramework), IsExplicit(false) { } + IsFramework(IsFramework), IsExplicit(false), NameVisibility(Hidden) { } /// \brief Construct a new module or submodule. Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, bool IsExplicit) : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), - UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit) { } + UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit), + NameVisibility(Hidden) { } ~Module(); diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 4cab303ba4d..d65da5d67bd 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -781,7 +781,8 @@ public: /// \returns True if an error occurred, false otherwise. bool serialize(raw_ostream &OS); - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path) { + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility) { // ASTUnit doesn't know how to load modules (not that this matters). return 0; } diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 9cd09ee10c0..21f8eeead3d 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -641,7 +641,8 @@ public: /// } - virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path); + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility); }; } // end namespace clang diff --git a/clang/include/clang/Lex/ModuleLoader.h b/clang/include/clang/Lex/ModuleLoader.h index 6a7fe0204f3..0bd97b6bd4b 100644 --- a/clang/include/clang/Lex/ModuleLoader.h +++ b/clang/include/clang/Lex/ModuleLoader.h @@ -14,13 +14,13 @@ #ifndef LLVM_CLANG_LEX_MODULE_LOADER_H #define LLVM_CLANG_LEX_MODULE_LOADER_H +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" namespace clang { class IdentifierInfo; -class Module; /// \brief A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. @@ -41,12 +41,17 @@ public: /// parameters. /// /// \param ImportLoc The location of the 'import' keyword. + /// /// \param Path The identifiers (and their locations) of the module /// "path", e.g., "std.vector" would be split into "std" and "vector". + /// + /// \param Visibility The visibility provided for the names in the loaded + /// module. /// /// \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) = 0; + virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path, + Module::NameVisibilityKind Visibility) = 0; }; } diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 0e659acfa0f..3f66eb51183 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -803,6 +803,16 @@ public: /// the actual file in the file system. ASTReadResult validateFileEntries(ModuleFile &M); + /// \brief Make the entities in the given module and any of its (non-explicit) + /// submodules visible to name lookup. + /// + /// \param Mod The module whose names should be made visible. + /// + /// \param Visibility The level of visibility to give the names in the module. + /// Visibility can only be increased over time. + void makeModuleVisible(Module *Mod, + Module::NameVisibilityKind NameVisibility); + /// \brief Set the AST callbacks listener. void setListener(ASTReaderListener *listener) { Listener.reset(listener); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 743a447c323..746c00a3619 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1069,12 +1069,17 @@ static void compileModule(CompilerInstance &ImportingInstance, } Module *CompilerInstance::loadModule(SourceLocation ImportLoc, - ModuleIdPath Path) { + ModuleIdPath Path, + Module::NameVisibilityKind Visibility) { // 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. - if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) + if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) { + // Make the named module visible. + if (LastModuleImportResult) + ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility); return LastModuleImportResult; + } // Determine what file we're searching from. SourceManager &SourceMgr = getSourceManager(); @@ -1253,7 +1258,9 @@ Module *CompilerInstance::loadModule(SourceLocation ImportLoc, } } - // FIXME: Tell the AST reader to make the named submodule visible. + // Make the named module visible. + if (Module) + ModuleManager->makeModuleVisible(Module, Visibility); LastModuleImportLoc = ImportLoc; LastModuleImportResult = Module; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 81cb5262098..836d21b2047 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1360,8 +1360,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, "__import_module__ " + PathString.str().str() + ";"); // Load the module. - // FIXME: Deal with __include_macros here. - TheModuleLoader.loadModule(IncludeTok.getLocation(), Path); + // 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); return; } diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index b01113041eb..180e1e2c258 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -593,7 +593,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); + (void)TheModuleLoader.loadModule(ModuleImportLoc, ModuleImportPath, + Module::MacrosVisible); } void Preprocessor::AddCommentHandler(CommentHandler *Handler) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 48f4c4f0cba..1e57a00f1f1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9892,7 +9892,8 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, } DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc, ModuleIdPath Path) { - Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path); + Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, + Module::AllVisible); if (!Mod) return true; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index d43f8c1f45d..258baebc05c 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2439,6 +2439,38 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries(ModuleFile &M) { return Success; } +void ASTReader::makeModuleVisible(Module *Mod, + Module::NameVisibilityKind NameVisibility) { + llvm::SmallPtrSet<Module *, 4> Visited; + llvm::SmallVector<Module *, 4> Stack; + Stack.push_back(Mod); + while (!Stack.empty()) { + Mod = Stack.back(); + Stack.pop_back(); + + if (NameVisibility <= Mod->NameVisibility) { + // This module already has this level of visibility (or greater), so + // there is nothing more to do. + continue; + } + + // Update the module's name visibility. + Mod->NameVisibility = NameVisibility; + + // FIXME: If we've already deserialized any names from this module, + // mark them as visible. + + // Push any non-explicit submodules onto the stack to be marked as + // visible. + for (llvm::StringMap<Module *>::iterator Sub = Mod->SubModules.begin(), + SubEnd = Mod->SubModules.end(); + Sub != SubEnd; ++Sub) { + if (!Sub->getValue()->IsExplicit && Visited.insert(Sub->getValue())) + Stack.push_back(Sub->getValue()); + } + } +} + ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type) { switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) { |