1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s 2*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s 3*f4a2713aSLionel Sambuc 4*f4a2713aSLionel Sambuc // Test code generation for the named return value optimization. 5*f4a2713aSLionel Sambuc class X { 6*f4a2713aSLionel Sambuc public: 7*f4a2713aSLionel Sambuc X(); 8*f4a2713aSLionel Sambuc X(const X&); 9*f4a2713aSLionel Sambuc ~X(); 10*f4a2713aSLionel Sambuc }; 11*f4a2713aSLionel Sambuc 12*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test0v 13*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test0v 14*f4a2713aSLionel Sambuc X test0() { 15*f4a2713aSLionel Sambuc X x; 16*f4a2713aSLionel Sambuc // CHECK: call {{.*}} @_ZN1XC1Ev 17*f4a2713aSLionel Sambuc // CHECK-NEXT: ret void 18*f4a2713aSLionel Sambuc 19*f4a2713aSLionel Sambuc // CHECK-EH: call {{.*}} @_ZN1XC1Ev 20*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: ret void 21*f4a2713aSLionel Sambuc return x; 22*f4a2713aSLionel Sambuc } 23*f4a2713aSLionel Sambuc 24*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test1b( 25*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test1b( 26*f4a2713aSLionel Sambuc X test1(bool B) { 27*f4a2713aSLionel Sambuc // CHECK: tail call {{.*}} @_ZN1XC1Ev 28*f4a2713aSLionel Sambuc // CHECK-NEXT: ret void 29*f4a2713aSLionel Sambuc X x; 30*f4a2713aSLionel Sambuc if (B) 31*f4a2713aSLionel Sambuc return (x); 32*f4a2713aSLionel Sambuc return x; 33*f4a2713aSLionel Sambuc // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev 34*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: ret void 35*f4a2713aSLionel Sambuc } 36*f4a2713aSLionel Sambuc 37*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test2b 38*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test2b 39*f4a2713aSLionel Sambuc X test2(bool B) { 40*f4a2713aSLionel Sambuc // No NRVO. 41*f4a2713aSLionel Sambuc 42*f4a2713aSLionel Sambuc X x; 43*f4a2713aSLionel Sambuc X y; 44*f4a2713aSLionel Sambuc if (B) 45*f4a2713aSLionel Sambuc return y; 46*f4a2713aSLionel Sambuc return x; 47*f4a2713aSLionel Sambuc 48*f4a2713aSLionel Sambuc // CHECK: call {{.*}} @_ZN1XC1Ev 49*f4a2713aSLionel Sambuc // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev 50*f4a2713aSLionel Sambuc // CHECK: call {{.*}} @_ZN1XC1ERKS_ 51*f4a2713aSLionel Sambuc // CHECK: call {{.*}} @_ZN1XC1ERKS_ 52*f4a2713aSLionel Sambuc // CHECK: call {{.*}} @_ZN1XD1Ev 53*f4a2713aSLionel Sambuc // CHECK: call {{.*}} @_ZN1XD1Ev 54*f4a2713aSLionel Sambuc // CHECK: ret void 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc // The block ordering in the -fexceptions IR is unfortunate. 57*f4a2713aSLionel Sambuc 58*f4a2713aSLionel Sambuc // CHECK-EH: call {{.*}} @_ZN1XC1Ev 59*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev 60*f4a2713aSLionel Sambuc // -> %invoke.cont, %lpad 61*f4a2713aSLionel Sambuc 62*f4a2713aSLionel Sambuc // %invoke.cont: 63*f4a2713aSLionel Sambuc // CHECK-EH: br i1 64*f4a2713aSLionel Sambuc // -> %if.then, %if.end 65*f4a2713aSLionel Sambuc 66*f4a2713aSLionel Sambuc // %if.then: returning 'x' 67*f4a2713aSLionel Sambuc // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ 68*f4a2713aSLionel Sambuc // -> %cleanup, %lpad1 69*f4a2713aSLionel Sambuc 70*f4a2713aSLionel Sambuc // %lpad: landing pad for ctor of 'y', dtor of 'y' 71*f4a2713aSLionel Sambuc // CHECK-EH: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 72*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: cleanup 73*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0 74*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1 75*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: br label 76*f4a2713aSLionel Sambuc // -> %eh.cleanup 77*f4a2713aSLionel Sambuc 78*f4a2713aSLionel Sambuc // %lpad1: landing pad for return copy ctors, EH cleanup for 'y' 79*f4a2713aSLionel Sambuc // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev 80*f4a2713aSLionel Sambuc // -> %eh.cleanup, %terminate.lpad 81*f4a2713aSLionel Sambuc 82*f4a2713aSLionel Sambuc // %if.end: returning 'y' 83*f4a2713aSLionel Sambuc // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ 84*f4a2713aSLionel Sambuc // -> %cleanup, %lpad1 85*f4a2713aSLionel Sambuc 86*f4a2713aSLionel Sambuc // %cleanup: normal cleanup for 'y' 87*f4a2713aSLionel Sambuc // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev 88*f4a2713aSLionel Sambuc // -> %invoke.cont11, %lpad 89*f4a2713aSLionel Sambuc 90*f4a2713aSLionel Sambuc // %invoke.cont11: normal cleanup for 'x' 91*f4a2713aSLionel Sambuc // CHECK-EH: call {{.*}} @_ZN1XD1Ev 92*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: ret void 93*f4a2713aSLionel Sambuc 94*f4a2713aSLionel Sambuc // %eh.cleanup: EH cleanup for 'x' 95*f4a2713aSLionel Sambuc // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev 96*f4a2713aSLionel Sambuc // -> %invoke.cont17, %terminate.lpad 97*f4a2713aSLionel Sambuc 98*f4a2713aSLionel Sambuc // %invoke.cont17: rethrow block for %eh.cleanup. 99*f4a2713aSLionel Sambuc // This really should be elsewhere in the function. 100*f4a2713aSLionel Sambuc // CHECK-EH: resume { i8*, i32 } 101*f4a2713aSLionel Sambuc 102*f4a2713aSLionel Sambuc // %terminate.lpad: terminate landing pad. 103*f4a2713aSLionel Sambuc // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 104*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: catch i8* null 105*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 106*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]] 107*f4a2713aSLionel Sambuc // CHECK-EH-NEXT: unreachable 108*f4a2713aSLionel Sambuc 109*f4a2713aSLionel Sambuc } 110*f4a2713aSLionel Sambuc 111*f4a2713aSLionel Sambuc X test3(bool B) { 112*f4a2713aSLionel Sambuc // FIXME: We don't manage to apply NRVO here, although we could. 113*f4a2713aSLionel Sambuc { 114*f4a2713aSLionel Sambuc X y; 115*f4a2713aSLionel Sambuc return y; 116*f4a2713aSLionel Sambuc } 117*f4a2713aSLionel Sambuc X x; 118*f4a2713aSLionel Sambuc return x; 119*f4a2713aSLionel Sambuc } 120*f4a2713aSLionel Sambuc 121*f4a2713aSLionel Sambuc extern "C" void exit(int) throw(); 122*f4a2713aSLionel Sambuc 123*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test4b 124*f4a2713aSLionel Sambuc X test4(bool B) { 125*f4a2713aSLionel Sambuc { 126*f4a2713aSLionel Sambuc // CHECK: tail call {{.*}} @_ZN1XC1Ev 127*f4a2713aSLionel Sambuc X x; 128*f4a2713aSLionel Sambuc // CHECK: br i1 129*f4a2713aSLionel Sambuc if (B) 130*f4a2713aSLionel Sambuc return x; 131*f4a2713aSLionel Sambuc } 132*f4a2713aSLionel Sambuc // CHECK: tail call {{.*}} @_ZN1XD1Ev 133*f4a2713aSLionel Sambuc // CHECK: tail call void @exit(i32 1) 134*f4a2713aSLionel Sambuc exit(1); 135*f4a2713aSLionel Sambuc } 136*f4a2713aSLionel Sambuc 137*f4a2713aSLionel Sambuc #ifdef __EXCEPTIONS 138*f4a2713aSLionel Sambuc // CHECK-EH-LABEL: define void @_Z5test5 139*f4a2713aSLionel Sambuc void may_throw(); 140*f4a2713aSLionel Sambuc X test5() { 141*f4a2713aSLionel Sambuc try { 142*f4a2713aSLionel Sambuc may_throw(); 143*f4a2713aSLionel Sambuc } catch (X x) { 144*f4a2713aSLionel Sambuc // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ 145*f4a2713aSLionel Sambuc // CHECK-EH: call void @__cxa_end_catch() 146*f4a2713aSLionel Sambuc // CHECK-EH: ret void 147*f4a2713aSLionel Sambuc return x; 148*f4a2713aSLionel Sambuc } 149*f4a2713aSLionel Sambuc } 150*f4a2713aSLionel Sambuc #endif 151*f4a2713aSLionel Sambuc 152*f4a2713aSLionel Sambuc // rdar://problem/10430868 153*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @_Z5test6v 154*f4a2713aSLionel Sambuc X test6() { 155*f4a2713aSLionel Sambuc X a __attribute__((aligned(8))); 156*f4a2713aSLionel Sambuc return a; 157*f4a2713aSLionel Sambuc // CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8 158*f4a2713aSLionel Sambuc // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]]) 159*f4a2713aSLionel Sambuc // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]]) 160*f4a2713aSLionel Sambuc // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]]) 161*f4a2713aSLionel Sambuc // CHECK-NEXT: ret void 162*f4a2713aSLionel Sambuc } 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind } 165