https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/135929
Add the appropriate diagnostic and fix the d-d case. >From 685749dcf6fbbb4905922ce002180217947ca8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Wed, 16 Apr 2025 08:37:23 +0200 Subject: [PATCH] [clang][bytecode] Fix comparing zero-sized pointers Add the appropriate diagnostic and fix the d-d case. --- clang/lib/AST/ByteCode/Interp.h | 30 ++++++++++++-------------- clang/lib/AST/ByteCode/Pointer.h | 9 ++++++-- clang/test/AST/ByteCode/arrays.cpp | 6 +++++- clang/test/AST/ByteCode/new-delete.cpp | 25 +++++++++++++++++++++ 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index b4e15b3ffbe68..88a011efe708e 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2141,12 +2141,25 @@ static inline bool DecPtr(InterpState &S, CodePtr OpPC) { /// 1) Pops a Pointer from the stack. /// 2) Pops another Pointer from the stack. -/// 3) Pushes the different of the indices of the two pointers on the stack. +/// 3) Pushes the difference of the indices of the two pointers on the stack. template <PrimType Name, class T = typename PrimConv<Name>::T> inline bool SubPtr(InterpState &S, CodePtr OpPC) { const Pointer &LHS = S.Stk.pop<Pointer>(); const Pointer &RHS = S.Stk.pop<Pointer>(); + if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) { + S.FFDiag(S.Current->getSource(OpPC), + diag::note_constexpr_pointer_arith_unspecified) + << LHS.toDiagnosticString(S.getASTContext()) + << RHS.toDiagnosticString(S.getASTContext()); + return false; + } + + if (LHS == RHS) { + S.Stk.push<T>(); + return true; + } + for (const Pointer &P : {LHS, RHS}) { if (P.isZeroSizeArray()) { QualType PtrT = P.getType(); @@ -2163,21 +2176,6 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) { } } - if (RHS.isZero()) { - S.Stk.push<T>(T::from(LHS.getIndex())); - return true; - } - - if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) { - // TODO: Diagnose. - return false; - } - - if (LHS.isZero() && RHS.isZero()) { - S.Stk.push<T>(); - return true; - } - T A = LHS.isBlockPointer() ? (LHS.isElementPastEnd() ? T::from(LHS.getNumElems()) : T::from(LHS.getIndex())) diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index 5eef9d2e1885e..8ede706f2736f 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -129,12 +129,17 @@ class Pointer { return false; if (isIntegralPointer()) return P.asIntPointer().Value == asIntPointer().Value && - Offset == P.Offset; + P.asIntPointer().Desc == asIntPointer().Desc && P.Offset == Offset; + + if (isFunctionPointer()) + return P.asFunctionPointer().getFunction() == + asFunctionPointer().getFunction() && + P.Offset == Offset; assert(isBlockPointer()); return P.asBlockPointer().Pointee == asBlockPointer().Pointee && P.asBlockPointer().Base == asBlockPointer().Base && - Offset == P.Offset; + P.Offset == Offset; } bool operator!=(const Pointer &P) const { return !(P == *this); } diff --git a/clang/test/AST/ByteCode/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp index 8af82163fd815..f60cc19b09bd2 100644 --- a/clang/test/AST/ByteCode/arrays.cpp +++ b/clang/test/AST/ByteCode/arrays.cpp @@ -106,7 +106,8 @@ constexpr int k1 = &arr[1] - &arr[0]; static_assert(k1 == 1, ""); static_assert((&arr[0] - &arr[1]) == -1, ""); -constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}} +constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}} \ + // expected-note {{arithmetic involving unrelated objects}} static_assert((arr + 0) == arr, ""); static_assert(&arr[0] == arr, ""); @@ -735,6 +736,9 @@ namespace ZeroSizeTypes { return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \ // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}} } + + constexpr int z[0]{}; + static_assert((z - z) == 0); } namespace InvalidIndex { diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index bd7351cbc3d4c..5ddd7070f6710 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -967,6 +967,31 @@ namespace PR45350 { static_assert(f(6) == 543210); } +namespace ZeroSizeSub { + consteval unsigned ptr_diff1() { + int *b = new int[0]; + unsigned d = 0; + d = b - b; + delete[] b; + + return d; + } + static_assert(ptr_diff1() == 0); + + + consteval unsigned ptr_diff2() { // both-error {{never produces a constant expression}} + int *a = new int[0]; + int *b = new int[0]; + + unsigned d = a - b; // both-note 2{{arithmetic involving unrelated objects}} + delete[] b; + delete[] a; + return d; + } + static_assert(ptr_diff2() == 0); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} +} + #else /// Make sure we reject this prior to C++20 constexpr int a() { // both-error {{never produces a constant expression}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits