summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Basic/Module.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/Module.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Module.cpp111
1 files changed, 86 insertions, 25 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/Module.cpp b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
index 03f9bd3..7308665 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Module.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Module.cpp
@@ -25,14 +25,14 @@
using namespace clang;
Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
- bool IsFramework, bool IsExplicit)
+ bool IsFramework, bool IsExplicit, unsigned VisibilityID)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
- Umbrella(), ASTFile(nullptr), IsMissingRequirement(false),
- IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
- IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
- IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
- InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden) {
+ Umbrella(), ASTFile(nullptr), VisibilityID(VisibilityID),
+ IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false),
+ IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
+ IsExternC(false), IsInferred(false), InferSubmodules(false),
+ InferExplicitSubmodules(false), InferExportWildcard(false),
+ ConfigMacrosExhaustive(false), NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
@@ -58,16 +58,21 @@ Module::~Module() {
/// language options has the given feature.
static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
const TargetInfo &Target) {
- return llvm::StringSwitch<bool>(Feature)
- .Case("altivec", LangOpts.AltiVec)
- .Case("blocks", LangOpts.Blocks)
- .Case("cplusplus", LangOpts.CPlusPlus)
- .Case("cplusplus11", LangOpts.CPlusPlus11)
- .Case("objc", LangOpts.ObjC1)
- .Case("objc_arc", LangOpts.ObjCAutoRefCount)
- .Case("opencl", LangOpts.OpenCL)
- .Case("tls", Target.isTLSSupported())
- .Default(Target.hasFeature(Feature));
+ bool HasFeature = llvm::StringSwitch<bool>(Feature)
+ .Case("altivec", LangOpts.AltiVec)
+ .Case("blocks", LangOpts.Blocks)
+ .Case("cplusplus", LangOpts.CPlusPlus)
+ .Case("cplusplus11", LangOpts.CPlusPlus11)
+ .Case("objc", LangOpts.ObjC1)
+ .Case("objc_arc", LangOpts.ObjCAutoRefCount)
+ .Case("opencl", LangOpts.OpenCL)
+ .Case("tls", Target.isTLSSupported())
+ .Default(Target.hasFeature(Feature));
+ if (!HasFeature)
+ HasFeature = std::find(LangOpts.ModuleFeatures.begin(),
+ LangOpts.ModuleFeatures.end(),
+ Feature) != LangOpts.ModuleFeatures.end();
+ return HasFeature;
}
bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
@@ -133,11 +138,11 @@ std::string Module::getFullModuleName() const {
return Result;
}
-const DirectoryEntry *Module::getUmbrellaDir() const {
- if (const FileEntry *Header = getUmbrellaHeader())
- return Header->getDir();
+Module::DirectoryName Module::getUmbrellaDir() const {
+ if (Header U = getUmbrellaHeader())
+ return {"", U.Entry->getDir()};
- return Umbrella.dyn_cast<const DirectoryEntry *>();
+ return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
}
ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
@@ -153,6 +158,19 @@ ArrayRef<const FileEntry *> Module::getTopHeaders(FileManager &FileMgr) {
return llvm::makeArrayRef(TopHeaders.begin(), TopHeaders.end());
}
+bool Module::directlyUses(const Module *Requested) const {
+ auto *Top = getTopLevelModule();
+
+ // A top-level module implicitly uses itself.
+ if (Requested->isSubModuleOf(Top))
+ return true;
+
+ for (auto *Use : Top->DirectUses)
+ if (Requested->isSubModuleOf(Use))
+ return true;
+ return false;
+}
+
void Module::addRequirement(StringRef Feature, bool RequiredState,
const LangOptions &LangOpts,
const TargetInfo &Target) {
@@ -316,15 +334,15 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS << "\n";
}
- if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
+ if (Header H = getUmbrellaHeader()) {
OS.indent(Indent + 2);
OS << "umbrella header \"";
- OS.write_escaped(UmbrellaHeader->getName());
+ OS.write_escaped(H.NameAsWritten);
OS << "\"\n";
- } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) {
+ } else if (DirectoryName D = getUmbrellaDir()) {
OS.indent(Indent + 2);
OS << "umbrella \"";
- OS.write_escaped(UmbrellaDir->getName());
+ OS.write_escaped(D.NameAsWritten);
OS << "\"\n";
}
@@ -457,4 +475,47 @@ void Module::dump() const {
print(llvm::errs());
}
+void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
+ VisibleCallback Vis, ConflictCallback Cb) {
+ if (isVisible(M))
+ return;
+ ++Generation;
+
+ struct Visiting {
+ Module *M;
+ Visiting *ExportedBy;
+ };
+
+ std::function<void(Visiting)> VisitModule = [&](Visiting V) {
+ // Modules that aren't available cannot be made visible.
+ if (!V.M->isAvailable())
+ return;
+
+ // Nothing to do for a module that's already visible.
+ unsigned ID = V.M->getVisibilityID();
+ if (ImportLocs.size() <= ID)
+ ImportLocs.resize(ID + 1);
+ else if (ImportLocs[ID].isValid())
+ return;
+
+ ImportLocs[ID] = Loc;
+ Vis(M);
+
+ // Make any exported modules visible.
+ SmallVector<Module *, 16> Exports;
+ V.M->getExportedModules(Exports);
+ for (Module *E : Exports)
+ VisitModule({E, &V});
+
+ for (auto &C : V.M->Conflicts) {
+ if (isVisible(C.Other)) {
+ llvm::SmallVector<Module*, 8> Path;
+ for (Visiting *I = &V; I; I = I->ExportedBy)
+ Path.push_back(I->M);
+ Cb(Path, C.Other, C.Message);
+ }
+ }
+ };
+ VisitModule({M, nullptr});
+}
OpenPOWER on IntegriCloud