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