eh.cpp revision c5f657fe308f22243f674fc1dfbe24915944d8bf
1// RUN: %clang_cc1 -fexceptions -triple x86_64-apple-darwin -std=c++0x -emit-llvm %s -o %t.ll 2// RUN: FileCheck --input-file=%t.ll %s 3 4struct test1_D { 5 double d; 6} d1; 7 8void test1() { 9 throw d1; 10} 11 12// CHECK: define void @_Z5test1v() 13// CHECK: [[FREEVAR:%.*]] = alloca i1 14// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* 15// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] 16// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) 17// CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] 18// CHECK-NEXT: store i1 true, i1* [[FREEVAR]] 19// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]] 20// CHECK-NEXT: [[EXN2:%.*]] = bitcast [[DSTAR]] [[EXN]] to i8* 21// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[EXN2]], i8* bitcast ([[DSTAR]] @d1 to i8*), i64 8, i32 8, i1 false) 22// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] 23// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%0* @_ZTI7test1_D to i8*), i8* null) noreturn 24// CHECK-NEXT: unreachable 25 26 27struct test2_D { 28 test2_D(const test2_D&o); 29 test2_D(); 30 virtual void bar() { } 31 int i; int j; 32} d2; 33 34void test2() { 35 throw d2; 36} 37 38// CHECK: define void @_Z5test2v() 39// CHECK: [[FREEVAR:%.*]] = alloca i1 40// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* 41// CHECK-NEXT: [[EXNSLOTVAR:%.*]] = alloca i8* 42// CHECK-NEXT: [[CLEANUPDESTVAR:%.*]] = alloca i32 43// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] 44// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16) 45// CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] 46// CHECK-NEXT: store i1 true, i1* [[FREEVAR]] 47// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSTAR:%[^*]*\*]] 48// CHECK-NEXT: invoke void @_ZN7test2_DC1ERKS_([[DSTAR]] [[EXN]], [[DSTAR]] @d2) 49// CHECK-NEXT: to label %[[CONT:.*]] unwind label %{{.*}} 50// : [[CONT]]: (can't check this in Release-Asserts builds) 51// CHECK: store i1 false, i1* [[FREEVAR]] 52// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%{{.*}}* @_ZTI7test2_D to i8*), i8* null) noreturn 53// CHECK-NEXT: unreachable 54 55 56struct test3_D { 57 test3_D() { } 58 test3_D(volatile test3_D&o); 59 virtual void bar(); 60}; 61 62void test3() { 63 throw (volatile test3_D *)0; 64} 65 66// CHECK: define void @_Z5test3v() 67// CHECK: [[FREEVAR:%.*]] = alloca i1 68// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8* 69// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] 70// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 8) 71// CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]] 72// CHECK-NEXT: store i1 true, i1* [[FREEVAR]] 73// CHECK-NEXT: [[EXN:%.*]] = bitcast i8* [[EXNOBJ]] to [[DSS:%[^*]*\*]]* 74// CHECK-NEXT: store [[DSS]] null, [[DSS]]* [[EXN]] 75// CHECK-NEXT: store i1 false, i1* [[FREEVAR]] 76// CHECK-NEXT: call void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast (%1* @_ZTIPV7test3_D to i8*), i8* null) noreturn 77// CHECK-NEXT: unreachable 78 79 80void test4() { 81 throw; 82} 83 84// CHECK: define void @_Z5test4v() 85// CHECK: call void @__cxa_rethrow() noreturn 86// CHECK-NEXT: unreachable 87 88 89// rdar://problem/7696549 90namespace test5 { 91 struct A { 92 A(); 93 A(const A&); 94 ~A(); 95 }; 96 97 void test() { 98 try { throw A(); } catch (A &x) {} 99 } 100// CHECK: define void @_ZN5test54testEv() 101// CHECK: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 1) 102// CHECK: [[EXNCAST:%.*]] = bitcast i8* [[EXNOBJ]] to [[A:%[^*]*]]* 103// CHECK-NEXT: invoke void @_ZN5test51AC1Ev([[A]]* [[EXNCAST]]) 104// CHECK: invoke void @__cxa_throw(i8* [[EXNOBJ]], i8* bitcast ({{%.*}}* @_ZTIN5test51AE to i8*), i8* bitcast (void ([[A]]*)* @_ZN5test51AD1Ev to i8*)) noreturn 105// CHECK-NEXT: to label {{%.*}} unwind label %[[HANDLER:[^ ]*]] 106// : [[HANDLER]]: (can't check this in Release-Asserts builds) 107// CHECK: {{%.*}} = call i32 @llvm.eh.typeid.for(i8* bitcast ({{%.*}}* @_ZTIN5test51AE to i8*)) 108} 109 110namespace test6 { 111 template <class T> struct allocator { 112 ~allocator() throw() { } 113 }; 114 115 void foo() { 116 allocator<int> a; 117 } 118} 119 120// PR7127 121namespace test7 { 122// CHECK: define i32 @_ZN5test73fooEv() 123 int foo() { 124// CHECK: [[FREEEXNOBJ:%.*]] = alloca i1 125// CHECK-NEXT: [[EXNALLOCVAR:%.*]] = alloca i8* 126// CHECK-NEXT: [[CAUGHTEXNVAR:%.*]] = alloca i8* 127// CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32 128// CHECK-NEXT: [[EHCLEANUPDESTVAR:%.*]] = alloca i32 129// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] 130 try { 131 try { 132// CHECK-NEXT: [[EXNALLOC:%.*]] = call i8* @__cxa_allocate_exception 133// CHECK-NEXT: store i8* [[EXNALLOC]], i8** [[EXNALLOCVAR]] 134// CHECK-NEXT: store i1 true, i1* [[FREEEXNOBJ]] 135// CHECK-NEXT: bitcast i8* [[EXNALLOC]] to i32* 136// CHECK-NEXT: store i32 1, i32* 137// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]] 138// CHECK-NEXT: invoke void @__cxa_throw(i8* [[EXNALLOC]], i8* bitcast (i8** @_ZTIi to i8*), i8* null 139 throw 1; 140 } 141 142// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() 143// CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] 144// CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null) 145// CHECK-NEXT: call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) 146// CHECK-NEXT: icmp eq 147// CHECK-NEXT: br i1 148// CHECK: load i8** [[CAUGHTEXNVAR]] 149// CHECK-NEXT: call i8* @__cxa_begin_catch 150// CHECK: invoke void @__cxa_rethrow 151 catch (int) { 152 throw; 153 } 154 } 155// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception() 156// CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]] 157// CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null) 158// CHECK-NEXT: store i32 1, i32* [[EHCLEANUPDESTVAR]] 159// CHECK-NEXT: call void @__cxa_end_catch() 160// CHECK-NEXT: br label 161// CHECK: load i8** [[CAUGHTEXNVAR]] 162// CHECK-NEXT: call i8* @__cxa_begin_catch 163// CHECK-NEXT: call void @__cxa_end_catch 164 catch (...) { 165 } 166// CHECK: ret i32 0 167 return 0; 168 } 169} 170 171// Ordering of destructors in a catch handler. 172namespace test8 { 173 struct A { A(const A&); ~A(); }; 174 void bar(); 175 176 // CHECK: define void @_ZN5test83fooEv() 177 void foo() { 178 try { 179 // CHECK: invoke void @_ZN5test83barEv() 180 bar(); 181 } catch (A a) { 182 // CHECK: call i8* @__cxa_get_exception_ptr 183 // CHECK-NEXT: bitcast 184 // CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_( 185 // CHECK: call i8* @__cxa_begin_catch 186 // CHECK-NEXT: invoke void @_ZN5test81AD1Ev( 187 // CHECK: call void @__cxa_end_catch() 188 // CHECK: ret void 189 } 190 } 191} 192 193// Constructor function-try-block must rethrow on fallthrough. 194// rdar://problem/7696603 195namespace test9 { 196 void opaque(); 197 198 struct A { A(); }; 199 200 // CHECK: define unnamed_addr void @_ZN5test91AC1Ev 201 // CHECK: call void @_ZN5test91AC2Ev 202 // CHECK-NEXT: ret void 203 204 // CHECK: define unnamed_addr void @_ZN5test91AC2Ev( 205 A::A() try { 206 // CHECK: invoke void @_ZN5test96opaqueEv() 207 opaque(); 208 } catch (int x) { 209 // CHECK: call i8* @__cxa_begin_catch 210 // CHECK: invoke void @_ZN5test96opaqueEv() 211 // CHECK: invoke void @__cxa_rethrow() 212 opaque(); 213 } 214 215 // landing pad from first call to invoke 216 // CHECK: call i8* @llvm.eh.exception 217 // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null) 218} 219 220// __cxa_end_catch can throw for some kinds of caught exceptions. 221namespace test10 { 222 void opaque(); 223 224 struct A { ~A(); }; 225 struct B { int x; }; 226 227 // CHECK: define void @_ZN6test103fooEv() 228 void foo() { 229 A a; // force a cleanup context 230 231 try { 232 // CHECK: invoke void @_ZN6test106opaqueEv() 233 opaque(); 234 } catch (int i) { 235 // CHECK: call i8* @__cxa_begin_catch 236 // CHECK-NEXT: bitcast 237 // CHECK-NEXT: load i32* 238 // CHECK-NEXT: store i32 239 // CHECK-NEXT: call void @__cxa_end_catch() nounwind 240 } catch (B a) { 241 // CHECK: call i8* @__cxa_begin_catch 242 // CHECK-NEXT: bitcast 243 // CHECK-NEXT: bitcast 244 // CHECK-NEXT: bitcast 245 // CHECK-NEXT: call void @llvm.memcpy 246 // CHECK-NEXT: invoke void @__cxa_end_catch() 247 } catch (...) { 248 // CHECK: call i8* @__cxa_begin_catch 249 // CHECK-NEXT: invoke void @__cxa_end_catch() 250 } 251 252 // CHECK: call void @_ZN6test101AD1Ev( 253 } 254} 255 256// __cxa_begin_catch returns pointers by value, even when catching by reference 257// <rdar://problem/8212123> 258namespace test11 { 259 void opaque(); 260 261 // CHECK: define void @_ZN6test113fooEv() 262 void foo() { 263 try { 264 // CHECK: invoke void @_ZN6test116opaqueEv() 265 opaque(); 266 } catch (int**&p) { 267 // CHECK: [[EXN:%.*]] = load i8** 268 // CHECK-NEXT: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind 269 // CHECK-NEXT: [[ADJ1:%.*]] = getelementptr i8* [[EXN]], i32 32 270 // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to i32*** 271 // CHECK-NEXT: store i32*** [[ADJ2]], i32**** [[P:%.*]] 272 // CHECK-NEXT: call void @__cxa_end_catch() nounwind 273 } 274 } 275 276 struct A {}; 277 278 // CHECK: define void @_ZN6test113barEv() 279 void bar() { 280 try { 281 // CHECK: [[EXNSLOT:%.*]] = alloca i8* 282 // CHECK-NEXT: [[P:%.*]] = alloca [[A:%.*]]**, 283 // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]]* 284 // CHECK-NEXT: invoke void @_ZN6test116opaqueEv() 285 opaque(); 286 } catch (A*&p) { 287 // CHECK: [[EXN:%.*]] = load i8** [[EXNSLOT]] 288 // CHECK-NEXT: [[ADJ1:%.*]] = call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind 289 // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to [[A]]* 290 // CHECK-NEXT: store [[A]]* [[ADJ2]], [[A]]** [[TMP]] 291 // CHECK-NEXT: store [[A]]** [[TMP]], [[A]]*** [[P]] 292 // CHECK-NEXT: call void @__cxa_end_catch() nounwind 293 } 294 } 295} 296 297// PR7686 298namespace test12 { 299 struct A { ~A(); }; 300 bool opaque(const A&); 301 302 // CHECK: define void @_ZN6test124testEv() 303 void test() { 304 // CHECK: [[X:%.*]] = alloca [[A:%.*]], 305 // CHECK: [[EHCLEANUPDEST:%.*]] = alloca i32 306 // CHECK: [[Y:%.*]] = alloca [[A]] 307 // CHECK: [[Z:%.*]] = alloca [[A]] 308 // CHECK: [[CLEANUPDEST:%.*]] = alloca i32 309 310 A x; 311 // CHECK: invoke zeroext i1 @_ZN6test126opaqueERKNS_1AE( 312 if (opaque(x)) { 313 A y; 314 A z; 315 316 // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Z]]) 317 // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Y]]) 318 319 // It'd be great if something eliminated this switch. 320 // CHECK: load i32* [[CLEANUPDEST]] 321 // CHECK-NEXT: switch i32 322 goto success; 323 } 324 325 success: 326 bool _ = true; 327 328 // CHECK: call void @_ZN6test121AD1Ev([[A]]* [[X]]) 329 // CHECK-NEXT: ret void 330 } 331} 332 333// Reduced from some TableGen code that was causing a self-host crash. 334namespace test13 { 335 struct A { ~A(); }; 336 337 void test0(int x) { 338 try { 339 switch (x) { 340 case 0: 341 break; 342 case 1:{ 343 A a; 344 break; 345 } 346 default: 347 return; 348 } 349 return; 350 } catch (int x) { 351 } 352 return; 353 } 354 355 void test1(int x) { 356 A y; 357 try { 358 switch (x) { 359 default: break; 360 } 361 } catch (int x) {} 362 } 363} 364 365// rdar://problem/8231514 366namespace test14 { 367 struct A { ~A(); }; 368 struct B { ~B(); }; 369 370 B b(); 371 void opaque(); 372 373 void foo() { 374 A a; 375 try { 376 B str = b(); 377 opaque(); 378 } catch (int x) { 379 } 380 } 381} 382 383// rdar://problem/8231514 384// JumpDests shouldn't get confused by scopes that aren't normal cleanups. 385namespace test15 { 386 struct A { ~A(); }; 387 388 bool opaque(int); 389 390 // CHECK: define void @_ZN6test153fooEv() 391 void foo() { 392 A a; 393 394 try { 395 // CHECK: [[X:%.*]] = alloca i32 396 // CHECK: store i32 10, i32* [[X]] 397 // CHECK-NEXT: br label 398 // -> while.cond 399 int x = 10; 400 401 while (true) { 402 // CHECK: load i32* [[X]] 403 // CHECK-NEXT: [[COND:%.*]] = invoke zeroext i1 @_ZN6test156opaqueEi 404 // CHECK: br i1 [[COND]] 405 if (opaque(x)) 406 // CHECK: br label 407 break; 408 409 // CHECK: br label 410 } 411 // CHECK: br label 412 } catch (int x) { } 413 414 // CHECK: call void @_ZN6test151AD1Ev 415 } 416} 417