From: Douglas Gregor Date: Sat, 26 Sep 2009 07:05:09 +0000 (+0000) Subject: Fix name lookup for friend class templates to consider anything in a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6102d98f3b806cc3f4a66cec27f5560b25ddd675;p=clang Fix name lookup for friend class templates to consider anything in a scope *up to and including* the innermost namespace scope, rather than just searching in the innermost namespace scope. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82849 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 72274525fd..d037f3f3e3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -577,18 +577,6 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, return true; } - Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName, - true); - } else if (TUK == TUK_Friend) { - // C++ [namespace.memdef]p3: - // [...] When looking for a prior declaration of a class or a function - // declared as a friend, and when the name of the friend class or - // function is neither a qualified name nor a template-id, scopes outside - // the innermost enclosing namespace scope are not considered. - SemanticContext = CurContext; - while (!SemanticContext->isFileContext()) - SemanticContext = SemanticContext->getLookupParent(); - Previous = LookupQualifiedName(SemanticContext, Name, LookupOrdinaryName, true); } else { @@ -601,7 +589,27 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); - if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) + if (PrevDecl && TUK == TUK_Friend) { + // C++ [namespace.memdef]p3: + // [...] When looking for a prior declaration of a class or a function + // declared as a friend, and when the name of the friend class or + // function is neither a qualified name nor a template-id, scopes outside + // the innermost enclosing namespace scope are not considered. + DeclContext *OutermostContext = CurContext; + while (!OutermostContext->isFileContext()) + OutermostContext = OutermostContext->getLookupParent(); + + if (OutermostContext->Equals(PrevDecl->getDeclContext()) || + OutermostContext->Encloses(PrevDecl->getDeclContext())) { + SemanticContext = PrevDecl->getDeclContext(); + } else { + // Declarations in outer scopes don't matter. However, the outermost + // context we computed is the semntic context for our new + // declaration. + PrevDecl = 0; + SemanticContext = OutermostContext; + } + } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) PrevDecl = 0; // If there is a previous declaration with the same name, check diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp new file mode 100644 index 0000000000..2ca7165aad --- /dev/null +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only %s + +template struct X0 { }; +struct X1 { }; + +struct Y { + template union X0; + template friend union X0; + + union X1; + friend union X1; +}; + + +// FIXME: Woefully inadequate for testing