1 // RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O0 %s 2 // RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -emit-llvm -O3 -disable-llvm-passes %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fcxx-exceptions -fno-rtti | FileCheck -check-prefix WIN32 -check-prefix WIN32-O3 -check-prefix WIN32-LIFETIME %s 3 4 struct A { 5 A(); 6 ~A(); 7 int a; 8 }; 9 10 A getA(); 11 12 int TakesTwo(A a, A b); 13 void HasEHCleanup() { 14 TakesTwo(getA(), getA()); 15 } 16 17 // With exceptions, we need to clean up at least one of these temporaries. 18 // WIN32-LABEL: define dso_local void @"?HasEHCleanup@@YAXXZ"() {{.*}} { 19 // WIN32: %[[base:.*]] = call i8* @llvm.stacksave() 20 // If this call throws, we have to restore the stack. 21 // WIN32: call void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}}) 22 // If this call throws, we have to cleanup the first temporary. 23 // WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}}) 24 // If this call throws, we have to cleanup the stacksave. 25 // WIN32: call noundef i32 @"?TakesTwo@@YAHUA@@0@Z" 26 // WIN32: call void @llvm.stackrestore 27 // WIN32: ret void 28 // 29 // There should be one dtor call for unwinding from the second getA. 30 // WIN32: cleanuppad 31 // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 32 // WIN32-NOT: @"??1A@@QAE@XZ" 33 // WIN32: } 34 35 36 // This test verifies the fix for a crash that occurred after 37 // fa87fa97fb79. 38 void HasEHCleanupNoexcept() noexcept { 39 TakesTwo(getA(), getA()); 40 } 41 42 // With exceptions, we need to clean up at least one of these temporaries. 43 // WIN32-LABEL: define dso_local void @"?HasEHCleanupNoexcept@@YAXXZ"() {{.*}} { 44 // WIN32: %[[base:.*]] = call i8* @llvm.stacksave() 45 // WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}}) 46 // WIN32: invoke void @"?getA@@YA?AUA@@XZ"(%struct.A* sret(%struct.A) align 4 %{{.*}}) 47 // WIN32: invoke noundef i32 @"?TakesTwo@@YAHUA@@0@Z" 48 // WIN32: call void @llvm.stackrestore 49 // WIN32: ret void 50 // 51 // Since all the calls terminate, there should be no dtors on the unwind 52 // WIN32: cleanuppad 53 // WIN32-NOT: @"??1A@@QAE@XZ" 54 // WIN32: } 55 56 57 void TakeRef(const A &a); 58 int HasDeactivatedCleanups() { 59 return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())); 60 } 61 62 // WIN32-LABEL: define dso_local noundef i32 @"?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { 63 // WIN32: %[[isactive:.*]] = alloca i1 64 // WIN32: call i8* @llvm.stacksave() 65 // WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]] 66 // WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 1 67 // WIN32: call x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 68 // WIN32: invoke void @"?TakeRef@@YAXABUA@@@Z" 69 // 70 // WIN32: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ"(%struct.A* {{[^,]*}} %[[arg1]]) 71 // WIN32: store i1 true, i1* %[[isactive]] 72 // 73 // WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0 74 // WIN32: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 75 // WIN32: invoke void @"?TakeRef@@YAXABUA@@@Z" 76 // WIN32: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 77 // WIN32: store i1 false, i1* %[[isactive]] 78 // 79 // WIN32: invoke noundef i32 @"?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]]) 80 // Destroy the two const ref temporaries. 81 // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 82 // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 83 // WIN32: ret i32 84 // 85 // Conditionally destroy arg1. 86 // WIN32: %[[cond:.*]] = load i1, i1* %[[isactive]] 87 // WIN32: br i1 %[[cond]] 88 // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"(%struct.A* {{[^,]*}} %[[arg1]]) 89 // WIN32: } 90 91 // Test putting the cleanups inside a conditional. 92 int CouldThrow(); 93 int HasConditionalCleanup(bool cond) { 94 return (cond ? TakesTwo(A(), A()) : CouldThrow()); 95 } 96 97 // WIN32-LABEL: define dso_local noundef i32 @"?HasConditionalCleanup@@YAH_N@Z"(i1 noundef zeroext %{{.*}}) {{.*}} { 98 // WIN32: store i1 false 99 // WIN32: br i1 100 // WIN32: call i8* @llvm.stacksave() 101 // WIN32: call x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ"(%struct.A* {{[^,]*}} %{{.*}}) 102 // WIN32: store i1 true 103 // WIN32: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ"(%struct.A* {{[^,]*}} %{{.*}}) 104 // WIN32: call noundef i32 @"?TakesTwo@@YAHUA@@0@Z" 105 // 106 // WIN32: call void @llvm.stackrestore 107 // 108 // WIN32: call noundef i32 @"?CouldThrow@@YAHXZ"() 109 // 110 // Only one dtor in the invoke for arg1 111 // WIN32: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 112 // WIN32-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ" 113 // WIN32: } 114 115 // Now test both. 116 int HasConditionalDeactivatedCleanups(bool cond) { 117 return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); 118 } 119 120 // WIN32-O0-LABEL: define dso_local noundef i32 @"?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { 121 // WIN32-O0: alloca i1 122 // WIN32-O0: %[[arg1_cond:.*]] = alloca i1 123 // Start all four cleanups as deactivated. 124 // WIN32-O0: store i1 false 125 // WIN32-O0: store i1 false 126 // WIN32-O0: store i1 false 127 // WIN32-O0: store i1 false 128 // WIN32-O0: br i1 129 // True condition. 130 // WIN32-O0: call x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 131 // WIN32-O0: store i1 true 132 // WIN32-O0: invoke void @"?TakeRef@@YAXABUA@@@Z" 133 // WIN32-O0: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 134 // WIN32-O0: store i1 true, i1* %[[arg1_cond]] 135 // WIN32-O0: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 136 // WIN32-O0: store i1 true 137 // WIN32-O0: invoke void @"?TakeRef@@YAXABUA@@@Z" 138 // WIN32-O0: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 139 // WIN32-O0: store i1 true 140 // WIN32-O0: store i1 false, i1* %[[arg1_cond]] 141 // WIN32-O0: invoke noundef i32 @"?TakesTwo@@YAHUA@@0@Z" 142 // False condition. 143 // WIN32-O0: invoke noundef i32 @"?CouldThrow@@YAHXZ"() 144 // Two normal cleanups for TakeRef args. 145 // WIN32-O0: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 146 // WIN32-O0-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ" 147 // WIN32-O0: ret i32 148 // 149 // Somewhere in the landing pad soup, we conditionally destroy arg1. 150 // WIN32-O0: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] 151 // WIN32-O0: br i1 %[[isactive]] 152 // WIN32-O0: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 153 // WIN32-O0: } 154 155 // WIN32-O3-LABEL: define dso_local noundef i32 @"?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { 156 // WIN32-O3: alloca i1 157 // WIN32-O3: alloca i1 158 // WIN32-O3: %[[arg1_cond:.*]] = alloca i1 159 // Start all four cleanups as deactivated. 160 // WIN32-O3: store i1 false 161 // WIN32-O3: store i1 false 162 // WIN32-O3: store i1 false 163 // WIN32-O3: store i1 false 164 // WIN32-O3: store i1 false 165 // WIN32-O3: store i1 false 166 // WIN32-O3: br i1 167 // True condition. 168 // WIN32-O3: call x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 169 // WIN32-O3: store i1 true 170 // WIN32-O3: invoke void @"?TakeRef@@YAXABUA@@@Z" 171 // WIN32-O3: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 172 // WIN32-O3: store i1 true, i1* %[[arg1_cond]] 173 // WIN32-O3: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 174 // WIN32-O3: store i1 true 175 // WIN32-O3: invoke void @"?TakeRef@@YAXABUA@@@Z" 176 // WIN32-O3: invoke x86_thiscallcc noundef %struct.A* @"??0A@@QAE@XZ" 177 // WIN32-O3: store i1 true 178 // WIN32-O3: store i1 false, i1* %[[arg1_cond]] 179 // WIN32-O3: invoke noundef i32 @"?TakesTwo@@YAHUA@@0@Z" 180 // False condition. 181 // WIN32-O3: invoke noundef i32 @"?CouldThrow@@YAHXZ"() 182 // Two normal cleanups for TakeRef args. 183 // WIN32-O3: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 184 // WIN32-O3-NOT: invoke x86_thiscallcc void @"??1A@@QAE@XZ" 185 // WIN32-O3: ret i32 186 // 187 // Somewhere in the landing pad soup, we conditionally destroy arg1. 188 // WIN32-O3: %[[isactive:.*]] = load i1, i1* %[[arg1_cond]] 189 // WIN32-O3: br i1 %[[isactive]] 190 // WIN32-O3: call x86_thiscallcc void @"??1A@@QAE@XZ"({{.*}}) 191 // WIN32-O3: } 192 193 namespace crash_on_partial_destroy { 194 struct A { 195 virtual ~A(); 196 }; 197 198 struct B : virtual A { 199 // Has an implicit destructor. 200 }; 201 202 struct C : B { 203 C(); 204 }; 205 206 void foo(); 207 // We used to crash when emitting this. 208 C::C() { foo(); } 209 210 // Verify that we don't bother with a vbtable lookup when adjusting the this 211 // pointer to call a base destructor from a constructor while unwinding. 212 // WIN32-LABEL: define dso_local {{.*}} @"??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} { 213 // WIN32: cleanuppad 214 // 215 // We shouldn't do any vbptr loads, just constant GEPs. 216 // WIN32-NOT: load 217 // WIN32: getelementptr i8, i8* %{{.*}}, i32 4 218 // WIN32-NOT: load 219 // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"* 220 // WIN32: call x86_thiscallcc void @"??1B@crash_on_partial_destroy@@UAE@XZ" 221 // 222 // WIN32-NOT: load 223 // WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8* 224 // WIN32-NOT: load 225 // WIN32: getelementptr inbounds i8, i8* %{{.*}}, i32 4 226 // WIN32-NOT: load 227 // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* 228 // WIN32: call x86_thiscallcc void @"??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) 229 // WIN32: } 230 } 231 232 namespace dont_call_terminate { 233 struct C { 234 ~C(); 235 }; 236 void g(); 237 void f() { 238 C c; 239 g(); 240 } 241 242 // WIN32-LABEL: define dso_local void @"?f@dont_call_terminate@@YAXXZ"() 243 // WIN32: invoke void @"?g@dont_call_terminate@@YAXXZ"() 244 // WIN32-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] 245 // 246 // WIN32: [[cont]] 247 // WIN32: call x86_thiscallcc void @"??1C@dont_call_terminate@@QAE@XZ"({{.*}}) 248 // 249 // WIN32: [[lpad]] 250 // WIN32-NEXT: cleanuppad 251 // WIN32: call x86_thiscallcc void @"??1C@dont_call_terminate@@QAE@XZ"({{.*}}) 252 } 253 254 namespace noexcept_false_dtor { 255 struct D { 256 ~D() noexcept(false); 257 }; 258 void f() { 259 D d; 260 CouldThrow(); 261 } 262 } 263 264 // WIN32-LABEL: define dso_local void @"?f@noexcept_false_dtor@@YAXXZ"() 265 // WIN32: invoke noundef i32 @"?CouldThrow@@YAHXZ"() 266 // WIN32: call x86_thiscallcc void @"??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* {{[^,]*}} %{{.*}}) 267 // WIN32: cleanuppad 268 // WIN32: call x86_thiscallcc void @"??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* {{[^,]*}} %{{.*}}) 269 // WIN32: cleanupret 270 271 namespace lifetime_marker { 272 struct C { 273 ~C(); 274 }; 275 void g(); 276 void f() { 277 C c; 278 g(); 279 } 280 281 // WIN32-LIFETIME-LABEL: define dso_local void @"?f@lifetime_marker@@YAXXZ"() 282 // WIN32-LIFETIME: %[[c:.*]] = alloca %"struct.lifetime_marker::C" 283 // WIN32-LIFETIME: %[[bc0:.*]] = bitcast %"struct.lifetime_marker::C"* %c to i8* 284 // WIN32-LIFETIME: call void @llvm.lifetime.start.p0i8(i64 1, i8* %[[bc0]]) 285 // WIN32-LIFETIME: invoke void @"?g@lifetime_marker@@YAXXZ"() 286 // WIN32-LIFETIME-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad0:[^ ]*]] 287 // 288 // WIN32-LIFETIME: [[cont]] 289 // WIN32-LIFETIME: call x86_thiscallcc void @"??1C@lifetime_marker@@QAE@XZ"({{.*}}) 290 // WIN32-LIFETIME: %[[bc1:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* 291 // WIN32-LIFETIME: call void @llvm.lifetime.end.p0i8(i64 1, i8* %[[bc1]]) 292 // 293 // WIN32-LIFETIME: [[lpad0]] 294 // WIN32-LIFETIME-NEXT: cleanuppad 295 // WIN32-LIFETIME: call x86_thiscallcc void @"??1C@lifetime_marker@@QAE@XZ"({{.*}}) 296 // WIN32-LIFETIME: cleanupret {{.*}} unwind label %[[lpad1:[^ ]*]] 297 // 298 // WIN32-LIFETIME: [[lpad1]] 299 // WIN32-LIFETIME-NEXT: cleanuppad 300 // WIN32-LIFETIME: %[[bc2:.*]] = bitcast %"struct.lifetime_marker::C"* %[[c]] to i8* 301 // WIN32-LIFETIME: call void @llvm.lifetime.end.p0i8(i64 1, i8* %[[bc2]]) 302 } 303 304 struct class_2 { 305 class_2(); 306 virtual ~class_2(); 307 }; 308 struct class_1 : virtual class_2 { 309 class_1(){throw "Unhandled exception";} 310 virtual ~class_1() {} 311 }; 312 struct class_0 : class_1 { 313 class_0() ; 314 virtual ~class_0() {} 315 }; 316 317 class_0::class_0() { 318 // WIN32: define dso_local x86_thiscallcc noundef %struct.class_0* @"??0class_0@@QAE@XZ"(%struct.class_0* {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived) 319 // WIN32: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4 320 // WIN32: %[[IS_MOST_DERIVED_VAL:.*]] = load i32, i32* %[[IS_MOST_DERIVED_VAR]] 321 // WIN32: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 322 // WIN32: br i1 %[[SHOULD_CALL_VBASE_CTORS]], label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]] 323 // WIN32: [[INIT_VBASES]] 324 // WIN32: br label %[[SKIP_VBASES]] 325 // WIN32: [[SKIP_VBASES]] 326 // ehcleanup: 327 // WIN32: %[[CLEANUPPAD:.*]] = cleanuppad within none [] 328 // WIN32-NEXT: bitcast %{{.*}}* %{{.*}} to i8* 329 // WIN32-NEXT: getelementptr inbounds i8, i8* %{{.*}}, i{{.*}} {{.}} 330 // WIN32-NEXT: bitcast i8* %{{.*}} to %{{.*}}* 331 // WIN32-NEXT: %[[SHOULD_CALL_VBASE_DTOR:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0 332 // WIN32-NEXT: br i1 %[[SHOULD_CALL_VBASE_DTOR]], label %[[DTOR_VBASE:.*]], label %[[SKIP_VBASE:.*]] 333 // WIN32: [[DTOR_VBASE]] 334 // WIN32-NEXT: call x86_thiscallcc void @"??1class_2@@UAE@XZ" 335 // WIN32: br label %[[SKIP_VBASE]] 336 // WIN32: [[SKIP_VBASE]] 337 } 338 339 namespace PR37146 { 340 // Check that IRGen doesn't emit calls to synthesized destructors for 341 // non-trival C structs. 342 343 // WIN32: define dso_local void @"?test@PR37146@@YAXXZ"() 344 // WIN32: call void @llvm.memset.p0i8.i32( 345 // WIN32: call i32 @"?getS@PR37146@@YA?AUS@1@XZ"( 346 // WIN32: call void @"?func@PR37146@@YAXUS@1@0@Z"( 347 // WIN32-NEXT: ret void 348 // WIN32-NEXT: {{^}$}} 349 350 struct S { 351 int f; 352 }; 353 354 void func(S, S); 355 S getS(); 356 357 void test() { 358 func(getS(), S()); 359 } 360 361 } 362