1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s 2*f4a2713aSLionel Sambuc 3*f4a2713aSLionel Sambuc struct A { 4*f4a2713aSLionel Sambuc A(); 5*f4a2713aSLionel Sambuc ~A(); 6*f4a2713aSLionel Sambuc int a; 7*f4a2713aSLionel Sambuc }; 8*f4a2713aSLionel Sambuc 9*f4a2713aSLionel Sambuc A getA(); 10*f4a2713aSLionel Sambuc 11*f4a2713aSLionel Sambuc int TakesTwo(A a, A b); 12*f4a2713aSLionel Sambuc void HasEHCleanup() { 13*f4a2713aSLionel Sambuc TakesTwo(getA(), getA()); 14*f4a2713aSLionel Sambuc } 15*f4a2713aSLionel Sambuc 16*f4a2713aSLionel Sambuc // With exceptions, we need to clean up at least one of these temporaries. 17*f4a2713aSLionel Sambuc // WIN32: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { 18*f4a2713aSLionel Sambuc // First one doesn't have any cleanups, no need for invoke. 19*f4a2713aSLionel Sambuc // WIN32: call void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) 20*f4a2713aSLionel Sambuc // If this call throws, we have to cleanup the first temporary. 21*f4a2713aSLionel Sambuc // WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) 22*f4a2713aSLionel Sambuc // If this call throws, we already popped our cleanups 23*f4a2713aSLionel Sambuc // WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" 24*f4a2713aSLionel Sambuc // WIN32: ret void 25*f4a2713aSLionel Sambuc // 26*f4a2713aSLionel Sambuc // There should be one dtor call for unwinding from the second getA. 27*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 28*f4a2713aSLionel Sambuc // WIN32: } 29*f4a2713aSLionel Sambuc 30*f4a2713aSLionel Sambuc void TakeRef(const A &a); 31*f4a2713aSLionel Sambuc int HasDeactivatedCleanups() { 32*f4a2713aSLionel Sambuc return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())); 33*f4a2713aSLionel Sambuc } 34*f4a2713aSLionel Sambuc 35*f4a2713aSLionel Sambuc // WIN32: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { 36*f4a2713aSLionel Sambuc // WIN32: %[[isactive:.*]] = alloca i1 37*f4a2713aSLionel Sambuc // WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 38*f4a2713aSLionel Sambuc // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 39*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]]) 40*f4a2713aSLionel Sambuc // WIN32: store i1 true, i1* %[[isactive]] 41*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 42*f4a2713aSLionel Sambuc // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 43*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 44*f4a2713aSLionel Sambuc // WIN32: store i1 false, i1* %[[isactive]] 45*f4a2713aSLionel Sambuc // WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" 46*f4a2713aSLionel Sambuc // Destroy the two const ref temporaries. 47*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 48*f4a2713aSLionel Sambuc // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" 49*f4a2713aSLionel Sambuc // WIN32: ret i32 50*f4a2713aSLionel Sambuc // 51*f4a2713aSLionel Sambuc // Conditionally destroy arg1. 52*f4a2713aSLionel Sambuc // WIN32: %[[cond:.*]] = load i1* %[[isactive]] 53*f4a2713aSLionel Sambuc // WIN32: br i1 %[[cond]] 54*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) 55*f4a2713aSLionel Sambuc // WIN32: } 56*f4a2713aSLionel Sambuc 57*f4a2713aSLionel Sambuc // Test putting the cleanups inside a conditional. 58*f4a2713aSLionel Sambuc int CouldThrow(); 59*f4a2713aSLionel Sambuc int HasConditionalCleanup(bool cond) { 60*f4a2713aSLionel Sambuc return (cond ? TakesTwo(A(), A()) : CouldThrow()); 61*f4a2713aSLionel Sambuc } 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc // WIN32: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} { 64*f4a2713aSLionel Sambuc // WIN32: store i1 false 65*f4a2713aSLionel Sambuc // WIN32: br i1 66*f4a2713aSLionel Sambuc // No cleanups, so we call and then activate a cleanup if it succeeds. 67*f4a2713aSLionel Sambuc // WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1:.*]]) 68*f4a2713aSLionel Sambuc // WIN32: store i1 true 69*f4a2713aSLionel Sambuc // Now we have a cleanup for the first aggregate, so we invoke. 70*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) 71*f4a2713aSLionel Sambuc // Now we have no cleanups because TakeTwo will destruct both args. 72*f4a2713aSLionel Sambuc // WIN32: call i32 @"\01?TakesTwo@@YAHUA@@0@Z" 73*f4a2713aSLionel Sambuc // Still no cleanups, so call. 74*f4a2713aSLionel Sambuc // WIN32: call i32 @"\01?CouldThrow@@YAHXZ"() 75*f4a2713aSLionel Sambuc // Somewhere in the landing pad for our single invoke, call the dtor. 76*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) 77*f4a2713aSLionel Sambuc // WIN32: } 78*f4a2713aSLionel Sambuc 79*f4a2713aSLionel Sambuc // Now test both. 80*f4a2713aSLionel Sambuc int HasConditionalDeactivatedCleanups(bool cond) { 81*f4a2713aSLionel Sambuc return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); 82*f4a2713aSLionel Sambuc } 83*f4a2713aSLionel Sambuc 84*f4a2713aSLionel Sambuc // WIN32: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { 85*f4a2713aSLionel Sambuc // WIN32: %[[arg1:.*]] = alloca %struct.A, align 4 86*f4a2713aSLionel Sambuc // WIN32: alloca i1 87*f4a2713aSLionel Sambuc // WIN32: %[[arg1_cond:.*]] = alloca i1 88*f4a2713aSLionel Sambuc // Start all four cleanups as deactivated. 89*f4a2713aSLionel Sambuc // WIN32: store i1 false 90*f4a2713aSLionel Sambuc // WIN32: store i1 false 91*f4a2713aSLionel Sambuc // WIN32: store i1 false 92*f4a2713aSLionel Sambuc // WIN32: store i1 false 93*f4a2713aSLionel Sambuc // WIN32: br i1 94*f4a2713aSLionel Sambuc // True condition. 95*f4a2713aSLionel Sambuc // WIN32: call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 96*f4a2713aSLionel Sambuc // WIN32: store i1 true 97*f4a2713aSLionel Sambuc // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 98*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) 99*f4a2713aSLionel Sambuc // WIN32: store i1 true, i1* %[[arg1_cond]] 100*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 101*f4a2713aSLionel Sambuc // WIN32: store i1 true 102*f4a2713aSLionel Sambuc // WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 103*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 104*f4a2713aSLionel Sambuc // WIN32: store i1 true 105*f4a2713aSLionel Sambuc // WIN32: store i1 false, i1* %[[arg1_cond]] 106*f4a2713aSLionel Sambuc // WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" 107*f4a2713aSLionel Sambuc // False condition. 108*f4a2713aSLionel Sambuc // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() 109*f4a2713aSLionel Sambuc // Two normal cleanups for TakeRef args. 110*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 111*f4a2713aSLionel Sambuc // WIN32: call x86_thiscallcc void @"\01??1A@@QAE@XZ" 112*f4a2713aSLionel Sambuc // WIN32: ret i32 113*f4a2713aSLionel Sambuc // 114*f4a2713aSLionel Sambuc // Somewhere in the landing pad soup, we conditionally destroy arg1. 115*f4a2713aSLionel Sambuc // WIN32: %[[isactive:.*]] = load i1* %[[arg1_cond]] 116*f4a2713aSLionel Sambuc // WIN32: br i1 %[[isactive]] 117*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) 118*f4a2713aSLionel Sambuc // WIN32: } 119*f4a2713aSLionel Sambuc 120*f4a2713aSLionel Sambuc namespace crash_on_partial_destroy { 121*f4a2713aSLionel Sambuc struct A { 122*f4a2713aSLionel Sambuc virtual ~A(); 123*f4a2713aSLionel Sambuc }; 124*f4a2713aSLionel Sambuc 125*f4a2713aSLionel Sambuc struct B : virtual A { 126*f4a2713aSLionel Sambuc // Has an implicit destructor. 127*f4a2713aSLionel Sambuc }; 128*f4a2713aSLionel Sambuc 129*f4a2713aSLionel Sambuc struct C : B { 130*f4a2713aSLionel Sambuc C(); 131*f4a2713aSLionel Sambuc }; 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc void foo(); 134*f4a2713aSLionel Sambuc // We used to crash when emitting this. 135*f4a2713aSLionel Sambuc C::C() { foo(); } 136*f4a2713aSLionel Sambuc 137*f4a2713aSLionel Sambuc // Verify that we don't bother with a vbtable lookup when adjusting the this 138*f4a2713aSLionel Sambuc // pointer to call a base destructor from a constructor while unwinding. 139*f4a2713aSLionel Sambuc // WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} { 140*f4a2713aSLionel Sambuc // WIN32: landingpad 141*f4a2713aSLionel Sambuc // 142*f4a2713aSLionel Sambuc // We shouldn't do any vbptr loads, just constant GEPs. 143*f4a2713aSLionel Sambuc // WIN32-NOT: load 144*f4a2713aSLionel Sambuc // WIN32: getelementptr i8* %{{.*}}, i32 4 145*f4a2713aSLionel Sambuc // WIN32-NOT: load 146*f4a2713aSLionel Sambuc // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"* 147*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" 148*f4a2713aSLionel Sambuc // 149*f4a2713aSLionel Sambuc // WIN32-NOT: load 150*f4a2713aSLionel Sambuc // WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8* 151*f4a2713aSLionel Sambuc // WIN32-NOT: load 152*f4a2713aSLionel Sambuc // WIN32: getelementptr inbounds i8* %{{.*}}, i64 4 153*f4a2713aSLionel Sambuc // WIN32-NOT: load 154*f4a2713aSLionel Sambuc // WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* 155*f4a2713aSLionel Sambuc // WIN32: invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ" 156*f4a2713aSLionel Sambuc // WIN32: } 157*f4a2713aSLionel Sambuc } 158