[clang] [clang] Prevent nested RecoveryExpr in BuildConvertedConstantExpression (PR #207072)
Hrólf Kraki via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 13 23:33:00 PDT 2026
https://github.com/Serosh-commits updated https://github.com/llvm/llvm-project/pull/207072
>From 1e46141a50fac27787966018522f09f32d22a082 Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Wed, 1 Jul 2026 22:51:09 +0530
Subject: [PATCH 1/5] [clang] Prevent nested RecoveryExpr in
BuildConvertedConstantExpression
---
clang/lib/Sema/SemaOverload.cpp | 2 ++
clang/test/SemaCXX/gh186656.cpp | 7 +++++++
clang/test/SemaCXX/gh202117.cpp | 6 ++++++
3 files changed, 15 insertions(+)
create mode 100644 clang/test/SemaCXX/gh186656.cpp
create mode 100644 clang/test/SemaCXX/gh202117.cpp
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 11e771bc240f1..f088425e139cf 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6469,6 +6469,8 @@ static ExprResult BuildConvertedConstantExpression(Sema &S, Expr *From,
return ExprError();
if (From->containsErrors()) {
+ if (isa<RecoveryExpr>(From))
+ return From;
// The expression already has errors, so the correct cast kind can't be
// determined. Use RecoveryExpr to keep the expected type T and mark the
// result as invalid, preventing further cascading errors.
diff --git a/clang/test/SemaCXX/gh186656.cpp b/clang/test/SemaCXX/gh186656.cpp
new file mode 100644
index 0000000000000..227489833da1b
--- /dev/null
+++ b/clang/test/SemaCXX/gh186656.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+template <template <int> typename> struct S;
+template <int, int = (foo<void, void>())> struct T; // expected-error {{use of undeclared identifier 'foo'}}
+template <typename...> struct U;
+
+using V = U<S<T>>;
diff --git a/clang/test/SemaCXX/gh202117.cpp b/clang/test/SemaCXX/gh202117.cpp
new file mode 100644
index 0000000000000..7fd0fddf598a7
--- /dev/null
+++ b/clang/test/SemaCXX/gh202117.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+template<template<decltype(foo())> typename T> struct S {}; // expected-error {{use of undeclared identifier 'foo'}}
+template<int*> struct P;
+
+S<P> s;
>From e1f9d89f7455568a248d33454f41ec11a2d03418 Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Fri, 10 Jul 2026 19:29:41 +0530
Subject: [PATCH 2/5] [clang] Avoid redundant RecoveryExpr for typed invalid
CCE
---
clang/lib/Sema/SemaOverload.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6fc5428b48769..eafda32198f11 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6499,8 +6499,9 @@ static ExprResult BuildConvertedConstantExpression(Sema &S, Expr *From,
return ExprError();
if (From->containsErrors()) {
- if (isa<RecoveryExpr>(From))
+ if (S.Context.hasSameType(From->getType(), T))
return From;
+
// The expression already has errors, so the correct cast kind can't be
// determined. Use RecoveryExpr to keep the expected type T and mark the
// result as invalid, preventing further cascading errors.
>From 8640837b32884821be35563b2f381fa4562c8c3c Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Tue, 14 Jul 2026 00:07:36 +0530
Subject: [PATCH 3/5] move tests
---
clang/test/SemaCXX/gh186656.cpp | 7 -------
clang/test/SemaCXX/gh202117.cpp | 6 ------
2 files changed, 13 deletions(-)
delete mode 100644 clang/test/SemaCXX/gh186656.cpp
delete mode 100644 clang/test/SemaCXX/gh202117.cpp
diff --git a/clang/test/SemaCXX/gh186656.cpp b/clang/test/SemaCXX/gh186656.cpp
deleted file mode 100644
index 227489833da1b..0000000000000
--- a/clang/test/SemaCXX/gh186656.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
-
-template <template <int> typename> struct S;
-template <int, int = (foo<void, void>())> struct T; // expected-error {{use of undeclared identifier 'foo'}}
-template <typename...> struct U;
-
-using V = U<S<T>>;
diff --git a/clang/test/SemaCXX/gh202117.cpp b/clang/test/SemaCXX/gh202117.cpp
deleted file mode 100644
index 7fd0fddf598a7..0000000000000
--- a/clang/test/SemaCXX/gh202117.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
-
-template<template<decltype(foo())> typename T> struct S {}; // expected-error {{use of undeclared identifier 'foo'}}
-template<int*> struct P;
-
-S<P> s;
>From 123bc2915f07d33de4aa80d4984130315f63e727 Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Tue, 14 Jul 2026 00:09:06 +0530
Subject: [PATCH 4/5] move tests
---
clang/test/SemaCXX/recovery-expr-type.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index 5a42a11b82da5..aebdfeef45b8f 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -185,3 +185,15 @@ 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 {
+template <template <int> typename> struct S;
+template <int, int = (foo<void, void>())> struct T; // expected-error {{use of undeclared identifier 'foo'}}
+template <typename...> struct U;
+using V = U<S<T>>;
+
+template<template<decltype(foo())> typename T> struct S2 {}; // expected-error {{use of undeclared identifier 'foo'}}
+template<int*> struct P;
+S2<P> s;
+} // namespace test17
+
>From 331e7ba1c02320b2aeffd735197948c857561bd0 Mon Sep 17 00:00:00 2001
From: Serosh-commits <janmejayapanda400 at gmail.com>
Date: Tue, 14 Jul 2026 12:02:34 +0530
Subject: [PATCH 5/5] feedback
---
clang/test/SemaCXX/recovery-expr-type.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index aebdfeef45b8f..bdab2940d6597 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -186,14 +186,16 @@ A<int, int> foo() { // expected-error {{implicit instantiation of undefined temp
}
}
-namespace test17 {
+namespace GH186656 {
template <template <int> typename> struct S;
template <int, int = (foo<void, void>())> struct T; // expected-error {{use of undeclared identifier 'foo'}}
template <typename...> struct U;
using V = U<S<T>>;
+} // namespace GH186656
-template<template<decltype(foo())> typename T> struct S2 {}; // expected-error {{use of undeclared identifier 'foo'}}
+namespace GH202117 {
+template<template<decltype(foo())> typename T> struct S {}; // expected-error {{use of undeclared identifier 'foo'}}
template<int*> struct P;
-S2<P> s;
-} // namespace test17
+S<P> s;
+} // namespace GH202117
More information about the cfe-commits
mailing list