diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1300,8 +1300,16 @@ // When performing a scope lookup, we want to find local extern decls. FindLocalExternScope FindLocals(R); + Scope *InnermostFileScope = nullptr; + DeclContext *InnermostFileScopeDC = nullptr; + + for (; S; S = S->getParent()) { + if (isNamespaceOrTranslationUnitScope(S)) { + if (!InnermostFileScope) + InnermostFileScope = S; + continue; + } - for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { bool SearchNamespaceScope = true; // Check whether the IdResolver has anything in this scope. for (; I != IEnd && S->isDeclScope(*I); ++I) { @@ -1385,6 +1393,9 @@ // If this is a file context, we need to perform unqualified name // lookup considering using directives. if (Ctx->isFileContext()) { + if (!InnermostFileScopeDC) + InnermostFileScopeDC = Ctx; + // If we haven't handled using directives yet, do so now. if (!VisitedUsingDirectives) { // Add using directives from this context up to the top level. @@ -1397,7 +1408,7 @@ // Find the innermost file scope, so we can add using directives // from local scopes. - Scope *InnermostFileScope = S; + InnermostFileScope = S; while (InnermostFileScope && !isNamespaceOrTranslationUnitScope(InnermostFileScope)) InnermostFileScope = InnermostFileScope->getParent(); @@ -1408,11 +1419,6 @@ VisitedUsingDirectives = true; } - if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) { - R.resolveKind(); - return true; - } - continue; } @@ -1428,6 +1434,8 @@ } } + S = InnermostFileScope; + // Stop if we ran out of scopes. // FIXME: This really, really shouldn't be happening. if (!S) return false; @@ -1446,6 +1454,14 @@ UDirs.done(); } + for (DeclContext *Ctx = InnermostFileScopeDC, *LastCtx = S->getEntity(); + Ctx && !Ctx->Equals(LastCtx); Ctx = Ctx->getLookupParent()) + if (Ctx->isFileContext() && + CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) { + R.resolveKind(); + return true; + } + // If we're not performing redeclaration lookup, do not look for local // extern declarations outside of a function scope. if (!R.isForRedeclaration()) @@ -1456,6 +1472,9 @@ // that aren't strictly lexical, and therefore we walk through the // context as well as walking through the scopes. for (; S; S = S->getParent()) { + if (!isNamespaceOrTranslationUnitScope(S)) + continue; + // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(*I); ++I) { diff --git a/clang/test/SemaCXX/namespace.cpp b/clang/test/SemaCXX/namespace.cpp --- a/clang/test/SemaCXX/namespace.cpp +++ b/clang/test/SemaCXX/namespace.cpp @@ -96,3 +96,12 @@ } } + +namespace N0 { + template class S; + template class C; +} + +template class N0::C { + void foo(S c) {} +};