[clang] [clang][bytecode] Diagnose subtracting pointers to array elements... (PR #150407)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 24 04:39:24 PDT 2025
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?= <tbaeder at 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;
+ }
+}
More information about the cfe-commits
mailing list