1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s 2 void *f(); 3 4 template <typename T> T* g() { 5 if (T* t = f()) 6 return t; 7 8 return 0; 9 } 10 11 void h() { 12 void *a = g<void>(); 13 } 14 15 struct X { 16 X(); 17 X(const X&); 18 ~X(); 19 operator bool(); 20 }; 21 22 struct Y { 23 Y(); 24 ~Y(); 25 }; 26 27 X getX(); 28 29 // CHECK-LABEL: define void @_Z11if_destructi( 30 void if_destruct(int z) { 31 // Verify that the condition variable is destroyed at the end of the 32 // "if" statement. 33 // CHECK: call void @_ZN1XC1Ev 34 // CHECK: call zeroext i1 @_ZN1XcvbEv 35 if (X x = X()) { 36 // CHECK: store i32 18 37 z = 18; 38 } 39 // CHECK: call void @_ZN1XD1Ev 40 // CHECK: store i32 17 41 z = 17; 42 43 // CHECK: call void @_ZN1XC1Ev 44 if (X x = X()) 45 Y y; 46 // CHECK: br 47 // CHECK: call void @_ZN1YC1Ev 48 // CHECK: call void @_ZN1YD1Ev 49 // CHECK: br 50 // CHECK: call void @_ZN1XD1Ev 51 52 // CHECK: call void @_Z4getXv 53 // CHECK: call zeroext i1 @_ZN1XcvbEv 54 // CHECK: call void @_ZN1XD1Ev 55 // CHECK: br 56 if (getX()) { } 57 58 // CHECK: ret 59 } 60 61 struct ConvertibleToInt { 62 ConvertibleToInt(); 63 ~ConvertibleToInt(); 64 operator int(); 65 }; 66 67 ConvertibleToInt getConvToInt(); 68 69 void switch_destruct(int z) { 70 // CHECK: call void @_ZN16ConvertibleToIntC1Ev 71 switch (ConvertibleToInt conv = ConvertibleToInt()) { 72 case 0: 73 break; 74 75 default: 76 // CHECK: store i32 19 77 z = 19; 78 break; 79 } 80 // CHECK: call void @_ZN16ConvertibleToIntD1Ev 81 // CHECK: store i32 20 82 z = 20; 83 84 // CHECK: call void @_Z12getConvToIntv 85 // CHECK: call i32 @_ZN16ConvertibleToIntcviEv 86 // CHECK: call void @_ZN16ConvertibleToIntD1Ev 87 switch(getConvToInt()) { 88 case 0: 89 break; 90 } 91 // CHECK: store i32 27 92 z = 27; 93 // CHECK: ret 94 } 95 96 int foo(); 97 98 // CHECK-LABEL: define void @_Z14while_destructi 99 void while_destruct(int z) { 100 // CHECK: [[Z:%.*]] = alloca i32 101 // CHECK: [[CLEANUPDEST:%.*]] = alloca i32 102 while (X x = X()) { 103 // CHECK: call void @_ZN1XC1Ev 104 // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv 105 // CHECK-NEXT: br i1 [[COND]] 106 107 // Loop-exit staging block. 108 // CHECK: store i32 3, i32* [[CLEANUPDEST]] 109 // CHECK-NEXT: br 110 111 // While body. 112 // CHECK: store i32 21, i32* [[Z]] 113 // CHECK: store i32 0, i32* [[CLEANUPDEST]] 114 // CHECK-NEXT: br 115 z = 21; 116 117 // Cleanup. 118 // CHECK: call void @_ZN1XD1Ev 119 // CHECK-NEXT: [[DEST:%.*]] = load i32, i32* [[CLEANUPDEST]] 120 // CHECK-NEXT: switch i32 [[DEST]] 121 } 122 123 // CHECK: store i32 22, i32* [[Z]] 124 z = 22; 125 126 // CHECK: call void @_Z4getXv 127 // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv 128 // CHECK-NEXT: call void @_ZN1XD1Ev 129 // CHECK-NEXT: br 130 while(getX()) { } 131 132 // CHECK: store i32 25, i32* [[Z]] 133 z = 25; 134 135 // CHECK: ret 136 } 137 138 // CHECK-LABEL: define void @_Z12for_destructi( 139 void for_destruct(int z) { 140 // CHECK: [[Z:%.*]] = alloca i32 141 // CHECK: [[CLEANUPDEST:%.*]] = alloca i32 142 // CHECK: [[I:%.*]] = alloca i32 143 // CHECK: call void @_ZN1YC1Ev 144 // CHECK-NEXT: br 145 // -> %for.cond 146 147 for(Y y = Y(); X x = X(); ++z) { 148 // %for.cond: The loop condition. 149 // CHECK: call void @_ZN1XC1Ev 150 // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv( 151 // CHECK-NEXT: br i1 [[COND]] 152 // -> %for.body, %for.cond.cleanup 153 154 // %for.cond.cleanup: Exit cleanup staging. 155 // CHECK: store i32 2, i32* [[CLEANUPDEST]] 156 // CHECK-NEXT: br 157 // -> %cleanup 158 159 // %for.body: 160 // CHECK: store i32 23, i32* [[Z]] 161 // CHECK-NEXT: br 162 // -> %for.inc 163 z = 23; 164 165 // %for.inc: 166 // CHECK: [[TMP:%.*]] = load i32, i32* [[Z]] 167 // CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1 168 // CHECK-NEXT: store i32 [[INC]], i32* [[Z]] 169 // CHECK-NEXT: store i32 0, i32* [[CLEANUPDEST]] 170 // CHECK-NEXT: br 171 // -> %cleanup 172 173 // %cleanup: Destroys X. 174 // CHECK: call void @_ZN1XD1Ev 175 // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32, i32* [[CLEANUPDEST]] 176 // CHECK-NEXT: switch i32 [[YDESTTMP]] 177 // 0 -> %cleanup.cont, default -> %cleanup1 178 179 // %cleanup.cont: (eliminable) 180 // CHECK: br 181 // -> %for.cond 182 183 // %cleanup1: Destroys Y. 184 // CHECK: call void @_ZN1YD1Ev( 185 // CHECK-NEXT: br 186 // -> %for.end 187 } 188 189 // %for.end: 190 // CHECK: store i32 24 191 z = 24; 192 193 // CHECK-NEXT: store i32 0, i32* [[I]] 194 // CHECK-NEXT: br 195 // -> %for.cond6 196 197 // %for.cond6: 198 // CHECK: call void @_Z4getXv 199 // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv 200 // CHECK-NEXT: call void @_ZN1XD1Ev 201 // CHECK-NEXT: br 202 // -> %for.body10, %for.end16 203 204 // %for.body10: 205 // CHECK: br 206 // -> %for.inc11 207 208 // %for.inc11: 209 // CHECK: call void @_Z4getXv 210 // CHECK-NEXT: load i32, i32* [[I]] 211 // CHECK-NEXT: add 212 // CHECK-NEXT: store 213 // CHECK-NEXT: call void @_ZN1XD1Ev 214 // CHECK-NEXT: br 215 // -> %for.cond6 216 int i = 0; 217 for(; getX(); getX(), ++i) { } 218 219 // %for.end16 220 // CHECK: store i32 26 221 z = 26; 222 223 // CHECK-NEXT: ret void 224 } 225 226 void do_destruct(int z) { 227 // CHECK-LABEL: define void @_Z11do_destruct 228 do { 229 // CHECK: store i32 77 230 z = 77; 231 // CHECK: call void @_Z4getXv 232 // CHECK: call zeroext i1 @_ZN1XcvbEv 233 // CHECK: call void @_ZN1XD1Ev 234 // CHECK: br 235 } while (getX()); 236 // CHECK: store i32 99 237 z = 99; 238 // CHECK: ret 239 } 240 241 int f(X); 242 243 template<typename T> 244 int instantiated(T x) { 245 int result; 246 247 // CHECK: call void @_ZN1XC1ERKS_ 248 // CHECK: call i32 @_Z1f1X 249 // CHECK: call void @_ZN1XD1Ev 250 // CHECK: br 251 // CHECK: store i32 2 252 // CHECK: br 253 // CHECK: store i32 3 254 if (f(x)) { result = 2; } else { result = 3; } 255 256 // CHECK: call void @_ZN1XC1ERKS_ 257 // CHECK: call i32 @_Z1f1X 258 // CHECK: call void @_ZN1XD1Ev 259 // CHECK: br 260 // CHECK: store i32 4 261 // CHECK: br 262 while (f(x)) { result = 4; } 263 264 // CHECK: call void @_ZN1XC1ERKS_ 265 // CHECK: call i32 @_Z1f1X 266 // CHECK: call void @_ZN1XD1Ev 267 // CHECK: br 268 // CHECK: store i32 6 269 // CHECK: br 270 // CHECK: call void @_ZN1XC1ERKS_ 271 // CHECK: call i32 @_Z1f1X 272 // CHECK: store i32 5 273 // CHECK: call void @_ZN1XD1Ev 274 // CHECK: br 275 for (; f(x); f(x), result = 5) { 276 result = 6; 277 } 278 279 // CHECK: call void @_ZN1XC1ERKS_ 280 // CHECK: call i32 @_Z1f1X 281 // CHECK: call void @_ZN1XD1Ev 282 // CHECK: switch i32 283 // CHECK: store i32 7 284 // CHECK: store i32 8 285 switch (f(x)) { 286 case 0: 287 result = 7; 288 break; 289 290 case 1: 291 result = 8; 292 } 293 294 // CHECK: store i32 9 295 // CHECK: br 296 // CHECK: call void @_ZN1XC1ERKS_ 297 // CHECK: call i32 @_Z1f1X 298 // CHECK: call void @_ZN1XD1Ev 299 // CHECK: br 300 do { 301 result = 9; 302 } while (f(x)); 303 304 // CHECK: store i32 10 305 // CHECK: call void @_ZN1XC1ERKS_ 306 // CHECK: call zeroext i1 @_ZN1XcvbEv 307 // CHECK: call void @_ZN1XD1Ev 308 // CHECK: br 309 do { 310 result = 10; 311 } while (X(x)); 312 313 // CHECK: ret i32 314 return result; 315 } 316 317 template int instantiated(X); 318