|
1 | 1 | // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 |
2 | | -// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s |
| 2 | +// RUN: %clang_cc1 -std=c23 -Wno-error=odr -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s |
3 | 3 |
|
4 | 4 | // This tests the codegen behavior of redefined tag types to ensure the |
5 | 5 | // generated code looks reasonable. |
@@ -46,3 +46,43 @@ enum E { |
46 | 46 | One, |
47 | 47 | Two |
48 | 48 | }; |
| 49 | + |
| 50 | +// Ensure that ignoring the incompatibility due to attributes does not cause a |
| 51 | +// crash. Note, this is undefined behavior in Clang until we implement |
| 52 | +// attribute structural compatibility logic, so this is not intended to verify |
| 53 | +// any particular behavior beyond "don't crash." |
| 54 | +struct T { |
| 55 | + _Alignas(double) int x; |
| 56 | +}; |
| 57 | + |
| 58 | +// CHECK-LABEL: define dso_local i32 @foo( |
| 59 | +// CHECK-SAME: i32 [[T_COERCE:%.*]]) #[[ATTR0]] { |
| 60 | +// CHECK-NEXT: [[ENTRY:.*:]] |
| 61 | +// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_T:%.*]], align 8 |
| 62 | +// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 0 |
| 63 | +// CHECK-NEXT: store i32 [[T_COERCE]], ptr [[COERCE_DIVE]], align 8 |
| 64 | +// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 0 |
| 65 | +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 8 |
| 66 | +// CHECK-NEXT: ret i32 [[TMP0]] |
| 67 | +// |
| 68 | +int foo(struct T t) { |
| 69 | + return t.x; |
| 70 | +} |
| 71 | + |
| 72 | +struct T { |
| 73 | + int x; |
| 74 | +}; |
| 75 | + |
| 76 | +// CHECK-LABEL: define dso_local i32 @bar( |
| 77 | +// CHECK-SAME: i32 [[T_COERCE:%.*]]) #[[ATTR0]] { |
| 78 | +// CHECK-NEXT: [[ENTRY:.*:]] |
| 79 | +// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_T:%.*]], align 8 |
| 80 | +// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 0 |
| 81 | +// CHECK-NEXT: store i32 [[T_COERCE]], ptr [[COERCE_DIVE]], align 8 |
| 82 | +// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_T]], ptr [[T]], i32 0, i32 0 |
| 83 | +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X]], align 8 |
| 84 | +// CHECK-NEXT: ret i32 [[TMP0]] |
| 85 | +// |
| 86 | +int bar(struct T t) { |
| 87 | + return t.x; |
| 88 | +} |
0 commit comments