cxx0x-initializer-stdinitializerlist.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s | FileCheck %s
  2. namespace std {
  3. typedef decltype(sizeof(int)) size_t;
  4. // libc++'s implementation
  5. template <class _E>
  6. class initializer_list
  7. {
  8. const _E* __begin_;
  9. size_t __size_;
  10. initializer_list(const _E* __b, size_t __s)
  11. : __begin_(__b),
  12. __size_(__s)
  13. {}
  14. public:
  15. typedef _E value_type;
  16. typedef const _E& reference;
  17. typedef const _E& const_reference;
  18. typedef size_t size_type;
  19. typedef const _E* iterator;
  20. typedef const _E* const_iterator;
  21. initializer_list() : __begin_(nullptr), __size_(0) {}
  22. size_t size() const {return __size_;}
  23. const _E* begin() const {return __begin_;}
  24. const _E* end() const {return __begin_ + __size_;}
  25. };
  26. }
  27. void fn1(int i) {
  28. // CHECK: define void @_Z3fn1i
  29. // temporary array
  30. // CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
  31. // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
  32. // CHECK-NEXT: store i32 1, i32*
  33. // CHECK-NEXT: getelementptr
  34. // CHECK-NEXT: store
  35. // CHECK-NEXT: getelementptr
  36. // CHECK-NEXT: load
  37. // CHECK-NEXT: store
  38. // init the list
  39. // CHECK-NEXT: getelementptr
  40. // CHECK-NEXT: getelementptr inbounds [3 x i32]*
  41. // CHECK-NEXT: store i32*
  42. // CHECK-NEXT: getelementptr
  43. // CHECK-NEXT: store i{{32|64}} 3
  44. std::initializer_list<int> intlist{1, 2, i};
  45. }
  46. struct destroyme1 {
  47. ~destroyme1();
  48. };
  49. struct destroyme2 {
  50. ~destroyme2();
  51. };
  52. struct witharg1 {
  53. witharg1(const destroyme1&);
  54. ~witharg1();
  55. };
  56. struct wantslist1 {
  57. wantslist1(std::initializer_list<destroyme1>);
  58. ~wantslist1();
  59. };
  60. void fn2() {
  61. // CHECK: define void @_Z3fn2v
  62. void target(std::initializer_list<destroyme1>);
  63. // objects should be destroyed before dm2, after call returns
  64. // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
  65. target({ destroyme1(), destroyme1() });
  66. // CHECK: call void @_ZN10destroyme1D1Ev
  67. destroyme2 dm2;
  68. // CHECK: call void @_ZN10destroyme2D1Ev
  69. }
  70. void fn3() {
  71. // CHECK: define void @_Z3fn3v
  72. // objects should be destroyed after dm2
  73. auto list = { destroyme1(), destroyme1() };
  74. destroyme2 dm2;
  75. // CHECK: call void @_ZN10destroyme2D1Ev
  76. // CHECK: call void @_ZN10destroyme1D1Ev
  77. }
  78. void fn4() {
  79. // CHECK: define void @_Z3fn4v
  80. void target(std::initializer_list<witharg1>);
  81. // objects should be destroyed before dm2, after call returns
  82. // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
  83. // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E
  84. target({ witharg1(destroyme1()), witharg1(destroyme1()) });
  85. // CHECK: call void @_ZN8witharg1D1Ev
  86. // CHECK: call void @_ZN10destroyme1D1Ev
  87. destroyme2 dm2;
  88. // CHECK: call void @_ZN10destroyme2D1Ev
  89. }
  90. void fn5() {
  91. // CHECK: define void @_Z3fn5v
  92. // temps should be destroyed before dm2
  93. // objects should be destroyed after dm2
  94. // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
  95. auto list = { witharg1(destroyme1()), witharg1(destroyme1()) };
  96. // CHECK: call void @_ZN10destroyme1D1Ev
  97. destroyme2 dm2;
  98. // CHECK: call void @_ZN10destroyme2D1Ev
  99. // CHECK: call void @_ZN8witharg1D1Ev
  100. }
  101. void fn6() {
  102. // CHECK: define void @_Z3fn6v
  103. void target(const wantslist1&);
  104. // objects should be destroyed before dm2, after call returns
  105. // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
  106. // CHECK: call void @_Z6targetRK10wantslist1
  107. target({ destroyme1(), destroyme1() });
  108. // CHECK: call void @_ZN10wantslist1D1Ev
  109. // CHECK: call void @_ZN10destroyme1D1Ev
  110. destroyme2 dm2;
  111. // CHECK: call void @_ZN10destroyme2D1Ev
  112. }
  113. void fn7() {
  114. // CHECK: define void @_Z3fn7v
  115. // temps should be destroyed before dm2
  116. // object should be destroyed after dm2
  117. // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
  118. wantslist1 wl = { destroyme1(), destroyme1() };
  119. // CHECK: call void @_ZN10destroyme1D1Ev
  120. destroyme2 dm2;
  121. // CHECK: call void @_ZN10destroyme2D1Ev
  122. // CHECK: call void @_ZN10wantslist1D1Ev
  123. }
  124. void fn8() {
  125. // CHECK: define void @_Z3fn8v
  126. void target(std::initializer_list<std::initializer_list<destroyme1>>);
  127. // objects should be destroyed before dm2, after call returns
  128. // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE
  129. std::initializer_list<destroyme1> inner;
  130. target({ inner, { destroyme1() } });
  131. // CHECK: call void @_ZN10destroyme1D1Ev
  132. // Only one destroy loop, since only one inner init list is directly inited.
  133. // CHECK-NOT: call void @_ZN10destroyme1D1Ev
  134. destroyme2 dm2;
  135. // CHECK: call void @_ZN10destroyme2D1Ev
  136. }
  137. void fn9() {
  138. // CHECK: define void @_Z3fn9v
  139. // objects should be destroyed after dm2
  140. std::initializer_list<destroyme1> inner;
  141. std::initializer_list<std::initializer_list<destroyme1>> list =
  142. { inner, { destroyme1() } };
  143. destroyme2 dm2;
  144. // CHECK: call void @_ZN10destroyme2D1Ev
  145. // CHECK: call void @_ZN10destroyme1D1Ev
  146. // Only one destroy loop, since only one inner init list is directly inited.
  147. // CHECK-NOT: call void @_ZN10destroyme1D1Ev
  148. // CHECK: ret void
  149. }
  150. struct haslist1 {
  151. std::initializer_list<int> il;
  152. haslist1();
  153. };
  154. // CHECK: define void @_ZN8haslist1C2Ev
  155. haslist1::haslist1()
  156. // CHECK: alloca [3 x i32]
  157. // CHECK: store i32 1
  158. // CHECK: store i32 2
  159. // CHECK: store i32 3
  160. // CHECK: store i{{32|64}} 3
  161. : il{1, 2, 3}
  162. {
  163. destroyme2 dm2;
  164. }
  165. struct haslist2 {
  166. std::initializer_list<destroyme1> il;
  167. haslist2();
  168. };
  169. // CHECK: define void @_ZN8haslist2C2Ev
  170. haslist2::haslist2()
  171. : il{destroyme1(), destroyme1()}
  172. {
  173. destroyme2 dm2;
  174. // CHECK: call void @_ZN10destroyme2D1Ev
  175. // CHECK: call void @_ZN10destroyme1D1Ev
  176. }
  177. void fn10() {
  178. // CHECK: define void @_Z4fn10v
  179. // CHECK: alloca [3 x i32]
  180. // CHECK: call noalias i8* @_Znwm
  181. // CHECK: store i32 1
  182. // CHECK: store i32 2
  183. // CHECK: store i32 3
  184. // CHECK: store i32*
  185. // CHECK: store i{{32|64}} 3
  186. (void) new std::initializer_list<int> {1, 2, 3};
  187. }
  188. void fn11() {
  189. // CHECK: define void @_Z4fn11v
  190. (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()};
  191. // CHECK: call void @_ZN10destroyme1D1Ev
  192. destroyme2 dm2;
  193. // CHECK: call void @_ZN10destroyme2D1Ev
  194. }