From 10ec0e4935e5d2efab4ee2731ccb350330dc5b34 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 19 Jul 2013 19:40:38 +0000 Subject: [PATCH] Fix for template substitution with packs. When we see a pack, and replace it with a template argument which is also a pack, we want to use the pack pattern, not the expanded pack. The caller should take care of expanding the pack afterwards. Fixes PR16646. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186713 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiate.cpp | 65 +++++++++++---------------- test/SemaTemplate/alias-templates.cpp | 23 ++++++++++ 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index e86c742679..3904daa47f 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -883,6 +883,16 @@ bool TemplateInstantiator::AlreadyTransformed(QualType T) { return true; } +static TemplateArgument +getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) { + assert(S.ArgumentPackSubstitutionIndex >= 0); + assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex]; + if (Arg.isPackExpansion()) + Arg = Arg.getPackExpansionPattern(); + return Arg; +} + Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { if (!D) return 0; @@ -902,10 +912,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { if (TTP->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); - - assert(getSema().ArgumentPackSubstitutionIndex >= 0); - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } TemplateName Template = Arg.getAsTemplate(); @@ -950,8 +957,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, if (getSema().ArgumentPackSubstitutionIndex == -1) return 0; - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } QualType T = Arg.getAsType(); @@ -1053,9 +1059,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, // keep the entire argument pack. return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg); } - - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } TemplateName Template = Arg.getAsTemplate(); @@ -1077,11 +1082,9 @@ TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, if (getSema().ArgumentPackSubstitutionIndex == -1) return Name; - const TemplateArgument &ArgPack = SubstPack->getArgumentPack(); - assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() && - "Pack substitution index out-of-range"); - return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex] - .getAsTemplate(); + TemplateArgument Arg = SubstPack->getArgumentPack(); + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); + return Arg.getAsTemplate(); } return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, @@ -1146,8 +1149,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, Arg); } - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg); @@ -1160,14 +1162,6 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( ExprResult result; QualType type; - // If the argument is a pack expansion, the parameter must actually be a - // parameter pack, and we should substitute the pattern itself, producing - // an expression which contains an unexpanded parameter pack. - if (arg.isPackExpansion()) { - assert(parm->isParameterPack() && "pack expansion for non-pack"); - arg = arg.getPackExpansionPattern(); - } - // The template argument itself might be an expression, in which // case we just return that expression. if (arg.getKind() == TemplateArgument::Expression) { @@ -1233,12 +1227,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( // We aren't expanding the parameter pack, so just return ourselves. return getSema().Owned(E); } - - const TemplateArgument &ArgPack = E->getArgumentPack(); - unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; - assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); - - const TemplateArgument &Arg = ArgPack.pack_begin()[Index]; + + TemplateArgument Arg = E->getArgumentPack(); + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); return transformNonTypeTemplateParmRef(E->getParameterPack(), E->getParameterPackLocation(), Arg); @@ -1409,8 +1400,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, return Result; } - assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); - Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } assert(Arg.getKind() == TemplateArgument::Type && @@ -1458,12 +1448,11 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType( NewTL.setNameLoc(TL.getNameLoc()); return TL.getType(); } - - const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack(); - unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; - assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); - - QualType Result = ArgPack.pack_begin()[Index].getAsType(); + + TemplateArgument Arg = TL.getTypePtr()->getArgumentPack(); + Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); + QualType Result = Arg.getAsType(); + Result = getSema().Context.getSubstTemplateTypeParmType( TL.getTypePtr()->getReplacedParameter(), Result); diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp index 20ba6e0cb7..eeb6b95189 100644 --- a/test/SemaTemplate/alias-templates.cpp +++ b/test/SemaTemplate/alias-templates.cpp @@ -166,3 +166,26 @@ namespace PR13136 { return 0; } } + +namespace PR16646 { + namespace test1 { + template struct DefaultValue { const T value=0;}; + template struct tuple {}; + template using Zero = tuple ...>; + template void f(const Zero &t); + void f() { + f(Zero()); + } + } + + namespace test2 { + template struct X {}; + template class temp> struct DefaultValue { const temp<0> value; }; + template struct tuple {}; + template class... Args> using Zero = tuple ...>; + template class... Args> void f(const Zero &t); + void f() { + f(Zero()); + } + } +} -- 2.40.0