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 <[email protected]> Date: Fri, 9 Oct 2026 22:17:40 +0530 Subject: [PATCH 1/2] 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 <[email protected]> Date: Sun, 25 Oct 2026 09:56:53 +0530 Subject: [PATCH 2/2] [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])'}} } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
