Skip to content

Commit 1c11e60

Browse files
committed
handle zero-length array pattern
1 parent 0ed60c2 commit 1c11e60

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4624,13 +4624,13 @@ void CodeGenFunction::EmitArrayBoundsConstraints(const ArraySubscriptExpr *E,
46244624
return;
46254625

46264626
llvm::APInt ArraySize = CAT->getSize();
4627-
if (ArraySize == 0)
4628-
return;
46294627

46304628
// Don't generate assumes for flexible array member pattern.
4631-
// Arrays of size 1 in structs are often used as placeholders for
4632-
// variable-length data (pre-C99 flexible array member idiom.)
4633-
if (ArraySize == 1) {
4629+
// Size-1 arrays: "struct { int len; char data[1]; }" (pre-C99 idiom.)
4630+
// Zero-length arrays: "struct { int len; char data[0]; }" (GCC extension
4631+
// https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html)
4632+
// Both patterns use arrays as placeholders for variable-length data.
4633+
if (ArraySize == 0 || ArraySize == 1) {
46344634
if (const auto *ME = dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) {
46354635
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
46364636
const RecordDecl *RD = FD->getParent();
@@ -4640,7 +4640,7 @@ void CodeGenFunction::EmitArrayBoundsConstraints(const ArraySubscriptExpr *E,
46404640
for (const auto *Field : RD->fields())
46414641
LastField = Field;
46424642
if (LastField == FD)
4643-
// This is a size-1 array as the last field in a struct.
4643+
// This is a zero-length or size-1 array as the last field.
46444644
// Likely a flexible array member pattern - skip assumes.
46454645
return;
46464646
}

clang/test/CodeGen/array-bounds-constraints-safety.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@
66
// intentionally accesses out-of-bounds for performance or compatibility.
77
// This test verifies that bounds constraints are only applied to safe cases.
88

9+
// CHECK-LABEL: define {{.*}} @test_zero_length_array
10+
struct ZeroLengthData {
11+
int count;
12+
int items[0]; // GNU C extension: zero-length array
13+
};
14+
15+
int test_zero_length_array(struct ZeroLengthData *d, int i) {
16+
// CHECK-NOT: call void @llvm.assume
17+
// Zero-length array as last field should not generate bounds constraints.
18+
// See https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
19+
return d->items[i];
20+
}
21+
922
// CHECK-LABEL: define {{.*}} @test_flexible_array_member
1023
struct Data {
1124
int count;

0 commit comments

Comments
 (0)