1 // RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s 2 3 namespace std { 4 typedef decltype(sizeof(int)) size_t; 5 6 // libc++'s implementation 7 template <class _E> 8 class initializer_list 9 { 10 const _E* __begin_; 11 size_t __size_; 12 13 initializer_list(const _E* __b, size_t __s) 14 : __begin_(__b), 15 __size_(__s) 16 {} 17 18 public: 19 typedef _E value_type; 20 typedef const _E& reference; 21 typedef const _E& const_reference; 22 typedef size_t size_type; 23 24 typedef const _E* iterator; 25 typedef const _E* const_iterator; 26 27 initializer_list() : __begin_(nullptr), __size_(0) {} 28 29 size_t size() const {return __size_;} 30 const _E* begin() const {return __begin_;} 31 const _E* end() const {return __begin_ + __size_;} 32 }; 33 } 34 35 struct destroyme1 { 36 ~destroyme1(); 37 }; 38 struct destroyme2 { 39 ~destroyme2(); 40 }; 41 struct witharg1 { 42 witharg1(const destroyme1&); 43 ~witharg1(); 44 }; 45 struct wantslist1 { 46 wantslist1(std::initializer_list<destroyme1>); 47 ~wantslist1(); 48 }; 49 50 // CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3] 51 // CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, i32 0, i32 0), i{{32|64}} 3 } 52 std::initializer_list<int> globalInitList1 = {1, 2, 3}; 53 54 namespace thread_local_global_array { 55 // FIXME: We should be able to constant-evaluate this even though the 56 // initializer is not a constant expression (pointers to thread_local 57 // objects aren't really a problem). 58 // 59 // CHECK: @_ZN25thread_local_global_array1xE = thread_local global 60 // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] 61 std::initializer_list<int> thread_local x = { 1, 2, 3, 4 }; 62 } 63 64 // CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer 65 // CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer 66 67 // CHECK: @_ZN15partly_constant1kE = global i32 0, align 4 68 // CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 69 // CHECK: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = private global {{.*}} zeroinitializer, align 8 70 // CHECK: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = private global [3 x {{.*}}] zeroinitializer, align 8 71 // CHECK: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4 72 // CHECK: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = private global [2 x i32] zeroinitializer, align 4 73 // CHECK: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = private constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 74 75 // CHECK: appending global 76 77 78 // thread_local initializer: 79 // CHECK: define internal void 80 // CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0), 81 // CHECK: i32** getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8 82 // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8 83 84 85 // CHECK: define internal void 86 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 0 87 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 1 88 // CHECK: __cxa_atexit 89 // CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i64 0, i64 0), 90 // CHECK: %[[WITHARG]]** getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 0), align 8 91 // CHECK: store i64 2, i64* getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 1), align 8 92 // CHECK: call void @_ZN10destroyme1D1Ev 93 // CHECK: call void @_ZN10destroyme1D1Ev 94 std::initializer_list<witharg1> globalInitList2 = { 95 witharg1(destroyme1()), witharg1(destroyme1()) 96 }; 97 98 void fn1(int i) { 99 // CHECK: define void @_Z3fn1i 100 // temporary array 101 // CHECK: [[array:%[^ ]+]] = alloca [3 x i32] 102 // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0 103 // CHECK-NEXT: store i32 1, i32* 104 // CHECK-NEXT: getelementptr 105 // CHECK-NEXT: store 106 // CHECK-NEXT: getelementptr 107 // CHECK-NEXT: load 108 // CHECK-NEXT: store 109 // init the list 110 // CHECK-NEXT: getelementptr 111 // CHECK-NEXT: getelementptr inbounds [3 x i32]* 112 // CHECK-NEXT: store i32* 113 // CHECK-NEXT: getelementptr 114 // CHECK-NEXT: store i{{32|64}} 3 115 std::initializer_list<int> intlist{1, 2, i}; 116 } 117 118 void fn2() { 119 // CHECK: define void @_Z3fn2v 120 void target(std::initializer_list<destroyme1>); 121 // objects should be destroyed before dm2, after call returns 122 // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E 123 target({ destroyme1(), destroyme1() }); 124 // CHECK: call void @_ZN10destroyme1D1Ev 125 destroyme2 dm2; 126 // CHECK: call void @_ZN10destroyme2D1Ev 127 } 128 129 void fn3() { 130 // CHECK: define void @_Z3fn3v 131 // objects should be destroyed after dm2 132 auto list = { destroyme1(), destroyme1() }; 133 destroyme2 dm2; 134 // CHECK: call void @_ZN10destroyme2D1Ev 135 // CHECK: call void @_ZN10destroyme1D1Ev 136 } 137 138 void fn4() { 139 // CHECK: define void @_Z3fn4v 140 void target(std::initializer_list<witharg1>); 141 // objects should be destroyed before dm2, after call returns 142 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 143 // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E 144 target({ witharg1(destroyme1()), witharg1(destroyme1()) }); 145 // CHECK: call void @_ZN8witharg1D1Ev 146 // CHECK: call void @_ZN10destroyme1D1Ev 147 destroyme2 dm2; 148 // CHECK: call void @_ZN10destroyme2D1Ev 149 } 150 151 void fn5() { 152 // CHECK: define void @_Z3fn5v 153 // temps should be destroyed before dm2 154 // objects should be destroyed after dm2 155 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 156 auto list = { witharg1(destroyme1()), witharg1(destroyme1()) }; 157 // CHECK: call void @_ZN10destroyme1D1Ev 158 destroyme2 dm2; 159 // CHECK: call void @_ZN10destroyme2D1Ev 160 // CHECK: call void @_ZN8witharg1D1Ev 161 } 162 163 void fn6() { 164 // CHECK: define void @_Z3fn6v 165 void target(const wantslist1&); 166 // objects should be destroyed before dm2, after call returns 167 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E 168 // CHECK: call void @_Z6targetRK10wantslist1 169 target({ destroyme1(), destroyme1() }); 170 // CHECK: call void @_ZN10wantslist1D1Ev 171 // CHECK: call void @_ZN10destroyme1D1Ev 172 destroyme2 dm2; 173 // CHECK: call void @_ZN10destroyme2D1Ev 174 } 175 176 void fn7() { 177 // CHECK: define void @_Z3fn7v 178 // temps should be destroyed before dm2 179 // object should be destroyed after dm2 180 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E 181 wantslist1 wl = { destroyme1(), destroyme1() }; 182 // CHECK: call void @_ZN10destroyme1D1Ev 183 destroyme2 dm2; 184 // CHECK: call void @_ZN10destroyme2D1Ev 185 // CHECK: call void @_ZN10wantslist1D1Ev 186 } 187 188 void fn8() { 189 // CHECK: define void @_Z3fn8v 190 void target(std::initializer_list<std::initializer_list<destroyme1>>); 191 // objects should be destroyed before dm2, after call returns 192 // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE 193 std::initializer_list<destroyme1> inner; 194 target({ inner, { destroyme1() } }); 195 // CHECK: call void @_ZN10destroyme1D1Ev 196 // Only one destroy loop, since only one inner init list is directly inited. 197 // CHECK-NOT: call void @_ZN10destroyme1D1Ev 198 destroyme2 dm2; 199 // CHECK: call void @_ZN10destroyme2D1Ev 200 } 201 202 void fn9() { 203 // CHECK: define void @_Z3fn9v 204 // objects should be destroyed after dm2 205 std::initializer_list<destroyme1> inner; 206 std::initializer_list<std::initializer_list<destroyme1>> list = 207 { inner, { destroyme1() } }; 208 destroyme2 dm2; 209 // CHECK: call void @_ZN10destroyme2D1Ev 210 // CHECK: call void @_ZN10destroyme1D1Ev 211 // Only one destroy loop, since only one inner init list is directly inited. 212 // CHECK-NOT: call void @_ZN10destroyme1D1Ev 213 // CHECK: ret void 214 } 215 216 struct haslist1 { 217 std::initializer_list<int> il; 218 haslist1(); 219 }; 220 221 // CHECK: define void @_ZN8haslist1C2Ev 222 haslist1::haslist1() 223 // CHECK: alloca [3 x i32] 224 // CHECK: store i32 1 225 // CHECK: store i32 2 226 // CHECK: store i32 3 227 // CHECK: store i{{32|64}} 3 228 : il{1, 2, 3} 229 { 230 destroyme2 dm2; 231 } 232 233 struct haslist2 { 234 std::initializer_list<destroyme1> il; 235 haslist2(); 236 }; 237 238 // CHECK: define void @_ZN8haslist2C2Ev 239 haslist2::haslist2() 240 : il{destroyme1(), destroyme1()} 241 { 242 destroyme2 dm2; 243 // CHECK: call void @_ZN10destroyme2D1Ev 244 // CHECK: call void @_ZN10destroyme1D1Ev 245 } 246 247 void fn10() { 248 // CHECK: define void @_Z4fn10v 249 // CHECK: alloca [3 x i32] 250 // CHECK: call noalias i8* @_Znw{{[jm]}} 251 // CHECK: store i32 1 252 // CHECK: store i32 2 253 // CHECK: store i32 3 254 // CHECK: store i32* 255 // CHECK: store i{{32|64}} 3 256 (void) new std::initializer_list<int> {1, 2, 3}; 257 } 258 259 void fn11() { 260 // CHECK: define void @_Z4fn11v 261 (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()}; 262 // CHECK: call void @_ZN10destroyme1D1Ev 263 destroyme2 dm2; 264 // CHECK: call void @_ZN10destroyme2D1Ev 265 } 266 267 namespace PR12178 { 268 struct string { 269 string(int); 270 ~string(); 271 }; 272 273 struct pair { 274 string a; 275 int b; 276 }; 277 278 struct map { 279 map(std::initializer_list<pair>); 280 }; 281 282 map m{ {1, 2}, {3, 4} }; 283 } 284 285 namespace rdar13325066 { 286 struct X { ~X(); }; 287 288 // CHECK: define void @_ZN12rdar133250664loopERNS_1XES1_ 289 void loop(X &x1, X &x2) { 290 // CHECK: br label 291 // CHECK: br i1 292 // CHECK: br label 293 // CHECK call void @_ZN12rdar133250661XD1Ev 294 // CHECK: br label 295 // CHECK: br label 296 // CHECK: call void @_ZN12rdar133250661XD1Ev 297 // CHECK: br i1 298 // CHECK: br label 299 // CHECK: ret void 300 for (X x : { x1, x2 }) { } 301 } 302 } 303 304 namespace dtors { 305 struct S { 306 S(); 307 ~S(); 308 }; 309 void z(); 310 311 // CHECK: define void @_ZN5dtors1fEv( 312 void f() { 313 // CHECK: call void @_ZN5dtors1SC1Ev( 314 // CHECK: call void @_ZN5dtors1SC1Ev( 315 std::initializer_list<S>{ S(), S() }; 316 317 // Destruction loop for underlying array. 318 // CHECK: br label 319 // CHECK: call void @_ZN5dtors1SD1Ev( 320 // CHECK: br i1 321 322 // CHECK: call void @_ZN5dtors1zEv( 323 z(); 324 325 // CHECK-NOT: call void @_ZN5dtors1SD1Ev( 326 } 327 328 // CHECK: define void @_ZN5dtors1gEv( 329 void g() { 330 // CHECK: call void @_ZN5dtors1SC1Ev( 331 // CHECK: call void @_ZN5dtors1SC1Ev( 332 auto x = std::initializer_list<S>{ S(), S() }; 333 334 // Destruction loop for underlying array. 335 // CHECK: br label 336 // CHECK: call void @_ZN5dtors1SD1Ev( 337 // CHECK: br i1 338 339 // CHECK: call void @_ZN5dtors1zEv( 340 z(); 341 342 // CHECK-NOT: call void @_ZN5dtors1SD1Ev( 343 } 344 345 // CHECK: define void @_ZN5dtors1hEv( 346 void h() { 347 // CHECK: call void @_ZN5dtors1SC1Ev( 348 // CHECK: call void @_ZN5dtors1SC1Ev( 349 std::initializer_list<S> x = { S(), S() }; 350 351 // CHECK-NOT: call void @_ZN5dtors1SD1Ev( 352 353 // CHECK: call void @_ZN5dtors1zEv( 354 z(); 355 356 // Destruction loop for underlying array. 357 // CHECK: br label 358 // CHECK: call void @_ZN5dtors1SD1Ev( 359 // CHECK: br i1 360 } 361 } 362 363 namespace partly_constant { 364 int k; 365 std::initializer_list<std::initializer_list<int>> &&il = { { 1, 2, 3 }, { 4, k }, { 5, 6, 7, 8 } }; 366 // First init list. 367 // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]], 368 // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_FIRST]], i64 0, i64 0), 369 // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 0) 370 // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 1) 371 // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]], 372 // 373 // Second init list array (non-constant). 374 // CHECK: store i32 4, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0) 375 // CHECK: load i32* @_ZN15partly_constant1kE 376 // CHECK: store i32 {{.*}}, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 1) 377 // 378 // Second init list. 379 // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0), 380 // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 0) 381 // CHECK: store i64 2, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 1) 382 // 383 // Third init list. 384 // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], 385 // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_THIRD]], i64 0, i64 0), 386 // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 2, i32 0) 387 // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4, i64 0, i64 2, i32 1) 388 // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], 389 // 390 // Outer init list. 391 // CHECK: store {{.*}}* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0), 392 // CHECK: {{.*}}** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 0) 393 // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 1) 394 // 395 // 'il' reference. 396 // CHECK: store {{.*}}* @[[PARTLY_CONSTANT_OUTER]], {{.*}}** @_ZN15partly_constant2ilE, align 8 397 } 398 399 namespace nested { 400 struct A { A(); ~A(); }; 401 struct B { const A &a; ~B(); }; 402 struct C { std::initializer_list<B> b; ~C(); }; 403 void f(); 404 // CHECK: define void @_ZN6nested1gEv( 405 void g() { 406 // CHECK: call void @_ZN6nested1AC1Ev( 407 // CHECK-NOT: call 408 // CHECK: call void @_ZN6nested1AC1Ev( 409 // CHECK-NOT: call 410 const C &c { { { A() }, { A() } } }; 411 412 // CHECK: call void @_ZN6nested1fEv( 413 // CHECK-NOT: call 414 f(); 415 416 // CHECK: call void @_ZN6nested1CD1Ev( 417 // CHECK-NOT: call 418 419 // Destroy B[2] array. 420 // FIXME: This isn't technically correct: reverse construction order would 421 // destroy the second B then the second A then the first B then the first A. 422 // CHECK: call void @_ZN6nested1BD1Ev( 423 // CHECK-NOT: call 424 // CHECK: br 425 426 // CHECK-NOT: call 427 // CHECK: call void @_ZN6nested1AD1Ev( 428 // CHECK-NOT: call 429 // CHECK: call void @_ZN6nested1AD1Ev( 430 // CHECK-NOT: call 431 // CHECK: } 432 } 433 } 434