From: Richard Smith Date: Fri, 23 May 2014 21:00:28 +0000 (+0000) Subject: [modules] If a referenced-but-not-instantiated class template specialization X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3ccca48c69e96f10485bc7eda0a1531dee22b775;p=clang [modules] If a referenced-but-not-instantiated class template specialization gets explicitly specialized, don't reuse the previous class template specialization declaration as a new declaration. The benefit here is fairly marginal, it harms source fidelity, and this is horrible to model if the specialization was imported from another module (without this change, it asserts or worse). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209552 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index dd2faf60d4..af80f1a5f6 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -6066,24 +6066,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // The canonical type QualType CanonType; - if (PrevDecl && - (PrevDecl->getSpecializationKind() == TSK_Undeclared || - TUK == TUK_Friend)) { - // Since the only prior class template specialization with these - // arguments was referenced but not declared, or we're only - // referencing this specialization as a friend, reuse that - // declaration node as our own, updating its source location and - // the list of outer template parameters to reflect our new declaration. - Specialization = PrevDecl; - Specialization->setLocation(TemplateNameLoc); - if (TemplateParameterLists.size() > 0) { - Specialization->setTemplateParameterListsInfo(Context, - TemplateParameterLists.size(), - TemplateParameterLists.data()); - } - PrevDecl = 0; - CanonType = Context.getTypeDeclType(Specialization); - } else if (isPartialSpecialization) { + if (isPartialSpecialization) { // Build the canonical type that describes the converted template // arguments of the class template partial specialization. TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); diff --git a/test/Modules/Inputs/cxx-templates-a.h b/test/Modules/Inputs/cxx-templates-a.h index 04acf5929d..12b647b52d 100644 --- a/test/Modules/Inputs/cxx-templates-a.h +++ b/test/Modules/Inputs/cxx-templates-a.h @@ -56,3 +56,10 @@ template struct WithPartialSpecialization { T &f() { static T t; return t; } }; typedef WithPartialSpecializationUse::type WithPartialSpecializationInstantiate; + +template<> struct WithExplicitSpecialization { + int n; + template T &inner_template() { + return n; + } +}; diff --git a/test/Modules/Inputs/cxx-templates-common.h b/test/Modules/Inputs/cxx-templates-common.h index a31be8758c..986c52b362 100644 --- a/test/Modules/Inputs/cxx-templates-common.h +++ b/test/Modules/Inputs/cxx-templates-common.h @@ -33,3 +33,6 @@ template struct Outer { template struct WithPartialSpecialization {}; typedef WithPartialSpecialization WithPartialSpecializationUse; + +template struct WithExplicitSpecialization; +typedef WithExplicitSpecialization WithExplicitSpecializationUse; diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp index a880c9b2f1..f68bc72a27 100644 --- a/test/Modules/cxx-templates.cpp +++ b/test/Modules/cxx-templates.cpp @@ -104,6 +104,7 @@ void g() { TemplateInstantiationVisibility tiv4; int &p = WithPartialSpecializationUse().f(); + int &q = WithExplicitSpecializationUse().inner_template(); } RedeclaredAsFriend raf1;