]> granicus.if.org Git - clang/commitdiff
If a partial specialization of a member template is declared within a class
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 26 Sep 2013 03:49:48 +0000 (03:49 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 26 Sep 2013 03:49:48 +0000 (03:49 +0000)
template and defined outside it, don't instantiate it twice when instantiating
the surrounding class template specialization. That would cause us to reject
the code because we think two partial specializations instantiated to produce
the same signature.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191418 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-partial-spec.cpp [new file with mode: 0644]

index dd10cbe2b7650d88d3460567e3716ae16d206513..d85f7e4b1b8db5302cfe4d716551fa72a150d5e0 100644 (file)
@@ -2142,13 +2142,25 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
 
     // Instantiate any out-of-line class template partial
     // specializations now.
-    for (TemplateDeclInstantiator::delayed_partial_spec_iterator 
+    for (TemplateDeclInstantiator::delayed_partial_spec_iterator
               P = Instantiator.delayed_partial_spec_begin(),
            PEnd = Instantiator.delayed_partial_spec_end();
          P != PEnd; ++P) {
       if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
-                                                                P->first,
-                                                                P->second)) {
+              P->first, P->second)) {
+        Instantiation->setInvalidDecl();
+        break;
+      }
+    }
+
+    // Instantiate any out-of-line variable template partial
+    // specializations now.
+    for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator
+              P = Instantiator.delayed_var_partial_spec_begin(),
+           PEnd = Instantiator.delayed_var_partial_spec_end();
+         P != PEnd; ++P) {
+      if (!Instantiator.InstantiateVarTemplatePartialSpecialization(
+              P->first, P->second)) {
         Instantiation->setInvalidDecl();
         break;
       }
index e03e8c55c9af18ec4cad6c6e69e585e33fda7aea..9779aa64ae595de20e8eb184b4f5df8911dc2027 100644 (file)
@@ -923,7 +923,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
     SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
     D->getPartialSpecializations(PartialSpecs);
     for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
-      if (PartialSpecs[I]->isOutOfLine())
+      if (PartialSpecs[I]->getFirstDeclaration()->isOutOfLine())
         OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
   }
 
@@ -1004,7 +1004,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
     SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
     D->getPartialSpecializations(PartialSpecs);
     for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
-      if (PartialSpecs[I]->isOutOfLine())
+      if (PartialSpecs[I]->getFirstDeclaration()->isOutOfLine())
         OutOfLineVarPartialSpecs.push_back(
             std::make_pair(Inst, PartialSpecs[I]));
   }
diff --git a/test/SemaTemplate/instantiate-partial-spec.cpp b/test/SemaTemplate/instantiate-partial-spec.cpp
new file mode 100644 (file)
index 0000000..1e820e4
--- /dev/null
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++1y -verify %s
+// expected-no-diagnostics
+
+template<typename T> struct A {
+  template<typename U> struct B;
+  template<typename U> struct B<U*>;
+};
+template<typename T> template<typename U> struct A<T>::B<U*> {};
+template struct A<int>;
+A<int>::B<int*> b;
+
+
+template<typename T> struct B {
+  template<typename U> static const int var1;
+  template<typename U> static const int var1<U*>;
+
+  template<typename U> static const int var2;
+};
+template<typename T> template<typename U> const int B<T>::var1<U*> = 1;
+template<typename T> template<typename U> const int B<T>::var2<U*> = 1;
+template struct B<int>;
+int b_test1[B<int>::var1<int*>];
+int b_test2[B<int>::var2<int*>];