================ @@ -0,0 +1,92 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -std=c2y -emit-llvm -o - %s | FileCheck %s + +// This tests the codegen behavior for _Countof. +// CHECK-LABEL: define dso_local i32 @test1( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[ARRAY:%.*]] = alloca [12 x i32], align 16 +// CHECK-NEXT: ret i32 12 +// +int test1() { + int array[12]; + return _Countof(array); +} + +// CHECK-LABEL: define dso_local i32 @test2( +// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align 8 +// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: [[VLA:%.*]] = alloca i32, i64 [[TMP1]], align 16 +// CHECK-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8 +// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP3]]) +// CHECK-NEXT: ret i32 [[CONV]] +// +int test2(int n) { + int array[n]; + return _Countof(array); +} + +// CHECK-LABEL: define dso_local i32 @test3( +// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32 +// CHECK-NEXT: ret i32 [[CONV]] +// +int test3(int n) { + return _Countof(int[n]); +} + +// CHECK-LABEL: define dso_local i32 @test4( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: ret i32 100 +// +int test4() { + return _Countof(float[100]); +} + +// CHECK-LABEL: define dso_local i32 @test5( +// CHECK-SAME: i32 noundef [[N:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[__VLA_EXPR0:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[X:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[N_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: [[TMP2:%.*]] = call ptr @llvm.stacksave.p0() +// CHECK-NEXT: store ptr [[TMP2]], ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: [[VLA:%.*]] = alloca [7 x i32], i64 [[TMP1]], align 16 +// CHECK-NEXT: store i64 [[TMP1]], ptr [[__VLA_EXPR0]], align 8 +// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP1]] to i32 +// CHECK-NEXT: store i32 [[CONV]], ptr [[X]], align 4 +// CHECK-NEXT: store i32 7, ptr [[Y]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[X]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[Y]], align 4 +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[SAVED_STACK]], align 8 +// CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[TMP5]]) +// CHECK-NEXT: ret i32 [[ADD]] +// +int test5(int n) { + int array[n][7]; + int x = _Countof(array); + int y = _Countof(*array); + return x + y; +} ---------------- AaronBallman wrote:
Good call, this has the same bug as the earlier test regarding what is and isn't an operand resulting in a constant expression. https://github.com/llvm/llvm-project/pull/133125 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits