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 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: @_ZL25globalInitList1__initlist = internal global [3 x i32] [i32 1, i32 2, i32 3] 51 // CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, i32 0, i32 0), i{{32|64}} 3 } 52 std::initializer_list<int> globalInitList1 = {1, 2, 3}; 53 54 // CHECK: @_ZL25globalInitList2__initlist = internal global [2 x %{{[^ ]*}}] zeroinitializer 55 // CHECK: @globalInitList2 = global %{{[^ ]+}} { %[[WITHARG:[^ *]+]]* getelementptr inbounds ([2 x 56 // CHECK: appending global 57 // CHECK: define internal void 58 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 0 59 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 1 60 // CHECK: __cxa_atexit 61 // CHECK: call void @_ZN10destroyme1D1Ev 62 // CHECK: call void @_ZN10destroyme1D1Ev 63 std::initializer_list<witharg1> globalInitList2 = { 64 witharg1(destroyme1()), witharg1(destroyme1()) 65 }; 66 67 void fn1(int i) { 68 // CHECK: define void @_Z3fn1i 69 // temporary array 70 // CHECK: [[array:%[^ ]+]] = alloca [3 x i32] 71 // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0 72 // CHECK-NEXT: store i32 1, i32* 73 // CHECK-NEXT: getelementptr 74 // CHECK-NEXT: store 75 // CHECK-NEXT: getelementptr 76 // CHECK-NEXT: load 77 // CHECK-NEXT: store 78 // init the list 79 // CHECK-NEXT: getelementptr 80 // CHECK-NEXT: getelementptr inbounds [3 x i32]* 81 // CHECK-NEXT: store i32* 82 // CHECK-NEXT: getelementptr 83 // CHECK-NEXT: store i{{32|64}} 3 84 std::initializer_list<int> intlist{1, 2, i}; 85 } 86 87 void fn2() { 88 // CHECK: define void @_Z3fn2v 89 void target(std::initializer_list<destroyme1>); 90 // objects should be destroyed before dm2, after call returns 91 // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E 92 target({ destroyme1(), destroyme1() }); 93 // CHECK: call void @_ZN10destroyme1D1Ev 94 destroyme2 dm2; 95 // CHECK: call void @_ZN10destroyme2D1Ev 96 } 97 98 void fn3() { 99 // CHECK: define void @_Z3fn3v 100 // objects should be destroyed after dm2 101 auto list = { destroyme1(), destroyme1() }; 102 destroyme2 dm2; 103 // CHECK: call void @_ZN10destroyme2D1Ev 104 // CHECK: call void @_ZN10destroyme1D1Ev 105 } 106 107 void fn4() { 108 // CHECK: define void @_Z3fn4v 109 void target(std::initializer_list<witharg1>); 110 // objects should be destroyed before dm2, after call returns 111 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 112 // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E 113 target({ witharg1(destroyme1()), witharg1(destroyme1()) }); 114 // CHECK: call void @_ZN8witharg1D1Ev 115 // CHECK: call void @_ZN10destroyme1D1Ev 116 destroyme2 dm2; 117 // CHECK: call void @_ZN10destroyme2D1Ev 118 } 119 120 void fn5() { 121 // CHECK: define void @_Z3fn5v 122 // temps should be destroyed before dm2 123 // objects should be destroyed after dm2 124 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 125 auto list = { witharg1(destroyme1()), witharg1(destroyme1()) }; 126 // CHECK: call void @_ZN10destroyme1D1Ev 127 destroyme2 dm2; 128 // CHECK: call void @_ZN10destroyme2D1Ev 129 // CHECK: call void @_ZN8witharg1D1Ev 130 } 131 132 void fn6() { 133 // CHECK: define void @_Z3fn6v 134 void target(const wantslist1&); 135 // objects should be destroyed before dm2, after call returns 136 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E 137 // CHECK: call void @_Z6targetRK10wantslist1 138 target({ destroyme1(), destroyme1() }); 139 // CHECK: call void @_ZN10wantslist1D1Ev 140 // CHECK: call void @_ZN10destroyme1D1Ev 141 destroyme2 dm2; 142 // CHECK: call void @_ZN10destroyme2D1Ev 143 } 144 145 void fn7() { 146 // CHECK: define void @_Z3fn7v 147 // temps should be destroyed before dm2 148 // object should be destroyed after dm2 149 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E 150 wantslist1 wl = { destroyme1(), destroyme1() }; 151 // CHECK: call void @_ZN10destroyme1D1Ev 152 destroyme2 dm2; 153 // CHECK: call void @_ZN10destroyme2D1Ev 154 // CHECK: call void @_ZN10wantslist1D1Ev 155 } 156 157 void fn8() { 158 // CHECK: define void @_Z3fn8v 159 void target(std::initializer_list<std::initializer_list<destroyme1>>); 160 // objects should be destroyed before dm2, after call returns 161 // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE 162 std::initializer_list<destroyme1> inner; 163 target({ inner, { destroyme1() } }); 164 // CHECK: call void @_ZN10destroyme1D1Ev 165 // Only one destroy loop, since only one inner init list is directly inited. 166 // CHECK-NOT: call void @_ZN10destroyme1D1Ev 167 destroyme2 dm2; 168 // CHECK: call void @_ZN10destroyme2D1Ev 169 } 170 171 void fn9() { 172 // CHECK: define void @_Z3fn9v 173 // objects should be destroyed after dm2 174 std::initializer_list<destroyme1> inner; 175 std::initializer_list<std::initializer_list<destroyme1>> list = 176 { inner, { destroyme1() } }; 177 destroyme2 dm2; 178 // CHECK: call void @_ZN10destroyme2D1Ev 179 // CHECK: call void @_ZN10destroyme1D1Ev 180 // Only one destroy loop, since only one inner init list is directly inited. 181 // CHECK-NOT: call void @_ZN10destroyme1D1Ev 182 // CHECK: ret void 183 } 184 185 struct haslist1 { 186 std::initializer_list<int> il; 187 haslist1(); 188 }; 189 190 // CHECK: define void @_ZN8haslist1C2Ev 191 haslist1::haslist1() 192 // CHECK: alloca [3 x i32] 193 // CHECK: store i32 1 194 // CHECK: store i32 2 195 // CHECK: store i32 3 196 // CHECK: store i{{32|64}} 3 197 : il{1, 2, 3} 198 { 199 destroyme2 dm2; 200 } 201 202 struct haslist2 { 203 std::initializer_list<destroyme1> il; 204 haslist2(); 205 }; 206 207 // CHECK: define void @_ZN8haslist2C2Ev 208 haslist2::haslist2() 209 : il{destroyme1(), destroyme1()} 210 { 211 destroyme2 dm2; 212 // CHECK: call void @_ZN10destroyme2D1Ev 213 // CHECK: call void @_ZN10destroyme1D1Ev 214 } 215 216 void fn10() { 217 // CHECK: define void @_Z4fn10v 218 // CHECK: alloca [3 x i32] 219 // CHECK: call noalias i8* @_Znw{{[jm]}} 220 // CHECK: store i32 1 221 // CHECK: store i32 2 222 // CHECK: store i32 3 223 // CHECK: store i32* 224 // CHECK: store i{{32|64}} 3 225 (void) new std::initializer_list<int> {1, 2, 3}; 226 } 227 228 void fn11() { 229 // CHECK: define void @_Z4fn11v 230 (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()}; 231 // CHECK: call void @_ZN10destroyme1D1Ev 232 destroyme2 dm2; 233 // CHECK: call void @_ZN10destroyme2D1Ev 234 } 235 236 namespace PR12178 { 237 struct string { 238 string(int); 239 ~string(); 240 }; 241 242 struct pair { 243 string a; 244 int b; 245 }; 246 247 struct map { 248 map(std::initializer_list<pair>); 249 }; 250 251 map m{ {1, 2}, {3, 4} }; 252 } 253