1 // RUN: %clang_cc1 -std=c++11 -S -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 void 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 55 struct destroyme1 { 56 ~destroyme1(); 57 }; 58 struct destroyme2 { 59 ~destroyme2(); 60 }; 61 struct witharg1 { 62 witharg1(const destroyme1&); 63 ~witharg1(); 64 }; 65 struct wantslist1 { 66 wantslist1(std::initializer_list<destroyme1>); 67 ~wantslist1(); 68 }; 69 70 void 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 81 void 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 90 void 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 103 void 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 115 void 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 128 void 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 140 void 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 154 void 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 168 struct haslist1 { 169 std::initializer_list<int> il; 170 haslist1(); 171 }; 172 173 // CHECK: define void @_ZN8haslist1C2Ev 174 haslist1::haslist1() 175 // CHECK: alloca [3 x i32] 176 // CHECK: store i32 1 177 // CHECK: store i32 2 178 // CHECK: store i32 3 179 // CHECK: store i{{32|64}} 3 180 : il{1, 2, 3} 181 { 182 destroyme2 dm2; 183 } 184 185 struct haslist2 { 186 std::initializer_list<destroyme1> il; 187 haslist2(); 188 }; 189 190 // CHECK: define void @_ZN8haslist2C2Ev 191 haslist2::haslist2() 192 : il{destroyme1(), destroyme1()} 193 { 194 destroyme2 dm2; 195 // CHECK: call void @_ZN10destroyme2D1Ev 196 // CHECK: call void @_ZN10destroyme1D1Ev 197 } 198 199 void fn10() { 200 // CHECK: define void @_Z4fn10v 201 // CHECK: alloca [3 x i32] 202 // CHECK: call noalias i8* @_Znw{{[jm]}} 203 // CHECK: store i32 1 204 // CHECK: store i32 2 205 // CHECK: store i32 3 206 // CHECK: store i32* 207 // CHECK: store i{{32|64}} 3 208 (void) new std::initializer_list<int> {1, 2, 3}; 209 } 210 211 void fn11() { 212 // CHECK: define void @_Z4fn11v 213 (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()}; 214 // CHECK: call void @_ZN10destroyme1D1Ev 215 destroyme2 dm2; 216 // CHECK: call void @_ZN10destroyme2D1Ev 217 } 218