|
| 1 | +// RUN: %clang_cc1 -std=c++2c -verify=expected,both %s -fexperimental-new-constant-interpreter |
| 2 | +// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s |
| 3 | + |
| 4 | +// both-no-diagnostics |
| 5 | + |
| 6 | +namespace std { |
| 7 | +typedef __SIZE_TYPE__ size_t; |
| 8 | +} |
| 9 | +extern "C++" { |
| 10 | +namespace std { |
| 11 | +template <typename> struct iterator_traits; |
| 12 | +} |
| 13 | +} |
| 14 | +namespace std { |
| 15 | +template <typename _Tp, _Tp __v> struct integral_constant { |
| 16 | + static constexpr _Tp value = __v; |
| 17 | +}; |
| 18 | +template <bool __v> using __bool_constant = integral_constant<bool, __v>; |
| 19 | +using false_type = __bool_constant<false>; |
| 20 | +template <bool, typename _Tp = void> struct enable_if { |
| 21 | + using type = _Tp; |
| 22 | +}; |
| 23 | +template <bool> struct __conditional { |
| 24 | + template <typename _Tp, typename> using type = _Tp; |
| 25 | +}; |
| 26 | +template <bool _Cond, typename _If, typename _Else> |
| 27 | +using __conditional_t = |
| 28 | + typename __conditional<_Cond>::template type<_If, _Else>; |
| 29 | +template <typename _Tp> |
| 30 | +struct is_empty : public __bool_constant<__is_empty(_Tp)> {}; |
| 31 | +template <typename _Tp, typename _Up> |
| 32 | +struct is_same : public __bool_constant<__is_same(_Tp, _Up)> {}; |
| 33 | +template <typename _Tp> struct remove_cv { |
| 34 | + using type = __remove_cv(_Tp); |
| 35 | +}; |
| 36 | +template <typename _Tp> struct tuple_size; |
| 37 | +template <typename _Tp, typename _Up = typename remove_cv<_Tp>::type, |
| 38 | + typename = typename enable_if<is_same<_Tp, _Up>::value>::type, |
| 39 | + size_t = tuple_size<_Tp>::value> |
| 40 | +using __enable_if_has_tuple_size = _Tp; |
| 41 | +template <typename _Tp> |
| 42 | +struct tuple_size<const __enable_if_has_tuple_size<_Tp>> |
| 43 | + : public tuple_size<_Tp> {}; |
| 44 | +template <size_t __i, typename _Tp> struct tuple_element; |
| 45 | +template <size_t __i, typename _Tp> |
| 46 | +using __tuple_element_t = typename tuple_element<__i, _Tp>::type; |
| 47 | +template <size_t __i, typename _Tp> struct tuple_element<__i, const _Tp> { |
| 48 | + using type = const __tuple_element_t<__i, _Tp>; |
| 49 | +}; |
| 50 | +template <size_t _Np, typename... _Types> struct _Nth_type { |
| 51 | + using type = __type_pack_element<_Np, _Types...>; |
| 52 | +}; |
| 53 | +template <typename _Tp> struct iterator_traits<_Tp *> { |
| 54 | + using reference = _Tp &; |
| 55 | +}; |
| 56 | +} // namespace std |
| 57 | +extern "C++" { |
| 58 | +void *operator new(std::size_t, void *__p); |
| 59 | +} |
| 60 | +namespace std { |
| 61 | +template <typename _Tp, typename... _Args> |
| 62 | +constexpr inline void _Construct(_Tp *__p, _Args &&...__args) { |
| 63 | + ::new (__p) _Tp(__args...); |
| 64 | +}; |
| 65 | +} // namespace std |
| 66 | +namespace __gnu_cxx { |
| 67 | +template <typename _Iterator, typename _Container> class __normal_iterator { |
| 68 | +protected: |
| 69 | + _Iterator _M_current; |
| 70 | + typedef std::iterator_traits<_Iterator> __traits_type; |
| 71 | + |
| 72 | +public: |
| 73 | + typedef _Iterator iterator_type; |
| 74 | + typedef typename __traits_type::reference reference; |
| 75 | + explicit constexpr __normal_iterator(const _Iterator &__i) |
| 76 | + : _M_current(__i) {}; |
| 77 | + constexpr reference operator*() const { return *_M_current; } |
| 78 | + constexpr __normal_iterator &operator++() { |
| 79 | + ++_M_current; |
| 80 | + return *this; |
| 81 | + } |
| 82 | + constexpr const _Iterator &base() const { return _M_current; } |
| 83 | +}; |
| 84 | +template <typename _Iterator, typename _Container> |
| 85 | +constexpr bool |
| 86 | +operator==(const __normal_iterator<_Iterator, _Container> &__lhs, |
| 87 | + const __normal_iterator<_Iterator, _Container> &__rhs) { |
| 88 | + return __lhs.base() == __rhs.base(); |
| 89 | +} |
| 90 | +} // namespace __gnu_cxx |
| 91 | +namespace std { |
| 92 | +template <typename _Tp> class __new_allocator {}; |
| 93 | +template <typename _Tp> using __allocator_base = __new_allocator<_Tp>; |
| 94 | +template <typename> struct allocator_traits; |
| 95 | +template <typename _Tp> class allocator : public __allocator_base<_Tp> { |
| 96 | +public: |
| 97 | + typedef _Tp value_type; |
| 98 | + constexpr _Tp *allocate(size_t __n) { |
| 99 | + __n *= sizeof(_Tp); |
| 100 | + return static_cast<_Tp *>(::operator new(__n)); |
| 101 | + } |
| 102 | + constexpr void deallocate(_Tp *__p, size_t __n) { ::operator delete(__p); } |
| 103 | +}; |
| 104 | +template <typename _Tp> struct allocator_traits<allocator<_Tp>> { |
| 105 | + using allocator_type = allocator<_Tp>; |
| 106 | + using pointer = _Tp *; |
| 107 | + using size_type = std::size_t; |
| 108 | + template <typename _Up> using rebind_alloc = allocator<_Up>; |
| 109 | + static constexpr pointer allocate(allocator_type &__a, size_type __n) { |
| 110 | + return __a.allocate(__n); |
| 111 | + } |
| 112 | + static constexpr void deallocate(allocator_type &__a, pointer __p, |
| 113 | + size_type __n) { |
| 114 | + __a.deallocate(__p, __n); |
| 115 | + } |
| 116 | +}; |
| 117 | +} // namespace std |
| 118 | +namespace __gnu_cxx { |
| 119 | +template <typename _Alloc, typename = typename _Alloc::value_type> |
| 120 | +struct __alloc_traits : std::allocator_traits<_Alloc> { |
| 121 | + typedef std::allocator_traits<_Alloc> _Base_type; |
| 122 | + template <typename _Tp> struct rebind { |
| 123 | + typedef typename _Base_type::template rebind_alloc<_Tp> other; |
| 124 | + }; |
| 125 | +}; |
| 126 | +} // namespace __gnu_cxx |
| 127 | +namespace std { |
| 128 | +template <typename _InputIterator, typename _ForwardIterator> |
| 129 | +constexpr _ForwardIterator __do_uninit_copy(_InputIterator __first, |
| 130 | + _InputIterator __last, |
| 131 | + _ForwardIterator __result) { |
| 132 | + _ForwardIterator __cur = __result; |
| 133 | + for (; __first != __last; ++__first, ++__cur) |
| 134 | + std::_Construct(&*__cur, *__first); |
| 135 | + return __cur; |
| 136 | +}; |
| 137 | +template <typename _InputIterator, typename _ForwardIterator, typename _Tp> |
| 138 | +constexpr inline _ForwardIterator |
| 139 | +__uninitialized_copy_a(_InputIterator __first, _InputIterator __last, |
| 140 | + _ForwardIterator __result, allocator<_Tp> &) { |
| 141 | + return std::__do_uninit_copy(__first, __last, __result); |
| 142 | +} |
| 143 | +template <typename _Tp, typename _Alloc> struct _Vector_base { |
| 144 | + typedef |
| 145 | + typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other |
| 146 | + _Tp_alloc_type; |
| 147 | + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer; |
| 148 | + struct _Vector_impl_data { |
| 149 | + pointer _M_start; |
| 150 | + pointer _M_finish; |
| 151 | + pointer _M_end_of_storage; |
| 152 | + }; |
| 153 | + struct _Vector_impl : public _Tp_alloc_type, public _Vector_impl_data {}; |
| 154 | + |
| 155 | +public: |
| 156 | + typedef _Alloc allocator_type; |
| 157 | + constexpr _Tp_alloc_type &_M_get_Tp_allocator() { return this->_M_impl; } |
| 158 | + constexpr _Vector_base(const allocator_type &__a) : _M_impl(__a) {} |
| 159 | + constexpr ~_Vector_base() { |
| 160 | + _M_deallocate(_M_impl._M_start, |
| 161 | + _M_impl._M_end_of_storage - _M_impl._M_start); |
| 162 | + } |
| 163 | + |
| 164 | +public: |
| 165 | + _Vector_impl _M_impl; |
| 166 | + constexpr pointer _M_allocate(size_t __n) { |
| 167 | + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; |
| 168 | + return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer(); |
| 169 | + } |
| 170 | + constexpr void _M_deallocate(pointer __p, size_t __n) { |
| 171 | + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; |
| 172 | + if (__p) |
| 173 | + _Tr::deallocate(_M_impl, __p, __n); |
| 174 | + } |
| 175 | + |
| 176 | +protected: |
| 177 | +}; |
| 178 | +template <typename _Tp, typename _Alloc = std::allocator<_Tp>> |
| 179 | +class vector : protected _Vector_base<_Tp, _Alloc> { |
| 180 | + typedef _Vector_base<_Tp, _Alloc> _Base; |
| 181 | + |
| 182 | +public: |
| 183 | + typedef _Tp value_type; |
| 184 | + typedef typename _Base::pointer pointer; |
| 185 | + typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator; |
| 186 | + typedef size_t size_type; |
| 187 | + typedef _Alloc allocator_type; |
| 188 | + using _Base::_M_get_Tp_allocator; |
| 189 | + |
| 190 | +public: |
| 191 | +private: |
| 192 | +public: |
| 193 | + constexpr vector(_Tp __l, const allocator_type &__a = allocator_type()) : _Base(__a) { |
| 194 | + |
| 195 | + } |
| 196 | + constexpr iterator begin() { return iterator(this->_M_impl._M_start); } |
| 197 | + constexpr iterator end() { return iterator(this->_M_impl._M_finish); } |
| 198 | + |
| 199 | +protected: |
| 200 | + template <typename _Iterator> |
| 201 | + constexpr void _M_range_initialize_n(_Iterator __first, _Iterator __last, |
| 202 | + size_type __n) { |
| 203 | + pointer __start = this->_M_impl._M_start = this->_M_allocate(((__n))); |
| 204 | + this->_M_impl._M_end_of_storage = __start + __n; |
| 205 | + this->_M_impl._M_finish = std::__uninitialized_copy_a( |
| 206 | + __first, __last, __start, _M_get_Tp_allocator()); |
| 207 | + } |
| 208 | +}; |
| 209 | +template <typename _Tp> struct __is_empty_non_tuple : is_empty<_Tp> {}; |
| 210 | +template <typename _Tp> |
| 211 | +using __empty_not_final = |
| 212 | + __conditional_t<__is_final(_Tp), false_type, __is_empty_non_tuple<_Tp>>; |
| 213 | +template <size_t _Idx, typename _Head, bool = __empty_not_final<_Head>::value> |
| 214 | +struct _Head_base; |
| 215 | +template <size_t _Idx, typename _Head> struct _Head_base<_Idx, _Head, false> { |
| 216 | + static constexpr const _Head &_M_head(const _Head_base &__b) { |
| 217 | + return __b._M_head_impl; |
| 218 | + } |
| 219 | + _Head _M_head_impl; |
| 220 | +}; |
| 221 | +template <size_t _Idx, typename... _Elements> struct _Tuple_impl; |
| 222 | +template <size_t _Idx, typename _Head> |
| 223 | +struct _Tuple_impl<_Idx, _Head> : private _Head_base<_Idx, _Head> { |
| 224 | + typedef _Head_base<_Idx, _Head> _Base; |
| 225 | + static constexpr const _Head &_M_head(const _Tuple_impl &__t) { |
| 226 | + return _Base::_M_head(__t); |
| 227 | + } |
| 228 | + explicit constexpr _Tuple_impl(const _Head &__head) : _Base(__head) {} |
| 229 | + |
| 230 | +protected: |
| 231 | +}; |
| 232 | +template <typename... _Elements> |
| 233 | +class tuple : public _Tuple_impl<0, _Elements...> { |
| 234 | + using _Inherited = _Tuple_impl<0, _Elements...>; |
| 235 | + |
| 236 | +public: |
| 237 | + template <typename = void> |
| 238 | + constexpr tuple(const _Elements &...__elements) : _Inherited(__elements...) {} |
| 239 | +}; |
| 240 | +template <typename... _Elements> |
| 241 | +struct tuple_size<tuple<_Elements...>> |
| 242 | + : public integral_constant<size_t, sizeof...(_Elements)> {}; |
| 243 | +template <size_t __i, typename... _Types> |
| 244 | +struct tuple_element<__i, tuple<_Types...>> { |
| 245 | + using type = typename _Nth_type<__i, _Types...>::type; |
| 246 | +}; |
| 247 | +template <size_t __i, typename _Head, typename... _Tail> |
| 248 | +constexpr const _Head & |
| 249 | +__get_helper(const _Tuple_impl<__i, _Head, _Tail...> &__t) { |
| 250 | + return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); |
| 251 | +}; |
| 252 | +template <size_t __i, typename... _Elements> |
| 253 | +constexpr const int get(const tuple<_Elements...> &&__t) { |
| 254 | + return std::__get_helper<__i>(__t); |
| 255 | +}; |
| 256 | +} // namespace std |
| 257 | +constexpr int foo() { |
| 258 | + std::vector<std::tuple<int>> data_tuples = {{1}}; |
| 259 | + for (const auto [id] : data_tuples) { |
| 260 | + int a = id + 3; |
| 261 | + } |
| 262 | + return 1; |
| 263 | +} |
| 264 | +static_assert(foo() == 1); |
0 commit comments