|  | // 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 %s | 
|  | // 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 %s | 
|  | // 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 %s | 
|  |  | 
|  | // CHECK: %[[STRUCT_TEST13_A:.*]] = type { i32, i32 } | 
|  |  | 
|  | typedef __typeof(sizeof(0)) size_t; | 
|  |  | 
|  | // Declare the reserved global placement new. | 
|  | void *operator new(size_t, void*); | 
|  |  | 
|  | // This just shouldn't crash. | 
|  | namespace test0 { | 
|  | struct allocator { | 
|  | allocator(); | 
|  | allocator(const allocator&); | 
|  | ~allocator(); | 
|  | }; | 
|  |  | 
|  | void f(); | 
|  | void g(bool b, bool c) { | 
|  | if (b) { | 
|  | if (!c) | 
|  | throw allocator(); | 
|  |  | 
|  | return; | 
|  | } | 
|  | f(); | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace test1 { | 
|  | struct A { A(int); A(int, int); ~A(); void *p; }; | 
|  |  | 
|  | A *a() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test11aEv() | 
|  | // CHECK:      [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) | 
|  | // CHECK-NEXT: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5) | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  | // CHECK:      call void @_ZdlPv(ptr [[NEW]]) | 
|  | return new A(5); | 
|  | } | 
|  |  | 
|  | A *b() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test11bEv() | 
|  | // CHECK:      [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) | 
|  | // CHECK-NEXT: [[FOO:%.*]] = invoke i32 @_ZN5test13fooEv() | 
|  | // CHECK:      invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[FOO]]) | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  | // CHECK:      call void @_ZdlPv(ptr [[NEW]]) | 
|  | extern int foo(); | 
|  | return new A(foo()); | 
|  | } | 
|  |  | 
|  | struct B { B(); ~B(); operator int(); int x; }; | 
|  | B makeB(); | 
|  |  | 
|  | A *c() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test11cEv() | 
|  | // CHECK:      [[ACTIVE:%.*]] = alloca i1 | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) | 
|  | // CHECK-NEXT: store i1 true, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T0:%.*]]) | 
|  | // CHECK:      [[T1:%.*]] = getelementptr inbounds [[B:%.*]], ptr [[T0]], i32 0, i32 0 | 
|  | // CHECK-NEXT: [[T2:%.*]] = load i32, ptr [[T1]], align 4 | 
|  | // CHECK-NEXT: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T2]]) | 
|  | // CHECK:      store i1 false, ptr [[ACTIVE]] | 
|  |  | 
|  | // CHECK98-NEXT: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK11-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  |  | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  | // CHECK:      [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: br i1 [[ISACTIVE]] | 
|  | // CHECK:      call void @_ZdlPv(ptr [[NEW]]) | 
|  | return new A(B().x); | 
|  | } | 
|  |  | 
|  | //   Terminate landing pads should call __cxa_begin_catch first. | 
|  | // CHECK98:      define linkonce_odr hidden void @__clang_call_terminate(ptr %0) [[NI_NR_NUW:#[0-9]+]] comdat | 
|  | // CHECK98-NEXT:   [[T0:%.*]] = call ptr @__cxa_begin_catch(ptr %0) [[NUW:#[0-9]+]] | 
|  | // CHECK98-NEXT:   call void @_ZSt9terminatev() [[NR_NUW:#[0-9]+]] | 
|  | // CHECK98-NEXT:   unreachable | 
|  |  | 
|  | A *d() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test11dEv() | 
|  | // CHECK:      [[ACTIVE:%.*]] = alloca i1 | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) | 
|  | // CHECK-NEXT: store i1 true, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T0:%.*]]) | 
|  | // CHECK:      [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK:      invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T1]]) | 
|  | // CHECK:      store i1 false, ptr [[ACTIVE]] | 
|  |  | 
|  | // CHECK98-NEXT: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK11-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  |  | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  | // CHECK:      [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: br i1 [[ISACTIVE]] | 
|  | // CHECK:      call void @_ZdlPv(ptr [[NEW]]) | 
|  | return new A(B()); | 
|  | } | 
|  |  | 
|  | A *e() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test11eEv() | 
|  | // CHECK:      [[ACTIVE:%.*]] = alloca i1 | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) | 
|  | // CHECK-NEXT: store i1 true, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T0:%.*]]) | 
|  | // CHECK:      [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK:      invoke void @_ZN5test11BC1Ev(ptr {{[^,]*}} [[T2:%.*]]) | 
|  | // CHECK:      [[T3:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T2]]) | 
|  | // CHECK:      invoke void @_ZN5test11AC1Eii(ptr {{[^,]*}} [[NEW]], i32 [[T1]], i32 [[T3]]) | 
|  | // CHECK:      store i1 false, ptr [[ACTIVE]] | 
|  |  | 
|  | // CHECK98-NEXT: invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]]) | 
|  | // CHECK11-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]]) | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK11:      call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  |  | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  | // CHECK:      [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: br i1 [[ISACTIVE]] | 
|  | // CHECK:      call void @_ZdlPv(ptr [[NEW]]) | 
|  | return new A(B(), B()); | 
|  | } | 
|  | A *f() { | 
|  | return new A(makeB().x); | 
|  | } | 
|  | A *g() { | 
|  | return new A(makeB()); | 
|  | } | 
|  | A *h() { | 
|  | return new A(makeB(), makeB()); | 
|  | } | 
|  |  | 
|  | A *i() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test11iEv() | 
|  | // CHECK:      [[X:%.*]] = alloca ptr, align 8 | 
|  | // CHECK:      [[ACTIVE:%.*]] = alloca i1 | 
|  | // CHECK:      [[NEW:%.*]] = call noalias nonnull ptr @_Znwm(i64 8) | 
|  | // CHECK-NEXT: store i1 true, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: invoke void @_ZN5test15makeBEv(ptr dead_on_unwind writable sret([[B:%.*]]) align 4 [[T0:%.*]]) | 
|  | // CHECK:      [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK:      invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[NEW]], i32 [[T1]]) | 
|  | // CHECK:      store i1 false, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: store ptr [[NEW]], ptr [[X]], align 8 | 
|  | // CHECK:      invoke void @_ZN5test15makeBEv(ptr dead_on_unwind writable sret([[B:%.*]]) align 4 [[T2:%.*]]) | 
|  | // CHECK:      [[RET:%.*]] = load ptr, ptr [[X]], align 8 | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]]) | 
|  | // CHECK11:      call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T2]]) | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  | // CHECK11:      call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[T0]]) | 
|  |  | 
|  | // CHECK:      ret ptr [[RET]] | 
|  | // CHECK:      [[ISACTIVE:%.*]] = load i1, ptr [[ACTIVE]] | 
|  | // CHECK-NEXT: br i1 [[ISACTIVE]] | 
|  | // CHECK:      call void @_ZdlPv(ptr [[NEW]]) | 
|  | A *x; | 
|  | return (x = new A(makeB()), makeB(), x); | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace test2 { | 
|  | struct A { | 
|  | A(int); A(int, int); ~A(); | 
|  | void *p; | 
|  | void *operator new(size_t); | 
|  | void operator delete(void*, size_t); | 
|  | }; | 
|  |  | 
|  | A *a() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test21aEv() | 
|  | // CHECK:      [[NEW:%.*]] = call ptr @_ZN5test21AnwEm(i64 8) | 
|  | // CHECK-NEXT: invoke void @_ZN5test21AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5) | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN5test21AdlEPvm(ptr [[NEW]], i64 8) | 
|  | // CHECK11:      call void @_ZN5test21AdlEPvm(ptr [[NEW]], i64 8) | 
|  |  | 
|  | // CHECK98:      call void @__clang_call_terminate(ptr {{%.*}}) [[NR_NUW]] | 
|  | return new A(5); | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace test3 { | 
|  | struct A { | 
|  | A(int); A(int, int); A(const A&); ~A(); | 
|  | void *p; | 
|  | void *operator new(size_t, void*, double); | 
|  | void operator delete(void*, void*, double); | 
|  | }; | 
|  |  | 
|  | void *foo(); | 
|  | double bar(); | 
|  | A makeA(), *makeAPtr(); | 
|  |  | 
|  | A *a() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test31aEv() | 
|  | // CHECK:      [[FOO:%.*]] = call ptr @_ZN5test33fooEv() | 
|  | // CHECK:      [[BAR:%.*]] = call double @_ZN5test33barEv() | 
|  | // CHECK:      [[NEW:%.*]] = call ptr @_ZN5test31AnwEmPvd(i64 8, ptr [[FOO]], double [[BAR]]) | 
|  | // CHECK-NEXT: invoke void @_ZN5test31AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5) | 
|  | // CHECK:      ret ptr [[NEW]] | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN5test31AdlEPvS1_d(ptr [[NEW]], ptr [[FOO]], double [[BAR]]) | 
|  | // CHECK11:      call void @_ZN5test31AdlEPvS1_d(ptr [[NEW]], ptr [[FOO]], double [[BAR]]) | 
|  |  | 
|  | // CHECK98:      call void @__clang_call_terminate(ptr {{%.*}}) [[NR_NUW]] | 
|  | return new(foo(),bar()) A(5); | 
|  | } | 
|  |  | 
|  | A *b(bool cond) { | 
|  |  | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test31bEb(i1 zeroext | 
|  | // CHECK:      [[SAVED0:%.*]] = alloca ptr | 
|  | // CHECK-NEXT: [[SAVED1:%.*]] = alloca ptr | 
|  | // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1 | 
|  |  | 
|  | // CHECK:      [[COND:%.*]] = trunc i8 {{.*}} to i1 | 
|  | // CHECK-NEXT: store i1 false, ptr [[CLEANUPACTIVE]] | 
|  | // CHECK-NEXT: br i1 [[COND]] | 
|  | return (cond ? | 
|  |  | 
|  | // CHECK:      [[FOO:%.*]] = call ptr @_ZN5test33fooEv() | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test31AnwEmPvd(i64 8, ptr [[FOO]], double [[CONST:.*]]) | 
|  | // CHECK-NEXT: store ptr [[NEW]], ptr [[SAVED0]] | 
|  | // CHECK-NEXT: store ptr [[FOO]], ptr [[SAVED1]] | 
|  | // CHECK-NEXT: store i1 true, ptr [[CLEANUPACTIVE]] | 
|  | // CHECK-NEXT: invoke void @_ZN5test35makeAEv(ptr dead_on_unwind writable sret([[A:%.*]]) align 8 [[NEW]]) | 
|  | // CHECK: br label | 
|  | //   -> cond.end | 
|  | new(foo(),10.0) A(makeA()) : | 
|  |  | 
|  | // CHECK:      [[MAKE:%.*]] = call ptr @_ZN5test38makeAPtrEv() | 
|  | // CHECK:      br label | 
|  | //   -> cond.end | 
|  | makeAPtr()); | 
|  |  | 
|  | // cond.end: | 
|  | // CHECK:      [[RESULT:%.*]] = phi ptr {{.*}}[[NEW]]{{.*}}[[MAKE]] | 
|  | // CHECK:      ret ptr [[RESULT]] | 
|  |  | 
|  | // in the EH path: | 
|  | // CHECK:      [[ISACTIVE:%.*]] = load i1, ptr [[CLEANUPACTIVE]] | 
|  | // CHECK-NEXT: br i1 [[ISACTIVE]] | 
|  | // CHECK:      [[V0:%.*]] = load ptr, ptr [[SAVED0]] | 
|  | // CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[SAVED1]] | 
|  |  | 
|  | // CHECK98-NEXT: invoke void @_ZN5test31AdlEPvS1_d(ptr [[V0]], ptr [[V1]], double [[CONST]]) | 
|  | // CHECK11-NEXT: call void @_ZN5test31AdlEPvS1_d(ptr [[V0]], ptr [[V1]], double [[CONST]]) | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace test4 { | 
|  | struct A { | 
|  | A(int); A(int, int); ~A(); | 
|  | void *p; | 
|  | void *operator new(size_t, void*, void*); | 
|  | void operator delete(void*, size_t, void*, void*); // not a match | 
|  | }; | 
|  |  | 
|  | A *a() { | 
|  | // CHECK:    define{{( dso_local)?}} ptr @_ZN5test41aEv() | 
|  | // CHECK:      [[FOO:%.*]] = call ptr @_ZN5test43fooEv() | 
|  | // CHECK-NEXT: [[BAR:%.*]] = call ptr @_ZN5test43barEv() | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test41AnwEmPvS1_(i64 8, ptr [[FOO]], ptr [[BAR]]) | 
|  | // CHECK-NEXT: call void @_ZN5test41AC1Ei(ptr {{[^,]*}} [[NEW]], i32 5) | 
|  | // CHECK-NEXT: ret ptr [[NEW]] | 
|  | extern void *foo(), *bar(); | 
|  |  | 
|  | return new(foo(),bar()) A(5); | 
|  | } | 
|  | } | 
|  |  | 
|  | // PR7908 | 
|  | namespace test5 { | 
|  | struct T { T(); ~T(); }; | 
|  |  | 
|  | struct A { | 
|  | A(const A &x, const T &t = T()); | 
|  | ~A(); | 
|  | }; | 
|  |  | 
|  | void foo(); | 
|  |  | 
|  | // CHECK-LABEL:    define{{.*}} void @_ZN5test54testEv() | 
|  | // CHECK:      [[EXNSLOT:%.*]] = alloca ptr | 
|  | // CHECK-NEXT: [[SELECTORSLOT:%.*]] = alloca i32 | 
|  | // CHECK-NEXT: [[A:%.*]] = alloca [[A_T:%.*]], align 1 | 
|  | // CHECK-NEXT: [[T:%.*]] = alloca [[T_T:%.*]], align 1 | 
|  | // CHECK-NEXT: invoke void @_ZN5test53fooEv() | 
|  | // CHECK:      [[EXN:%.*]] = load ptr, ptr [[EXNSLOT]] | 
|  | // CHECK-NEXT: [[ADJ:%.*]] = call ptr @__cxa_get_exception_ptr(ptr [[EXN]]) | 
|  | // CHECK-NEXT: invoke void @_ZN5test51TC1Ev(ptr {{[^,]*}} [[T]]) | 
|  | // 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]]) | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN5test51TD1Ev(ptr {{[^,]*}} [[T]]) | 
|  | // CHECK11:      call void @_ZN5test51TD1Ev(ptr {{[^,]*}} [[T]]) | 
|  |  | 
|  | // CHECK98:      call ptr @__cxa_begin_catch(ptr [[EXN]]) [[NUW]] | 
|  | // CHECK98-NEXT: invoke void @_ZN5test51AD1Ev(ptr {{[^,]*}} [[A:%.*]]) | 
|  |  | 
|  | // CHECK:      call void @__cxa_end_catch() | 
|  | void test() { | 
|  | try { | 
|  | foo(); | 
|  | } catch (A a) { | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // PR9303: invalid assert on this | 
|  | namespace test6 { | 
|  | bool cond(); | 
|  | void test() { | 
|  | try { | 
|  | lbl: | 
|  | if (cond()) goto lbl; | 
|  | } catch (...) { | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // PR9298 | 
|  | namespace test7 { | 
|  | struct A { A(); ~A(); }; | 
|  | struct B { | 
|  | // The throw() operator means that a bad allocation is signalled | 
|  | // with a null return, which means that the initializer is | 
|  | // evaluated conditionally. | 
|  | static void *operator new(size_t size) throw(); | 
|  | B(const A&, B*); | 
|  | ~B(); | 
|  | }; | 
|  |  | 
|  | B *test() { | 
|  | // CHECK: define{{( dso_local)?}} ptr @_ZN5test74testEv() | 
|  | // CHECK:      [[OUTER_NEW:%.*]] = alloca i1 | 
|  | // CHECK-NEXT: alloca [[A:%.*]], | 
|  | // CHECK-NEXT: alloca ptr | 
|  | // CHECK-NEXT: alloca i32 | 
|  | // CHECK-NEXT: [[OUTER_A:%.*]] = alloca i1 | 
|  | // CHECK-NEXT: alloca ptr | 
|  | // CHECK-NEXT: [[INNER_NEW:%.*]] = alloca i1 | 
|  | // CHECK-NEXT: alloca [[A:%.*]] | 
|  | // CHECK-NEXT: [[INNER_A:%.*]] = alloca i1 | 
|  |  | 
|  | // Allocate the outer object. | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test71BnwEm( | 
|  | // CHECK-NEXT: icmp eq ptr [[NEW]], null | 
|  |  | 
|  | // These stores, emitted before the outermost conditional branch, | 
|  | // deactivate the temporary cleanups. | 
|  | // CHECK-NEXT: store i1 false, ptr [[OUTER_NEW]] | 
|  | // CHECK-NEXT: store i1 false, ptr [[OUTER_A]] | 
|  | // CHECK-NEXT: store i1 false, ptr [[INNER_NEW]] | 
|  | // CHECK-NEXT: store i1 false, ptr [[INNER_A]] | 
|  | // CHECK-NEXT: br i1 | 
|  |  | 
|  | // We passed the first null check; activate that cleanup and continue. | 
|  | // CHECK:      store i1 true, ptr [[OUTER_NEW]] | 
|  |  | 
|  | // Create the first A temporary and activate that cleanup. | 
|  | // CHECK-NEXT: invoke void @_ZN5test71AC1Ev( | 
|  | // CHECK:      store i1 true, ptr [[OUTER_A]] | 
|  |  | 
|  | // Allocate the inner object. | 
|  | // CHECK-NEXT: [[NEW:%.*]] = call ptr @_ZN5test71BnwEm( | 
|  | // CHECK-NEXT: icmp eq ptr [[NEW]], null | 
|  | // CHECK-NEXT: br i1 | 
|  |  | 
|  | // We passed the second null check; save that pointer, activate | 
|  | // that cleanup, and continue. | 
|  | // CHECK:      store ptr [[NEW]] | 
|  | // CHECK-NEXT: store i1 true, ptr [[INNER_NEW]] | 
|  |  | 
|  | // Build the second A temporary and activate that cleanup. | 
|  | // CHECK-NEXT: invoke void @_ZN5test71AC1Ev( | 
|  | // CHECK:      store i1 true, ptr [[INNER_A]] | 
|  |  | 
|  | // Build the inner B object and deactivate the inner delete cleanup. | 
|  | // CHECK-NEXT: invoke void @_ZN5test71BC1ERKNS_1AEPS0_( | 
|  | // CHECK:      store i1 false, ptr [[INNER_NEW]] | 
|  | // CHECK:      phi | 
|  |  | 
|  | // Build the outer B object and deactivate the outer delete cleanup. | 
|  | // CHECK-NEXT: invoke void @_ZN5test71BC1ERKNS_1AEPS0_( | 
|  | // CHECK:      store i1 false, ptr [[OUTER_NEW]] | 
|  | // CHECK:      phi | 
|  | // CHECK-NEXT: store ptr | 
|  |  | 
|  | // Destroy the inner A object. | 
|  | // CHECK-NEXT: load i1, ptr [[INNER_A]] | 
|  | // CHECK-NEXT: br i1 | 
|  |  | 
|  | // CHECK98:    invoke void @_ZN5test71AD1Ev( | 
|  | // CHECK11:    call void @_ZN5test71AD1Ev( | 
|  |  | 
|  | // Destroy the outer A object. | 
|  | // CHECK:      load i1, ptr [[OUTER_A]] | 
|  | // CHECK-NEXT: br i1 | 
|  |  | 
|  | // CHECK98:    invoke void @_ZN5test71AD1Ev( | 
|  | // CHECK11:    call void @_ZN5test71AD1Ev( | 
|  |  | 
|  | return new B(A(), new B(A(), 0)); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Just don't crash. | 
|  | namespace test8 { | 
|  | struct A { | 
|  | // Having both of these is required to trigger the assert we're | 
|  | // trying to avoid. | 
|  | A(const A&); | 
|  | A&operator=(const A&); | 
|  |  | 
|  | ~A(); | 
|  | }; | 
|  |  | 
|  | A makeA(); | 
|  | void test() { | 
|  | throw makeA(); | 
|  | } | 
|  | // CHECK-LABEL: define{{.*}} void @_ZN5test84testEv | 
|  | } | 
|  |  | 
|  | // Make sure we generate the correct code for the delete[] call which | 
|  | // happens if A::A() throws.  (We were previously calling delete[] on | 
|  | // a pointer to the first array element, not the pointer returned by new[].) | 
|  | // PR10870 | 
|  | namespace test9 { | 
|  | struct A { | 
|  | A(); | 
|  | ~A(); | 
|  | }; | 
|  | A* test() { | 
|  | return new A[10]; | 
|  | } | 
|  | // CHECK: define{{.*}} ptr @_ZN5test94testEv | 
|  | // CHECK: [[TEST9_NEW:%.*]] = call noalias nonnull ptr @_Znam | 
|  | // CHECK: call void @_ZdaPv(ptr [[TEST9_NEW]]) | 
|  | } | 
|  |  | 
|  | // In a destructor with a function-try-block, a return statement in a | 
|  | // catch handler behaves differently from running off the end of the | 
|  | // catch handler.  PR13102. | 
|  | namespace test10 { | 
|  | extern void cleanup(); | 
|  | extern bool suppress; | 
|  |  | 
|  | struct A { ~A(); }; | 
|  | A::~A() try { cleanup(); } catch (...) { return; } | 
|  | // CHECK-LABEL:    define{{.*}} void @_ZN6test101AD1Ev( | 
|  | // CHECK:      invoke void @_ZN6test107cleanupEv() | 
|  | // CHECK-NOT:  rethrow | 
|  | // CHECK:      ret void | 
|  |  | 
|  | struct B { ~B(); }; | 
|  | B::~B() try { cleanup(); } catch (...) {} | 
|  | // CHECK-LABEL:    define{{.*}} void @_ZN6test101BD1Ev( | 
|  | // CHECK:      invoke void @_ZN6test107cleanupEv() | 
|  | // CHECK:      call ptr @__cxa_begin_catch | 
|  | // CHECK-NEXT: invoke void @__cxa_rethrow() | 
|  | // CHECK:      unreachable | 
|  |  | 
|  | struct C { ~C(); }; | 
|  | C::~C() try { cleanup(); } catch (...) { if (suppress) return; } | 
|  | // CHECK-LABEL:    define{{.*}} void @_ZN6test101CD1Ev( | 
|  | // CHECK:      invoke void @_ZN6test107cleanupEv() | 
|  | // CHECK:      call ptr @__cxa_begin_catch | 
|  | // CHECK-NEXT: load i8, ptr @_ZN6test108suppressE, align 1 | 
|  | // CHECK-NEXT: trunc | 
|  | // CHECK-NEXT: br i1 | 
|  |  | 
|  | // CHECK98:      call void @__cxa_end_catch() | 
|  | // CHECK98-NEXT: br label | 
|  | // THROWEND11:        invoke void @__cxa_end_catch() | 
|  | // THROWEND11-NEXT:   to label %invoke.cont[[#]] unwind label %terminate.lpad | 
|  | // NOTHROWEND11:      call void @__cxa_end_catch() | 
|  | // NOTHROWEND11-NEXT: br label %try.cont | 
|  |  | 
|  | // CHECK:      invoke void @__cxa_rethrow() | 
|  | // CHECK:      unreachable | 
|  |  | 
|  | // CHECK:      terminate.lpad: | 
|  | // CHECK:        call void @__clang_call_terminate( | 
|  | } | 
|  |  | 
|  | // Ensure that an exception in a constructor destroys | 
|  | // already-constructed array members.  PR14514 | 
|  | namespace test11 { | 
|  | struct A { | 
|  | A(); | 
|  | ~A() {} | 
|  | }; | 
|  |  | 
|  | struct C { | 
|  | A single; | 
|  | A array[2][3]; | 
|  |  | 
|  | C(); | 
|  | }; | 
|  |  | 
|  | C::C() { | 
|  | throw 0; | 
|  | } | 
|  | // CHECK-LABEL:    define{{.*}} void @_ZN6test111CC2Ev( | 
|  | // CHECK:      [[THIS:%.*]] = load ptr, ptr {{%.*}} | 
|  | //   Construct single. | 
|  | // CHECK-NEXT: call void @_ZN6test111AC1Ev(ptr {{[^,]*}} [[THIS]]) | 
|  | //   Construct array. | 
|  | // CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[THIS]], i32 0, i32 1 | 
|  | // CHECK-NEXT: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A:%.*]]]], ptr [[ARRAY]], i32 0, i32 0, i32 0 | 
|  | // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[ARRAYBEGIN]], i64 6 | 
|  | // CHECK-NEXT: br label | 
|  | // CHECK:      [[CUR:%.*]] = phi ptr [ [[ARRAYBEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] | 
|  | // CHECK-NEXT: invoke void @_ZN6test111AC1Ev(ptr {{[^,]*}} [[CUR]]) | 
|  | // CHECK:      [[NEXT]] = getelementptr inbounds [[A:%.*]], ptr [[CUR]], i64 1 | 
|  | // CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[NEXT]], [[ARRAYEND]] | 
|  | // CHECK-NEXT: br i1 [[DONE]], | 
|  | //   throw 0; | 
|  | // CHECK:      invoke void @__cxa_throw( | 
|  | //   Landing pad 1, from constructor in array-initialization loop: | 
|  | // CHECK:      landingpad | 
|  | //     - First, destroy already-constructed bits of array. | 
|  | // CHECK:      [[EMPTY:%.*]] = icmp eq ptr [[ARRAYBEGIN]], [[CUR]] | 
|  | // CHECK-NEXT: br i1 [[EMPTY]] | 
|  | // CHECK:      [[AFTER:%.*]] = phi ptr [ [[CUR]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] | 
|  | // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A:%.*]], ptr [[AFTER]], i64 -1 | 
|  |  | 
|  | // CHECK98-NEXT: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]]) | 
|  | // CHECK11-NEXT: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]]) | 
|  |  | 
|  | // CHECK:      [[DONE:%.*]] = icmp eq ptr [[ELT]], [[ARRAYBEGIN]] | 
|  | // CHECK-NEXT: br i1 [[DONE]], | 
|  | //     - Next, chain to cleanup for single. | 
|  | // CHECK:      br label | 
|  | //   Landing pad 2, from throw site. | 
|  | // CHECK:      landingpad | 
|  | //     - First, destroy all of array. | 
|  | // CHECK:      [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A:%.*]]]], ptr [[ARRAY]], i32 0, i32 0, i32 0 | 
|  | // CHECK-NEXT: [[ARRAYEND:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[ARRAYBEGIN]], i64 6 | 
|  | // CHECK-NEXT: br label | 
|  | // CHECK:      [[AFTER:%.*]] = phi ptr [ [[ARRAYEND]], {{%.*}} ], [ [[ELT:%.*]], {{%.*}} ] | 
|  | // CHECK-NEXT: [[ELT]] = getelementptr inbounds [[A]], ptr [[AFTER]], i64 -1 | 
|  |  | 
|  | // CHECK98-NEXT: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]]) | 
|  | // CHECK11-NEXT: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[ELT]]) | 
|  |  | 
|  | // CHECK:      [[DONE:%.*]] = icmp eq ptr [[ELT]], [[ARRAYBEGIN]] | 
|  | // CHECK-NEXT: br i1 [[DONE]], | 
|  | //     - Next, chain to cleanup for single. | 
|  | // CHECK:      br label | 
|  | //   Finally, the cleanup for single. | 
|  |  | 
|  | // CHECK98:      invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[THIS]]) | 
|  | // CHECK11:      call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[THIS]]) | 
|  |  | 
|  | // CHECK:      br label | 
|  | // CHECK:      resume | 
|  | //   (After this is a terminate landingpad.) | 
|  | } | 
|  |  | 
|  | namespace test12 { | 
|  | struct A { | 
|  | void operator delete(void *, void *); | 
|  | A(); | 
|  | }; | 
|  |  | 
|  | A *test(void *ptr) { | 
|  | return new (ptr) A(); | 
|  | } | 
|  | // CHECK-LABEL: define {{.*}} @_ZN6test124testEPv( | 
|  | // CHECK:       [[PTR:%.*]] = load ptr, ptr | 
|  | // CHECK-NEXT:  invoke void @_ZN6test121AC1Ev(ptr {{[^,]*}} [[PTR]]) | 
|  | // CHECK:       ret ptr [[PTR]] | 
|  |  | 
|  | // CHECK98:       invoke void @_ZN6test121AdlEPvS1_(ptr [[PTR]], ptr [[PTR]]) | 
|  | // CHECK11:       call void @_ZN6test121AdlEPvS1_(ptr [[PTR]], ptr [[PTR]]) | 
|  | } | 
|  |  | 
|  | namespace test13 { | 
|  |  | 
|  | struct A { | 
|  | A(); | 
|  | ~A(); | 
|  | int a, b; | 
|  | }; | 
|  |  | 
|  | // CHECK: define{{.*}} void @_ZN6test134testEi( | 
|  | // CHECK: %[[REF_TMP:.*]] = alloca %[[STRUCT_TEST13_A]], align 4 | 
|  | // CHECK: %[[CLEANUP_COND:.*]] = alloca i1, align 1 | 
|  | // CHECK: %[[REF_TMP1:.*]] = alloca %[[STRUCT_TEST13_A]], align 4 | 
|  | // CHECK: %[[CLEANUP_COND2:.*]] = alloca i1, align 1 | 
|  |  | 
|  | // CHECK: call void @_ZN6test131AC1Ev(ptr {{[^,]*}} %[[REF_TMP]]) | 
|  | // CHECK: store i1 true, ptr %[[CLEANUP_COND]], align 1 | 
|  | // CHECK: br | 
|  |  | 
|  | // CHECK: invoke void @_ZN6test131AC1Ev(ptr {{[^,]*}} %[[REF_TMP1]]) | 
|  |  | 
|  | // CHECK: store i1 true, ptr %[[CLEANUP_COND2]], align 1 | 
|  | // CHECK: br | 
|  |  | 
|  | // Check the flag before destructing the temporary. | 
|  |  | 
|  | // CHECK: landingpad { ptr, i32 } | 
|  | // CHECK: %[[CLEANUP_IS_ACTIVE:.*]] = load i1, ptr %[[CLEANUP_COND]], align 1 | 
|  | // CHECK: br i1 %[[CLEANUP_IS_ACTIVE]], | 
|  |  | 
|  | // CHECK: void @_ZN6test131AD1Ev(ptr {{[^,]*}} %[[REF_TMP]]) | 
|  |  | 
|  | void test(int c) { | 
|  | const A &s = c ? static_cast<const A &>(A()) : static_cast<const A &>(A()); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | // CHECK98: attributes [[NI_NR_NUW]] = { noinline noreturn nounwind {{.*}} } |