https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/150407

... if the elements are in different arrays.

>From 5b97525a1317f88a409cd0ab2b8b64cc3885edc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Thu, 24 Jul 2025 13:38:10 +0200
Subject: [PATCH] [clang][bytecode] Diagnose subtracting pointers to array
 elements...

... if the elements are in different arrays.
---
 clang/lib/AST/ByteCode/Interp.h    | 19 +++++++++++++++++++
 clang/test/AST/ByteCode/arrays.cpp | 21 +++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index b42c7665c3a35..a37cacedb627b 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2383,6 +2383,25 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
     return false;
   }
 
+  // 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.isRoot() && !RHS.isRoot() && LHS.isBlockPointer() &&
+      RHS.isBlockPointer()) {
+    Pointer A = LHS;
+    if (LHS.isArrayElement())
+      A = LHS.expand().getArray();
+
+    Pointer B = RHS;
+    if (RHS.isArrayElement())
+      B = RHS.expand().getArray();
+
+    if (A != B)
+      S.CCEDiag(S.Current->getSource(OpPC),
+                diag::note_constexpr_pointer_subtraction_not_same_array);
+  }
+
   if (LHS == RHS) {
     S.Stk.push<T>();
     return true;
diff --git a/clang/test/AST/ByteCode/arrays.cpp 
b/clang/test/AST/ByteCode/arrays.cpp
index 2dd51c2fa6711..1329071c7188d 100644
--- a/clang/test/AST/ByteCode/arrays.cpp
+++ b/clang/test/AST/ByteCode/arrays.cpp
@@ -779,3 +779,24 @@ namespace DiscardedSubScriptExpr {
     return true;
   }
 }
+
+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 {{must be 
initialized by a constant expression}} \
+                                             // both-note {{subtracted 
pointers are not elements of the same array}}
+  struct S {
+    int a;
+    int b;
+    constexpr S() : a(1), b(2) {}
+  };
+
+  constexpr int  f5() { // both-error {{never produces a constant expression}}
+    struct S s;
+    int d = &s.b - &s.a; // both-note {{subtracted pointers are not elements 
of the same array}}
+    return d;
+  }
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to