From: Richard Smith Date: Wed, 25 Jan 2012 02:14:59 +0000 (+0000) Subject: Fix PR11848: decree that an alias template contains an unexpanded parameter pack X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c0536c8294fc4453f0f1d1cf24a62bfc725fd492;p=clang Fix PR11848: decree that an alias template contains an unexpanded parameter pack iff its substitution contains an unexpanded parameter pack. This has the effect that we now reject declarations such as this (which we used to crash when expanding): template using Int = int; template void f(Int ...ints); The standard is inconsistent on how this case should be treated. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148905 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7b30c500c6..b6ce59e977 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1889,7 +1889,9 @@ TemplateSpecializationType(TemplateName T, Canon.isNull()? T.isDependent() : Canon->isDependentType(), Canon.isNull()? T.isDependent() : Canon->isInstantiationDependentType(), - false, T.containsUnexpandedParameterPack()), + false, + Canon.isNull()? T.containsUnexpandedParameterPack() + : Canon->containsUnexpandedParameterPack()), Template(T), NumArgs(NumArgs) { assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); @@ -1922,7 +1924,7 @@ TemplateSpecializationType(TemplateName T, if (Args[Arg].getKind() == TemplateArgument::Type && Args[Arg].getAsType()->isVariablyModifiedType()) setVariablyModified(); - if (Args[Arg].containsUnexpandedParameterPack()) + if (Canon.isNull() && Args[Arg].containsUnexpandedParameterPack()) setContainsUnexpandedParameterPack(); new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2b96a1c744..e183f1f1c1 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1510,7 +1510,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // FIXME: When OldParm is a parameter pack and NewParm is not a parameter // pack, we actually have a set of instantiated locations. Maintain this set! if (OldParm->isParameterPack() && !NewParm->isParameterPack()) { - // Add the new parameter to + // Add the new parameter to the instantiated parameter pack. CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm); } else { // Introduce an Old -> New mapping diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp index 79d6849a6e..c0f9e21b35 100644 --- a/test/SemaTemplate/alias-templates.cpp +++ b/test/SemaTemplate/alias-templates.cpp @@ -68,3 +68,36 @@ itt::thing ith(itr); itt::rebind btr; itt::rebind_thing btt(btr); + +namespace PR11848 { + template using U = int; + + template + void f(U i, U ...is) { // expected-error {{type 'U' (aka 'int') of function parameter pack does not contain any unexpanded parameter packs}} + return i + f(is...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} + } + + template + struct S { + S(U...ts); // expected-error {{does not contain any unexpanded parameter packs}} + }; + + template + struct Hidden1 { + template + Hidden1(typename T::template U ...ts); + }; + + template + struct Hidden2 { + Hidden2(typename T::template U ...ts); + }; + + struct Hide { + template using U = int; + }; + + // FIXME: This case crashes clang at the moment. + //Hidden1 h1; + Hidden2 h2(1, 2); +}