[clang] [clang] Return early if a value dependent recovery init appeared in constant evaluation context in legacy constant evaluator (PR #225027)
Yihan Wang via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 21 01:36:47 PDT 2026
https://github.com/yronglin created https://github.com/llvm/llvm-project/pull/225027
A recovery default member initializer can be value-dependent even when the expression referring to the variable is not. Clang should return early to avoid crash.
This fix the issue found in https://github.com/llvm/llvm-project/issues/185874#issuecomment-4058045596.
>From 3edc1351d0c6044693461d29171497543d759fd2 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 21 Sep 2026 01:22:22 -0700
Subject: [PATCH] [clang] Return early if a value dependent recovery init
appeared in constant evaluation context in legacy constant evaluator
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
clang/docs/ReleaseNotes.md | 3 +++
clang/lib/AST/ExprConstant.cpp | 5 +++++
clang/test/SemaCXX/recovery-expr-type.cpp | 10 ++++++++++
3 files changed, 18 insertions(+)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7e3e8468914c7f..025c332ceb831f 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -673,6 +673,9 @@ features cannot lower the translation-unit ABI level;
using ``__is_constructible`` on a nested class template inside the definition
of the containing class. (#GH215166)
+- Fixed a crash issue when a value dependent recovery init appeared in constant
+ evaluation context in legacy constant evaluator.
+
- Fixed a bug where Clang incorrectly required `promise.return_value()` for a
dependent `co_return` operand that inits to `void`, instead of using
`promise.return_void()`. (#GH218368)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 92424918328419..2f75e69e55aafb 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3520,6 +3520,11 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// Used to be C++20 [expr.const]p5.12:
// ... reference has a preceding initialization and either ...
if (Init && Init->isValueDependent()) {
+ // A recovery initializer can be value-dependent even when the expression
+ // referring to the variable is not.
+ if (Init->containsErrors())
+ return false;
+
// The DeclRefExpr is not value-dependent, but the variable it refers to
// has a value-dependent initializer. This should only happen in
// constant-folding cases, where the variable is not actually of a suitable
diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index bdab2940d6597c..542a2fae5d8490 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -199,3 +199,13 @@ template<int*> struct P;
S<P> s;
} // namespace GH202117
+namespace test17 {
+struct A { int arr[1]; };
+struct B {
+ static constexpr A &a = A{{0}}; // expected-error {{non-const lvalue reference to type 'A' cannot bind to a temporary of type 'A'}}
+};
+
+B x;
+
+int v = x.a.arr[0]; // Do not crash when evaluating a static reference with an invalid initializer.
+} // namespace test17
More information about the cfe-commits
mailing list