diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/Module.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/Module.cpp | 111 |
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}); +} |