[clang] [clang][Sema] fix crash on invalid expression with trailing return type and template keyword (PR #191972)

via cfe-commits cfe-commits at lists.llvm.org
Sun Apr 19 19:47:19 PDT 2026


https://github.com/firstmoonlight updated https://github.com/llvm/llvm-project/pull/191972

>From cfd43c4cc781cec16c7b25a1e67665959302a331 Mon Sep 17 00:00:00 2001
From: victorl <liuvicsen at gmail.com>
Date: Tue, 14 Apr 2026 14:31:01 +0800
Subject: [PATCH 1/3] [clang][Sema] fix crash on invalid expression with
 trailing return type and template keyword

---
 clang/lib/Sema/SemaExprCXX.cpp            |  3 ++-
 clang/test/Modules/cxx20-10-2-ex5.cpp     |  3 +--
 clang/test/SemaCXX/recovery-expr-type.cpp | 17 ++++++++++++-----
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f7e005a40363c..8de0d6c026ef4 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1514,7 +1514,8 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
                                           RParenOrBraceLoc, ListInitialization);
   if (Result.isInvalid())
     Result = CreateRecoveryExpr(TInfo->getTypeLoc().getBeginLoc(),
-                                RParenOrBraceLoc, exprs, Ty);
+                                RParenOrBraceLoc, exprs, Ty->isIncompleteType() ? QualType() : Ty);
+
   return Result;
 }
 
diff --git a/clang/test/Modules/cxx20-10-2-ex5.cpp b/clang/test/Modules/cxx20-10-2-ex5.cpp
index f222568072393..b14234d44e3be 100644
--- a/clang/test/Modules/cxx20-10-2-ex5.cpp
+++ b/clang/test/Modules/cxx20-10-2-ex5.cpp
@@ -61,6 +61,5 @@ int main() {
   auto f = rootFinder(2); // OK
                           // error: A is incomplete
   return A{45}.value;     // expected-error {{invalid use of incomplete type 'A'}}
-                          // expected-error at -1 {{member access into incomplete type 'A'}}
-                          // expected-note at std-10-2-ex5-tu1.cpp:12 2{{forward declaration of 'A'}}
+                          // expected-note at std-10-2-ex5-tu1.cpp:12 {{forward declaration of 'A'}}
 }
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index 5a42a11b82da5..fd38f453afc27 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -104,8 +104,7 @@ void test() {
 // verify the secondary diagnostic "cannot initialize" is emitted.
 namespace test8 {
 typedef int arr[];
-int v = arr(); // expected-error {{array types cannot be value-initialized}} \
-                  expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'arr'}}
+int v = arr(); // expected-error {{array types cannot be value-initialized}}
 }
 
 namespace test9 {
@@ -178,10 +177,18 @@ void f() {
 
 namespace test16 {
 // verify we do not crash on incomplete class type.
-template<typename T, typename U> struct A; // expected-note 5{{template is declared here}}
+template<typename T, typename U> struct A; // expected-note 3{{template is declared here}}
 A<int, int> foo() { // expected-error {{implicit instantiation of undefined template}}
   if (1 == 1)
-    return A<int, int>{1}; // expected-error 2{{implicit instantiation of undefined template}}
-  return A<int, int>(1); // expected-error 2{{implicit instantiation of undefined template}}
+    return A<int, int>{1}; // expected-error {{implicit instantiation of undefined template}}
+  return A<int, int>(1); // expected-error {{implicit instantiation of undefined template}}
 }
 }
+
+namespace test17 {
+// Verify we do not crash on trailing expression with template keyword.
+int a((enum b )b {       } // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
+                          // expected-error {{invalid use of incomplete type}} \
+                          // expected-note {{forward declaration of}}
+         -> template c);  // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
+}

>From 2020a1f40f6da33329e4052f9596289ff69b1a2b Mon Sep 17 00:00:00 2001
From: victorl <liuvicsen at gmail.com>
Date: Mon, 20 Apr 2026 10:01:55 +0800
Subject: [PATCH 2/3] Revert "[clang][Sema] fix crash on invalid expression
 with trailing return type and template keyword"

This reverts commit cfd43c4cc781cec16c7b25a1e67665959302a331.
---
 clang/lib/Sema/SemaExprCXX.cpp            |  3 +--
 clang/test/Modules/cxx20-10-2-ex5.cpp     |  3 ++-
 clang/test/SemaCXX/recovery-expr-type.cpp | 17 +++++------------
 3 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 8de0d6c026ef4..f7e005a40363c 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1514,8 +1514,7 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
                                           RParenOrBraceLoc, ListInitialization);
   if (Result.isInvalid())
     Result = CreateRecoveryExpr(TInfo->getTypeLoc().getBeginLoc(),
-                                RParenOrBraceLoc, exprs, Ty->isIncompleteType() ? QualType() : Ty);
-
+                                RParenOrBraceLoc, exprs, Ty);
   return Result;
 }
 
diff --git a/clang/test/Modules/cxx20-10-2-ex5.cpp b/clang/test/Modules/cxx20-10-2-ex5.cpp
index b14234d44e3be..f222568072393 100644
--- a/clang/test/Modules/cxx20-10-2-ex5.cpp
+++ b/clang/test/Modules/cxx20-10-2-ex5.cpp
@@ -61,5 +61,6 @@ int main() {
   auto f = rootFinder(2); // OK
                           // error: A is incomplete
   return A{45}.value;     // expected-error {{invalid use of incomplete type 'A'}}
-                          // expected-note at std-10-2-ex5-tu1.cpp:12 {{forward declaration of 'A'}}
+                          // expected-error at -1 {{member access into incomplete type 'A'}}
+                          // expected-note at std-10-2-ex5-tu1.cpp:12 2{{forward declaration of 'A'}}
 }
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index fd38f453afc27..5a42a11b82da5 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -104,7 +104,8 @@ void test() {
 // verify the secondary diagnostic "cannot initialize" is emitted.
 namespace test8 {
 typedef int arr[];
-int v = arr(); // expected-error {{array types cannot be value-initialized}}
+int v = arr(); // expected-error {{array types cannot be value-initialized}} \
+                  expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'arr'}}
 }
 
 namespace test9 {
@@ -177,18 +178,10 @@ void f() {
 
 namespace test16 {
 // verify we do not crash on incomplete class type.
-template<typename T, typename U> struct A; // expected-note 3{{template is declared here}}
+template<typename T, typename U> struct A; // expected-note 5{{template is declared here}}
 A<int, int> foo() { // expected-error {{implicit instantiation of undefined template}}
   if (1 == 1)
-    return A<int, int>{1}; // expected-error {{implicit instantiation of undefined template}}
-  return A<int, int>(1); // expected-error {{implicit instantiation of undefined template}}
+    return A<int, int>{1}; // expected-error 2{{implicit instantiation of undefined template}}
+  return A<int, int>(1); // expected-error 2{{implicit instantiation of undefined template}}
 }
 }
-
-namespace test17 {
-// Verify we do not crash on trailing expression with template keyword.
-int a((enum b )b {       } // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
-                          // expected-error {{invalid use of incomplete type}} \
-                          // expected-note {{forward declaration of}}
-         -> template c);  // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
-}

>From 3fb7d74cc09505c202b8abb64da4d1f97082a909 Mon Sep 17 00:00:00 2001
From: victorl <liuvicsen at gmail.com>
Date: Mon, 20 Apr 2026 10:44:23 +0800
Subject: [PATCH 3/3] [clang][Sema] fix crash on invalid expression with
 trailing return type and template keyword

---
 clang/lib/Sema/SemaExprCXX.cpp            | 2 ++
 clang/test/SemaCXX/recovery-expr-type.cpp | 8 ++++++++
 2 files changed, 10 insertions(+)

diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index f7e005a40363c..4343f6da406b0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -7047,6 +7047,8 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
   // call.  We'll do more incomplete-type checks later in the lookup process,
   // so just skip this check for ObjC types.
   if (!BaseType->isRecordType()) {
+    if (Base->containsErrors() && BaseType->isIncompleteType())
+      return ExprError();
     ObjectType = ParsedType::make(BaseType);
     MayBePseudoDestructor = true;
     return Base;
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index 5a42a11b82da5..b93dd6b2fbe79 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -185,3 +185,11 @@ A<int, int> foo() { // expected-error {{implicit instantiation of undefined temp
   return A<int, int>(1); // expected-error 2{{implicit instantiation of undefined template}}
 }
 }
+
+namespace test17 {
+// Verify we do not crash on trailing expression with template keyword.
+int a((enum b )b {       } // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
+                          // expected-error {{invalid use of incomplete type}} \
+                          // expected-note {{forward declaration of}}
+         -> template c);
+}



More information about the cfe-commits mailing list