xref: /llvm-project/clang/test/CodeGenCXX/pr58798.cpp (revision 6daa005b90c8122751d04c6eba0fa1259e912cfe)
1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes
2 // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions | FileCheck %s
3 
4 // CHECK: Function Attrs: mustprogress noinline nounwind optnone willreturn memory(read)
5 // CHECK-LABEL: define {{[^@]+}}@_Z54early_caller_of_callee_with_clang_attr_with_clang_attri
6 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
7 // CHECK-NEXT:  entry:
8 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
9 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
10 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
11 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z22callee_with_clang_attri(i32 noundef [[TMP0]]) #[[ATTR3:[0-9]+]]
12 // CHECK-NEXT:    ret i32 [[CALL]]
13 //
14 
15 // CHECK: Function Attrs: mustprogress noinline nounwind optnone willreturn memory(read)
16 // CHECK-LABEL: define {{[^@]+}}@_Z22callee_with_clang_attri
17 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR0]] {
18 // CHECK-NEXT:  entry:
19 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
20 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
21 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
22 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0
23 // CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
24 // CHECK:       if.then:
25 // CHECK-NEXT:    [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR4:[0-9]+]]
26 // CHECK-NEXT:    store i32 42, ptr [[EXCEPTION]], align 16
27 // CHECK-NEXT:    call void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIi, ptr null) #[[ATTR5:[0-9]+]]
28 // CHECK-NEXT:    unreachable
29 // CHECK:       if.end:
30 // CHECK-NEXT:    ret i32 24
31 //
32 
33 // CHECK: Function Attrs: mustprogress noinline nounwind optnone
34 // CHECK-LABEL: define {{[^@]+}}@_Z52early_caller_of_callee_with_clang_attr_with_cxx_attri
35 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR1:[0-9]+]] {
36 // CHECK-NEXT:  entry:
37 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
38 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
39 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
40 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z22callee_with_clang_attri(i32 noundef [[TMP0]]) #[[ATTR3]]
41 // CHECK-NEXT:    ret i32 [[CALL]]
42 //
43 
44 // CHECK: Function Attrs: mustprogress noinline nounwind optnone willreturn memory(read)
45 // CHECK-LABEL: define {{[^@]+}}@_Z52early_caller_of_callee_with_cxx_attr_with_clang_attri
46 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR0]] {
47 // CHECK-NEXT:  entry:
48 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
49 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
50 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
51 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z20callee_with_cxx_attri(i32 noundef [[TMP0]]) #[[ATTR4]]
52 // CHECK-NEXT:    ret i32 [[CALL]]
53 //
54 
55 // CHECK: Function Attrs: mustprogress noinline nounwind optnone
56 // CHECK-LABEL: define {{[^@]+}}@_Z20callee_with_cxx_attri
57 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR1]] personality ptr @__gxx_personality_v0 {
58 // CHECK-NEXT:  entry:
59 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
60 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
61 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
62 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0
63 // CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
64 // CHECK:       if.then:
65 // CHECK-NEXT:    [[EXCEPTION:%.*]] = call ptr @__cxa_allocate_exception(i64 4) #[[ATTR4]]
66 // CHECK-NEXT:    store i32 42, ptr [[EXCEPTION]], align 16
67 // CHECK-NEXT:    invoke void @__cxa_throw(ptr [[EXCEPTION]], ptr @_ZTIi, ptr null) #[[ATTR5]]
68 // CHECK-NEXT:    to label [[UNREACHABLE:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
69 // CHECK:       if.end:
70 // CHECK-NEXT:    ret i32 24
71 // CHECK:       terminate.lpad:
72 // CHECK-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
73 // CHECK-NEXT:    catch ptr null
74 // CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
75 // CHECK-NEXT:    call void @__clang_call_terminate(ptr [[TMP2]]) #[[ATTR6:[0-9]+]]
76 // CHECK-NEXT:    unreachable
77 // CHECK:       unreachable:
78 // CHECK-NEXT:    unreachable
79 //
80 
81 // CHECK: Function Attrs: mustprogress noinline nounwind optnone
82 // CHECK-LABEL: define {{[^@]+}}@_Z50early_caller_of_callee_with_cxx_attr_with_cxx_attri
83 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR1]] {
84 // CHECK-NEXT:  entry:
85 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
86 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
87 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
88 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z20callee_with_cxx_attri(i32 noundef [[TMP0]]) #[[ATTR4]]
89 // CHECK-NEXT:    ret i32 [[CALL]]
90 //
91 
92 
93 // Forward declarations:
94 
95 __attribute__((pure)) int callee_with_clang_attr(int a);
96 int callee_with_cxx_attr(int a) noexcept;
97 
98 // Calls to forward declarations:
99 
early_caller_of_callee_with_clang_attr_with_clang_attr(int a)100 __attribute__((pure)) int early_caller_of_callee_with_clang_attr_with_clang_attr(int a) {
101   return callee_with_clang_attr(a);
102 }
103 
early_caller_of_callee_with_clang_attr_with_cxx_attr(int a)104 int early_caller_of_callee_with_clang_attr_with_cxx_attr(int a) noexcept {
105   return callee_with_clang_attr(a);
106 }
107 
early_caller_of_callee_with_cxx_attr_with_clang_attr(int a)108 __attribute__((pure)) int early_caller_of_callee_with_cxx_attr_with_clang_attr(int a) {
109   return callee_with_cxx_attr(a);
110 }
111 
early_caller_of_callee_with_cxx_attr_with_cxx_attr(int a)112 int early_caller_of_callee_with_cxx_attr_with_cxx_attr(int a) noexcept {
113   return callee_with_cxx_attr(a);
114 }
115 
116 // Definitions:
117 
callee_with_clang_attr(int a)118 __attribute__((pure)) int callee_with_clang_attr(int a) {
119   if(a)
120     throw int(42);
121   return 24;
122 }
123 
callee_with_cxx_attr(int a)124 int callee_with_cxx_attr(int a) noexcept {
125   if(a)
126     throw int(42);
127   return 24;
128 }
129 
130 // Calls to definitions:
131 
132 // CHECK: Function Attrs: mustprogress noinline nounwind optnone willreturn memory(read)
133 // CHECK-LABEL: define {{[^@]+}}@_Z53late_caller_of_callee_with_clang_attr_with_clang_attri
134 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR0]] {
135 // CHECK-NEXT:  entry:
136 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
137 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
138 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
139 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z22callee_with_clang_attri(i32 noundef [[TMP0]]) #[[ATTR3]]
140 // CHECK-NEXT:    ret i32 [[CALL]]
141 //
late_caller_of_callee_with_clang_attr_with_clang_attr(int a)142 __attribute__((pure)) int late_caller_of_callee_with_clang_attr_with_clang_attr(int a) {
143   return callee_with_clang_attr(a);
144 }
145 
146 // CHECK: Function Attrs: mustprogress noinline nounwind optnone
147 // CHECK-LABEL: define {{[^@]+}}@_Z51late_caller_of_callee_with_clang_attr_with_cxx_attri
148 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR1]] {
149 // CHECK-NEXT:  entry:
150 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
151 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
152 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
153 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z22callee_with_clang_attri(i32 noundef [[TMP0]]) #[[ATTR3]]
154 // CHECK-NEXT:    ret i32 [[CALL]]
155 //
late_caller_of_callee_with_clang_attr_with_cxx_attr(int a)156 int late_caller_of_callee_with_clang_attr_with_cxx_attr(int a) noexcept {
157   return callee_with_clang_attr(a);
158 }
159 
160 // CHECK: Function Attrs: mustprogress noinline nounwind optnone willreturn memory(read)
161 // CHECK-LABEL: define {{[^@]+}}@_Z51late_caller_of_callee_with_cxx_attr_with_clang_attri
162 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR0]] {
163 // CHECK-NEXT:  entry:
164 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
165 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
166 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
167 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z20callee_with_cxx_attri(i32 noundef [[TMP0]]) #[[ATTR4]]
168 // CHECK-NEXT:    ret i32 [[CALL]]
169 //
late_caller_of_callee_with_cxx_attr_with_clang_attr(int a)170 __attribute__((pure)) int late_caller_of_callee_with_cxx_attr_with_clang_attr(int a) {
171   return callee_with_cxx_attr(a);
172 }
173 
174 // CHECK: Function Attrs: mustprogress noinline nounwind optnone
175 // CHECK-LABEL: define {{[^@]+}}@_Z49late_caller_of_callee_with_cxx_attr_with_cxx_attri
176 // CHECK-SAME: (i32 noundef [[A:%.*]]) #[[ATTR1]] {
177 // CHECK-NEXT:  entry:
178 // CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
179 // CHECK-NEXT:    store i32 [[A]], ptr [[A_ADDR]], align 4
180 // CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
181 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z20callee_with_cxx_attri(i32 noundef [[TMP0]]) #[[ATTR4]]
182 // CHECK-NEXT:    ret i32 [[CALL]]
183 //
late_caller_of_callee_with_cxx_attr_with_cxx_attr(int a)184 int late_caller_of_callee_with_cxx_attr_with_cxx_attr(int a) noexcept {
185   return callee_with_cxx_attr(a);
186 }
187