123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s | FileCheck %s
- namespace std {
- typedef decltype(sizeof(int)) size_t;
- // libc++'s implementation
- template <class _E>
- class initializer_list
- {
- const _E* __begin_;
- size_t __size_;
- initializer_list(const _E* __b, size_t __s)
- : __begin_(__b),
- __size_(__s)
- {}
- public:
- typedef _E value_type;
- typedef const _E& reference;
- typedef const _E& const_reference;
- typedef size_t size_type;
- typedef const _E* iterator;
- typedef const _E* const_iterator;
- initializer_list() : __begin_(nullptr), __size_(0) {}
- size_t size() const {return __size_;}
- const _E* begin() const {return __begin_;}
- const _E* end() const {return __begin_ + __size_;}
- };
- }
- void fn1(int i) {
- // CHECK: define void @_Z3fn1i
- // temporary array
- // CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
- // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
- // CHECK-NEXT: store i32 1, i32*
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: store
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: load
- // CHECK-NEXT: store
- // init the list
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: getelementptr inbounds [3 x i32]*
- // CHECK-NEXT: store i32*
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: store i{{32|64}} 3
- std::initializer_list<int> intlist{1, 2, i};
- }
- struct destroyme1 {
- ~destroyme1();
- };
- struct destroyme2 {
- ~destroyme2();
- };
- struct witharg1 {
- witharg1(const destroyme1&);
- ~witharg1();
- };
- struct wantslist1 {
- wantslist1(std::initializer_list<destroyme1>);
- ~wantslist1();
- };
- void fn2() {
- // CHECK: define void @_Z3fn2v
- void target(std::initializer_list<destroyme1>);
- // objects should be destroyed before dm2, after call returns
- // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
- target({ destroyme1(), destroyme1() });
- // CHECK: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- }
- void fn3() {
- // CHECK: define void @_Z3fn3v
- // objects should be destroyed after dm2
- auto list = { destroyme1(), destroyme1() };
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- // CHECK: call void @_ZN10destroyme1D1Ev
- }
- void fn4() {
- // CHECK: define void @_Z3fn4v
- void target(std::initializer_list<witharg1>);
- // objects should be destroyed before dm2, after call returns
- // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
- // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E
- target({ witharg1(destroyme1()), witharg1(destroyme1()) });
- // CHECK: call void @_ZN8witharg1D1Ev
- // CHECK: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- }
- void fn5() {
- // CHECK: define void @_Z3fn5v
- // temps should be destroyed before dm2
- // objects should be destroyed after dm2
- // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
- auto list = { witharg1(destroyme1()), witharg1(destroyme1()) };
- // CHECK: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- // CHECK: call void @_ZN8witharg1D1Ev
- }
- void fn6() {
- // CHECK: define void @_Z3fn6v
- void target(const wantslist1&);
- // objects should be destroyed before dm2, after call returns
- // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
- // CHECK: call void @_Z6targetRK10wantslist1
- target({ destroyme1(), destroyme1() });
- // CHECK: call void @_ZN10wantslist1D1Ev
- // CHECK: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- }
- void fn7() {
- // CHECK: define void @_Z3fn7v
- // temps should be destroyed before dm2
- // object should be destroyed after dm2
- // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
- wantslist1 wl = { destroyme1(), destroyme1() };
- // CHECK: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- // CHECK: call void @_ZN10wantslist1D1Ev
- }
- void fn8() {
- // CHECK: define void @_Z3fn8v
- void target(std::initializer_list<std::initializer_list<destroyme1>>);
- // objects should be destroyed before dm2, after call returns
- // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE
- std::initializer_list<destroyme1> inner;
- target({ inner, { destroyme1() } });
- // CHECK: call void @_ZN10destroyme1D1Ev
- // Only one destroy loop, since only one inner init list is directly inited.
- // CHECK-NOT: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- }
- void fn9() {
- // CHECK: define void @_Z3fn9v
- // objects should be destroyed after dm2
- std::initializer_list<destroyme1> inner;
- std::initializer_list<std::initializer_list<destroyme1>> list =
- { inner, { destroyme1() } };
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- // CHECK: call void @_ZN10destroyme1D1Ev
- // Only one destroy loop, since only one inner init list is directly inited.
- // CHECK-NOT: call void @_ZN10destroyme1D1Ev
- // CHECK: ret void
- }
- struct haslist1 {
- std::initializer_list<int> il;
- haslist1();
- };
- // CHECK: define void @_ZN8haslist1C2Ev
- haslist1::haslist1()
- // CHECK: alloca [3 x i32]
- // CHECK: store i32 1
- // CHECK: store i32 2
- // CHECK: store i32 3
- // CHECK: store i{{32|64}} 3
- : il{1, 2, 3}
- {
- destroyme2 dm2;
- }
- struct haslist2 {
- std::initializer_list<destroyme1> il;
- haslist2();
- };
- // CHECK: define void @_ZN8haslist2C2Ev
- haslist2::haslist2()
- : il{destroyme1(), destroyme1()}
- {
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- // CHECK: call void @_ZN10destroyme1D1Ev
- }
- void fn10() {
- // CHECK: define void @_Z4fn10v
- // CHECK: alloca [3 x i32]
- // CHECK: call noalias i8* @_Znwm
- // CHECK: store i32 1
- // CHECK: store i32 2
- // CHECK: store i32 3
- // CHECK: store i32*
- // CHECK: store i{{32|64}} 3
- (void) new std::initializer_list<int> {1, 2, 3};
- }
- void fn11() {
- // CHECK: define void @_Z4fn11v
- (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()};
- // CHECK: call void @_ZN10destroyme1D1Ev
- destroyme2 dm2;
- // CHECK: call void @_ZN10destroyme2D1Ev
- }
|