1*67e74705SXin Li // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s 2*67e74705SXin Li 3*67e74705SXin Li // Test IR generation for partial destruction of aggregates. 4*67e74705SXin Li 5*67e74705SXin Li void opaque(); 6*67e74705SXin Li 7*67e74705SXin Li // Initializer lists. 8*67e74705SXin Li namespace test0 { 9*67e74705SXin Li struct A { A(int); A(); ~A(); void *v; }; test()10*67e74705SXin Li void test() { 11*67e74705SXin Li A as[10] = { 5, 7 }; 12*67e74705SXin Li opaque(); 13*67e74705SXin Li } 14*67e74705SXin Li // CHECK-LABEL: define void @_ZN5test04testEv() 15*67e74705SXin Li // CHECK-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 16*67e74705SXin Li // CHECK: [[AS:%.*]] = alloca [10 x [[A:%.*]]], align 17*67e74705SXin Li // CHECK-NEXT: [[ENDVAR:%.*]] = alloca [[A]]* 18*67e74705SXin Li // CHECK-NEXT: [[EXN:%.*]] = alloca i8* 19*67e74705SXin Li // CHECK-NEXT: [[SEL:%.*]] = alloca i32 20*67e74705SXin Li 21*67e74705SXin Li // Initialize. 22*67e74705SXin Li // CHECK-NEXT: [[E_BEGIN:%.*]] = getelementptr inbounds [10 x [[A]]], [10 x [[A]]]* [[AS]], i64 0, i64 0 23*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[E_BEGIN]], [[A]]** [[ENDVAR]] 24*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AC1Ei([[A]]* [[E_BEGIN]], i32 5) 25*67e74705SXin Li // CHECK: [[E1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[E_BEGIN]], i64 1 26*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[E1]], [[A]]** [[ENDVAR]] 27*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AC1Ei([[A]]* [[E1]], i32 7) 28*67e74705SXin Li // CHECK: [[E2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[E1]], i64 1 29*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[E2]], [[A]]** [[ENDVAR]] 30*67e74705SXin Li // CHECK-NEXT: [[E_END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[E_BEGIN]], i64 10 31*67e74705SXin Li // CHECK-NEXT: br label 32*67e74705SXin Li // CHECK: [[E_CUR:%.*]] = phi [[A]]* [ [[E2]], {{%.*}} ], [ [[E_NEXT:%.*]], {{%.*}} ] 33*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[E_CUR]]) 34*67e74705SXin Li // CHECK: [[E_NEXT]] = getelementptr inbounds [[A]], [[A]]* [[E_CUR]], i64 1 35*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[E_NEXT]], [[A]]** [[ENDVAR]] 36*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[E_NEXT]], [[E_END]] 37*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]], 38*67e74705SXin Li 39*67e74705SXin Li // Run. 40*67e74705SXin Li // CHECK: invoke void @_Z6opaquev() 41*67e74705SXin Li 42*67e74705SXin Li // Normal destroy. 43*67e74705SXin Li // CHECK: [[ED_BEGIN:%.*]] = getelementptr inbounds [10 x [[A]]], [10 x [[A]]]* [[AS]], i32 0, i32 0 44*67e74705SXin Li // CHECK-NEXT: [[ED_END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[ED_BEGIN]], i64 10 45*67e74705SXin Li // CHECK-NEXT: br label 46*67e74705SXin Li // CHECK: [[ED_AFTER:%.*]] = phi [[A]]* [ [[ED_END]], {{%.*}} ], [ [[ED_CUR:%.*]], {{%.*}} ] 47*67e74705SXin Li // CHECK-NEXT: [[ED_CUR]] = getelementptr inbounds [[A]], [[A]]* [[ED_AFTER]], i64 -1 48*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[ED_CUR]]) 49*67e74705SXin Li // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_CUR]], [[ED_BEGIN]] 50*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]], 51*67e74705SXin Li // CHECK: ret void 52*67e74705SXin Li 53*67e74705SXin Li // Partial destroy for initialization. 54*67e74705SXin Li // CHECK: landingpad { i8*, i32 } 55*67e74705SXin Li // CHECK-NEXT: cleanup 56*67e74705SXin Li // CHECK: [[PARTIAL_END:%.*]] = load [[A]]*, [[A]]** [[ENDVAR]] 57*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[E_BEGIN]], [[PARTIAL_END]] 58*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]], 59*67e74705SXin Li // CHECK: [[E_AFTER:%.*]] = phi [[A]]* [ [[PARTIAL_END]], {{%.*}} ], [ [[E_CUR:%.*]], {{%.*}} ] 60*67e74705SXin Li // CHECK-NEXT: [[E_CUR]] = getelementptr inbounds [[A]], [[A]]* [[E_AFTER]], i64 -1 61*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) 62*67e74705SXin Li // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[E_CUR]], [[E_BEGIN]] 63*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]], 64*67e74705SXin Li 65*67e74705SXin Li // Primary EH destructor. 66*67e74705SXin Li // CHECK: landingpad { i8*, i32 } 67*67e74705SXin Li // CHECK-NEXT: cleanup 68*67e74705SXin Li // CHECK: [[E0:%.*]] = getelementptr inbounds [10 x [[A]]], [10 x [[A]]]* [[AS]], i32 0, i32 0 69*67e74705SXin Li // CHECK-NEXT: [[E_END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[E0]], i64 10 70*67e74705SXin Li // CHECK-NEXT: br label 71*67e74705SXin Li 72*67e74705SXin Li // Partial destructor for primary normal destructor. 73*67e74705SXin Li // FIXME: There's some really bad block ordering here which causes 74*67e74705SXin Li // the partial destroy for the primary normal destructor to fall 75*67e74705SXin Li // within the primary EH destructor. 76*67e74705SXin Li // CHECK: landingpad { i8*, i32 } 77*67e74705SXin Li // CHECK-NEXT: cleanup 78*67e74705SXin Li // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]] 79*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]] 80*67e74705SXin Li // CHECK: [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ] 81*67e74705SXin Li // CHECK-NEXT: [[EDD_CUR]] = getelementptr inbounds [[A]], [[A]]* [[EDD_AFTER]], i64 -1 82*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[EDD_CUR]]) 83*67e74705SXin Li // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[EDD_CUR]], [[ED_BEGIN]] 84*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]] 85*67e74705SXin Li 86*67e74705SXin Li // Back to the primary EH destructor. 87*67e74705SXin Li // CHECK: [[E_AFTER:%.*]] = phi [[A]]* [ [[E_END]], {{%.*}} ], [ [[E_CUR:%.*]], {{%.*}} ] 88*67e74705SXin Li // CHECK-NEXT: [[E_CUR]] = getelementptr inbounds [[A]], [[A]]* [[E_AFTER]], i64 -1 89*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test01AD1Ev([[A]]* [[E_CUR]]) 90*67e74705SXin Li // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[E_CUR]], [[E0]] 91*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]], 92*67e74705SXin Li 93*67e74705SXin Li } 94*67e74705SXin Li 95*67e74705SXin Li namespace test1 { 96*67e74705SXin Li struct A { A(); A(int); ~A(); }; 97*67e74705SXin Li struct B { A x, y, z; int w; }; 98*67e74705SXin Li test()99*67e74705SXin Li void test() { 100*67e74705SXin Li B v = { 5, 6, 7, 8 }; 101*67e74705SXin Li } 102*67e74705SXin Li // CHECK-LABEL: define void @_ZN5test14testEv() 103*67e74705SXin Li // CHECK-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 104*67e74705SXin Li // CHECK: [[V:%.*]] = alloca [[B:%.*]], align 4 105*67e74705SXin Li // CHECK-NEXT: alloca i8* 106*67e74705SXin Li // CHECK-NEXT: alloca i32 107*67e74705SXin Li // CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B]], [[B]]* [[V]], i32 0, i32 0 108*67e74705SXin Li // CHECK-NEXT: call void @_ZN5test11AC1Ei([[A:%.*]]* [[X]], i32 5) 109*67e74705SXin Li // CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds [[B]], [[B]]* [[V]], i32 0, i32 1 110*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[Y]], i32 6) 111*67e74705SXin Li // CHECK: [[Z:%.*]] = getelementptr inbounds [[B]], [[B]]* [[V]], i32 0, i32 2 112*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test11AC1Ei([[A]]* [[Z]], i32 7) 113*67e74705SXin Li // CHECK: [[W:%.*]] = getelementptr inbounds [[B]], [[B]]* [[V]], i32 0, i32 3 114*67e74705SXin Li // CHECK-NEXT: store i32 8, i32* [[W]], align 4 115*67e74705SXin Li // CHECK-NEXT: call void @_ZN5test11BD1Ev([[B]]* [[V]]) 116*67e74705SXin Li // CHECK-NEXT: ret void 117*67e74705SXin Li 118*67e74705SXin Li // FIXME: again, the block ordering is pretty bad here 119*67e74705SXin Li // CHECK: landingpad { i8*, i32 } 120*67e74705SXin Li // CHECK-NEXT: cleanup 121*67e74705SXin Li // CHECK: landingpad { i8*, i32 } 122*67e74705SXin Li // CHECK-NEXT: cleanup 123*67e74705SXin Li // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[Y]]) 124*67e74705SXin Li // CHECK: invoke void @_ZN5test11AD1Ev([[A]]* [[X]]) 125*67e74705SXin Li } 126*67e74705SXin Li 127*67e74705SXin Li namespace test2 { 128*67e74705SXin Li struct A { A(); ~A(); }; 129*67e74705SXin Li test()130*67e74705SXin Li void test() { 131*67e74705SXin Li A v[4][7]; 132*67e74705SXin Li 133*67e74705SXin Li // CHECK-LABEL: define void @_ZN5test24testEv() 134*67e74705SXin Li // CHECK-SAME: personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 135*67e74705SXin Li // CHECK: [[V:%.*]] = alloca [4 x [7 x [[A:%.*]]]], align 1 136*67e74705SXin Li // CHECK-NEXT: alloca i8* 137*67e74705SXin Li // CHECK-NEXT: alloca i32 138*67e74705SXin Li 139*67e74705SXin Li // Main initialization loop. 140*67e74705SXin Li // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [4 x [7 x [[A]]]], [4 x [7 x [[A]]]]* [[V]], i32 0, i32 0, i32 0 141*67e74705SXin Li // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 28 142*67e74705SXin Li // CHECK-NEXT: br label 143*67e74705SXin Li // CHECK: [[CUR:%.*]] = phi [[A]]* [ [[BEGIN]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] 144*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test21AC1Ev([[A]]* [[CUR]]) 145*67e74705SXin Li // CHECK: [[NEXT:%.*]] = getelementptr inbounds [[A]], [[A]]* [[CUR]], i64 1 146*67e74705SXin Li // CHECK-NEXT: [[DONE:%.*]] = icmp eq [[A]]* [[NEXT]], [[END]] 147*67e74705SXin Li // CHECK-NEXT: br i1 [[DONE]], 148*67e74705SXin Li 149*67e74705SXin Li // Partial destruction landing pad. 150*67e74705SXin Li // CHECK: landingpad { i8*, i32 } 151*67e74705SXin Li // CHECK-NEXT: cleanup 152*67e74705SXin Li // CHECK: [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[CUR]] 153*67e74705SXin Li // CHECK-NEXT: br i1 [[EMPTY]], 154*67e74705SXin Li // CHECK: [[PAST:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[DEL:%.*]], {{%.*}} ] 155*67e74705SXin Li // CHECK-NEXT: [[DEL]] = getelementptr inbounds [[A]], [[A]]* [[PAST]], i64 -1 156*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test21AD1Ev([[A]]* [[DEL]]) 157*67e74705SXin Li // CHECK: [[T0:%.*]] = icmp eq [[A]]* [[DEL]], [[BEGIN]] 158*67e74705SXin Li // CHECK-NEXT: br i1 [[T0]], 159*67e74705SXin Li } 160*67e74705SXin Li 161*67e74705SXin Li } 162*67e74705SXin Li 163*67e74705SXin Li // PR10351 164*67e74705SXin Li namespace test3 { 165*67e74705SXin Li struct A { A(); ~A(); void *p; }; 166*67e74705SXin Li struct B { Btest3::B167*67e74705SXin Li B() {} 168*67e74705SXin Li A a; 169*67e74705SXin Li }; 170*67e74705SXin Li test()171*67e74705SXin Li B *test() { 172*67e74705SXin Li return new B[10]; 173*67e74705SXin Li // invoke void @_ZN5test31BD1Ev( 174*67e74705SXin Li } 175*67e74705SXin Li } 176*67e74705SXin Li 177*67e74705SXin Li namespace test4 { 178*67e74705SXin Li struct A { A(unsigned i); ~A(); }; test()179*67e74705SXin Li void test() { 180*67e74705SXin Li A v[2][3] = { { A(0), A(1), A(2) }, { A(3), A(4), A(5) } }; 181*67e74705SXin Li } 182*67e74705SXin Li } 183*67e74705SXin Li // CHECK-LABEL: define void @_ZN5test44testEv() 184*67e74705SXin Li // CHECK: [[ARRAY:%.*]] = alloca [2 x [3 x [[A:%.*]]]], align 185*67e74705SXin Li // CHECK: [[A0:%.*]] = getelementptr inbounds [2 x [3 x [[A]]]], [2 x [3 x [[A]]]]* [[ARRAY]], i64 0, i64 0 186*67e74705SXin Li // CHECK-NEXT: store [3 x [[A]]]* [[A0]], 187*67e74705SXin Li // CHECK-NEXT: [[A00:%.*]] = getelementptr inbounds [3 x [[A]]], [3 x [[A]]]* [[A0]], i64 0, i64 0 188*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[A00]], 189*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A00]], i32 0) 190*67e74705SXin Li // CHECK: [[A01:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A00]], i64 1 191*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[A01]], 192*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A01]], i32 1) 193*67e74705SXin Li // CHECK: [[A02:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A01]], i64 1 194*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[A02]], 195*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A02]], i32 2) 196*67e74705SXin Li // CHECK: [[A1:%.*]] = getelementptr inbounds [3 x [[A]]], [3 x [[A]]]* [[A0]], i64 1 197*67e74705SXin Li // CHECK-NEXT: store [3 x [[A]]]* [[A1]], 198*67e74705SXin Li // CHECK-NEXT: [[A10:%.*]] = getelementptr inbounds [3 x [[A]]], [3 x [[A]]]* [[A1]], i64 0, i64 0 199*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[A10]], 200*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A10]], i32 3) 201*67e74705SXin Li // CHECK: [[A11:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A10]], i64 1 202*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[A11]], 203*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A11]], i32 4) 204*67e74705SXin Li // CHECK: [[A12:%.*]] = getelementptr inbounds [[A]], [[A]]* [[A11]], i64 1 205*67e74705SXin Li // CHECK-NEXT: store [[A]]* [[A12]], 206*67e74705SXin Li // CHECK-NEXT: invoke void @_ZN5test41AC1Ej([[A]]* [[A12]], i32 5) 207