diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -165,14 +165,20 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ SpecializedTemplate, Args, PrevDecl), TemplateParams(Params), ArgsAsWritten(ArgInfos), InstantiatedFromMember(nullptr, false) { - AdoptTemplateParameterList(Params, this); + if (AdoptTemplateParameterList(Params, this)) + setInvalidDecl(); } ClassTemplatePartialSpecializationDecl * @@ -1097,14 +1109,15 @@ // 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 @@ 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 @@ 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 --- a/clang/test/SemaTemplate/deduction-crash.cpp +++ b/clang/test/SemaTemplate/deduction-crash.cpp @@ -161,3 +161,13 @@ } } + +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'}} +}