forked from OSchip/llvm-project
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:
parent
dab63c1434
commit
651c73ce78
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue