aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Module.h27
-rw-r--r--clang/lib/Basic/Module.cpp62
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp2
-rw-r--r--clang/lib/Lex/ModuleMap.cpp8
-rw-r--r--clang/lib/Serialization/ASTReader.cpp6
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;
}