From: Douglas Gregor Date: Fri, 9 Oct 2009 21:11:42 +0000 (+0000) Subject: When declaring a friend class template, we may end up finding an X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d7e5bdb23c6ba2786cf94788c9af555e2c1276ce;p=clang When declaring a friend class template, we may end up finding an injected-class-name (e.g., when we're referring to other specializations of the current class template). Make sure that we see the template rather than the injected-class-name. Fixes PR4768. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83672 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 219d73146e..3ee257a94e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -616,6 +616,22 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // whether this is a valid redeclaration. ClassTemplateDecl *PrevClassTemplate = dyn_cast_or_null(PrevDecl); + + // We may have found the injected-class-name of a class template, + // class template partial specialization, or class template specialization. + // In these cases, grab the template that is being defined or specialized. + if (!PrevClassTemplate && PrevDecl && isa(PrevDecl) && + cast(PrevDecl)->isInjectedClassName()) { + PrevDecl = cast(PrevDecl->getDeclContext()); + PrevClassTemplate + = cast(PrevDecl)->getDescribedClassTemplate(); + if (!PrevClassTemplate && isa(PrevDecl)) { + PrevClassTemplate + = cast(PrevDecl) + ->getSpecializedTemplate(); + } + } + if (PrevClassTemplate) { // Ensure that the template parameter lists are compatible. if (!TemplateParameterListsAreEqual(TemplateParams, diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp index df27c920b7..9a483aeb5b 100644 --- a/test/SemaTemplate/friend-template.cpp +++ b/test/SemaTemplate/friend-template.cpp @@ -28,3 +28,19 @@ namespace N { template void f0(T) { } template void f1(T) { } // expected-error{{redefinition}} } + +// PR4768 +template +struct X0 { + template friend struct X0; +}; + +template +struct X0 { + template friend struct X0; +}; + +template<> +struct X0 { + template friend struct X0; +};