Skip to content

Commit 559df83

Browse files
authored
[clang][bytecode] Fix subtracting zero-sized pointers (#135929)
Add the appropriate diagnostic and fix the d-d case.
1 parent 11857be commit 559df83

File tree

4 files changed

+51
-19
lines changed

4 files changed

+51
-19
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,12 +2141,25 @@ static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
21412141

21422142
/// 1) Pops a Pointer from the stack.
21432143
/// 2) Pops another Pointer from the stack.
2144-
/// 3) Pushes the different of the indices of the two pointers on the stack.
2144+
/// 3) Pushes the difference of the indices of the two pointers on the stack.
21452145
template <PrimType Name, class T = typename PrimConv<Name>::T>
21462146
inline bool SubPtr(InterpState &S, CodePtr OpPC) {
21472147
const Pointer &LHS = S.Stk.pop<Pointer>();
21482148
const Pointer &RHS = S.Stk.pop<Pointer>();
21492149

2150+
if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
2151+
S.FFDiag(S.Current->getSource(OpPC),
2152+
diag::note_constexpr_pointer_arith_unspecified)
2153+
<< LHS.toDiagnosticString(S.getASTContext())
2154+
<< RHS.toDiagnosticString(S.getASTContext());
2155+
return false;
2156+
}
2157+
2158+
if (LHS == RHS) {
2159+
S.Stk.push<T>();
2160+
return true;
2161+
}
2162+
21502163
for (const Pointer &P : {LHS, RHS}) {
21512164
if (P.isZeroSizeArray()) {
21522165
QualType PtrT = P.getType();
@@ -2163,21 +2176,6 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
21632176
}
21642177
}
21652178

2166-
if (RHS.isZero()) {
2167-
S.Stk.push<T>(T::from(LHS.getIndex()));
2168-
return true;
2169-
}
2170-
2171-
if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
2172-
// TODO: Diagnose.
2173-
return false;
2174-
}
2175-
2176-
if (LHS.isZero() && RHS.isZero()) {
2177-
S.Stk.push<T>();
2178-
return true;
2179-
}
2180-
21812179
T A = LHS.isBlockPointer()
21822180
? (LHS.isElementPastEnd() ? T::from(LHS.getNumElems())
21832181
: T::from(LHS.getIndex()))

clang/lib/AST/ByteCode/Pointer.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,17 @@ class Pointer {
129129
return false;
130130
if (isIntegralPointer())
131131
return P.asIntPointer().Value == asIntPointer().Value &&
132-
Offset == P.Offset;
132+
P.asIntPointer().Desc == asIntPointer().Desc && P.Offset == Offset;
133+
134+
if (isFunctionPointer())
135+
return P.asFunctionPointer().getFunction() ==
136+
asFunctionPointer().getFunction() &&
137+
P.Offset == Offset;
133138

134139
assert(isBlockPointer());
135140
return P.asBlockPointer().Pointee == asBlockPointer().Pointee &&
136141
P.asBlockPointer().Base == asBlockPointer().Base &&
137-
Offset == P.Offset;
142+
P.Offset == Offset;
138143
}
139144

140145
bool operator!=(const Pointer &P) const { return !(P == *this); }

clang/test/AST/ByteCode/arrays.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ constexpr int k1 = &arr[1] - &arr[0];
106106
static_assert(k1 == 1, "");
107107
static_assert((&arr[0] - &arr[1]) == -1, "");
108108

109-
constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}}
109+
constexpr int k2 = &arr2[1] - &arr[0]; // both-error {{must be initialized by a constant expression}} \
110+
// expected-note {{arithmetic involving unrelated objects}}
110111

111112
static_assert((arr + 0) == arr, "");
112113
static_assert(&arr[0] == arr, "");
@@ -735,6 +736,9 @@ namespace ZeroSizeTypes {
735736
return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \
736737
// both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}
737738
}
739+
740+
constexpr int z[0]{};
741+
static_assert((z - z) == 0);
738742
}
739743

740744
namespace InvalidIndex {

clang/test/AST/ByteCode/new-delete.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,31 @@ namespace PR45350 {
967967
static_assert(f(6) == 543210);
968968
}
969969

970+
namespace ZeroSizeSub {
971+
consteval unsigned ptr_diff1() {
972+
int *b = new int[0];
973+
unsigned d = 0;
974+
d = b - b;
975+
delete[] b;
976+
977+
return d;
978+
}
979+
static_assert(ptr_diff1() == 0);
980+
981+
982+
consteval unsigned ptr_diff2() { // both-error {{never produces a constant expression}}
983+
int *a = new int[0];
984+
int *b = new int[0];
985+
986+
unsigned d = a - b; // both-note 2{{arithmetic involving unrelated objects}}
987+
delete[] b;
988+
delete[] a;
989+
return d;
990+
}
991+
static_assert(ptr_diff2() == 0); // both-error {{not an integral constant expression}} \
992+
// both-note {{in call to}}
993+
}
994+
970995
#else
971996
/// Make sure we reject this prior to C++20
972997
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)