<rdar://problem/13540899> Collect using directives from all of the semantic contexts not represented by scopes.

This fixes a regression I introduced in r178136, where we would not
consider the using directives from the semantic declaration contexts
that aren't represented by the lexical scopes (Scope) when performing
unqualified name lookup. This lead to horribly funny diagnostics like
"no identifier named 'foo'; did you mean 'foo'?".

llvm-svn: 179067
This commit is contained in:
Douglas Gregor 2013-04-08 23:11:25 +00:00
parent 065fd35268
commit cc9406c055
2 changed files with 44 additions and 8 deletions

View File

@ -884,6 +884,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// } // }
// } // }
// //
UnqualUsingDirectiveSet UDirs;
bool VisitedUsingDirectives = false;
DeclContext *OutsideOfTemplateParamDC = 0; DeclContext *OutsideOfTemplateParamDC = 0;
for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity());
@ -957,9 +959,24 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// If this is a file context, we need to perform unqualified name // If this is a file context, we need to perform unqualified name
// lookup considering using directives. // lookup considering using directives.
if (Ctx->isFileContext()) { if (Ctx->isFileContext()) {
UnqualUsingDirectiveSet UDirs; // If we haven't handled using directives yet, do so now.
UDirs.visit(Ctx, Ctx); if (!VisitedUsingDirectives) {
UDirs.done(); // Add using directives from this context up to the top level.
for (DeclContext *UCtx = Ctx; UCtx; UCtx = UCtx->getParent())
UDirs.visit(UCtx, UCtx);
// Find the innermost file scope, so we can add using directives
// from local scopes.
Scope *InnermostFileScope = S;
while (InnermostFileScope &&
!isNamespaceOrTranslationUnitScope(InnermostFileScope))
InnermostFileScope = InnermostFileScope->getParent();
UDirs.visitScopeChain(Initial, InnermostFileScope);
UDirs.done();
VisitedUsingDirectives = true;
}
if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) { if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) {
R.resolveKind(); R.resolveKind();
@ -994,10 +1011,10 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// //
// FIXME: Cache this sorted list in Scope structure, and DeclContext, so we // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we
// don't build it for each lookup! // don't build it for each lookup!
if (!VisitedUsingDirectives) {
UnqualUsingDirectiveSet UDirs; UDirs.visitScopeChain(Initial, S);
UDirs.visitScopeChain(Initial, S); UDirs.done();
UDirs.done(); }
// Lookup namespace scope, and global scope. // Lookup namespace scope, and global scope.
// Unqualified name lookup in C++ requires looking into scopes // Unqualified name lookup in C++ requires looking into scopes

View File

@ -47,3 +47,22 @@ class Other {
void Other::foo(YFloat a, YFloat b) { void Other::foo(YFloat a, YFloat b) {
YFloat c = a - b; YFloat c = a - b;
} }
// <rdar://problem/13540899>
namespace Other {
void other_foo();
}
namespace M2 {
using namespace Other;
namespace MInner {
class Bar {
void bar();
};
}
}
void M2::MInner::Bar::bar() {
other_foo();
}