Author: Timm Baeder Date: 2026-07-16T11:11:48+02:00 New Revision: c1ba7d0aaad6baa898c6735f71a99791839a1847
URL: https://github.com/llvm/llvm-project/commit/c1ba7d0aaad6baa898c6735f71a99791839a1847 DIFF: https://github.com/llvm/llvm-project/commit/c1ba7d0aaad6baa898c6735f71a99791839a1847.diff LOG: Reapply "[clang][bytecode] Diagnose pointer subtractions of elements … (#209998) …of different arrays" (#209969) This reverts commit 745b946cbbf30708044b4a2c4a7726d0c02ca0de. Use only one `fold()` for the virtual base offset assertions. The pointer subtraction _is_ invalid, but the current interpreter doesn't diagnose it since the `LValueDesignator`s are invalid. Added: Modified: clang/lib/AST/ByteCode/Interp.h clang/lib/AST/ByteCode/Pointer.cpp clang/lib/AST/ByteCode/Pointer.h clang/test/AST/ByteCode/cxx11.cpp clang/test/AST/ByteCode/virtual-bases.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 2df52bbf460c7..405f4a29ec982 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2747,7 +2747,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()) @@ -2771,6 +2771,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 1cd4370185209..243a2c9ea4b8f 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 417c28b46875a..c06347318dafa 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -999,7 +999,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 1e3668f8f2e99..d920f0d4eb7f9 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -482,3 +482,22 @@ namespace SubobjectCompare { // both-note {{comparison of addresses of subobjects of diff erent 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 diff 1 = &a[2] - &a[0]; + constexpr int diff 2 = &a[1][3] - &a[1][0]; + constexpr int diff 3 = &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 diff 4 = (&b + 1) - &b; + constexpr int diff 5 = &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 diff 6 = &a[1][2].n - &a[1][2].n; + constexpr int diff 7 = (A*)&a[0][1] - (A*)&a[0][0]; // both-error {{constant expression}} \ + // both-note {{subtracted pointers are not elements of the same array}} + constexpr auto diff 8 = &a[1][2].n - (&a[1][2].n + 1); +} diff --git a/clang/test/AST/ByteCode/virtual-bases.cpp b/clang/test/AST/ByteCode/virtual-bases.cpp index 38614cf9990c4..1543249ec69fe 100644 --- a/clang/test/AST/ByteCode/virtual-bases.cpp +++ b/clang/test/AST/ByteCode/virtual-bases.cpp @@ -439,21 +439,21 @@ namespace Offsets { constexpr C c{12}; #if !defined(_WIN32) #if __SIZEOF_SIZE_T__ == 8 - static_assert( (fold((char*)&c.c) - fold((char*)&c)) == 12); - static_assert( (fold((char*)&c.b) - fold((char*)&c)) == 8); - static_assert( (fold((char*)&c.a) - fold((char*)&c)) == 20); - static_assert( (fold((char*)&c.x) - fold((char*)&c)) == 16); + static_assert( (fold((char*)&c.c - (char*)&c)) == 12); + static_assert( (fold((char*)&c.b - (char*)&c)) == 8); + static_assert( (fold((char*)&c.a - (char*)&c)) == 20); + static_assert( (fold((char*)&c.x - (char*)&c)) == 16); #else - static_assert( (fold((char*)&c.c) - fold((char*)&c)) == 8); - static_assert( (fold((char*)&c.b) - fold((char*)&c)) == 4); - static_assert( (fold((char*)&c.a) - fold((char*)&c)) == 16); - static_assert( (fold((char*)&c.x) - fold((char*)&c)) == 12); + static_assert( (fold((char*)&c.c - (char*)&c)) == 8); + static_assert( (fold((char*)&c.b - (char*)&c)) == 4); + static_assert( (fold((char*)&c.a - (char*)&c)) == 16); + static_assert( (fold((char*)&c.x - (char*)&c)) == 12); #endif # else - static_assert( (fold((char*)&c.c) - fold((char*)&c)) == 16); - static_assert( (fold((char*)&c.b) - fold((char*)&c)) == 8); - static_assert( (fold((char*)&c.a) - fold((char*)&c)) == 28); - static_assert( (fold((char*)&c.x) - fold((char*)&c)) == 24); + static_assert( (fold((char*)&c.c - (char*)&c)) == 16); + static_assert( (fold((char*)&c.b - (char*)&c)) == 8); + static_assert( (fold((char*)&c.a - (char*)&c)) == 28); + static_assert( (fold((char*)&c.x - (char*)&c)) == 24); #endif static_assert( (fold((char*)&c.c) != fold((char*)&c))); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
