PR19372: Keep checking template arguments after we see an argument pack

expansion into a parameter pack; we know that we're still filling in that
parameter's arguments. Previously, if we hit this case for an alias template,
we'd try to substitute using non-canonical template arguments.

llvm-svn: 221832
This commit is contained in:
Richard Smith 2014-11-12 23:38:38 +00:00
parent 8870ad2439
commit 96d71c3936
2 changed files with 25 additions and 28 deletions

View File

@ -3695,12 +3695,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
ArgumentPack.size(), Converted))
return true;
if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
isa<TypeAliasTemplateDecl>(Template) &&
!(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() &&
!getExpandedPackSize(*Param))) {
bool PackExpansionIntoNonPack =
TemplateArgs[ArgIdx].getArgument().isPackExpansion() &&
(!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param));
if (PackExpansionIntoNonPack && isa<TypeAliasTemplateDecl>(Template)) {
// Core issue 1430: we have a pack expansion as an argument to an
// alias template, and it's not part of a final parameter pack. This
// alias template, and it's not part of a parameter pack. This
// can't be canonicalized, so reject it now.
Diag(TemplateArgs[ArgIdx].getLocation(),
diag::err_alias_template_expansion_into_fixed_list)
@ -3723,16 +3723,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
++Param;
}
// If we just saw a pack expansion, then directly convert the remaining
// arguments, because we don't know what parameters they'll match up
// with.
if (TemplateArgs[ArgIdx-1].getArgument().isPackExpansion()) {
bool InFinalParameterPack = Param != ParamEnd &&
Param + 1 == ParamEnd &&
(*Param)->isTemplateParameterPack() &&
!getExpandedPackSize(*Param);
if (!InFinalParameterPack && !ArgumentPack.empty()) {
// If we just saw a pack expansion into a non-pack, then directly convert
// the remaining arguments, because we don't know what parameters they'll
// match up with.
if (PackExpansionIntoNonPack) {
if (!ArgumentPack.empty()) {
// If we were part way through filling in an expanded parameter pack,
// fall back to just producing individual arguments.
Converted.insert(Converted.end(),
@ -3741,22 +3736,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
}
while (ArgIdx < NumArgs) {
if (InFinalParameterPack)
ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument());
else
Converted.push_back(TemplateArgs[ArgIdx].getArgument());
Converted.push_back(TemplateArgs[ArgIdx].getArgument());
++ArgIdx;
}
// Push the argument pack onto the list of converted arguments.
if (InFinalParameterPack && !ArgumentPack.empty()) {
Converted.push_back(
TemplateArgument::CreatePackCopy(Context,
ArgumentPack.data(),
ArgumentPack.size()));
ArgumentPack.clear();
}
return false;
}

View File

@ -178,3 +178,17 @@ namespace PR21536 {
template<typename ...T> void f(S<T...>);
void g() { f(S<int, int>()); }
}
namespace PR19372 {
template <template<typename...> class C, typename ...Us> struct BindBack {
template <typename ...Ts> using apply = C<Ts..., Us...>;
};
template <typename, typename...> struct Y;
template <typename ...Ts> using Z = Y<Ts...>;
using T = BindBack<Z, int>::apply<>;
using T = Z<int>;
using U = BindBack<Z, int, int>::apply<char>;
using U = Z<char, int, int>;
}