[clang] [Clang]Preserve array information when reconstructing LValues (#223064) (PR #230599)
Aditya Roy Chowdhury via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 05:36:33 PDT 2026
https://github.com/adiroy28852 updated https://github.com/llvm/llvm-project/pull/230599
>From 46ddf7e600e677652bed7de2b1404ef1c754ef0b Mon Sep 17 00:00:00 2001
From: Aditya Roy Chowdhury <adityaroy2.ar.ar at gmail.com>
Date: Fri, 9 Oct 2026 22:17:40 +0530
Subject: [PATCH 1/3] updated condition for reconstructed LValue information
(#223064)
---
clang/lib/AST/ExprConstant.cpp | 4 ---
.../SemaCXX/constant-expression-cxx2a.cpp | 29 +++++++++++++++++++
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34c3e39807c7f1..63fdb508a24675 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -208,10 +208,6 @@ namespace {
ArraySize = 0;
MostDerivedLength = I + 1;
IsArray = false;
- } else {
- // Path[I] describes a base class.
- ArraySize = 0;
- IsArray = false;
}
}
return MostDerivedLength;
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 870865646a61e2..b9816f074c3cc6 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1544,3 +1544,32 @@ namespace GH197403 {
}
static_assert(test() == 0);
}
+
+namespace GH223064 {
+ struct A {
+ int n;
+ };
+ struct B : A {} b[2];
+
+ constexpr int *base_array_element() {
+ A *p = b;
+ return &static_cast<B *>(p)[1].n;
+ }
+ static_assert(base_array_element() == &b[1].n);
+
+ struct Padding {
+ int pad;
+ };
+ struct C : Padding, B {} c[2];
+
+ constexpr int *indirect_nonfirst_base_array_element() {
+ A *p = c;
+ return &static_cast<C *>(p)[1].n;
+ }
+ static_assert(indirect_nonfirst_base_array_element() == &c[1].n);
+
+ constexpr int *out_of_bounds(A *p) {
+ return &static_cast<B *>(p)[2].n; // expected-note {{cannot access base class of pointer past the end of object}}
+ }
+ static_assert(out_of_bounds(b) == nullptr); // expected-error {{static assertion is not an integral constant expression}} \ expected-note {{in call to 'out_of_bounds(&b[0])'}}
+}
>From 51ab7945fb8df9b50fe1fc6d3a0e222277affec1 Mon Sep 17 00:00:00 2001
From: Aditya Roy Chowdhury <adityaroy2.ar.ar at gmail.com>
Date: Sun, 25 Oct 2026 09:56:53 +0530
Subject: [PATCH 2/3] [Clang][ConstantExpr] Preserve array metadata for base
subobjects
---
clang/lib/AST/ExprConstant.cpp | 12 ++++++---
.../SemaCXX/constant-expression-cxx2a.cpp | 25 ++++++++++++++++++-
2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 63fdb508a24675..d2428777713593 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -208,6 +208,9 @@ namespace {
ArraySize = 0;
MostDerivedLength = I + 1;
IsArray = false;
+ } else {
+ // Path[I] describes a base class. The base is part of the current
+ // most-derived object, so preserve its array information.
}
}
return MostDerivedLength;
@@ -4596,10 +4599,11 @@ static bool AreElementsOfSameArray(QualType ObjType,
if (A.Entries.size() != B.Entries.size())
return false;
- bool IsArray = A.MostDerivedIsArrayElement;
- if (IsArray && A.MostDerivedPathLength != A.Entries.size())
- // A is a subobject of the array element.
- return false;
+ // A base-class subobject of an array element is not itself an element of
+ // that array. Treat it as a non-array object, while retaining the array
+ // information for casts back to the most-derived type.
+ bool IsArray = A.MostDerivedIsArrayElement &&
+ A.MostDerivedPathLength == A.Entries.size();
// If A (and B) designates an array element, the last entry will be the array
// index. That doesn't have to match. Otherwise, we're in the 'implicit array
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index b9816f074c3cc6..dcfd7d5c5ed131 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1557,6 +1557,12 @@ namespace GH223064 {
}
static_assert(base_array_element() == &b[1].n);
+ constexpr int pointer_difference() {
+ A *p = b;
+ return p - p;
+ }
+ static_assert(pointer_difference() == 0);
+
struct Padding {
int pad;
};
@@ -1568,8 +1574,25 @@ namespace GH223064 {
}
static_assert(indirect_nonfirst_base_array_element() == &c[1].n);
+ struct MemberArray {
+ B item[2];
+ } member[2];
+ constexpr int *member_array_element() {
+ A *p = member[0].item;
+ return &static_cast<B *>(p)[1].n;
+ }
+ static_assert(member_array_element() == &member[0].item[1].n);
+
+ B nested[2][2];
+ constexpr int *nested_array_element() {
+ A *p = nested[0];
+ return &static_cast<B *>(p)[1].n;
+ }
+ static_assert(nested_array_element() == &nested[0][1].n);
+
constexpr int *out_of_bounds(A *p) {
return &static_cast<B *>(p)[2].n; // expected-note {{cannot access base class of pointer past the end of object}}
}
- static_assert(out_of_bounds(b) == nullptr); // expected-error {{static assertion is not an integral constant expression}} \ expected-note {{in call to 'out_of_bounds(&b[0])'}}
+ static_assert(out_of_bounds(b) == nullptr); // expected-error {{static assertion expression is not an integral constant expression}} \
+ // expected-note {{in call to 'out_of_bounds(&b[0])'}}
}
>From fc63e45059a1b1afe013ce993ba7b20a7bec9eaa Mon Sep 17 00:00:00 2001
From: Aditya Roy Chowdhury <adityaroy2.ar.ar at gmail.com>
Date: Sun, 25 Oct 2026 18:00:07 +0530
Subject: [PATCH 3/3] [Clang][ConstantExpr] Test base-object pointer
subtraction
---
clang/test/SemaCXX/constant-expression-cxx2a.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index dcfd7d5c5ed131..2cf030be614129 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1563,6 +1563,9 @@ namespace GH223064 {
}
static_assert(pointer_difference() == 0);
+ constexpr auto difference(A *p, A *q) { return p - q; }
+ static_assert(difference(&b[1], &b[0]) == 1);
+
struct Padding {
int pad;
};
More information about the cfe-commits
mailing list