[modules] If a referenced-but-not-instantiated class template specialization
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 23 May 2014 21:00:28 +0000 (21:00 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 23 May 2014 21:00:28 +0000 (21:00 +0000)
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

lib/Sema/SemaTemplate.cpp
test/Modules/Inputs/cxx-templates-a.h
test/Modules/Inputs/cxx-templates-common.h
test/Modules/cxx-templates.cpp

index dd2faf60d4a726b94a37ddff95c106ab84f8fc89..af80f1a5f6e33827d0c0a0ab1f99c96e7fef0098 100644 (file)
@@ -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);
index 04acf5929d10fa8f018dc6bf87b7e9e11a0b72c1..12b647b52de01b13fdc6f7e9c748a81966c7b079 100644 (file)
@@ -56,3 +56,10 @@ template<typename T> struct WithPartialSpecialization<T*> {
   T &f() { static T t; return t; }
 };
 typedef WithPartialSpecializationUse::type WithPartialSpecializationInstantiate;
+
+template<> struct WithExplicitSpecialization<int> {
+  int n;
+  template<typename T> T &inner_template() {
+    return n;
+  }
+};
index a31be8758cca825ffcd8dba0ec710167dd170768..986c52b362c01eec597a4a2665b2c64d4d2883a5 100644 (file)
@@ -33,3 +33,6 @@ template<typename T> struct Outer {
 
 template<typename T> struct WithPartialSpecialization {};
 typedef WithPartialSpecialization<int*> WithPartialSpecializationUse;
+
+template<typename T> struct WithExplicitSpecialization;
+typedef WithExplicitSpecialization<int> WithExplicitSpecializationUse;
index a880c9b2f18685388accb9a6ab08a9a857d8b121..f68bc72a27166b78bd0f0f90f61d89564365f29c 100644 (file)
@@ -104,6 +104,7 @@ void g() {
   TemplateInstantiationVisibility<char[4]> tiv4;
 
   int &p = WithPartialSpecializationUse().f();
+  int &q = WithExplicitSpecializationUse().inner_template<int>();
 }
 
 RedeclaredAsFriend<int> raf1;