https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/209496
None >From c5910f5935db8ac654ce28ff6722a62368b13477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Tue, 14 Jul 2026 13:11:20 +0200 Subject: [PATCH] asdf --- clang/lib/AST/ByteCode/Interp.h | 10 ++++++- clang/lib/AST/ByteCode/Pointer.cpp | 42 +++++++++++++++++++++++++++--- clang/lib/AST/ByteCode/Pointer.h | 2 +- clang/test/AST/ByteCode/cxx11.cpp | 18 +++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 201679017c98b..9893b57d92bac 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2738,7 +2738,7 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC, uint32_t ElemSize) { return false; } - if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) { + if (!Pointer::hasSameBase(LHS, RHS)) { S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_pointer_arith_unspecified) << LHS.toDiagnosticString(S.getASTContext()) @@ -2762,6 +2762,14 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC, uint32_t ElemSize) { return true; } + // C++11 [expr.add]p6: + // Unless both pointers point to elements of the same array object, or + // one past the last element of the array object, the behavior is + // undefined. + if (LHS.isBlockPointer() && !Pointer::elemsOfSameArray(LHS, RHS)) + S.CCEDiag(S.Current->getSource(OpPC), + diag::note_constexpr_pointer_subtraction_not_same_array); + std::optional<size_t> VL = LHS.computeLayoutOffset(S.getASTContext()); if (!VL) return false; diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 43af58d7bcb83..844483834b31a 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -815,9 +815,45 @@ bool Pointer::pointToSameBlock(const Pointer &A, const Pointer &B) { return A.block() == B.block(); } -bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) { - return hasSameBase(A, B) && A.BS.Base == B.BS.Base && - A.getFieldDesc()->IsArray; +bool Pointer::elemsOfSameArray(const Pointer &A, const Pointer &B) { + assert(hasSameBase(A, B)); + assert(A.isBlockPointer()); + assert(B.isBlockPointer()); + + if (A.BS.Base == B.BS.Base) + return true; + + if (A.isBaseClass() || B.isBaseClass()) + return false; + + if (A.getField() || B.getField()) + return false; + + auto closestArray = [](const Pointer &P) -> PtrView { + if (P.isArrayRoot()) + return P.view(); + + PtrView V = P.view(); + if (V.isArrayElement() || V.isOnePastEnd()) + V = V.expand().getArray(); + + if (P.isRoot()) + return P.view(); + + while (!V.isRoot() && !V.getFieldDesc()->IsArray) { + if (V.isArrayElement()) { + V = V.expand().getArray(); + break; + } + V = V.getBase(); + } + return V; + }; + + if (closestArray(A) != closestArray(B)) + return false; + + return true; } bool Pointer::pointsToLiteral() const { diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index dda5ac61ef126..75d3d8d51df6f 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -1015,7 +1015,7 @@ class Pointer { /// Checks if two pointers are comparable. static bool hasSameBase(const Pointer &A, const Pointer &B); /// Checks if two pointers can be subtracted. - static bool hasSameArray(const Pointer &A, const Pointer &B); + static bool elemsOfSameArray(const Pointer &A, const Pointer &B); /// Checks if both given pointers point to the same block. static bool pointToSameBlock(const Pointer &A, const Pointer &B); diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp index 3553ab3ba68ad..9a879e14912ba 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -475,3 +475,21 @@ namespace SubobjectCompare { // both-note {{comparison of addresses of subobjects of different base classes has unspecified value}} static_assert((void*)(X*)&z != (void*)(Y*)&z, ""); } + +namespace SubPtr { + struct A {}; + struct B : A { int n; int m; }; + B a[3][3]; + + constexpr int diff1 = &a[2] - &a[0]; + constexpr int diff2 = &a[1][3] - &a[1][0]; + constexpr int diff3 = &a[2][0] - &a[1][0]; // both-error {{constant expression}} \ + // both-note {{subtracted pointers are not elements of the same array}} + // static_assert(&a[2][0] == &a[1][3], ""); FIXME + constexpr int diff4 = (&b + 1) - &b; + constexpr int diff5 = &a[1][2].n - &a[1][0].n; // both-error {{constant expression}} \ + // both-note {{subtracted pointers are not elements of the same array}} + constexpr int diff6 = &a[1][2].n - &a[1][2].n; + constexpr int diff7 = (A*)&a[0][1] - (A*)&a[0][0]; // both-error {{constant expression}} \ + // both-note {{subtracted pointers are not elements of the same array}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
