From 00b4b039f02d338ae4774797053235a7e65abbde Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 14 May 2010 04:53:42 +0000 Subject: [PATCH] Make sure to search semantic scopes and appropriate template-parameter scopes during unqualified name lookup that has fallen out to namespace scope. Fixes PR7133. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103766 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaLookup.cpp | 64 ++++++++++++++----- test/SemaCXX/nested-name-spec.cpp | 16 +++++ .../nested-name-spec-template.cpp | 7 ++ 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 337a4a3ce3..31c33e963c 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -761,10 +761,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // context as well as walking through the scopes. for (; S; S = S->getParent()) { - DeclContext *Ctx = static_cast(S->getEntity()); - if (Ctx && Ctx->isTransparentContext()) - continue; - // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { @@ -778,21 +774,57 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { } } - // If we have a context, and it's not a context stashed in the - // template parameter scope for an out-of-line definition, also - // look into that context. - if (Ctx && !(Found && S && S->isTemplateParamScope())) { - assert(Ctx->isFileContext() && - "We should have been looking only at file context here already."); + if (Found && S->isTemplateParamScope()) { + R.resolveKind(); + return true; + } - // Look into context considering using-directives. - if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) - Found = true; + DeclContext *Ctx = static_cast(S->getEntity()); + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && + S->getParent() && !S->getParent()->isTemplateParamScope()) { + // We've just searched the last template parameter scope and + // found nothing, so look into the the contexts between the + // lexical and semantic declaration contexts returned by + // findOuterContext(). This implements the name lookup behavior + // of C++ [temp.local]p8. + Ctx = OutsideOfTemplateParamDC; + OutsideOfTemplateParamDC = 0; } + + if (Ctx) { + DeclContext *OuterCtx; + bool SearchAfterTemplateScope; + llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); + if (SearchAfterTemplateScope) + OutsideOfTemplateParamDC = OuterCtx; - if (Found) { - R.resolveKind(); - return true; + for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { + // We do not directly look into transparent contexts, since + // those entities will be found in the nearest enclosing + // non-transparent context. + if (Ctx->isTransparentContext()) + continue; + + // If we have a context, and it's not a context stashed in the + // template parameter scope for an out-of-line definition, also + // look into that context. + if (!(Found && S && S->isTemplateParamScope())) { + assert(Ctx->isFileContext() && + "We should have been looking only at file context here already."); + + // Look into context considering using-directives. + if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) + Found = true; + } + + if (Found) { + R.resolveKind(); + return true; + } + + if (R.isForRedeclaration() && !Ctx->isTransparentContext()) + return false; + } } if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext()) diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 59a8e8c45d..0dc1097e38 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -228,3 +228,19 @@ namespace test3 { A::execute(path); // expected-error {{incomplete type 'test3::A' named in nested name specifier}} } } + +namespace PR7133 { + namespace A { + class Foo; + } + + namespace A { + namespace B { + bool foo(Foo &); + } + } + + bool A::B::foo(Foo &) { + return false; + } +} diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp index 9d25a051e8..54e615b4ab 100644 --- a/test/SemaTemplate/nested-name-spec-template.cpp +++ b/test/SemaTemplate/nested-name-spec-template.cpp @@ -64,3 +64,10 @@ namespace test1 { template T pair::* const pair::mem_array[2] = { &pair::x, &pair::y }; } + +typedef int T; +namespace N1 { + template T f0(); +} + +template T N1::f0() { } -- 2.40.0