Rename IsMissingRequirement to IsUnimportable and set it for shadowed
authorRichard Smith <richard@metafoo.co.uk>
Fri, 17 Apr 2020 23:23:41 +0000 (16:23 -0700)
committerRichard Smith <richard@metafoo.co.uk>
Sat, 18 Apr 2020 05:48:56 +0000 (22:48 -0700)
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
clang/lib/Basic/Module.cpp
clang/lib/Frontend/CompilerInstance.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Serialization/ASTReader.cpp

index c47eb45..b14f6b5 100644 (file)
@@ -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.
   ///
index 5fd7d30..22e1da4 100644 (file)
@@ -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) {
index 470429c..0140a75 100644 (file)
@@ -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());
index bff4e11..2c79bb2 100644 (file)
@@ -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());
   }
index 62dd233..e2f89f5 100644 (file)
@@ -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;
     }