diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index b8ec59ee1d6931a8d76365b8869c3ff21bd820f0..60f5bc196e0a3e1152cbe721fdc7781255699d9e 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -4166,9 +4166,17 @@ MarkUsedTemplateParameters(ASTContext &Ctx, if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E)) E = Expansion->getPattern(); - // Skip through any implicit casts we added while type-checking. - while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) - E = ICE->getSubExpr(); + // Skip through any implicit casts we added while type-checking, and any + // substitutions performed by template alias expansion. + while (1) { + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + E = ICE->getSubExpr(); + else if (const SubstNonTypeTemplateParmExpr *Subst = + dyn_cast<SubstNonTypeTemplateParmExpr>(E)) + E = Subst->getReplacement(); + else + break; + } // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to // find other occurrences of template parameters. diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 7416d1230178e0387e01bd857193a43aa00b1305..239a0d73ebc3cdccded2ad7e2b82eb1b85bcf29e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -851,7 +851,7 @@ namespace { private: ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, SourceLocation loc, - const TemplateArgument &arg); + TemplateArgument arg); }; } @@ -1140,10 +1140,18 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( NonTypeTemplateParmDecl *parm, SourceLocation loc, - const TemplateArgument &arg) { + TemplateArgument arg) { 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) { diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp index a074bc4e1e6b90cc968f2a44e0b6e5c16081ef51..cd796b8603d23df9d440fba671ebacc09d1c87a3 100644 --- a/test/SemaTemplate/alias-templates.cpp +++ b/test/SemaTemplate/alias-templates.cpp @@ -109,3 +109,22 @@ namespace PR13243 { template<typename A, int I> void f(X<A>, Ci<I>) {} template void f(X<int>, C<0>); } + +namespace PR13136 { + template <typename T, T... Numbers> + struct NumberTuple { }; + + template <unsigned int... Numbers> + using MyNumberTuple = NumberTuple<unsigned int, Numbers...>; + + template <typename U, unsigned int... Numbers> + void foo(U&&, MyNumberTuple<Numbers...>); + + template <typename U, unsigned int... Numbers> + void bar(U&&, NumberTuple<unsigned int, Numbers...>); + + int main() { + foo(1, NumberTuple<unsigned int, 0, 1>()); + bar(1, NumberTuple<unsigned int, 0, 1>()); + } +}