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