1 // RUN: %clang_cc1 -no-opaque-pointers -Wno-unused-value -triple i686-linux-gnu -emit-llvm -o - %s | FileCheck %s 2 // rdar: //8540501 3 extern "C" int printf(...); 4 extern "C" void abort(); 5 6 struct 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 15 struct 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 24 A foo(int j) 25 { 26 return ({ j ? A(1) : A(0); }); 27 } 28 29 30 void 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 40 void foo3() 41 { 42 const A &b = ({ A a(1); a; }); 43 if (b.i != 1) 44 abort(); 45 } 46 47 void 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 59 int main() 60 { 61 foo2(); 62 foo3(); 63 foo4(); 64 return foo(1).i-1; 65 } 66 67 // rdar: // 8600553 68 int a[128]; 69 int* 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. 78 int 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. 94 int bar(A, int); 95 extern "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. 114 extern "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? 125 int &getref(); 126 extern "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 noundef nonnull align 4 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. 144 struct ByVal { int x[3]; }; 145 extern "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* noundef byval(%struct.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. 157 extern "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); 174 extern "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 194 extern "C" void then(int); 195 196 // CHECK-LABEL: @{{.*}}volatile_load 197 void 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 noundef 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 noundef 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 noundef 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 233 template<typename T> 234 void 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 noundef 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 noundef 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 noundef 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 } 268 template void volatile_load_template<int>(); 269