https://github.com/ArtyomZabroda updated https://github.com/llvm/llvm-project/pull/142278
>From 6fc280bb5583ee4f1713cb1447b8b86993b7abb7 Mon Sep 17 00:00:00 2001 From: Artyom Zabroda <artyomzabr...@gmail.com> Date: Sat, 31 May 2025 18:44:21 +0300 Subject: [PATCH 1/2] [clang] Fix bad error recovery when classes are defined inside template aliases --- clang/lib/Sema/SemaConcept.cpp | 8 ++++++++ clang/lib/Sema/SemaDeclCXX.cpp | 9 ++++++++- clang/test/SemaCXX/concept-crash-on-diagnostic.cpp | 13 +++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index c6a54dc141ded..1c654f46e23b3 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -220,6 +220,14 @@ static ExprResult EvaluateAtomicConstraint( if (Inst.isInvalid()) return ExprError(); + if (const TemplateTypeParmType *TTPT = + dyn_cast<TemplateTypeParmType>(AtomicExpr->getType().getDesugaredType(S.Context))) { + TemplateTypeParmDecl *TTPD = TTPT->getDecl(); + if (TTPD->isInvalidDecl()) { + return ExprError(); + } + } + llvm::FoldingSetNodeID ID; if (Template && DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 55e078f3180a2..3efd18c0dcd96 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13717,8 +13717,15 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, const ParsedAttributesView &AttrList, TypeResult Type, Decl *DeclFromDeclSpec) { - if (Type.isInvalid()) + if (Type.isInvalid()) { + for (TemplateParameterList *TPL : TemplateParamLists) { + for (NamedDecl *D : *TPL) { + D->setInvalidDecl(true); + } + } return nullptr; + } + bool Invalid = false; DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp index 1efed72522fef..af254828b0fe7 100644 --- a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp +++ b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp @@ -60,3 +60,16 @@ concept atomicish = requires() { }; atomicish<int> f(); // expected-error {{expected 'auto' or 'decltype(auto)' after concept name}} } // namespace GH138820 + +namespace GH91564 { +template <class T> using A = struct B { // expected-error {{'GH91564::B' cannot be defined in a type alias template}} + template <class> void f() requires (T()); // expected-note {{candidate template ignored: failed template argument deduction}} +}; +template void B::f<void>(); // expected-error {{explicit instantiation of 'f' does not refer to a function template, variable template, member function, member class, or static data member}} + +template <class T> using C = struct D { // expected-error {{'GH91564::D' cannot be defined in a type alias template}} + using E = T; +}; +template <class> void g() requires (D::E()); // expected-note {{candidate template ignored: failed template argument deduction}} +template void g<void>(); // expected-error {{explicit instantiation of 'g' does not refer to a function template, variable template, member function, member class, or static data member}} +} \ No newline at end of file >From c52af95007c2efaac1d44f3ff36e6a8021d6b70f Mon Sep 17 00:00:00 2001 From: Artyom Zabroda <artyomzabr...@gmail.com> Date: Wed, 4 Jun 2025 14:16:26 +0300 Subject: [PATCH 2/2] very inaccurate fix --- clang/include/clang/Parse/Parser.h | 2 ++ clang/lib/Parse/ParseDeclCXX.cpp | 17 +++++++++++++++++ clang/lib/Sema/SemaConcept.cpp | 8 -------- clang/lib/Sema/SemaDecl.cpp | 4 ++-- clang/lib/Sema/SemaDeclCXX.cpp | 9 +-------- .../SemaCXX/concept-crash-on-diagnostic.cpp | 8 ++++---- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index c4bef4729fd36..90f17465bce7d 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -8909,6 +8909,8 @@ class Parser : public CodeCompletionHandler { bool OuterMightBeMessageSend = false); ///@} + + TemplateParameterLists *TemplateParamsFromAlias = nullptr; }; } // end namespace clang diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 2cf33a856c4f4..4069d257b0150 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -886,11 +886,17 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); Decl *DeclFromDeclSpec = nullptr; + + this->TemplateParamsFromAlias = TemplateInfo.TemplateParams; + TypeResult TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind != ParsedTemplateKind::NonTemplate ? DeclaratorContext::AliasTemplate : DeclaratorContext::AliasDecl, AS, &DeclFromDeclSpec, &Attrs); + + this->TemplateParamsFromAlias = nullptr; + if (OwnedType) *OwnedType = DeclFromDeclSpec; @@ -2173,6 +2179,17 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, assert(Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || isClassCompatibleKeyword()); + + if (TemplateParamsFromAlias) { + for (const TemplateParameterList *TPL : *TemplateParamsFromAlias) { + for (NamedDecl *D : *TPL) { + D->setInvalidDecl(true); + auto *TTPD = dyn_cast<TemplateTypeParmDecl>(D); + TTPD->setTypeForDecl(Actions.Context.IntTy.getTypePtr()); + } + } + } + if (SkipBody.ShouldSkip) SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType, TagOrTempResult.get()); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 1c654f46e23b3..c6a54dc141ded 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -220,14 +220,6 @@ static ExprResult EvaluateAtomicConstraint( if (Inst.isInvalid()) return ExprError(); - if (const TemplateTypeParmType *TTPT = - dyn_cast<TemplateTypeParmType>(AtomicExpr->getType().getDesugaredType(S.Context))) { - TemplateTypeParmDecl *TTPD = TTPT->getDecl(); - if (TTPD->isInvalidDecl()) { - return ExprError(); - } - } - llvm::FoldingSetNodeID ID; if (Template && DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 86b871396ec90..50c09bd3cdea7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -288,8 +288,8 @@ static ParsedType buildNamedType(Sema &S, const CXXScopeSpec *SS, QualType T, case Type::ObjCTypeParam: case Type::TemplateTypeParm: return ParsedType::make(T); - default: - llvm_unreachable("Unexpected Type Class"); + //default: + //llvm_unreachable("Unexpected Type Class"); } if (!SS || SS->isEmpty()) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3efd18c0dcd96..55e078f3180a2 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -13717,15 +13717,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, const ParsedAttributesView &AttrList, TypeResult Type, Decl *DeclFromDeclSpec) { - if (Type.isInvalid()) { - for (TemplateParameterList *TPL : TemplateParamLists) { - for (NamedDecl *D : *TPL) { - D->setInvalidDecl(true); - } - } + if (Type.isInvalid()) return nullptr; - } - bool Invalid = false; DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp index af254828b0fe7..fa3eb1372bd3f 100644 --- a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp +++ b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp @@ -63,13 +63,13 @@ atomicish<int> f(); // expected-error {{expected 'auto' or 'decltype(auto)' afte namespace GH91564 { template <class T> using A = struct B { // expected-error {{'GH91564::B' cannot be defined in a type alias template}} - template <class> void f() requires (T()); // expected-note {{candidate template ignored: failed template argument deduction}} + template <class> void f() requires (T()); // expected-error {{atomic constraint must be of type 'bool' (found 'int')}} expected-note {{explicit instantiation refers here}} }; -template void B::f<void>(); // expected-error {{explicit instantiation of 'f' does not refer to a function template, variable template, member function, member class, or static data member}} +template void B::f<void>(); // expected-error {{explicit instantiation of undefined function template 'f'}} template <class T> using C = struct D { // expected-error {{'GH91564::D' cannot be defined in a type alias template}} using E = T; }; -template <class> void g() requires (D::E()); // expected-note {{candidate template ignored: failed template argument deduction}} -template void g<void>(); // expected-error {{explicit instantiation of 'g' does not refer to a function template, variable template, member function, member class, or static data member}} +template <class> void g() requires (D::E()); // expected-error {{atomic constraint must be of type 'bool' (found 'D::E' (aka 'int'))}} expected-note {{explicit instantiation refers here}} +template void g<void>(); // expected-error {{explicit instantiation of undefined function template 'g'}} } \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits