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: {{.*}} getelementptr inbounds %class.X, %class.X* %y, i32 0, i32 0 58 // CHECK-NEXT: call void @llvm.lifetime.start 59 // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev 60 // CHECK: call {{.*}} @_ZN1XC1ERKS_ 61 // CHECK: call {{.*}} @_ZN1XC1ERKS_ 62 // CHECK: call {{.*}} @_ZN1XD1Ev 63 // CHECK-NEXT: call void @llvm.lifetime.end 64 // CHECK: call {{.*}} @_ZN1XD1Ev 65 // CHECK-NEXT: call void @llvm.lifetime.end 66 // CHECK: ret void 67 68 // The block ordering in the -fexceptions IR is unfortunate. 69 70 // CHECK-EH: call void @llvm.lifetime.start 71 // CHECK-EH-NEXT: call {{.*}} @_ZN1XC1Ev 72 // CHECK-EH: call void @llvm.lifetime.start 73 // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev 74 // -> %invoke.cont, %lpad 75 76 // %invoke.cont: 77 // CHECK-EH: br i1 78 // -> %if.then, %if.end 79 80 // %if.then: returning 'x' 81 // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ 82 // -> %cleanup, %lpad1 83 84 // %lpad: landing pad for ctor of 'y', dtor of 'y' 85 // CHECK-EH: [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 86 // CHECK-EH-NEXT: cleanup 87 // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0 88 // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1 89 // CHECK-EH-NEXT: br label 90 // -> %eh.cleanup 91 92 // %lpad1: landing pad for return copy ctors, EH cleanup for 'y' 93 // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev 94 // -> %eh.cleanup, %terminate.lpad 95 96 // %if.end: returning 'y' 97 // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ 98 // -> %cleanup, %lpad1 99 100 // %cleanup: normal cleanup for 'y' 101 // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev 102 // -> %invoke.cont11, %lpad 103 104 // %invoke.cont11: normal cleanup for 'x' 105 // CHECK-EH: call void @llvm.lifetime.end 106 // CHECK-EH-NEXT: call {{.*}} @_ZN1XD1Ev 107 // CHECK-EH-NEXT: call void @llvm.lifetime.end 108 // CHECK-EH-NEXT: ret void 109 110 // %eh.cleanup: EH cleanup for 'x' 111 // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev 112 // -> %invoke.cont17, %terminate.lpad 113 114 // %invoke.cont17: rethrow block for %eh.cleanup. 115 // This really should be elsewhere in the function. 116 // CHECK-EH: resume { i8*, i32 } 117 118 // %terminate.lpad: terminate landing pad. 119 // CHECK-EH: [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) 120 // CHECK-EH-NEXT: catch i8* null 121 // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0 122 // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]] 123 // CHECK-EH-NEXT: unreachable 124 125 } 126 127 // CHECK-LABEL: define void @_Z5test3b 128 X test3(bool B) { 129 // CHECK: tail call {{.*}} @_ZN1XC1Ev 130 // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ 131 // CHECK: call {{.*}} @_ZN1XC1Ev 132 // CHECK: call {{.*}} @_ZN1XC1ERKS_ 133 if (B) { 134 X y; 135 return y; 136 } 137 // FIXME: we should NRVO this variable too. 138 X x; 139 return x; 140 } 141 142 extern "C" void exit(int) throw(); 143 144 // CHECK-LABEL: define void @_Z5test4b 145 X test4(bool B) { 146 { 147 // CHECK: tail call {{.*}} @_ZN1XC1Ev 148 X x; 149 // CHECK: br i1 150 if (B) 151 return x; 152 } 153 // CHECK: tail call {{.*}} @_ZN1XD1Ev 154 // CHECK: tail call void @exit(i32 1) 155 exit(1); 156 } 157 158 #ifdef __EXCEPTIONS 159 // CHECK-EH-LABEL: define void @_Z5test5 160 void may_throw(); 161 X test5() { 162 try { 163 may_throw(); 164 } catch (X x) { 165 // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_ 166 // CHECK-EH: call void @__cxa_end_catch() 167 // CHECK-EH: ret void 168 return x; 169 } 170 } 171 #endif 172 173 // rdar://problem/10430868 174 // CHECK-LABEL: define void @_Z5test6v 175 X test6() { 176 X a __attribute__((aligned(8))); 177 return a; 178 // CHECK: [[A:%.*]] = alloca [[X:%.*]], align 8 179 // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0 180 // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[PTR]]) 181 // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]]) 182 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* dereferenceable({{[0-9]+}}) [[A]]) 183 // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]]) 184 // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[PTR]]) 185 // CHECK-NEXT: ret void 186 } 187 188 // CHECK-LABEL: define void @_Z5test7b 189 X test7(bool b) { 190 // CHECK: tail call {{.*}} @_ZN1XC1Ev 191 // CHECK-NEXT: ret 192 if (b) { 193 X x; 194 return x; 195 } 196 return X(); 197 } 198 199 // CHECK-LABEL: define void @_Z5test8b 200 X test8(bool b) { 201 // CHECK: tail call {{.*}} @_ZN1XC1Ev 202 // CHECK-NEXT: ret 203 if (b) { 204 X x; 205 return x; 206 } else { 207 X y; 208 return y; 209 } 210 } 211 212 Y<int> test9() { 213 Y<int>::f(); 214 } 215 216 // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv 217 // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev 218 219 // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind } 220