summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-01-06 00:09:23 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-01-06 00:09:23 +0000
commite2a1566b84f21019220c0707dd2920a6e76762b4 (patch)
tree646cc17b22ccbc3eb3fbe7b987bd90d5e2ed1511 /lib/Sema/SemaLookup.cpp
parent938d946ab39a2659172ad417f0ffcb23746014c2 (diff)
When name lookup finds a non-imported declaration and looks back along the
redecl chain for an imported declaration, make sure to check the IDNS of prior imported decls. Otherwise we can end up finding an invisible friend declaration and incorrectly believing that it should be visible. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321916 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r--lib/Sema/SemaLookup.cpp57
1 files changed, 28 insertions, 29 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index a9db973851..fb83c0f05e 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1656,7 +1656,8 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
///
/// \returns D, or a visible previous declaration of D, whichever is more recent
/// and visible. If no declaration of D is visible, returns null.
-static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
+static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D,
+ unsigned IDNS) {
assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
for (auto RD : D->redecls()) {
@@ -1668,7 +1669,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
// FIXME: This is wrong in the case where the previous declaration is not
// visible in the same scope as D. This needs to be done much more
// carefully.
- if (LookupResult::isVisible(SemaRef, ND))
+ if (ND->isInIdentifierNamespace(IDNS) &&
+ LookupResult::isVisible(SemaRef, ND))
return ND;
}
@@ -1693,14 +1695,15 @@ NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
auto *Key = ND->getCanonicalDecl();
if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key))
return Acceptable;
- auto *Acceptable =
- isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key);
+ auto *Acceptable = isVisible(getSema(), Key)
+ ? Key
+ : findAcceptableDecl(getSema(), Key, IDNS);
if (Acceptable)
getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable));
return Acceptable;
}
- return findAcceptableDecl(getSema(), D);
+ return findAcceptableDecl(getSema(), D, IDNS);
}
/// @brief Perform unqualified name lookup starting from a given
@@ -3329,6 +3332,23 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
// lookup (11.4).
DeclContext::lookup_result R = NS->lookup(Name);
for (auto *D : R) {
+ auto *Underlying = D;
+ if (auto *USD = dyn_cast<UsingShadowDecl>(D))
+ Underlying = USD->getTargetDecl();
+
+ if (!isa<FunctionDecl>(Underlying) &&
+ !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) {
@@ -3350,22 +3370,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
continue;
}
- auto *Underlying = D;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
-
- if (!isa<FunctionDecl>(Underlying) &&
- !isa<FunctionTemplateDecl>(Underlying))
- continue;
-
- if (!isVisible(D)) {
- D = findAcceptableDecl(*this, D);
- if (!D)
- continue;
- if (auto *USD = dyn_cast<UsingShadowDecl>(D))
- Underlying = USD->getTargetDecl();
- }
-
// FIXME: Preserve D as the FoundDecl.
Result.insert(Underlying);
}
@@ -3865,17 +3869,13 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) {
bool AnyVisibleDecls = !NewDecls.empty();
for (/**/; DI != DE; ++DI) {
- NamedDecl *VisibleDecl = *DI;
- if (!LookupResult::isVisible(SemaRef, *DI))
- VisibleDecl = findAcceptableDecl(SemaRef, *DI);
-
- if (VisibleDecl) {
+ if (LookupResult::isVisible(SemaRef, *DI)) {
if (!AnyVisibleDecls) {
// Found a visible decl, discard all hidden ones.
AnyVisibleDecls = true;
NewDecls.clear();
}
- NewDecls.push_back(VisibleDecl);
+ NewDecls.push_back(*DI);
} else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
NewDecls.push_back(*DI);
}
@@ -3945,8 +3945,7 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
// Only consider visible declarations and declarations from modules with
// names that exactly match.
- if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo &&
- !findAcceptableDecl(SemaRef, ND))
+ if (!LookupResult::isVisible(SemaRef, ND) && Name != Typo)
return;
FoundName(Name->getName());