626 lines · cpp
1// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++98 -o - -fcxx-exceptions -fexceptions | FileCheck -check-prefix=CHECK -check-prefix=CHECK98 %s2// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions | FileCheck --check-prefixes=CHECK,CHECK11,THROWEND11 %s3// RUN: %clang_cc1 -no-enable-noundef-analysis %s -triple=x86_64-linux-gnu -emit-llvm -std=c++11 -o - -fcxx-exceptions -fexceptions -fassume-nothrow-exception-dtor | FileCheck --check-prefixes=CHECK,CHECK11,NOTHROWEND11 %s4 5// CHECK: %[[STRUCT_TEST13_A:.*]] = type { i32, i32 }6 7typedef __typeof(sizeof(0)) size_t;8 9// Declare the reserved global placement new.10void *operator new(size_t, void*);11 12// This just shouldn't crash.13namespace test0 {14 struct allocator {15 allocator();16 allocator(const allocator&);17 ~allocator();18 };19 20 void f();21 void g(bool b, bool c) {22 if (b) {23 if (!c)24 throw allocator();25 26 return;27 }28 f();29 }30}31 32namespace test1 {33 struct A { A(int); A(int, int); ~A(); void *p; };34 35 A *a() {36 // CHECK: define{{( dso_local)?}} ptr @_ZN5test11aEv()37 // CHECK: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8)38 // CHECK-NEXT: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5)39 // CHECK: ret ptr [[NEW]]40 // CHECK: call void @_ZdlPv(ptr [[NEW]])41 return new A(5);42 }43 44 A *b() {45 // CHECK: define{{( dso_local)?}} ptr @_ZN5test11bEv()46 // CHECK: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8)47 // CHECK-NEXT: [[FOO:%.*]] = invoke i32 @_ZN5test13fooEv()48 // CHECK: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[FOO]])49 // CHECK: ret ptr [[NEW]]50 // CHECK: call void @_ZdlPv(ptr [[NEW]])51 extern int foo();52 return new A(foo());53 }54 55 struct B { B(); ~B(); operator int(); int x; };56 B makeB();57 58 A *c() {59 // CHECK: define{{( dso_local)?}} ptr @_ZN5test11cEv()60 // CHECK: [[ACTIVE:%.*]] = alloca i161 // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8)62 // CHECK-NEXT: store i1 true, ptr [[ACTIVE]]63 // CHECK-NEXT: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T0:%.*]])64 // CHECK: [[T1:%.*]] = getelementptr inbounds nuw [[B:%.*]], ptr [[T0]], i32 0, i32 065 // CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[T1]], align 466 // CHECK-NEXT: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T2]])67 // CHECK: store i1 false, ptr [[ACTIVE]]68 69 // CHECK98-NEXT: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])70 // CHECK11-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])71 72 // CHECK: ret ptr [[NEW]]73 // CHECK: [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]]74 // CHECK-NEXT: br i1 [[ISACTIVE]]75 // CHECK: call void @_ZdlPv(ptr [[NEW]])76 return new A(B().x);77 }78 79 // Terminate landing pads should call __cxa_begin_catch first.80 // CHECK98: define linkonce_odr hidden void @__clang_call_terminate(ptr %0) [[NI_NR_NUW:#[0-9]+]] comdat81 // CHECK98-NEXT: [[T0:%.*]] = call ptr @__cxa_begin_catch(ptr %0) [[NUW:#[0-9]+]]82 // CHECK98-NEXT: call void @_ZSt9terminatev() [[NR_NUW:#[0-9]+]]83 // CHECK98-NEXT: unreachable84 85 A *d() {86 // CHECK: define{{( dso_local)?}} ptr @_ZN5test11dEv()87 // CHECK: [[ACTIVE:%.*]] = alloca i188 // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8)89 // CHECK-NEXT: store i1 true, ptr [[ACTIVE]]90 // CHECK-NEXT: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T0:%.*]])91 // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]])92 // CHECK: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T1]])93 // CHECK: store i1 false, ptr [[ACTIVE]]94 95 // CHECK98-NEXT: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])96 // CHECK11-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])97 98 // CHECK: ret ptr [[NEW]]99 // CHECK: [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]]100 // CHECK-NEXT: br i1 [[ISACTIVE]]101 // CHECK: call void @_ZdlPv(ptr [[NEW]])102 return new A(B());103 }104 105 A *e() {106 // CHECK: define{{( dso_local)?}} ptr @_ZN5test11eEv()107 // CHECK: [[ACTIVE:%.*]] = alloca i1108 // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8)109 // CHECK-NEXT: store i1 true, ptr [[ACTIVE]]110 // CHECK-NEXT: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T0:%.*]])111 // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]])112 // CHECK: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T2:%.*]])113 // CHECK: [[T3:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T2]])114 // CHECK: invoke void @_ZN5test11AC1Eii(ptr {{[^,]*}} [[NEW]], i32 [[T1]], i32 [[T3]])115 // CHECK: store i1 false, ptr [[ACTIVE]]116 117 // CHECK98-NEXT: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]])118 // CHECK11-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]])119 120 // CHECK98: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])121 // CHECK11: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])122 123 // CHECK: ret ptr [[NEW]]124 // CHECK: [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]]125 // CHECK-NEXT: br i1 [[ISACTIVE]]126 // CHECK: call void @_ZdlPv(ptr [[NEW]])127 return new A(B(), B());128 }129 A *f() {130 return new A(makeB().x);131 }132 A *g() {133 return new A(makeB());134 }135 A *h() {136 return new A(makeB(), makeB());137 }138 139 A *i() {140 // CHECK: define{{( dso_local)?}} ptr @_ZN5test11iEv()141 // CHECK: [[X:%.*]] = alloca ptr, align 8142 // CHECK: [[ACTIVE:%.*]] = alloca i1143 // CHECK: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8)144 // CHECK-NEXT: store i1 true, ptr [[ACTIVE]]145 // CHECK-NEXT: invoke void @_ZN5test15makeBEv(ptr dead_on_unwind writable sret([[B:%.*]]) align 4 [[T0:%.*]])146 // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]])147 // CHECK: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T1]])148 // CHECK: store i1 false, ptr [[ACTIVE]]149 // CHECK-NEXT: store ptr [[NEW]], ptr [[X]], align 8150 // CHECK: invoke void @_ZN5test15makeBEv(ptr dead_on_unwind writable sret([[B:%.*]]) align 4 [[T2:%.*]])151 // CHECK: [[RET:%.*]] = load ptr, ptr [[X]], align 8152 153 // CHECK98: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]])154 // CHECK11: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]])155 156 // CHECK98: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])157 // CHECK11: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]])158 159 // CHECK: ret ptr [[RET]]160 // CHECK: [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]]161 // CHECK-NEXT: br i1 [[ISACTIVE]]162 // CHECK: call void @_ZdlPv(ptr [[NEW]])163 A *x;164 return (x = new A(makeB()), makeB(), x);165 }166}167 168namespace test2 {169 struct A {170 A(int); A(int, int); ~A();171 void *p;172 void *operator new(size_t);173 void operator delete(void*, size_t);174 };175 176 A *a() {177 // CHECK: define{{( dso_local)?}} ptr @_ZN5test21aEv()178 // CHECK: [[NEW:%.*]] = call ptr @_ZN5test21AnwEm(i64 8)179 // CHECK-NEXT: invoke void @_ZN5test21AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5)180 // CHECK: ret ptr [[NEW]]181 182 // CHECK98: invoke void @_ZN5test21AdlEPvm(ptr [[NEW]], i64 8)183 // CHECK11: call void @_ZN5test21AdlEPvm(ptr [[NEW]], i64 8)184 185 // CHECK98: call void @__clang_call_terminate(ptr {{%.*}}) [[NR_NUW]]186 return new A(5);187 }188}189 190namespace test3 {191 struct A {192 A(int); A(int, int); A(const A&); ~A();193 void *p;194 void *operator new(size_t, void*, double);195 void operator delete(void*, void*, double);196 };197 198 void *foo();199 double bar();200 A makeA(), *makeAPtr();201 202 A *a() {203 // CHECK: define{{( dso_local)?}} ptr @_ZN5test31aEv()204 // CHECK: [[FOO:%.*]] = call ptr @_ZN5test33fooEv()205 // CHECK: [[BAR:%.*]] = call double @_ZN5test33barEv()206 // CHECK: [[NEW:%.*]] = call ptr @_ZN5test31AnwEmPvd(i64 8, ptr [[FOO]], double [[BAR]])207 // CHECK-NEXT: invoke void @_ZN5test31AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5)208 // CHECK: ret ptr [[NEW]]209 210 // CHECK98: invoke void @_ZN5test31AdlEPvS1_d(ptr [[NEW]], ptr [[FOO]], double [[BAR]])211 // CHECK11: call void @_ZN5test31AdlEPvS1_d(ptr [[NEW]], ptr [[FOO]], double [[BAR]])212 213 // CHECK98: call void @__clang_call_terminate(ptr {{%.*}}) [[NR_NUW]]214 return new(foo(),bar()) A(5);215 }216 217 A *b(bool cond) {218 219 // CHECK: define{{( dso_local)?}} ptr @_ZN5test31bEb(i1 zeroext220 // CHECK: [[SAVED0:%.*]] = alloca ptr221 // CHECK-NEXT: [[SAVED1:%.*]] = alloca ptr222 // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1223 224 // CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1225 // CHECK-NEXT: store i1 false, ptr [[CLEANUPACTIVE]]226 // CHECK-NEXT: br i1 [[COND]]227 return (cond ?228 229 // CHECK: [[FOO:%.*]] = call ptr @_ZN5test33fooEv()230 // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test31AnwEmPvd(i64 8, ptr [[FOO]], double [[CONST:.*]])231 // CHECK-NEXT: store ptr [[NEW]], ptr [[SAVED0]]232 // CHECK-NEXT: store ptr [[FOO]], ptr [[SAVED1]]233 // CHECK-NEXT: store i1 true, ptr [[CLEANUPACTIVE]]234 // CHECK-NEXT: invoke void @_ZN5test35makeAEv(ptr dead_on_unwind writable sret([[A:%.*]]) align 8 [[NEW]])235 // CHECK: br label236 // -> cond.end237 new(foo(),10.0) A(makeA()) :238 239 // CHECK: [[MAKE:%.*]] = call ptr @_ZN5test38makeAPtrEv()240 // CHECK: br label241 // -> cond.end242 makeAPtr());243 244 // cond.end:245 // CHECK: [[RESULT:%.*]] = phi ptr {{.*}}[[NEW]]{{.*}}[[MAKE]]246 // CHECK: ret ptr [[RESULT]]247 248 // in the EH path:249 // CHECK: [[ISACTIVE:%.*]] = load i1, ptr [[CLEANUPACTIVE]]250 // CHECK-NEXT: br i1 [[ISACTIVE]]251 // CHECK: [[V0:%.*]] = load ptr, ptr [[SAVED0]]252 // CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[SAVED1]]253 254 // CHECK98-NEXT: invoke void @_ZN5test31AdlEPvS1_d(ptr [[V0]], ptr [[V1]], double [[CONST]])255 // CHECK11-NEXT: call void @_ZN5test31AdlEPvS1_d(ptr [[V0]], ptr [[V1]], double [[CONST]])256 }257}258 259namespace test4 {260 struct A {261 A(int); A(int, int); ~A();262 void *p;263 void *operator new(size_t, void*, void*);264 void operator delete(void*, size_t, void*, void*); // not a match265 };266 267 A *a() {268 // CHECK: define{{( dso_local)?}} ptr @_ZN5test41aEv()269 // CHECK: [[FOO:%.*]] = call ptr @_ZN5test43fooEv()270 // CHECK-NEXT: [[BAR:%.*]] = call ptr @_ZN5test43barEv()271 // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test41AnwEmPvS1_(i64 8, ptr [[FOO]], ptr [[BAR]])272 // CHECK-NEXT: call void @_ZN5test41AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5)273 // CHECK-NEXT: ret ptr [[NEW]]274 extern void *foo(), *bar();275 276 return new(foo(),bar()) A(5);277 }278}279 280// PR7908281namespace test5 {282 struct T { T(); ~T(); };283 284 struct A {285 A(const A &x, const T &t = T());286 ~A();287 };288 289 void foo();290 291 // CHECK-LABEL: define{{.*}} void @_ZN5test54testEv()292 // CHECK: [[EXNSLOT:%.*]] = alloca ptr293 // CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32294 // CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]], align 1295 // CHECK-NEXT: [[T:%.*]] = alloca [[T_T:%.*]], align 1296 // CHECK-NEXT: invoke void @_ZN5test53fooEv()297 // CHECK: [[EXN:%.*]] = load ptr, ptr [[EXNSLOT]]298 // CHECK-NEXT: [[ADJ:%.*]] = call ptr @__cxa_get_exception_ptr(ptr [[EXN]])299 // CHECK-NEXT: invoke void @_ZN5test51TC1Ev(ptr {{[^,]*}} [[T]])300 // CHECK: invoke void @_ZN5test51AC1ERKS0_RKNS_1TE(ptr {{[^,]*}} [[A:%.*]], ptr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[ADJ]], ptr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[T]])301 302 // CHECK98: invoke void @_ZN5test51TD1Ev(ptr {{[^,]*}} [[T]])303 // CHECK11: call void @_ZN5test51TD1Ev(ptr {{[^,]*}} [[T]])304 305 // CHECK98: call ptr @__cxa_begin_catch(ptr [[EXN]]) [[NUW]]306 // CHECK98-NEXT: invoke void @_ZN5test51AD1Ev(ptr {{[^,]*}} [[A:%.*]])307 308 // CHECK: call void @__cxa_end_catch()309 void test() {310 try {311 foo();312 } catch (A a) {313 }314 }315}316 317// PR9303: invalid assert on this318namespace test6 {319 bool cond();320 void test() {321 try {322 lbl:323 if (cond()) goto lbl;324 } catch (...) {325 }326 }327}328 329// PR9298330namespace test7 {331 struct A { A(); ~A(); };332 struct B {333 // The throw() operator means that a bad allocation is signalled334 // with a null return, which means that the initializer is335 // evaluated conditionally.336 static void *operator new(size_t size) throw();337 B(const A&, B*);338 ~B();339 };340 341 B *test() {342 // CHECK: define{{( dso_local)?}} ptr @_ZN5test74testEv()343 // CHECK: [[OUTER_NEW:%.*]] = alloca i1344 // CHECK-NEXT: alloca [[A:%.*]],345 // CHECK-NEXT: alloca ptr346 // CHECK-NEXT: alloca i32347 // CHECK-NEXT: [[OUTER_A:%.*]] = alloca i1348 // CHECK-NEXT: alloca ptr349 // CHECK-NEXT: [[INNER_NEW:%.*]] = alloca i1350 // CHECK-NEXT: alloca [[A:%.*]]351 // CHECK-NEXT: [[INNER_A:%.*]] = alloca i1352 353 // Allocate the outer object.354 // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test71BnwEm(355 // CHECK-NEXT: icmp eq ptr [[NEW]], null356 357 // These stores, emitted before the outermost conditional branch,358 // deactivate the temporary cleanups.359 // CHECK-NEXT: store i1 false, ptr [[OUTER_NEW]]360 // CHECK-NEXT: store i1 false, ptr [[OUTER_A]]361 // CHECK-NEXT: store i1 false, ptr [[INNER_NEW]]362 // CHECK-NEXT: store i1 false, ptr [[INNER_A]]363 // CHECK-NEXT: br i1364 365 // We passed the first null check; activate that cleanup and continue.366 // CHECK: store i1 true, ptr [[OUTER_NEW]]367 368 // Create the first A temporary and activate that cleanup.369 // CHECK-NEXT: invoke void @_ZN5test71AC1Ev(370 // CHECK: store i1 true, ptr [[OUTER_A]]371 372 // Allocate the inner object.373 // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test71BnwEm(374 // CHECK-NEXT: icmp eq ptr [[NEW]], null375 // CHECK-NEXT: br i1376 377 // We passed the second null check; save that pointer, activate378 // that cleanup, and continue.379 // CHECK: store ptr [[NEW]]380 // CHECK-NEXT: store i1 true, ptr [[INNER_NEW]]381 382 // Build the second A temporary and activate that cleanup.383 // CHECK-NEXT: invoke void @_ZN5test71AC1Ev(384 // CHECK: store i1 true, ptr [[INNER_A]]385 386 // Build the inner B object and deactivate the inner delete cleanup.387 // CHECK-NEXT: invoke void @_ZN5test71BC1ERKNS_1AEPS0_(388 // CHECK: store i1 false, ptr [[INNER_NEW]]389 // CHECK: phi390 391 // Build the outer B object and deactivate the outer delete cleanup.392 // CHECK-NEXT: invoke void @_ZN5test71BC1ERKNS_1AEPS0_(393 // CHECK: store i1 false, ptr [[OUTER_NEW]]394 // CHECK: phi395 // CHECK-NEXT: store ptr396 397 // Destroy the inner A object.398 // CHECK-NEXT: load i1, ptr [[INNER_A]]399 // CHECK-NEXT: br i1400 401 // CHECK98: invoke void @_ZN5test71AD1Ev(402 // CHECK11: call void @_ZN5test71AD1Ev(403 404 // Destroy the outer A object.405 // CHECK: load i1, ptr [[OUTER_A]]406 // CHECK-NEXT: br i1407 408 // CHECK98: invoke void @_ZN5test71AD1Ev(409 // CHECK11: call void @_ZN5test71AD1Ev(410 411 return new B(A(), new B(A(), 0));412 }413}414 415// Just don't crash.416namespace test8 {417 struct A {418 // Having both of these is required to trigger the assert we're419 // trying to avoid.420 A(const A&);421 A&operator=(const A&);422 423 ~A();424 };425 426 A makeA();427 void test() {428 throw makeA();429 }430 // CHECK-LABEL: define{{.*}} void @_ZN5test84testEv431}432 433// Make sure we generate the correct code for the delete[] call which434// happens if A::A() throws. (We were previously calling delete[] on435// a pointer to the first array element, not the pointer returned by new[].)436// PR10870437namespace test9 {438 struct A {439 A();440 ~A();441 };442 A* test() {443 return new A[10];444 }445 // CHECK: define{{.*}} ptr @_ZN5test94testEv446 // CHECK: [[TEST9_NEW:%.*]] = call noalias nonnull ptr @_Znam447 // CHECK: call void @_ZdaPv(ptr [[TEST9_NEW]])448}449 450// In a destructor with a function-try-block, a return statement in a451// catch handler behaves differently from running off the end of the452// catch handler. PR13102.453namespace test10 {454 extern void cleanup();455 extern bool suppress;456 457 struct A { ~A(); };458 A::~A() try { cleanup(); } catch (...) { return; }459 // CHECK-LABEL: define{{.*}} void @_ZN6test101AD1Ev(460 // CHECK: invoke void @_ZN6test107cleanupEv()461 // CHECK-NOT: rethrow462 // CHECK: ret void463 464 struct B { ~B(); };465 B::~B() try { cleanup(); } catch (...) {}466 // CHECK-LABEL: define{{.*}} void @_ZN6test101BD1Ev(467 // CHECK: invoke void @_ZN6test107cleanupEv()468 // CHECK: call ptr @__cxa_begin_catch469 // CHECK-NEXT: invoke void @__cxa_rethrow()470 // CHECK: unreachable471 472 struct C { ~C(); };473 C::~C() try { cleanup(); } catch (...) { if (suppress) return; }474 // CHECK-LABEL: define{{.*}} void @_ZN6test101CD1Ev(475 // CHECK: invoke void @_ZN6test107cleanupEv()476 // CHECK: call ptr @__cxa_begin_catch477 // CHECK-NEXT: load i8, ptr @_ZN6test108suppressE, align 1478 // CHECK-NEXT: trunc479 // CHECK-NEXT: br i1480 481 // CHECK98: call void @__cxa_end_catch()482 // CHECK98-NEXT: br label483 // THROWEND11: invoke void @__cxa_end_catch()484 // THROWEND11-NEXT: to label %invoke.cont[[#]] unwind label %terminate.lpad485 // NOTHROWEND11: call void @__cxa_end_catch()486 // NOTHROWEND11-NEXT: br label %try.cont487 488 // CHECK: invoke void @__cxa_rethrow()489 // CHECK: unreachable490 491 // CHECK: terminate.lpad:492 // CHECK: call void @__clang_call_terminate(493}494 495// Ensure that an exception in a constructor destroys496// already-constructed array members. PR14514497namespace test11 {498 struct A {499 A();500 ~A() {}501 };502 503 struct C {504 A single;505 A array[2][3];506 507 C();508 };509 510 C::C() {511 throw 0;512 }513 // CHECK-LABEL: define{{.*}} void @_ZN6test111CC2Ev(514 // CHECK: [[THIS:%.*]] = load ptr, ptr {{%.*}}515 // Construct single.516 // CHECK-NEXT: call void @_ZN6test111AC1Ev(ptr {{[^,]*}} [[THIS]])517 // Construct array.518 // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds nuw [[C:%.*]], ptr [[THIS]], i32 0, i32 1519 // CHECK-NEXT: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A:%.*]]]], ptr [[ARRAY]], i32 0, i32 0, i32 0520 // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[ARRAYBEGIN]], i64 6521 // CHECK-NEXT: br label522 // CHECK: [[CUR:%.*]] = phi ptr [ [[ARRAYBEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ]523 // CHECK-NEXT: invoke void @_ZN6test111AC1Ev(ptr {{[^,]*}} [[CUR]])524 // CHECK: [[NEXT]] = getelementptr inbounds [[A:%.*]], ptr [[CUR]], i64 1525 // CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[NEXT]], [[ARRAYEND]]526 // CHECK-NEXT: br i1 [[DONE]],527 // throw 0;528 // CHECK: invoke void @__cxa_throw(529 // Landing pad 1, from constructor in array-initialization loop:530 // CHECK: landingpad531 // - First, destroy already-constructed bits of array.532 // CHECK: [[EMPTY:%.*]] = icmp eq ptr [[ARRAYBEGIN]], [[CUR]]533 // CHECK-NEXT: br i1 [[EMPTY]]534 // CHECK: [[AFTER:%.*]] = phi ptr [ [[CUR]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]535 // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A:%.*]], ptr [[AFTER]], i64 -1536 537 // CHECK98-NEXT: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]])538 // CHECK11-NEXT: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]])539 540 // CHECK: [[DONE:%.*]] = icmp eq ptr [[ELT]], [[ARRAYBEGIN]]541 // CHECK-NEXT: br i1 [[DONE]],542 // - Next, chain to cleanup for single.543 // CHECK: br label544 // Landing pad 2, from throw site.545 // CHECK: landingpad546 // - First, destroy all of array.547 // CHECK: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A:%.*]]]], ptr [[ARRAY]], i32 0, i32 0, i32 0548 // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[ARRAYBEGIN]], i64 6549 // CHECK-NEXT: br label550 // CHECK: [[AFTER:%.*]] = phi ptr [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ]551 // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]], ptr [[AFTER]], i64 -1552 553 // CHECK98-NEXT: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]])554 // CHECK11-NEXT: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]])555 556 // CHECK: [[DONE:%.*]] = icmp eq ptr [[ELT]], [[ARRAYBEGIN]]557 // CHECK-NEXT: br i1 [[DONE]],558 // - Next, chain to cleanup for single.559 // CHECK: br label560 // Finally, the cleanup for single.561 562 // CHECK98: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[THIS]])563 // CHECK11: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[THIS]])564 565 // CHECK: br label566 // CHECK: resume567 // (After this is a terminate landingpad.)568}569 570namespace test12 {571 struct A {572 void operator delete(void *, void *);573 A();574 };575 576 A *test(void *ptr) {577 return new (ptr) A();578 }579 // CHECK-LABEL: define {{.*}} @_ZN6test124testEPv(580 // CHECK: [[PTR:%.*]] = load ptr, ptr581 // CHECK-NEXT: invoke void @_ZN6test121AC1Ev(ptr {{[^,]*}} [[PTR]])582 // CHECK: ret ptr [[PTR]]583 584 // CHECK98: invoke void @_ZN6test121AdlEPvS1_(ptr [[PTR]], ptr [[PTR]])585 // CHECK11: call void @_ZN6test121AdlEPvS1_(ptr [[PTR]], ptr [[PTR]])586}587 588namespace test13 {589 590struct A {591 A();592 ~A();593 int a, b;594};595 596// CHECK: define{{.*}} void @_ZN6test134testEi(597// CHECK: %[[REF_TMP:.*]] = alloca %[[STRUCT_TEST13_A]], align 4598// CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1599// CHECK: %[[REF_TMP1:.*]] = alloca %[[STRUCT_TEST13_A]], align 4600// CHECK: %[[CLEANUP_COND2:.*]] = alloca i1, align 1601 602// CHECK: call void @_ZN6test131AC1Ev(ptr {{[^,]*}} %[[REF_TMP]])603// CHECK: store i1 true, ptr %[[CLEANUP_COND]], align 1604// CHECK: br605 606// CHECK: invoke void @_ZN6test131AC1Ev(ptr {{[^,]*}} %[[REF_TMP1]])607 608// CHECK: store i1 true, ptr %[[CLEANUP_COND2]], align 1609// CHECK: br610 611// Check the flag before destructing the temporary.612 613// CHECK: landingpad { ptr, i32 }614// CHECK: %[[CLEANUP_IS_ACTIVE:.*]] = load i1, ptr %[[CLEANUP_COND]], align 1615// CHECK: br i1 %[[CLEANUP_IS_ACTIVE]],616 617// CHECK: void @_ZN6test131AD1Ev(ptr {{[^,]*}} %[[REF_TMP]])618 619void test(int c) {620 const A &s = c ? static_cast<const A &>(A()) : static_cast<const A &>(A());621}622 623}624 625// CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind {{.*}} }626