[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / test / CodeGenCXX / stmtexpr.cpp
blob6e19ce864813f64ea3d96b3d589a3b01f93b429c
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();
5 struct A
7 int i;
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); }
14 struct B
16 int 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); }
23 A foo(int j)
25 return ({ j ? A(1) : A(0); });
29 void foo2()
31 A b = ({ A a(1); A a1(2); A a2(3); a1; a2; a; });
32 if (b.i != 1)
33 abort();
34 A c = ({ A a(1); A a1(2); A a2(3); a1; a2; a; A a3(4); a2; a3; });
35 if (c.i != 4)
36 abort();
39 void foo3()
41 const A &b = ({ A a(1); a; });
42 if (b.i != 1)
43 abort();
46 void foo4()
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; });
54 if (b.i != 1)
55 abort();
58 int main()
60 foo2();
61 foo3();
62 foo4();
63 return foo(1).i-1;
66 int a[128];
67 int* foo5() {
68 // CHECK-NOT: memcpy
69 // Check that array-to-pointer conversion occurs in a
70 // statement-expression.
71 return (({ a; }));
74 // Make sure this doesn't crash.
75 int foo5(bool b) {
76 int y = 0;
77 y = ({ A a(1); if (b) goto G; a.i; });
78 G: return y;
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.
91 int bar(A, int);
92 extern "C" int cleanup_exit_scalar(bool b) {
93 int v = bar(A(1), ({ if (b) return 42; 13; }));
94 return v;
97 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_scalar({{.*}})
98 // CHECK: call {{.*}} @_ZN1AC1Ei
99 // Spill after bar.
100 // CHECK: %[[v:[^ ]*]] = call{{.*}} i32 @_Z3bar1Ai({{.*}})
101 // CHECK-NEXT: store i32 %[[v]], ptr %[[tmp:[^, ]*]]
102 // Do cleanup.
103 // CHECK: call {{.*}} @_ZN1AD1Ev
104 // CHECK: switch
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);
113 return v;
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
121 // lvalues?
122 int &getref();
123 extern "C" int cleanup_exit_lvalue(bool cond) {
124 int &r = (A(1), ({ if (cond) return 0; (void)0; }), getref());
125 return r;
127 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_lvalue({{.*}})
128 // CHECK: call {{.*}} @_ZN1AC1Ei
129 // Spill after bar.
130 // CHECK: %[[v:[^ ]*]] = call noundef nonnull align 4 dereferenceable(4) ptr @_Z6getrefv({{.*}})
131 // CHECK-NEXT: store ptr %[[v]], ptr %[[tmp:[^, ]*]]
132 // Do cleanup.
133 // CHECK: call {{.*}} @_ZN1AD1Ev
134 // CHECK: switch
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);
144 return r.x[0];
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
149 // CHECK: switch
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) {
155 int local = 42;
156 int &r = (A(1), ({ if (cond) return 0; (void)0; }), local);
157 return r;
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
165 // CHECK: switch
166 // CHECK: store ptr %local, ptr %r, align 4
168 // We handle ExprWithCleanups for complex evaluation type separately, and it had
169 // the same bug.
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; }));
173 return (float)v;
176 // CHECK-LABEL: define{{.*}} i32 @cleanup_exit_complex({{.*}})
177 // CHECK: call {{.*}} @_ZN1AC1Ei
178 // Spill after bar.
179 // CHECK: call {{.*}} @_Z11bar_complex1Ai({{.*}})
180 // CHECK: store float %{{.*}}, ptr %[[tmp1:[^, ]*]]
181 // CHECK: store float %{{.*}}, ptr %[[tmp2:[^, ]*]]
182 // Do cleanup.
183 // CHECK: call {{.*}} @_ZN1AD1Ev
184 // CHECK: switch
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() {
195 volatile int n;
197 // CHECK-NOT: load volatile
198 // CHECK: load volatile
199 // CHECK-NOT: load volatile
200 ({n;});
202 // CHECK-LABEL: @then(i32 noundef 1)
203 then(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)
211 then(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)
219 then(3);
221 // CHECK-NOT: load volatile
222 // CHECK: load volatile
223 // CHECK-NOT: load volatile
224 ({if (true) n;});
226 // CHECK: }
229 // CHECK-LABEL: @{{.*}}volatile_load_template
230 template<typename T>
231 void volatile_load_template() {
232 volatile T n;
234 // CHECK-NOT: load volatile
235 // CHECK: load volatile
236 // CHECK-NOT: load volatile
237 ({n;});
239 // CHECK-LABEL: @then(i32 noundef 1)
240 then(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)
248 then(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)
256 then(3);
258 // CHECK-NOT: load volatile
259 // CHECK: load volatile
260 // CHECK-NOT: load volatile
261 ({if (true) n;});
263 // CHECK: }
265 template void volatile_load_template<int>();