Fix pr9789, assert-on-invalid while instantiating an (invalid) class template with a non-final parameter pack. Also improve the warning for non-final parameter packs in this scenario so it only fires once, rather than once for every template parameter after the non-final parameter pack.

llvm-svn: 142473
This commit is contained in:
David Blaikie 2011-10-19 05:19:50 +00:00
parent dab63c1434
commit 651c73ce78
2 changed files with 18 additions and 18 deletions

View File

@ -1195,9 +1195,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
bool SawDefaultArgument = false; bool SawDefaultArgument = false;
SourceLocation PreviousDefaultArgLoc; SourceLocation PreviousDefaultArgLoc;
bool SawParameterPack = false;
SourceLocation ParameterPackLoc;
// Dummy initialization to avoid warnings. // Dummy initialization to avoid warnings.
TemplateParameterList::iterator OldParam = NewParams->end(); TemplateParameterList::iterator OldParam = NewParams->end();
if (OldParams) if (OldParams)
@ -1212,18 +1209,11 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
SourceLocation OldDefaultLoc; SourceLocation OldDefaultLoc;
SourceLocation NewDefaultLoc; SourceLocation NewDefaultLoc;
// Variables used to diagnose missing default arguments // Variable used to diagnose missing default arguments
bool MissingDefaultArg = false; bool MissingDefaultArg = false;
// C++0x [temp.param]p11: // Variable used to diagnose non-final parameter packs
// If a template parameter of a primary class template or alias template bool SawParameterPack = false;
// is a template parameter pack, it shall be the last template parameter.
if (SawParameterPack &&
(TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
Diag(ParameterPackLoc,
diag::err_template_param_pack_must_be_last_template_parameter);
Invalid = true;
}
if (TemplateTypeParmDecl *NewTypeParm if (TemplateTypeParmDecl *NewTypeParm
= dyn_cast<TemplateTypeParmDecl>(*NewParam)) { = dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
@ -1243,7 +1233,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
assert(!NewTypeParm->hasDefaultArgument() && assert(!NewTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!"); "Parameter packs can't have a default argument!");
SawParameterPack = true; SawParameterPack = true;
ParameterPackLoc = NewTypeParm->getLocation();
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
NewTypeParm->hasDefaultArgument()) { NewTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
@ -1288,7 +1277,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
assert(!NewNonTypeParm->hasDefaultArgument() && assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!"); "Parameter packs can't have a default argument!");
SawParameterPack = true; SawParameterPack = true;
ParameterPackLoc = NewNonTypeParm->getLocation();
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
NewNonTypeParm->hasDefaultArgument()) { NewNonTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
@ -1313,7 +1301,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
} else if (SawDefaultArgument) } else if (SawDefaultArgument)
MissingDefaultArg = true; MissingDefaultArg = true;
} else { } else {
// Check the presence of a default argument here.
TemplateTemplateParmDecl *NewTemplateParm TemplateTemplateParmDecl *NewTemplateParm
= cast<TemplateTemplateParmDecl>(*NewParam); = cast<TemplateTemplateParmDecl>(*NewParam);
@ -1323,6 +1310,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
continue; continue;
} }
// Check the presence of a default argument here.
if (NewTemplateParm->hasDefaultArgument() && if (NewTemplateParm->hasDefaultArgument() &&
DiagnoseDefaultTemplateArgument(*this, TPC, DiagnoseDefaultTemplateArgument(*this, TPC,
NewTemplateParm->getLocation(), NewTemplateParm->getLocation(),
@ -1336,7 +1324,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
assert(!NewTemplateParm->hasDefaultArgument() && assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!"); "Parameter packs can't have a default argument!");
SawParameterPack = true; SawParameterPack = true;
ParameterPackLoc = NewTemplateParm->getLocation();
} else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
NewTemplateParm->hasDefaultArgument()) { NewTemplateParm->hasDefaultArgument()) {
OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
@ -1363,6 +1350,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
MissingDefaultArg = true; MissingDefaultArg = true;
} }
// C++0x [temp.param]p11:
// If a template parameter of a primary class template or alias template
// is a template parameter pack, it shall be the last template parameter.
if (SawParameterPack && (NewParam + 1) != NewParamEnd &&
(TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) {
Diag((*NewParam)->getLocation(),
diag::err_template_param_pack_must_be_last_template_parameter);
Invalid = true;
}
if (RedundantDefaultArg) { if (RedundantDefaultArg) {
// C++ [temp.param]p12: // C++ [temp.param]p12:
// A template-parameter shall not be given default arguments // A template-parameter shall not be given default arguments
@ -3047,6 +3044,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// in arguments for non-template parameter packs. // in arguments for non-template parameter packs.
if ((*Param)->isTemplateParameterPack()) { if ((*Param)->isTemplateParameterPack()) {
if (!HasParameterPack)
return true;
if (ArgumentPack.empty()) if (ArgumentPack.empty())
Converted.push_back(TemplateArgument(0, 0)); Converted.push_back(TemplateArgument(0, 0));
else { else {

View File

@ -24,8 +24,9 @@ template<template<class> class M = vector, template<class> class... Metas>
// If a template-parameter of a primary class template or alias template is a // If a template-parameter of a primary class template or alias template is a
// template parameter pack, it shall be the last template-parameter. // template parameter pack, it shall be the last template-parameter.
template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}}
int After> int After, int After2>
struct X0t; struct X0t;
X0t<int> pr9789();
template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}}
int After> int After>
using A0t = int; using A0t = int;