Skip to content

Commit d1a6327

Browse files
authored
[C2y] Fix _Countof handling of VLAs (#141621)
It turns out that getVLASize() does not get you the size of a single dimension of the VLA, it gets you the full count of all elements. This caused _Countof to return invalid values on VLA ranks. Now switched to using getVLAElements1D() instead, which only gets a single dimension. Fixes #141409
1 parent 7c9e0d5 commit d1a6327

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3574,20 +3574,20 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
35743574
CGF.EmitIgnoredExpr(E->getArgumentExpr());
35753575
}
35763576

3577-
auto VlaSize = CGF.getVLASize(VAT);
3578-
llvm::Value *size = VlaSize.NumElts;
3577+
// For _Countof, we just want to return the size of a single dimension.
3578+
if (Kind == UETT_CountOf)
3579+
return CGF.getVLAElements1D(VAT).NumElts;
35793580

35803581
// For sizeof and __datasizeof, we need to scale the number of elements
3581-
// by the size of the array element type. For _Countof, we just want to
3582-
// return the size directly.
3583-
if (Kind != UETT_CountOf) {
3584-
// Scale the number of non-VLA elements by the non-VLA element size.
3585-
CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type);
3586-
if (!eltSize.isOne())
3587-
size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), size);
3588-
}
3582+
// by the size of the array element type.
3583+
auto VlaSize = CGF.getVLASize(VAT);
35893584

3590-
return size;
3585+
// Scale the number of non-VLA elements by the non-VLA element size.
3586+
CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type);
3587+
if (!eltSize.isOne())
3588+
return CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize),
3589+
VlaSize.NumElts);
3590+
return VlaSize.NumElts;
35913591
}
35923592
}
35933593
} else if (E->getKind() == UETT_OpenMPRequiredSimdAlign) {

clang/test/C/C2y/n3369_3.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,57 @@ void test4(int n) {
164164
int y = _Countof(int[n++][7]);
165165
}
166166

167+
// CHECK-64-LABEL: define dso_local void @test5(
168+
// CHECK-64-SAME: ) #[[ATTR0]] {
169+
// CHECK-64-NEXT: [[ENTRY:.*:]]
170+
// CHECK-64-NEXT: [[J:%.*]] = alloca i32, align
171+
// CHECK-64-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align
172+
// CHECK-64-NEXT: [[A:%.*]] = alloca i32, align
173+
// CHECK-64-NEXT: [[B:%.*]] = alloca i32, align
174+
// CHECK-64-NEXT: [[C:%.*]] = alloca i32, align
175+
// CHECK-64-NEXT: [[D:%.*]] = alloca i32, align
176+
// CHECK-64-NEXT: store i32 2, ptr [[J]], align
177+
// CHECK-64-NEXT: [[TMP0:%.*]] = call ptr @llvm.stacksave.p0()
178+
// CHECK-64-NEXT: store ptr [[TMP0]], ptr [[SAVED_STACK]], align
179+
// CHECK-64-NEXT: [[VLA:%.*]] = alloca i32, i64 120, align
180+
// CHECK-64-NEXT: store i32 1, ptr [[A]], align
181+
// CHECK-64-NEXT: store i32 4, ptr [[B]], align
182+
// CHECK-64-NEXT: store i32 5, ptr [[C]], align
183+
// CHECK-64-NEXT: store i32 6, ptr [[D]], align
184+
// CHECK-64-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SAVED_STACK]], align
185+
// CHECK-64-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP1]])
186+
// CHECK-64-NEXT: ret void
187+
//
188+
// CHECK-32-LABEL: define dso_local void @test5(
189+
// CHECK-32-SAME: ) #[[ATTR0]] {
190+
// CHECK-32-NEXT: [[ENTRY:.*:]]
191+
// CHECK-32-NEXT: [[J:%.*]] = alloca i32, align
192+
// CHECK-32-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align
193+
// CHECK-32-NEXT: [[A:%.*]] = alloca i32, align
194+
// CHECK-32-NEXT: [[B:%.*]] = alloca i32, align
195+
// CHECK-32-NEXT: [[C:%.*]] = alloca i32, align
196+
// CHECK-32-NEXT: [[D:%.*]] = alloca i32, align
197+
// CHECK-32-NEXT: store i32 2, ptr [[J]], align
198+
// CHECK-32-NEXT: [[TMP0:%.*]] = call ptr @llvm.stacksave.p0()
199+
// CHECK-32-NEXT: store ptr [[TMP0]], ptr [[SAVED_STACK]], align
200+
// CHECK-32-NEXT: [[VLA:%.*]] = alloca i32, i32 120, align
201+
// CHECK-32-NEXT: store i32 1, ptr [[A]], align
202+
// CHECK-32-NEXT: store i32 4, ptr [[B]], align
203+
// CHECK-32-NEXT: store i32 5, ptr [[C]], align
204+
// CHECK-32-NEXT: store i32 6, ptr [[D]], align
205+
// CHECK-32-NEXT: [[TMP1:%.*]] = load ptr, ptr [[SAVED_STACK]], align
206+
// CHECK-32-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP1]])
207+
// CHECK-32-NEXT: ret void
208+
//
209+
void test5() {
210+
// Ensure we're getting the variable-length dimensions correctly. We were
211+
// previously returning the size of all VLA dimensions multiplied together
212+
// to get the total element count rather than the element count for a single
213+
// array rank. See GH141409
214+
const int j = 2;
215+
int arr[1][j + 2][j + 3][j + 4];
216+
int a = _Countof arr;
217+
int b = _Countof *arr;
218+
int c = _Countof **arr;
219+
int d = _Countof ***arr;
220+
}

0 commit comments

Comments
 (0)