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