Skip to content

Commit

Permalink
[clang][Interp] Diagnose pointer subtraction on zero-size arrays (llv…
Browse files Browse the repository at this point in the history
  • Loading branch information
tbaederr authored Aug 14, 2024
1 parent 3cab7c5 commit 13008aa
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
16 changes: 16 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1987,6 +1987,22 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
const Pointer &LHS = S.Stk.pop<Pointer>();
const Pointer &RHS = S.Stk.pop<Pointer>();

for (const Pointer &P : {LHS, RHS}) {
if (P.isZeroSizeArray()) {
QualType PtrT = P.getType();
while (auto *AT = dyn_cast<ArrayType>(PtrT))
PtrT = AT->getElementType();

QualType ArrayTy = S.getCtx().getConstantArrayType(
PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_pointer_subtraction_zero_size)
<< ArrayTy;

return false;
}
}

if (RHS.isZero()) {
S.Stk.push<T>(T::from(LHS.getIndex()));
return true;
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,11 @@ class Pointer {
bool isElementPastEnd() const { return Offset == PastEndMark; }

/// Checks if the pointer is pointing to a zero-size array.
bool isZeroSizeArray() const { return getFieldDesc()->isZeroSizeArray(); }
bool isZeroSizeArray() const {
if (const auto *Desc = getFieldDesc())
return Desc->isZeroSizeArray();
return false;
}

/// Dereferences the pointer, if it's live.
template <typename T> T &deref() const {
Expand Down
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,3 +632,16 @@ constexpr int fail(const int &p) {
}
static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}

namespace ZeroSizeTypes {
constexpr int (*p1)[0] = 0, (*p2)[0] = 0;
constexpr int k = p2 - p1; // both-error {{constexpr variable 'k' must be initialized by a constant expression}} \
// 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}}

int arr[5][0];
constexpr int f() { // both-error {{never produces a constant expression}}
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}}
}
}

0 comments on commit 13008aa

Please sign in to comment.