From 37adc4f957c2383a625e2e593ba1d18a25d92b91 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Fri, 24 Sep 2021 22:18:54 +0200 Subject: [PATCH] [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 Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D110460 --- clang/lib/AST/DeclTemplate.cpp | 76 +++++++++++++-------- clang/test/SemaTemplate/deduction-crash.cpp | 10 +++ 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index a25185067b9c..fa73c5386649 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -165,14 +165,20 @@ unsigned TemplateParameterList::getDepth() const { return cast(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(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(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(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(Decl)); - - return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); + bool Invalid = AdoptTemplateParameterList(Params, cast(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 * diff --git a/clang/test/SemaTemplate/deduction-crash.cpp b/clang/test/SemaTemplate/deduction-crash.cpp index 2c58fefa065f..86ec9f7980a7 100644 --- a/clang/test/SemaTemplate/deduction-crash.cpp +++ b/clang/test/SemaTemplate/deduction-crash.cpp @@ -161,3 +161,13 @@ evaluateSelectionRequirement(InputT &&Value) { // expected-error {{cannot } } + +namespace PR51872_part1 { + template class T1 { template 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'}} +}