1 // RUN: %clang_cc1 -Wno-unused-value -triple i686-linux-gnu -emit-llvm -o - %s | FileCheck %s
2 extern "C" int printf(...);
3 extern "C" void abort();
8 A (int j
) : i(j
) {printf("this = %p A(%d)\n", this, j
);}
9 A (const A
&j
) : i(j
.i
) {printf("this = %p const A&(%d)\n", this, i
);}
10 A
& operator= (const A
&j
) { i
= j
.i
; abort(); return *this; }
11 ~A() { printf("this = %p ~A(%d)\n", this, i
); }
17 B (const A
& a
) { i
= a
.i
; }
18 B() {printf("this = %p B()\n", this);}
19 B (const B
&j
) : i(j
.i
) {printf("this = %p const B&(%d)\n", this, i
);}
20 ~B() { printf("this = %p ~B(%d)\n", this, i
); }
25 return ({ j
? A(1) : A(0); });
31 A b
= ({ A
a(1); A
a1(2); A
a2(3); a1
; a2
; a
; });
34 A c
= ({ A
a(1); A
a1(2); A
a2(3); a1
; a2
; a
; A
a3(4); a2
; a3
; });
41 const A
&b
= ({ A
a(1); a
; });
48 // CHECK: call {{.*}} @_ZN1AC1Ei
49 // CHECK: call {{.*}} @_ZN1AC1ERKS_
50 // CHECK: call {{.*}} @_ZN1AD1Ev
51 // CHECK: call {{.*}} @_ZN1BC1ERK1A
52 // CHECK: call {{.*}} @_ZN1AD1Ev
53 const B
&b
= ({ A
a(1); a
; });
69 // Check that array-to-pointer conversion occurs in a
70 // statement-expression.
74 // Make sure this doesn't crash.
77 y
= ({ A
a(1); if (b
) goto G
; a
.i
; });
81 // When we emit a full expression with cleanups that contains branches out of
82 // the full expression, the result of the inner expression (the call to
83 // call_with_cleanups in this case) may not dominate the fallthrough destination
84 // of the shared cleanup block.
86 // In this case the CFG will be a sequence of two diamonds, but the only
87 // dynamically possible execution paths are both left hand branches and both
88 // right hand branches. The first diamond LHS will call bar, and the second
89 // diamond LHS will assign the result to v, but the call to bar does not
90 // dominate the assignment.
92 extern "C" int cleanup_exit_scalar(bool b
) {
93 int v
= bar(A(1), ({ if (b
) return 42; 13; }));
97 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar({{.*}})
98 // CHECK: call {{.*}} @_ZN1AC1Ei
100 // CHECK: %[[v:[^ ]*]] = call{{.*}} i32 @_Z3bar1Ai({{.*}})
101 // CHECK-NEXT: store i32 %[[v]], ptr %[[tmp:[^, ]*]]
103 // CHECK: call {{.*}} @_ZN1AD1Ev
105 // Reload before v assignment.
106 // CHECK: %[[v:[^ ]*]] = load i32, ptr %[[tmp]]
107 // CHECK-NEXT: store i32 %[[v]], ptr %v
109 // No need to spill when the expression result is a constant, constants don't
110 // have dominance problems.
111 extern "C" int cleanup_exit_scalar_constant(bool b
) {
112 int v
= (A(1), (void)({ if (b
) return 42; 0; }), 13);
116 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar_constant({{.*}})
117 // CHECK: store i32 13, ptr %v
119 // Check for the same bug for lvalue expression evaluation kind.
120 // FIXME: What about non-reference lvalues, like bitfield lvalues and vector
123 extern "C" int cleanup_exit_lvalue(bool cond
) {
124 int &r
= (A(1), ({ if (cond
) return 0; (void)0; }), getref());
127 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue({{.*}})
128 // CHECK: call {{.*}} @_ZN1AC1Ei
130 // CHECK: %[[v:[^ ]*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_Z6getrefv({{.*}})
131 // CHECK-NEXT: store ptr %[[v]], ptr %[[tmp:[^, ]*]]
133 // CHECK: call {{.*}} @_ZN1AD1Ev
135 // Reload before v assignment.
136 // CHECK: %[[v:[^ ]*]] = load ptr, ptr %[[tmp]]
137 // CHECK-NEXT: store ptr %[[v]], ptr %r
139 // Bind the reference to a byval argument. It is not an instruction or Constant,
140 // so it's a bit of a corner case.
141 struct ByVal
{ int x
[3]; };
142 extern "C" int cleanup_exit_lvalue_byval(bool cond
, ByVal arg
) {
143 ByVal
&r
= (A(1), ({ if (cond
) return 0; (void)ByVal(); }), arg
);
146 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_byval({{.*}}, ptr noundef byval(%struct.ByVal) align 4 %arg)
147 // CHECK: call {{.*}} @_ZN1AC1Ei
148 // CHECK: call {{.*}} @_ZN1AD1Ev
150 // CHECK: store ptr %arg, ptr %r
152 // Bind the reference to a local variable. We don't need to spill it. Binding a
153 // reference to it doesn't generate any instructions.
154 extern "C" int cleanup_exit_lvalue_local(bool cond
) {
156 int &r
= (A(1), ({ if (cond
) return 0; (void)0; }), local
);
159 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_local({{.*}})
160 // CHECK: %local = alloca i32
161 // CHECK: store i32 42, ptr %local
162 // CHECK: call {{.*}} @_ZN1AC1Ei
163 // CHECK-NOT: store ptr %local
164 // CHECK: call {{.*}} @_ZN1AD1Ev
166 // CHECK: store ptr %local, ptr %r, align 4
168 // We handle ExprWithCleanups for complex evaluation type separately, and it had
170 _Complex
float bar_complex(A
, int);
171 extern "C" int cleanup_exit_complex(bool b
) {
172 _Complex
float v
= bar_complex(A(1), ({ if (b
) return 42; 13; }));
176 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_complex({{.*}})
177 // CHECK: call {{.*}} @_ZN1AC1Ei
179 // CHECK: call {{.*}} @_Z11bar_complex1Ai({{.*}})
180 // CHECK: store float %{{.*}}, ptr %[[tmp1:[^, ]*]]
181 // CHECK: store float %{{.*}}, ptr %[[tmp2:[^, ]*]]
183 // CHECK: call {{.*}} @_ZN1AD1Ev
185 // Reload before v assignment.
186 // CHECK: %[[v1:[^ ]*]] = load float, ptr %[[tmp1]]
187 // CHECK: %[[v2:[^ ]*]] = load float, ptr %[[tmp2]]
188 // CHECK: store float %[[v1]], ptr %v.realp
189 // CHECK: store float %[[v2]], ptr %v.imagp
191 extern "C" void then(int);
193 // CHECK-LABEL: @{{.*}}volatile_load
194 void volatile_load() {
197 // CHECK-NOT: load volatile
198 // CHECK: load volatile
199 // CHECK-NOT: load volatile
202 // CHECK-LABEL: @then(i32 noundef 1)
205 // CHECK-NOT: load volatile
206 // CHECK: load volatile
207 // CHECK-NOT: load volatile
208 ({goto lab
; lab
: n
;});
210 // CHECK-LABEL: @then(i32 noundef 2)
213 // CHECK-NOT: load volatile
214 // CHECK: load volatile
215 // CHECK-NOT: load volatile
216 ({[[gsl::suppress("foo")]] n
;});
218 // CHECK-LABEL: @then(i32 noundef 3)
221 // CHECK-NOT: load volatile
222 // CHECK: load volatile
223 // CHECK-NOT: load volatile
229 // CHECK-LABEL: @{{.*}}volatile_load_template
231 void volatile_load_template() {
234 // CHECK-NOT: load volatile
235 // CHECK: load volatile
236 // CHECK-NOT: load volatile
239 // CHECK-LABEL: @then(i32 noundef 1)
242 // CHECK-NOT: load volatile
243 // CHECK: load volatile
244 // CHECK-NOT: load volatile
245 ({goto lab
; lab
: n
;});
247 // CHECK-LABEL: @then(i32 noundef 2)
250 // CHECK-NOT: load volatile
251 // CHECK: load volatile
252 // CHECK-NOT: load volatile
253 ({[[gsl::suppress("foo")]] n
;});
255 // CHECK-LABEL: @then(i32 noundef 3)
258 // CHECK-NOT: load volatile
259 // CHECK: load volatile
260 // CHECK-NOT: load volatile
265 template void volatile_load_template
<int>();