cxx0x-initializer-stdinitializerlist.cpp revision 211c8ddb5b500ed84833751363d0cfe1115f4dd3
1// RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -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 35struct destroyme1 { 36 ~destroyme1(); 37}; 38struct destroyme2 { 39 ~destroyme2(); 40}; 41struct witharg1 { 42 witharg1(const destroyme1&); 43 ~witharg1(); 44}; 45struct 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 } 52std::initializer_list<int> globalInitList1 = {1, 2, 3}; 53 54namespace 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 69std::initializer_list<witharg1> globalInitList2 = { 70 witharg1(destroyme1()), witharg1(destroyme1()) 71}; 72 73void 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 93void 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 104void 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 113void 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 126void 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 138void 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 151void 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 163void 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 177void 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 191struct haslist1 { 192 std::initializer_list<int> il; 193 haslist1(); 194}; 195 196// CHECK: define void @_ZN8haslist1C2Ev 197haslist1::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 208struct haslist2 { 209 std::initializer_list<destroyme1> il; 210 haslist2(); 211}; 212 213// CHECK: define void @_ZN8haslist2C2Ev 214haslist2::haslist2() 215 : il{destroyme1(), destroyme1()} 216{ 217 destroyme2 dm2; 218 // CHECK: call void @_ZN10destroyme2D1Ev 219 // CHECK: call void @_ZN10destroyme1D1Ev 220} 221 222void 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 234void 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 242namespace 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 260namespace 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 279namespace dtors { 280 struct S { 281 S(); 282 ~S(); 283 }; 284 void f() { 285 std::initializer_list<S>{ S(), S() }; 286 } 287 void g() { 288 auto x = std::initializer_list<S>{ S(), S() }; 289 } 290} 291