summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/Module.h20
-rw-r--r--clang/include/clang/Frontend/ASTUnit.h3
-rw-r--r--clang/include/clang/Frontend/CompilerInstance.h3
-rw-r--r--clang/include/clang/Lex/ModuleLoader.h9
-rw-r--r--clang/include/clang/Serialization/ASTReader.h10
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp13
-rw-r--r--clang/lib/Lex/PPDirectives.cpp6
-rw-r--r--clang/lib/Lex/Preprocessor.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp3
-rw-r--r--clang/lib/Serialization/ASTReader.cpp32
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)) {
OpenPOWER on IntegriCloud