[clang] [clang][AST] Preserve most-derived array info for base subobjects in constant evaluator. (PR #223663)
Akshay Kumar Dubey via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 05:05:38 PDT 2026
https://github.com/akshaydubey05 updated https://github.com/llvm/llvm-project/pull/223663
>From 237f236a27fb86e1749c8101457f39eb61e62ab5 Mon Sep 17 00:00:00 2001
From: Akshay Dubey <akshaymani513 at gmail.com>
Date: Tue, 15 Sep 2026 17:17:15 +0530
Subject: [PATCH 1/2] [clang][AST] Preserve most-derived array info for base
subobjects in constant evaluator
When reconstructing an LValue from an APValue, findMostDerivedSubobject was resetting ArraySize = 0 and IsArray = false when encountering a base class path entry.
A base class subobject is not a most-derived object and should inherit the most-derived object's properties (IsArray, ArraySize, MostDerivedType, and MostDerivedPathLength) from the containing most-derived object, matching SubobjectDesignator::addDeclUnchecked.
Fixes #223064
---
clang/docs/ReleaseNotes.md | 2 ++
clang/lib/AST/ExprConstant.cpp | 7 +++---
.../SemaCXX/constant-expression-cxx11.cpp | 22 +++++++++++++++++++
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 043a0ddae2a6c..875f59ff9853a 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -554,6 +554,8 @@ features cannot lower the translation-unit ABI level;
#### Bug Fixes to C++ Support
+- Fixed a bug where constant evaluation lost track of most-derived array information
+ when reconstructing an lvalue referring to a base subobject of an array element. (#GH223064)
- Fixed false-positive module ODR diagnostics when a type is found through a
using-declaration in one definition and directly in another. ODR hashing also
now distinguishes differently qualified uses of types found through
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 1286c77ad1c69..014d1a6b1b0e6 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -235,11 +235,10 @@ namespace {
ArraySize = 0;
MostDerivedLength = I + 1;
IsArray = false;
- } else {
- // Path[I] describes a base class.
- ArraySize = 0;
- IsArray = false;
}
+ // Otherwise, Path[I] describes a base class. It inherits the most-derived
+ // properties (IsArray, ArraySize, Type, MostDerivedLength) from the
+ // containing most-derived object.
}
return MostDerivedLength;
}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 7b483a4238652..dc5d2def4aebd 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2747,3 +2747,25 @@ namespace GH154567 {
constexpr S s{};
static_assert(s.val.i == 0, "");
}
+
+namespace GH223064 {
+ struct A { int n; };
+ struct B : A {} b[2];
+
+ constexpr int *f() {
+ A *p = b;
+ return &static_cast<B*>(p)[1].n;
+ }
+ static_assert(f() == &b[1].n, "");
+
+ struct Base1 { int x; };
+ struct Base2 : Base1 { int y; };
+ struct Derived : Base2 { int z; } arr[3];
+
+ constexpr int *g() {
+ Base1 *p = arr;
+ return &static_cast<Derived*>(p)[2].z;
+ }
+ static_assert(g() == &arr[2].z, "");
+}
+
>From 3bfa3c4f8f44c8e9205e906b6707b300b0f36638 Mon Sep 17 00:00:00 2001
From: Akshay Dubey <akshaymani513 at gmail.com>
Date: Tue, 15 Sep 2026 17:35:26 +0530
Subject: [PATCH 2/2] [clang][test] Fix C++11 compatibility in GH223064 test
case
---
clang/test/SemaCXX/constant-expression-cxx11.cpp | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index dc5d2def4aebd..30b8af5f0bf3d 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2752,20 +2752,19 @@ namespace GH223064 {
struct A { int n; };
struct B : A {} b[2];
- constexpr int *f() {
- A *p = b;
+ constexpr int *f(A *p) {
return &static_cast<B*>(p)[1].n;
}
- static_assert(f() == &b[1].n, "");
+ static_assert(f(b) == &b[1].n, "");
struct Base1 { int x; };
struct Base2 : Base1 { int y; };
struct Derived : Base2 { int z; } arr[3];
- constexpr int *g() {
- Base1 *p = arr;
+ constexpr int *g(Base1 *p) {
return &static_cast<Derived*>(p)[2].z;
}
- static_assert(g() == &arr[2].z, "");
+ static_assert(g(arr) == &arr[2].z, "");
}
+
More information about the cfe-commits
mailing list