/// 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;
~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; }
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.
///
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),
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);
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;
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))
continue;
Current->IsAvailable = false;
- Current->IsMissingRequirement |= MissingRequirement;
+ Current->IsUnimportable |= Unimportable;
for (submodule_iterator Sub = Current->submodule_begin(),
SubEnd = Current->submodule_end();
Sub != SubEnd; ++Sub) {
// 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);
}
}
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);
// 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());
}