[clang] set templates as invalid when any of the parameters are invalid

See PR51872 for the original repro.

This fixes a crash when converting a templated constructor into a deduction
guide, in case any of the template parameters were invalid.

Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D110460
This commit is contained in:
Matheus Izvekov 2021-09-24 22:18:54 +02:00
parent f4cfda03d6
commit 37adc4f957
2 changed files with 56 additions and 30 deletions

View File

@ -165,14 +165,20 @@ unsigned TemplateParameterList::getDepth() const {
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
}
static void AdoptTemplateParameterList(TemplateParameterList *Params,
static bool AdoptTemplateParameterList(TemplateParameterList *Params,
DeclContext *Owner) {
bool Invalid = false;
for (NamedDecl *P : *Params) {
P->setDeclContext(Owner);
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
if (AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner))
Invalid = true;
if (P->isInvalidDecl())
Invalid = true;
}
return Invalid;
}
void TemplateParameterList::
@ -339,14 +345,15 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
// FunctionTemplateDecl Implementation
//===----------------------------------------------------------------------===//
FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl) {
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
return new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
FunctionTemplateDecl *
FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl) {
bool Invalid = AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
auto *TD = new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
if (Invalid)
TD->setInvalidDecl();
return TD;
}
FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
@ -438,15 +445,16 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
// ClassTemplateDecl Implementation
//===----------------------------------------------------------------------===//
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
DeclContext *DC,
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl) {
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
bool Invalid = AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
auto *TD = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
if (Invalid)
TD->setInvalidDecl();
return TD;
}
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
@ -1005,8 +1013,11 @@ ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params,
Expr *ConstraintExpr) {
AdoptTemplateParameterList(Params, DC);
return new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
bool Invalid = AdoptTemplateParameterList(Params, DC);
auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
if (Invalid)
TD->setInvalidDecl();
return TD;
}
ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,
@ -1039,7 +1050,8 @@ ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
SpecializedTemplate, Args, PrevDecl),
TemplateParams(Params), ArgsAsWritten(ArgInfos),
InstantiatedFromMember(nullptr, false) {
AdoptTemplateParameterList(Params, this);
if (AdoptTemplateParameterList(Params, this))
setInvalidDecl();
}
ClassTemplatePartialSpecializationDecl *
@ -1097,14 +1109,15 @@ FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
// TypeAliasTemplateDecl Implementation
//===----------------------------------------------------------------------===//
TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl) {
AdoptTemplateParameterList(Params, DC);
return new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
TypeAliasTemplateDecl *
TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl) {
bool Invalid = AdoptTemplateParameterList(Params, DC);
auto *TD = new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
if (Invalid)
TD->setInvalidDecl();
return TD;
}
TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
@ -1151,8 +1164,11 @@ VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params,
VarDecl *Decl) {
AdoptTemplateParameterList(Params, DC);
return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
bool Invalid = AdoptTemplateParameterList(Params, DC);
auto *TD = new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
if (Invalid)
TD->setInvalidDecl();
return TD;
}
VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
@ -1334,8 +1350,8 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
TInfo, S, Args),
TemplateParams(Params), ArgsAsWritten(ArgInfos),
InstantiatedFromMember(nullptr, false) {
// TODO: The template parameters should be in DC by now. Verify.
// AdoptTemplateParameterList(Params, DC);
if (AdoptTemplateParameterList(Params, DC))
setInvalidDecl();
}
VarTemplatePartialSpecializationDecl *

View File

@ -161,3 +161,13 @@ evaluateSelectionRequirement<void>(InputT &&Value) { // expected-error {{cannot
}
}
namespace PR51872_part1 {
template<int> class T1 { template <struct U1> T1(); };
// expected-error@-1 {{non-type template parameter has incomplete type 'struct U1'}}
// expected-note@-2 {{forward declaration of 'PR51872_part1::U1'}}
T1 t1 = 0;
// expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'T1'}}
// expected-note@-6 {{candidate template ignored: could not match 'T1<>' against 'int'}}
}