If a partial specialization of a member template is declared within a class
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
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dd10cbe..d85f7e4 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2142,13 +2142,25 @@
 
     // 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;
       }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e03e8c5..9779aa6 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -923,7 +923,7 @@
     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 @@
     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
index 0000000..1e820e4
--- /dev/null
+++ b/test/SemaTemplate/instantiate-partial-spec.cpp
@@ -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*>];