From fc76b4ad3da3c1f5fdc34370a55d613b3ca7af73 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 17 Apr 2020 16:23:41 -0700 Subject: [PATCH] Rename IsMissingRequirement to IsUnimportable and set it for shadowed modules too. This more accurately reflects the semantics of this flag, as distinct from "IsAvailable", which (in an explicit modules world) only describes whether a module is buildable, not whether it's importable. --- clang/include/clang/Basic/Module.h | 27 ++++++++++++-- clang/lib/Basic/Module.cpp | 62 ++++++++++++++++++++------------- clang/lib/Frontend/CompilerInstance.cpp | 2 +- clang/lib/Lex/ModuleMap.cpp | 8 ++--- clang/lib/Serialization/ASTReader.cpp | 6 ++-- 5 files changed, 69 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index c47eb45..b14f6b5 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -207,8 +207,10 @@ public: /// A module with the same name that shadows this module. Module *ShadowingModule = nullptr; - /// Whether this module is missing a feature from \c Requirements. - unsigned IsMissingRequirement : 1; + /// Whether this module has declared itself unimportable, either because + /// it's missing a requirement from \p Requirements or because it's been + /// shadowed by another module. + unsigned IsUnimportable : 1; /// Whether we tried and failed to load a module file for this module. unsigned HasIncompatibleModuleFile : 1; @@ -384,6 +386,25 @@ public: ~Module(); + /// Determine whether this module has been declared unimportable. + bool isUnimportable() const { return IsUnimportable; } + + /// Determine whether this module has been declared unimportable. + /// + /// \param LangOpts The language options used for the current + /// translation unit. + /// + /// \param Target The target options used for the current translation unit. + /// + /// \param Req If this module is unimportable because of a missing + /// requirement, this parameter will be set to one of the requirements that + /// is not met for use of this module. + /// + /// \param ShadowingModule If this module is unimportable because it is + /// shadowed, this parameter will be set to the shadowing module. + bool isUnimportable(const LangOptions &LangOpts, const TargetInfo &Target, + Requirement &Req, Module *&ShadowingModule) const; + /// Determine whether this module is available for use within the /// current translation unit. bool isAvailable() const { return IsAvailable; } @@ -535,7 +556,7 @@ public: const TargetInfo &Target); /// Mark this module and all of its submodules as unavailable. - void markUnavailable(bool MissingRequirement = false); + void markUnavailable(bool Unimportable); /// Find the submodule with the given name. /// diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 5fd7d30..22e1da4 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -37,7 +37,7 @@ using namespace clang; Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, bool IsExplicit, unsigned VisibilityID) : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), - VisibilityID(VisibilityID), IsMissingRequirement(false), + VisibilityID(VisibilityID), IsUnimportable(false), HasIncompatibleModuleFile(false), IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), IsInferred(false), @@ -46,17 +46,12 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, NoUndeclaredIncludes(false), ModuleMapIsPrivate(false), HasUmbrellaDir(false), NameVisibility(Hidden) { if (Parent) { - if (!Parent->isAvailable()) - IsAvailable = false; - if (Parent->IsSystem) - IsSystem = true; - if (Parent->IsExternC) - IsExternC = true; - if (Parent->NoUndeclaredIncludes) - NoUndeclaredIncludes = true; - if (Parent->ModuleMapIsPrivate) - ModuleMapIsPrivate = true; - IsMissingRequirement = Parent->IsMissingRequirement; + IsAvailable = Parent->isAvailable(); + IsUnimportable = Parent->isUnimportable(); + IsSystem = Parent->IsSystem; + IsExternC = Parent->IsExternC; + NoUndeclaredIncludes = Parent->NoUndeclaredIncludes; + ModuleMapIsPrivate = Parent->ModuleMapIsPrivate; Parent->SubModuleIndex[Name] = Parent->SubModules.size(); Parent->SubModules.push_back(this); @@ -132,25 +127,42 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, return HasFeature; } -bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, - Requirement &Req, - UnresolvedHeaderDirective &MissingHeader, - Module *&ShadowingModule) const { - if (IsAvailable) - return true; +bool Module::isUnimportable(const LangOptions &LangOpts, + const TargetInfo &Target, Requirement &Req, + Module *&ShadowingModule) const { + if (!IsUnimportable) + return false; for (const Module *Current = this; Current; Current = Current->Parent) { if (Current->ShadowingModule) { ShadowingModule = Current->ShadowingModule; - return false; + return true; } for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) { if (hasFeature(Current->Requirements[I].first, LangOpts, Target) != Current->Requirements[I].second) { Req = Current->Requirements[I]; - return false; + return true; } } + } + + llvm_unreachable("could not find a reason why module is unimportable"); +} + +bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, + Requirement &Req, + UnresolvedHeaderDirective &MissingHeader, + Module *&ShadowingModule) const { + if (IsAvailable) + return true; + + if (isUnimportable(LangOpts, Target, Req, ShadowingModule)) + return false; + + // FIXME: All missing headers are listed on the top-level module. Should we + // just look there? + for (const Module *Current = this; Current; Current = Current->Parent) { if (!Current->MissingHeaders.empty()) { MissingHeader = Current->MissingHeaders.front(); return false; @@ -287,12 +299,12 @@ void Module::addRequirement(StringRef Feature, bool RequiredState, if (hasFeature(Feature, LangOpts, Target) == RequiredState) return; - markUnavailable(/*MissingRequirement*/true); + markUnavailable(/*Unimportable*/true); } -void Module::markUnavailable(bool MissingRequirement) { - auto needUpdate = [MissingRequirement](Module *M) { - return M->IsAvailable || (!M->IsMissingRequirement && MissingRequirement); +void Module::markUnavailable(bool Unimportable) { + auto needUpdate = [Unimportable](Module *M) { + return M->IsAvailable || (!M->IsUnimportable && Unimportable); }; if (!needUpdate(this)) @@ -308,7 +320,7 @@ void Module::markUnavailable(bool MissingRequirement) { continue; Current->IsAvailable = false; - Current->IsMissingRequirement |= MissingRequirement; + Current->IsUnimportable |= Unimportable; for (submodule_iterator Sub = Current->submodule_begin(), SubEnd = Current->submodule_end(); Sub != SubEnd; ++Sub) { diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 470429c..0140a75 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1576,7 +1576,7 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { Stack.push_back(M); while (!Stack.empty()) { Module *Current = Stack.pop_back_val(); - if (Current->IsMissingRequirement) continue; + if (Current->IsUnimportable) continue; Current->IsAvailable = true; Stack.insert(Stack.end(), Current->submodule_begin(), Current->submodule_end()); diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index bff4e11..2c79bb2 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -282,7 +282,7 @@ void ModuleMap::resolveHeader(Module *Mod, // resolved. (Such a module still can't be built though, except from // preprocessed source.) if (!Header.Size && !Header.ModTime) - Mod->markUnavailable(); + Mod->markUnavailable(/*Unimportable=*/false); } } @@ -1094,7 +1094,7 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, /*IsExplicit=*/false, NumCreatedModules++); Result->ShadowingModule = ShadowingModule; - Result->IsAvailable = false; + Result->markUnavailable(/*Unimportable*/true); ModuleScopeIDs[Result] = CurrentModuleScopeID; ShadowModules.push_back(Result); @@ -2096,9 +2096,9 @@ void ModuleMapParser::parseModuleDecl() { // If the module meets all requirements but is still unavailable, mark the // whole tree as unavailable to prevent it from building. - if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && + if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable && ActiveModule->Parent) { - ActiveModule->getTopLevelModule()->markUnavailable(); + ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false); ActiveModule->getTopLevelModule()->MissingHeaders.append( ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 62dd233..e2f89f5 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5539,9 +5539,9 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // imported module file. CurrentModule->Requirements.clear(); CurrentModule->MissingHeaders.clear(); - CurrentModule->IsMissingRequirement = - ParentModule && ParentModule->IsMissingRequirement; - CurrentModule->IsAvailable = !CurrentModule->IsMissingRequirement; + CurrentModule->IsUnimportable = + ParentModule && ParentModule->IsUnimportable; + CurrentModule->IsAvailable = !CurrentModule->IsUnimportable; break; } -- 2.7.4