summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r--lib/Sema/SemaLookup.cpp161
1 files changed, 72 insertions, 89 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 0ab70e9dca375..effccc2f3d383 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -186,9 +186,7 @@ namespace {
list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common));
}
- void done() {
- llvm::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator());
- }
+ void done() { llvm::sort(list, UnqualUsingEntry::Comparator()); }
typedef ListTy::const_iterator const_iterator;
@@ -1392,23 +1390,25 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() {
return LookupModulesCache;
}
+/// Determine whether the module M is part of the current module from the
+/// perspective of a module-private visibility check.
+static bool isInCurrentModule(const Module *M, const LangOptions &LangOpts) {
+ // If M is the global module fragment of a module that we've not yet finished
+ // parsing, then it must be part of the current module.
+ return M->getTopLevelModuleName() == LangOpts.CurrentModule ||
+ (M->Kind == Module::GlobalModuleFragment && !M->Parent);
+}
+
bool Sema::hasVisibleMergedDefinition(NamedDecl *Def) {
- for (Module *Merged : Context.getModulesWithMergedDefinition(Def))
+ for (const Module *Merged : Context.getModulesWithMergedDefinition(Def))
if (isModuleVisible(Merged))
return true;
return false;
}
bool Sema::hasMergedDefinitionInCurrentModule(NamedDecl *Def) {
- // FIXME: When not in local visibility mode, we can't tell the difference
- // between a declaration being visible because we merged a local copy of
- // the same declaration into it, and it being visible because its owning
- // module is visible.
- if (Def->getModuleOwnershipKind() == Decl::ModuleOwnershipKind::Visible &&
- getLangOpts().ModulesLocalVisibility)
- return true;
- for (Module *Merged : Context.getModulesWithMergedDefinition(Def))
- if (Merged->getTopLevelModuleName() == getLangOpts().CurrentModule)
+ for (const Module *Merged : Context.getModulesWithMergedDefinition(Def))
+ if (isInCurrentModule(Merged, getLangOpts()))
return true;
return false;
}
@@ -1428,8 +1428,6 @@ hasVisibleDefaultArgument(Sema &S, const ParmDecl *D,
if (!DefaultArg.isInherited() && Modules) {
auto *NonConstD = const_cast<ParmDecl*>(D);
Modules->push_back(S.getOwningModule(NonConstD));
- const auto &Merged = S.Context.getModulesWithMergedDefinition(NonConstD);
- Modules->insert(Modules->end(), Merged.begin(), Merged.end());
}
// If there was a previous default argument, maybe its parameter is visible.
@@ -1464,11 +1462,8 @@ static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
HasFilteredRedecls = true;
- if (Modules) {
+ if (Modules)
Modules->push_back(R->getOwningModule());
- const auto &Merged = S.Context.getModulesWithMergedDefinition(R);
- Modules->insert(Modules->end(), Merged.begin(), Merged.end());
- }
}
// Only return false if there is at least one redecl that is not filtered out.
@@ -1519,27 +1514,11 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
assert(D->isHidden() && "should not call this: not in slow case");
Module *DeclModule = SemaRef.getOwningModule(D);
- if (!DeclModule) {
- // A module-private declaration with no owning module means this is in the
- // global module in the C++ Modules TS. This is visible within the same
- // translation unit only.
- // FIXME: Don't assume that "same translation unit" means the same thing
- // as "not from an AST file".
- assert(D->isModulePrivate() && "hidden decl has no module");
- if (!D->isFromASTFile() || SemaRef.hasMergedDefinitionInCurrentModule(D))
- return true;
- } else {
- // If the owning module is visible, and the decl is not module private,
- // then the decl is visible too. (Module private is ignored within the same
- // top-level module.)
- if (D->isModulePrivate()
- ? DeclModule->getTopLevelModuleName() ==
- SemaRef.getLangOpts().CurrentModule ||
- SemaRef.hasMergedDefinitionInCurrentModule(D)
- : SemaRef.isModuleVisible(DeclModule) ||
- SemaRef.hasVisibleMergedDefinition(D))
- return true;
- }
+ assert(DeclModule && "hidden decl has no owning module");
+
+ // If the owning module is visible, the decl is visible.
+ if (SemaRef.isModuleVisible(DeclModule, D->isModulePrivate()))
+ return true;
// Determine whether a decl context is a file context for the purpose of
// visibility. This looks through some (export and linkage spec) transparent
@@ -1589,29 +1568,41 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
return VisibleWithinParent;
}
- // FIXME: All uses of DeclModule below this point should also check merged
- // modules.
- if (!DeclModule)
- return false;
+ return false;
+}
+
+bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) {
+ // The module might be ordinarily visible. For a module-private query, that
+ // means it is part of the current module. For any other query, that means it
+ // is in our visible module set.
+ if (ModulePrivate) {
+ if (isInCurrentModule(M, getLangOpts()))
+ return true;
+ } else {
+ if (VisibleModules.isVisible(M))
+ return true;
+ }
+
+ // Otherwise, it might be visible by virtue of the query being within a
+ // template instantiation or similar that is permitted to look inside M.
// Find the extra places where we need to look.
- const auto &LookupModules = SemaRef.getLookupModules();
+ const auto &LookupModules = getLookupModules();
if (LookupModules.empty())
return false;
- // If our lookup set contains the decl's module, it's visible.
- if (LookupModules.count(DeclModule))
+ // If our lookup set contains the module, it's visible.
+ if (LookupModules.count(M))
return true;
- // If the declaration isn't exported, it's not visible in any other module.
- if (D->isModulePrivate())
+ // For a module-private query, that's everywhere we get to look.
+ if (ModulePrivate)
return false;
- // Check whether DeclModule is transitively exported to an import of
- // the lookup set.
- return std::any_of(LookupModules.begin(), LookupModules.end(),
- [&](const Module *M) {
- return M->isModuleVisible(DeclModule); });
+ // Check whether M is transitively exported to an import of the lookup set.
+ return llvm::any_of(LookupModules, [&](const Module *LookupM) {
+ return LookupM->isModuleVisible(M);
+ });
}
bool Sema::isVisibleSlow(const NamedDecl *D) {
@@ -3346,38 +3337,29 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
!isa<FunctionTemplateDecl>(Underlying))
continue;
- if (!isVisible(D)) {
- D = findAcceptableDecl(
- *this, D, (Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend));
- if (!D)
- continue;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
- }
-
- // If the only declaration here is an ordinary friend, consider
- // it only if it was declared in an associated classes.
- if ((D->getIdentifierNamespace() & Decl::IDNS_Ordinary) == 0) {
- // If it's neither ordinarily visible nor a friend, we can't find it.
- if ((D->getIdentifierNamespace() & Decl::IDNS_OrdinaryFriend) == 0)
- continue;
-
- bool DeclaredInAssociatedClass = false;
- for (Decl *DI = D; DI; DI = DI->getPreviousDecl()) {
- DeclContext *LexDC = DI->getLexicalDeclContext();
- if (isa<CXXRecordDecl>(LexDC) &&
- AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)) &&
- isVisible(cast<NamedDecl>(DI))) {
- DeclaredInAssociatedClass = true;
+ // The declaration is visible to argument-dependent lookup if either
+ // it's ordinarily visible or declared as a friend in an associated
+ // class.
+ bool Visible = false;
+ for (D = D->getMostRecentDecl(); D;
+ D = cast_or_null<NamedDecl>(D->getPreviousDecl())) {
+ if (D->getIdentifierNamespace() & Decl::IDNS_Ordinary) {
+ if (isVisible(D)) {
+ Visible = true;
+ break;
+ }
+ } else if (D->getFriendObjectKind()) {
+ auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext());
+ if (AssociatedClasses.count(RD) && isVisible(D)) {
+ Visible = true;
break;
}
}
- if (!DeclaredInAssociatedClass)
- continue;
}
// FIXME: Preserve D as the FoundDecl.
- Result.insert(Underlying);
+ if (Visible)
+ Result.insert(Underlying);
}
}
}
@@ -3628,8 +3610,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
// Find results in this base class (and its bases).
ShadowContextRAII Shadow(Visited);
- LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer,
- Visited, IncludeDependentBases, LoadExternal);
+ LookupVisibleDecls(RD, Result, QualifiedNameLookup, /*InBaseClass=*/true,
+ Consumer, Visited, IncludeDependentBases,
+ LoadExternal);
}
}
@@ -3998,9 +3981,9 @@ void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND,
// Compute an upper bound on the allowable edit distance, so that the
// edit-distance algorithm can short-circuit.
- unsigned UpperBound = (TypoStr.size() + 2) / 3 + 1;
+ unsigned UpperBound = (TypoStr.size() + 2) / 3;
unsigned ED = TypoStr.edit_distance(Name, true, UpperBound);
- if (ED >= UpperBound) return;
+ if (ED > UpperBound) return;
TypoCorrection TC(&SemaRef.Context.Idents.get(Name), ND, NNS, ED);
if (isKeyword) TC.makeKeyword();
@@ -4070,7 +4053,7 @@ void TypoCorrectionConsumer::addNamespaces(
}
// Do not transform this into an iterator-based loop. The loop body can
// trigger the creation of further types (through lazy deserialization) and
- // invalide iterators into this list.
+ // invalid iterators into this list.
auto &Types = SemaRef.getASTContext().getTypes();
for (unsigned I = 0; I != Types.size(); ++I) {
const auto *TI = Types[I];
@@ -4211,7 +4194,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() {
SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy());
OldOStream << Typo->getName();
// If correction candidate would be an identical written qualified
- // identifer, then the existing CXXScopeSpec probably included a
+ // identifier, then the existing CXXScopeSpec probably included a
// typedef that didn't get accounted for properly.
if (OldOStream.str() == NewQualified)
break;
@@ -4628,7 +4611,7 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer(
getLangOpts().ModulesSearchAll) {
// The following has the side effect of loading the missing module.
getModuleLoader().lookupMissingImports(Typo->getName(),
- TypoName.getLocStart());
+ TypoName.getBeginLoc());
}
CorrectionCandidateCallback &CCCRef = *CCC;
@@ -5061,12 +5044,12 @@ void Sema::diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
if (!Def)
Def = Decl;
- Module *Owner = getOwningModule(Decl);
+ Module *Owner = getOwningModule(Def);
assert(Owner && "definition of hidden declaration is not in a module");
llvm::SmallVector<Module*, 8> OwningModules;
OwningModules.push_back(Owner);
- auto Merged = Context.getModulesWithMergedDefinition(Decl);
+ auto Merged = Context.getModulesWithMergedDefinition(Def);
OwningModules.insert(OwningModules.end(), Merged.begin(), Merged.end());
diagnoseMissingImport(Loc, Decl, Decl->getLocation(), OwningModules, MIK,