[clang] [clang] Fix bad error recovery when classes are defined inside template (PR #142278)

Artyom Zabroda via cfe-commits cfe-commits at lists.llvm.org
Sat May 31 09:06:42 PDT 2025


https://github.com/ArtyomZabroda created https://github.com/llvm/llvm-project/pull/142278

Fixes #91564

This is my first pull request to the LLVM and I would appreciate any feedback.

>From 6fc280bb5583ee4f1713cb1447b8b86993b7abb7 Mon Sep 17 00:00:00 2001
From: Artyom Zabroda <artyomzabroda at gmail.com>
Date: Sat, 31 May 2025 18:44:21 +0300
Subject: [PATCH] [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



More information about the cfe-commits mailing list