From: Richard Smith Date: Thu, 26 Sep 2013 03:49:48 +0000 (+0000) Subject: If a partial specialization of a member template is declared within a class X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e688ddf351d5d77d18cd01727e672e4b69706b23;p=clang 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 dd10cbe2b7..d85f7e4b1b 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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; } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index e03e8c55c9..9779aa64ae 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -923,7 +923,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { SmallVector 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 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 0000000000..1e820e411a --- /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 struct A { + template struct B; + template struct B; +}; +template template struct A::B {}; +template struct A; +A::B b; + + +template struct B { + template static const int var1; + template static const int var1; + + template static const int var2; +}; +template template const int B::var1 = 1; +template template const int B::var2 = 1; +template struct B; +int b_test1[B::var1]; +int b_test2[B::var2];