Clang Project

clang_source_code/test/CodeGenCXX/stmtexpr.cpp
1// RUN: %clang_cc1 -Wno-unused-value -triple i686-linux-gnu -emit-llvm -o - %s | FileCheck %s
2// rdar: //8540501
3extern "C" int printf(...);
4extern "C" void abort();
5
6struct A
7{
8  int i;
9  A (int j) : i(j) {printf("this = %p A(%d)\n", this, j);}
10  A (const A &j) : i(j.i) {printf("this = %p const A&(%d)\n", this, i);}
11  A& operator= (const A &j) { i = j.i; abort(); return *this; }
12  ~A() { printf("this = %p ~A(%d)\n", this, i); }
13};
14
15struct B
16{
17  int i;
18  B (const A& a) { i = a.i; }
19  B() {printf("this = %p B()\n", this);}
20  B (const B &j) : i(j.i) {printf("this = %p const B&(%d)\n", this, i);}
21  ~B() { printf("this = %p ~B(%d)\n", this, i); }
22};
23
24A foo(int j)
25{
26  return ({ j ? A(1) : A(0); });
27}
28
29
30void foo2()
31{
32  A b = ({ A a(1); A a1(2); A a2(3); a1; a2; a; });
33  if (b.i != 1)
34    abort(); 
35  A c = ({ A a(1); A a1(2); A a2(3); a1; a2; a; A a3(4); a2; a3; });
36  if (c.i != 4)
37    abort(); 
38}
39
40void foo3()
41{
42  const A &b = ({ A a(1); a; });
43  if (b.i != 1)
44    abort();
45}
46
47void foo4()
48{
49// CHECK: call {{.*}} @_ZN1AC1Ei
50// CHECK: call {{.*}} @_ZN1AC1ERKS_
51// CHECK: call {{.*}} @_ZN1AD1Ev
52// CHECK: call {{.*}} @_ZN1BC1ERK1A
53// CHECK: call {{.*}} @_ZN1AD1Ev
54  const B &b = ({ A a(1); a; });
55  if (b.i != 1)
56    abort();
57}
58
59int main()
60{
61  foo2();
62  foo3();
63  foo4();
64  return foo(1).i-1;
65}
66
67// rdar: // 8600553
68int a[128];
69int* foo5() {
70// CHECK-NOT: memcpy
71  // Check that array-to-pointer conversion occurs in a
72  // statement-expression.
73  return (({ a; }));
74}
75
76// <rdar://problem/14074868>
77// Make sure this doesn't crash.
78int foo5(bool b) {
79  int y = 0;
80  y = ({ A a(1); if (b) goto G; a.i; });
81  G: return y;
82}
83
84// When we emit a full expression with cleanups that contains branches out of
85// the full expression, the result of the inner expression (the call to
86// call_with_cleanups in this case) may not dominate the fallthrough destination
87// of the shared cleanup block.
88//
89// In this case the CFG will be a sequence of two diamonds, but the only
90// dynamically possible execution paths are both left hand branches and both
91// right hand branches. The first diamond LHS will call bar, and the second
92// diamond LHS will assign the result to v, but the call to bar does not
93// dominate the assignment.
94int bar(A, int);
95extern "C" int cleanup_exit_scalar(bool b) {
96  int v = bar(A(1), ({ if (b) return 42; 13; }));
97  return v;
98}
99
100// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar({{.*}})
101// CHECK: call {{.*}} @_ZN1AC1Ei
102//    Spill after bar.
103// CHECK: %[[v:[^ ]*]] = call{{.*}} i32 @_Z3bar1Ai({{.*}})
104// CHECK-NEXT: store i32 %[[v]], i32* %[[tmp:[^, ]*]]
105//    Do cleanup.
106// CHECK: call {{.*}} @_ZN1AD1Ev
107// CHECK: switch
108//    Reload before v assignment.
109// CHECK: %[[v:[^ ]*]] = load i32, i32* %[[tmp]]
110// CHECK-NEXT: store i32 %[[v]], i32* %v
111
112// No need to spill when the expression result is a constant, constants don't
113// have dominance problems.
114extern "C" int cleanup_exit_scalar_constant(bool b) {
115  int v = (A(1), (void)({ if (b) return 42; 0; }), 13);
116  return v;
117}
118
119// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar_constant({{.*}})
120// CHECK: store i32 13, i32* %v
121
122// Check for the same bug for lvalue expression evaluation kind.
123// FIXME: What about non-reference lvalues, like bitfield lvalues and vector
124// lvalues?
125int &getref();
126extern "C" int cleanup_exit_lvalue(bool cond) {
127  int &r = (A(1), ({ if (cond) return 0; (void)0; }), getref());
128  return r;
129}
130// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue({{.*}})
131// CHECK: call {{.*}} @_ZN1AC1Ei
132//    Spill after bar.
133// CHECK: %[[v:[^ ]*]] = call dereferenceable(4) i32* @_Z6getrefv({{.*}})
134// CHECK-NEXT: store i32* %[[v]], i32** %[[tmp:[^, ]*]]
135//    Do cleanup.
136// CHECK: call {{.*}} @_ZN1AD1Ev
137// CHECK: switch
138//    Reload before v assignment.
139// CHECK: %[[v:[^ ]*]] = load i32*, i32** %[[tmp]]
140// CHECK-NEXT: store i32* %[[v]], i32** %r
141
142// Bind the reference to a byval argument. It is not an instruction or Constant,
143// so it's a bit of a corner case.
144struct ByVal { int x[3]; };
145extern "C" int cleanup_exit_lvalue_byval(bool cond, ByVal arg) {
146  ByVal &r = (A(1), ({ if (cond) return 0; (void)ByVal(); }), arg);
147  return r.x[0];
148}
149// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_byval({{.*}}, %struct.ByVal* byval align 4 %arg)
150// CHECK: call {{.*}} @_ZN1AC1Ei
151// CHECK: call {{.*}} @_ZN1AD1Ev
152// CHECK: switch
153// CHECK: store %struct.ByVal* %arg, %struct.ByVal** %r
154
155// Bind the reference to a local variable. We don't need to spill it. Binding a
156// reference to it doesn't generate any instructions.
157extern "C" int cleanup_exit_lvalue_local(bool cond) {
158  int local = 42;
159  int &r = (A(1), ({ if (cond) return 0; (void)0; }), local);
160  return r;
161}
162// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue_local({{.*}})
163// CHECK: %local = alloca i32
164// CHECK: store i32 42, i32* %local
165// CHECK: call {{.*}} @_ZN1AC1Ei
166// CHECK-NOT: store i32* %local
167// CHECK: call {{.*}} @_ZN1AD1Ev
168// CHECK: switch
169// CHECK: store i32* %local, i32** %r, align 4
170
171// We handle ExprWithCleanups for complex evaluation type separately, and it had
172// the same bug.
173_Complex float bar_complex(A, int);
174extern "C" int cleanup_exit_complex(bool b) {
175  _Complex float v = bar_complex(A(1), ({ if (b) return 42; 13; }));
176  return (float)v;
177}
178
179// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_complex({{.*}})
180// CHECK: call {{.*}} @_ZN1AC1Ei
181//    Spill after bar.
182// CHECK: call {{.*}} @_Z11bar_complex1Ai({{.*}})
183// CHECK: store float %{{.*}}, float* %[[tmp1:[^, ]*]]
184// CHECK: store float %{{.*}}, float* %[[tmp2:[^, ]*]]
185//    Do cleanup.
186// CHECK: call {{.*}} @_ZN1AD1Ev
187// CHECK: switch
188//    Reload before v assignment.
189// CHECK: %[[v1:[^ ]*]] = load float, float* %[[tmp1]]
190// CHECK: %[[v2:[^ ]*]] = load float, float* %[[tmp2]]
191// CHECK: store float %[[v1]], float* %v.realp
192// CHECK: store float %[[v2]], float* %v.imagp
193
194extern "C" void then(int);
195
196// CHECK-LABEL: @{{.*}}volatile_load
197void volatile_load() {
198  volatile int n;
199
200  // CHECK-NOT: load volatile
201  // CHECK: load volatile
202  // CHECK-NOT: load volatile
203  ({n;});
204
205  // CHECK-LABEL: @then(i32 1)
206  then(1);
207
208  // CHECK-NOT: load volatile
209  // CHECK: load volatile
210  // CHECK-NOT: load volatile
211  ({goto lab; lab: n;});
212
213  // CHECK-LABEL: @then(i32 2)
214  then(2);
215
216  // CHECK-NOT: load volatile
217  // CHECK: load volatile
218  // CHECK-NOT: load volatile
219  ({[[gsl::suppress("foo")]] n;});
220
221  // CHECK-LABEL: @then(i32 3)
222  then(3);
223
224  // CHECK-NOT: load volatile
225  // CHECK: load volatile
226  // CHECK-NOT: load volatile
227  ({if (true) n;});
228
229  // CHECK: }
230}
231
232// CHECK-LABEL: @{{.*}}volatile_load_template
233template<typename T>
234void volatile_load_template() {
235  volatile T n;
236
237  // CHECK-NOT: load volatile
238  // CHECK: load volatile
239  // CHECK-NOT: load volatile
240  ({n;});
241
242  // CHECK-LABEL: @then(i32 1)
243  then(1);
244
245  // CHECK-NOT: load volatile
246  // CHECK: load volatile
247  // CHECK-NOT: load volatile
248  ({goto lab; lab: n;});
249
250  // CHECK-LABEL: @then(i32 2)
251  then(2);
252
253  // CHECK-NOT: load volatile
254  // CHECK: load volatile
255  // CHECK-NOT: load volatile
256  ({[[gsl::suppress("foo")]] n;});
257
258  // CHECK-LABEL: @then(i32 3)
259  then(3);
260
261  // CHECK-NOT: load volatile
262  // CHECK: load volatile
263  // CHECK-NOT: load volatile
264  ({if (true) n;});
265
266  // CHECK: }
267}
268template void volatile_load_template<int>();
269