cxx0x-initializer-stdinitializerlist.cpp revision af130fd78267ee9e2395b758a7d827b07ce317a0
1// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s | FileCheck %s 2 3namespace 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 35void fn1(int i) { 36 // CHECK: define void @_Z3fn1i 37 // temporary array 38 // CHECK: [[array:%[^ ]+]] = alloca [3 x i32] 39 // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0 40 // CHECK-NEXT: store i32 1, i32* 41 // CHECK-NEXT: getelementptr 42 // CHECK-NEXT: store 43 // CHECK-NEXT: getelementptr 44 // CHECK-NEXT: load 45 // CHECK-NEXT: store 46 // init the list 47 // CHECK-NEXT: getelementptr 48 // CHECK-NEXT: getelementptr inbounds [3 x i32]* 49 // CHECK-NEXT: store i32* 50 // CHECK-NEXT: getelementptr 51 // CHECK-NEXT: store i{{32|64}} 3 52 std::initializer_list<int> intlist{1, 2, i}; 53} 54 55struct destroyme1 { 56 ~destroyme1(); 57}; 58struct destroyme2 { 59 ~destroyme2(); 60}; 61struct witharg1 { 62 witharg1(const destroyme1&); 63 ~witharg1(); 64}; 65struct wantslist1 { 66 wantslist1(std::initializer_list<destroyme1>); 67 ~wantslist1(); 68}; 69 70void fn2() { 71 // CHECK: define void @_Z3fn2v 72 void target(std::initializer_list<destroyme1>); 73 // objects should be destroyed before dm2, after call returns 74 // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E 75 target({ destroyme1(), destroyme1() }); 76 // CHECK: call void @_ZN10destroyme1D1Ev 77 destroyme2 dm2; 78 // CHECK: call void @_ZN10destroyme2D1Ev 79} 80 81void fn3() { 82 // CHECK: define void @_Z3fn3v 83 // objects should be destroyed after dm2 84 auto list = { destroyme1(), destroyme1() }; 85 destroyme2 dm2; 86 // CHECK: call void @_ZN10destroyme2D1Ev 87 // CHECK: call void @_ZN10destroyme1D1Ev 88} 89 90void fn4() { 91 // CHECK: define void @_Z3fn4v 92 void target(std::initializer_list<witharg1>); 93 // objects should be destroyed before dm2, after call returns 94 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 95 // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E 96 target({ witharg1(destroyme1()), witharg1(destroyme1()) }); 97 // CHECK: call void @_ZN8witharg1D1Ev 98 // CHECK: call void @_ZN10destroyme1D1Ev 99 destroyme2 dm2; 100 // CHECK: call void @_ZN10destroyme2D1Ev 101} 102 103void fn5() { 104 // CHECK: define void @_Z3fn5v 105 // temps should be destroyed before dm2 106 // objects should be destroyed after dm2 107 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 108 auto list = { witharg1(destroyme1()), witharg1(destroyme1()) }; 109 // CHECK: call void @_ZN10destroyme1D1Ev 110 destroyme2 dm2; 111 // CHECK: call void @_ZN10destroyme2D1Ev 112 // CHECK: call void @_ZN8witharg1D1Ev 113} 114 115void fn6() { 116 // CHECK: define void @_Z3fn6v 117 void target(const wantslist1&); 118 // objects should be destroyed before dm2, after call returns 119 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E 120 // CHECK: call void @_Z6targetRK10wantslist1 121 target({ destroyme1(), destroyme1() }); 122 // CHECK: call void @_ZN10wantslist1D1Ev 123 // CHECK: call void @_ZN10destroyme1D1Ev 124 destroyme2 dm2; 125 // CHECK: call void @_ZN10destroyme2D1Ev 126} 127 128void fn7() { 129 // CHECK: define void @_Z3fn7v 130 // temps should be destroyed before dm2 131 // object should be destroyed after dm2 132 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E 133 wantslist1 wl = { destroyme1(), destroyme1() }; 134 // CHECK: call void @_ZN10destroyme1D1Ev 135 destroyme2 dm2; 136 // CHECK: call void @_ZN10destroyme2D1Ev 137 // CHECK: call void @_ZN10wantslist1D1Ev 138} 139 140void fn8() { 141 // CHECK: define void @_Z3fn8v 142 void target(std::initializer_list<std::initializer_list<destroyme1>>); 143 // objects should be destroyed before dm2, after call returns 144 // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE 145 std::initializer_list<destroyme1> inner; 146 target({ inner, { destroyme1() } }); 147 // CHECK: call void @_ZN10destroyme1D1Ev 148 // Only one destroy loop, since only one inner init list is directly inited. 149 // CHECK-NOT: call void @_ZN10destroyme1D1Ev 150 destroyme2 dm2; 151 // CHECK: call void @_ZN10destroyme2D1Ev 152} 153 154void fn9() { 155 // CHECK: define void @_Z3fn9v 156 // objects should be destroyed after dm2 157 std::initializer_list<destroyme1> inner; 158 std::initializer_list<std::initializer_list<destroyme1>> list = 159 { inner, { destroyme1() } }; 160 destroyme2 dm2; 161 // CHECK: call void @_ZN10destroyme2D1Ev 162 // CHECK: call void @_ZN10destroyme1D1Ev 163 // Only one destroy loop, since only one inner init list is directly inited. 164 // CHECK-NOT: call void @_ZN10destroyme1D1Ev 165 // CHECK: ret void 166} 167