Skip to content

Commit 6dca319

Browse files
committed
zero sized arrays
1 parent 0400b9a commit 6dca319

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,8 +1039,15 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
10391039
if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))
10401040
return false;
10411041

1042+
QualType ElemType = LHS->getType()->getPointeeType();
1043+
CharUnits ElemTypeSize;
1044+
if (ElemType->isVoidType() || ElemType->isFunctionType())
1045+
ElemTypeSize = CharUnits::One();
1046+
else
1047+
ElemTypeSize = Ctx.getASTContext().getTypeSizeInChars(ElemType);
1048+
10421049
PrimType IntT = classifyPrim(E->getType());
1043-
if (!this->emitSubPtr(IntT, E))
1050+
if (!this->emitSubPtr(IntT, ElemTypeSize.isZero(), E))
10441051
return false;
10451052
return DiscardResult ? this->emitPop(IntT, E) : true;
10461053
}

clang/lib/AST/ByteCode/Interp.h

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2390,7 +2390,7 @@ static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
23902390
/// 2) Pops another Pointer from the stack.
23912391
/// 3) Pushes the difference of the indices of the two pointers on the stack.
23922392
template <PrimType Name, class T = typename PrimConv<Name>::T>
2393-
inline bool SubPtr(InterpState &S, CodePtr OpPC) {
2393+
inline bool SubPtr(InterpState &S, CodePtr OpPC, bool ElemSizeIsZero) {
23942394
const Pointer &LHS = S.Stk.pop<Pointer>();
23952395
const Pointer &RHS = S.Stk.pop<Pointer>();
23962396

@@ -2402,25 +2402,23 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
24022402
return false;
24032403
}
24042404

2405-
if (LHS == RHS) {
2406-
S.Stk.push<T>();
2407-
return true;
2408-
}
2405+
if (ElemSizeIsZero) {
2406+
QualType PtrT = LHS.getType();
2407+
while (auto *AT = dyn_cast<ArrayType>(PtrT))
2408+
PtrT = AT->getElementType();
24092409

2410-
for (const Pointer &P : {LHS, RHS}) {
2411-
if (P.isZeroSizeArray()) {
2412-
QualType PtrT = P.getType();
2413-
while (auto *AT = dyn_cast<ArrayType>(PtrT))
2414-
PtrT = AT->getElementType();
2410+
QualType ArrayTy = S.getASTContext().getConstantArrayType(
2411+
PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
2412+
S.FFDiag(S.Current->getSource(OpPC),
2413+
diag::note_constexpr_pointer_subtraction_zero_size)
2414+
<< ArrayTy;
24152415

2416-
QualType ArrayTy = S.getASTContext().getConstantArrayType(
2417-
PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
2418-
S.FFDiag(S.Current->getSource(OpPC),
2419-
diag::note_constexpr_pointer_subtraction_zero_size)
2420-
<< ArrayTy;
2416+
return false;
2417+
}
24212418

2422-
return false;
2423-
}
2419+
if (LHS == RHS) {
2420+
S.Stk.push<T>();
2421+
return true;
24242422
}
24252423

24262424
int64_t A64 =

clang/lib/AST/ByteCode/Opcodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ def SubOffset : AluOpcode;
543543
// [Pointer, Pointer] -> [Integral]
544544
def SubPtr : Opcode {
545545
let Types = [IntegerTypeClass];
546+
let Args = [ArgBool];
546547
let HasGroup = 1;
547548
}
548549

clang/test/AST/ByteCode/arrays.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,10 @@ namespace ZeroSizeTypes {
731731
// both-note {{subtraction of pointers to type 'int[0]' of zero size}} \
732732
// both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}
733733

734+
constexpr int k2 = p1 - p1; // both-error {{constexpr variable 'k2' must be initialized by a constant expression}} \
735+
// both-note {{subtraction of pointers to type 'int[0]' of zero size}} \
736+
// both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}}
737+
734738
int arr[5][0];
735739
constexpr int f() { // both-error {{never produces a constant expression}}
736740
return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,16 @@ namespace HugeAllocation {
11041104
}
11051105
#endif
11061106

1107+
namespace ZeroSizeArray {
1108+
constexpr int foo() {
1109+
int *A = new int[0];
1110+
int diff = A - (&A[0]);
1111+
delete[] A;
1112+
return diff;
1113+
}
1114+
static_assert(foo() == 0);
1115+
}
1116+
11071117
#else
11081118
/// Make sure we reject this prior to C++20
11091119
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)