llvm-project/clang/test/CodeGen/linux-kernel-struct-union-initializer.c
yabinc 627746581b
Reapply "[clang][CodeGen] Zero init unspecified fields in initializers in C" (#109898) (#110051)
This reverts commit d50eaac12f0cdfe27e942290942b06889ab12a8c. Also fixes
a bug calculating offsets for bit fields in the original patch.
2024-10-14 16:32:24 -07:00

276 lines
9.4 KiB
C

// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=gnu11 -verify -emit-llvm %s -o - | FileCheck %s
// expected-no-diagnostics
union U1 {
int x;
char y[16];
};
struct S1 {
int x;
union U1 y;
};
union U2 {
int x;
char y[16];
} __attribute__((__aligned__(32)));
struct S2 {
int x;
long long y;
char z[8];
} __attribute__((__aligned__(32)));
struct S3 {
char x;
unsigned char y : 4;
unsigned char z : 7;
} __attribute__((packed));
union U1 global_u1 = {};
union U1 global_u2 = {3};
union U1 global_u2_from_cast = (union U1)3;
struct S1 global_s1 = {};
struct S1 global_s2 = {
.x = 3,
};
struct S1 global_s3 = {.x = 3, .y = {.x = 6}};
const union U1 global_const_u1 = {4};
struct S1 global_s3_from_const_u1 = {.y = global_const_u1};
union U2 global_u3 = {};
struct S2 global_s4 = {};
struct S2 global_s5 = {.x = 1};
struct S3 global_s6 = {101, 15, 123};
// Test empty initializer for union.
//.
// CHECK: @global_u1 = global %union.U1 zeroinitializer, align 4
// CHECK: @global_u2 = global %union.U1 { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @global_u2_from_cast = global { i32, [12 x i8] } { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @global_s1 = global %struct.S1 zeroinitializer, align 4
// CHECK: @global_s2 = global %struct.S1 { i32 3, %union.U1 zeroinitializer }, align 4
// CHECK: @global_s3 = global %struct.S1 { i32 3, %union.U1 { i32 6, [12 x i8] zeroinitializer } }, align 4
// CHECK: @global_const_u1 = constant %union.U1 { i32 4, [12 x i8] zeroinitializer }, align 4
// CHECK: @global_s3_from_const_u1 = global %struct.S1 { i32 0, %union.U1 { i32 4, [12 x i8] zeroinitializer } }, align 4
// CHECK: @global_u3 = global %union.U2 zeroinitializer, align 32
// CHECK: @global_s4 = global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } zeroinitializer, align 32
// CHECK: @global_s5 = global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } { i32 1, [4 x i8] zeroinitializer, i64 0, [8 x i8] zeroinitializer, [8 x i8] zeroinitializer }, align 32
// CHECK: @global_s6 = global { i8, i8, i8 } { i8 101, i8 -65, i8 7 }, align 1
// CHECK: @test2.a = internal global %union.U1 zeroinitializer, align 4
// CHECK: @__const.test3.a = private unnamed_addr constant %union.U1 { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @test4.a = internal global %union.U1 { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @test6.s = internal global %struct.S1 zeroinitializer, align 4
// CHECK: @__const.test7.s = private unnamed_addr constant %struct.S1 { i32 3, %union.U1 zeroinitializer }, align 4
// CHECK: @test8.s = internal global %struct.S1 { i32 3, %union.U1 zeroinitializer }, align 4
// CHECK: @__const.test9.s = private unnamed_addr constant %struct.S1 { i32 3, %union.U1 { i32 6, [12 x i8] zeroinitializer } }, align 4
// CHECK: @test10.s = internal global %struct.S1 { i32 3, %union.U1 { i32 6, [12 x i8] zeroinitializer } }, align 4
// CHECK: @test12.a = internal global %union.U2 zeroinitializer, align 32
// CHECK: @test14.s = internal global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } zeroinitializer, align 32
// CHECK: @__const.test15.s = private unnamed_addr constant { i32, [4 x i8], i64, [8 x i8], [8 x i8] } { i32 1, [4 x i8] zeroinitializer, i64 0, [8 x i8] zeroinitializer, [8 x i8] zeroinitializer }, align 32
// CHECK: @test16.s = internal global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } { i32 1, [4 x i8] zeroinitializer, i64 0, [8 x i8] zeroinitializer, [8 x i8] zeroinitializer }, align 32
//.
// CHECK-LABEL: define dso_local void @test1(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 16, i1 false)
// CHECK-NEXT: ret void
//
void test1() {
union U1 a = {};
}
// Test empty initializer for union. Use static variable.
// CHECK-LABEL: define dso_local void @test2(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test2() {
static union U1 a = {};
}
// Test only initializing a small field for union.
// CHECK-LABEL: define dso_local void @test3(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A]], ptr align 4 @__const.test3.a, i64 16, i1 false)
// CHECK-NEXT: ret void
//
void test3() {
union U1 a = {3};
}
// Test only initializing a small field for union. Use static variable.
// CHECK-LABEL: define dso_local void @test4(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test4() {
static union U1 a = {3};
}
// Test union in struct. Use empty initializer for the struct.
// CHECK-LABEL: define dso_local void @test5(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[S]], i8 0, i64 20, i1 false)
// CHECK-NEXT: ret void
//
void test5() {
struct S1 s = {};
}
// Test union in struct. Use empty initializer for the struct. Use static variable.
// CHECK-LABEL: define dso_local void @test6(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test6() {
static struct S1 s = {};
}
// Test union in struct. Initialize other fields of the struct.
// CHECK-LABEL: define dso_local void @test7(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[S]], ptr align 4 @__const.test7.s, i64 20, i1 false)
// CHECK-NEXT: ret void
//
void test7() {
struct S1 s = {
.x = 3,
};
}
// Test union in struct. Initialize other fields of the struct. Use static variable.
// CHECK-LABEL: define dso_local void @test8(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test8() {
static struct S1 s = {
.x = 3,
};
}
// Test union in struct. Initialize a small field for union.
// CHECK-LABEL: define dso_local void @test9(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[S]], ptr align 4 @__const.test9.s, i64 20, i1 false)
// CHECK-NEXT: ret void
//
void test9() {
struct S1 s = {.x = 3,
.y = {
.x = 6,
}};
}
// Test union in struct. Initialize a small field for union. Use static variable.
// CHECK-LABEL: define dso_local void @test10(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test10() {
static struct S1 s = {.x = 3,
.y = {
.x = 6,
}};
}
// Test empty initializer for union with padding.
// CHECK-LABEL: define dso_local void @test11(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U2:%.*]], align 32
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 32 [[A]], i8 0, i64 32, i1 false)
// CHECK-NEXT: ret void
//
void test11() {
union U2 a = {};
}
// Test empty initializer for union with padding. Use static variable.
// CHECK-LABEL: define dso_local void @test12(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test12() {
static union U2 a = {};
}
// Test empty initializer for struct with padding.
// CHECK-LABEL: define dso_local void @test13(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 32
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 32 [[S]], i8 0, i64 32, i1 false)
// CHECK-NEXT: ret void
//
void test13() {
struct S2 s = {};
}
// Test empty initializer for struct with padding. Use static variable.
// CHECK-LABEL: define dso_local void @test14(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test14() {
static struct S2 s = {};
}
// Test partial initialization for struct with padding.
// CHECK-LABEL: define dso_local void @test15(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 32
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 32 [[S]], ptr align 32 @__const.test15.s, i64 32, i1 false)
// CHECK-NEXT: ret void
//
void test15() {
struct S2 s = {.x = 1};
}
// Test partial initialization for struct with padding. Use static variable.
// CHECK-LABEL: define dso_local void @test16(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test16() {
static struct S2 s = {.x = 1};
}
//.
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
// CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
//.
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
//.