528 lines · cpp
1// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s2// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s3 4/// This used to cause an assertion failure because we were deallocating a5/// dynamic block that was already dead.6 7namespace std {8inline namespace __1 {9template <class _Tp, _Tp __v> struct integral_constant {10 static inline constexpr const _Tp value = __v;11};12typedef integral_constant<bool, true> true_type;13typedef integral_constant<bool, false> false_type;14template <bool _Val> using _BoolConstant = integral_constant<bool, _Val>;15template <class _Tp> using __remove_cv_t = __remove_cv(_Tp);16template <class _Tp> using remove_cv_t = __remove_cv_t<_Tp>;17template <class _Tp>18inline constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp);19template <class _Tp>20using __libcpp_remove_reference_t = __remove_reference_t(_Tp);21template <class _Tp>22constexpr _Tp &&forward(__libcpp_remove_reference_t<_Tp> &__t) noexcept;23template <bool _Bp, class _If, class _Then> struct conditional {24 using type = _If;25};26template <bool _Bp, class _IfRes, class _ElseRes>27using conditional_t = typename conditional<_Bp, _IfRes, _ElseRes>::type;28template <class _Tp, class _Up>29using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;30using size_t = decltype(sizeof(int));31template <class _Tp> using __decay_t = __decay(_Tp);32template <class _Tp> using decay_t = __decay_t<_Tp>;33template <bool, class _Tp = void> struct enable_if;34template <class _Tp> struct enable_if<true, _Tp> {35 typedef _Tp type;36};37template <bool _Bp, class _Tp = void>38using __enable_if_t = typename enable_if<_Bp, _Tp>::type;39template <class _Bp, class _Dp>40inline constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp);41template <class _Tp> _Tp &&__declval(int);42template <class _Tp> decltype(std::__declval<_Tp>(0)) declval() noexcept;43template <class _Ret, class _Fp, class... _Args> struct __invokable_r {};44template <class _Fp, class... _Args>45using __is_invocable = __invokable_r<void, _Fp, _Args...>;46template <class _Func, class... _Args>47inline const bool __is_invocable_v = __is_invocable<_Func, _Args...>::value;48template <class _Func, class... _Args>49struct __invoke_result50 : enable_if<__is_invocable_v<_Func, _Args...>,51 typename __invokable_r<void, _Func, _Args...>::_Result> {};52template <class _Fn, class... _Args>53struct invoke_result : __invoke_result<_Fn, _Args...> {};54template <class _Tp, class... _Args>55inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);56template <class _Tp>57constexpr __libcpp_remove_reference_t<_Tp> &&move(_Tp &&__t) noexcept;58template <class _Tp> inline constexpr bool is_enum_v = __is_enum(_Tp);59template <class _From, class _To>60inline constexpr bool is_convertible_v = __is_convertible(_From, _To);61template <class _From, class _To>62concept convertible_to = is_convertible_v<_From, _To> &&63 requires { static_cast<_To>(std::declval<_From>()); };64template <class _Tp, class _Up>65concept __same_as_impl = _IsSame<_Tp, _Up>::value;66template <class _Tp, class _Up>67concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;68template <class _Tp> using __remove_cvref_t = __remove_cvref(_Tp);69template <class _Tp> using remove_cvref_t = __remove_cvref_t<_Tp>;70template <class _Tp>71using __make_const_lvalue_ref = const __libcpp_remove_reference_t<_Tp> &;72template <class _Lhs, class _Rhs>73concept assignable_from =74 is_lvalue_reference_v<_Lhs> &&75 requires(_Lhs __lhs, _Rhs &&__rhs) {76 { __lhs = std::forward<_Rhs>(__rhs) } -> same_as<_Lhs>;77 };78template <class _Tp>79struct is_nothrow_destructible80 : integral_constant<bool, __is_nothrow_destructible(_Tp)> {};81template <class _Tp>82inline constexpr bool is_nothrow_destructible_v =83 is_nothrow_destructible<_Tp>::value;84template <class _Tp>85concept destructible = is_nothrow_destructible_v<_Tp>;86template <class _Tp, class... _Args>87concept constructible_from =88 destructible<_Tp> && is_constructible_v<_Tp, _Args...>;89template <class _Tp>90concept __default_initializable = requires { ::new _Tp; };91template <class _Tp>92concept default_initializable = constructible_from<_Tp> && requires {93 _Tp{};94} && __default_initializable<_Tp>;95template <class _Tp>96concept move_constructible =97 constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>;98template <class _Tp> inline constexpr bool is_class_v = __is_class(_Tp);99template <class _Tp> inline constexpr bool is_union_v = __is_union(_Tp);100template <class _Tp>101concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;102namespace ranges {103namespace __swap {104template <class _Tp, class _Up>105concept __unqualified_swappable_with =106 (__class_or_enum<remove_cvref_t<_Tp>> ||107 __class_or_enum<remove_cvref_t<_Up>>) &&108 requires(_Tp &&__t, _Up &&__u) {109 swap(std::forward<_Tp>(__t), std::forward<_Up>(__u));110 };111template <class _Tp>112concept __exchangeable = !__unqualified_swappable_with<_Tp &, _Tp &> &&113 move_constructible<_Tp> && assignable_from<_Tp &, _Tp>;114struct __fn {115 template <__exchangeable _Tp>116 constexpr void operator()(_Tp &__x, _Tp &__y) const;117};118} // namespace __swap119inline namespace __cpo {120inline constexpr auto swap = __swap::__fn{};121}122} // namespace ranges123template <class _Tp> inline constexpr bool is_object_v = __is_object(_Tp);124template <class _Tp>125concept movable = is_object_v<_Tp> && move_constructible<_Tp> &&126 assignable_from<_Tp &, _Tp>;127template <class _Tp>128concept copyable =129 assignable_from<_Tp &, const _Tp &> && assignable_from<_Tp &, const _Tp>;130template <class _Dp, class _Bp>131concept derived_from =132 is_base_of_v<_Bp, _Dp> &&133 is_convertible_v<const volatile _Dp *, const volatile _Bp *>;134template <class _Tp>135concept __boolean_testable_impl = convertible_to<_Tp, bool>;136template <class _Tp>137concept __boolean_testable =138 __boolean_testable_impl<_Tp> && requires(_Tp &&__t) {139 { !std::forward<_Tp>(__t) } -> __boolean_testable_impl;140 };141template <class _Tp, class _Up>142concept __weakly_equality_comparable_with = requires(143 __make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {144 { __u != __t } -> __boolean_testable;145};146template <class _Tp>147concept semiregular = copyable<_Tp> && default_initializable<_Tp>;148template <template <class...> class _Templ, class... _Args,149 class = _Templ<_Args...>>150true_type __sfinae_test_impl(int);151template <template <class...> class, class...>152false_type __sfinae_test_impl(...);153template <template <class...> class _Templ, class... _Args>154using _IsValidExpansion =155 decltype(std::__sfinae_test_impl<_Templ, _Args...>(0));156template <class _Tp>157using __test_for_primary_template =158 __enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>;159template <class _Tp>160using __is_primary_template =161 _IsValidExpansion<__test_for_primary_template, _Tp>;162template <class> struct iterator_traits;163template <class> struct __cond_value_type;164template <class _Tp>165 requires is_object_v<_Tp>166struct __cond_value_type<_Tp> {167 using value_type = remove_cv_t<_Tp>;168};169template <class _Tp>170concept __has_member_value_type = requires { typename _Tp::value_type; };171template <class> struct indirectly_readable_traits;172template <class _Tp>173struct indirectly_readable_traits<_Tp *> : __cond_value_type<_Tp> {};174template <__has_member_value_type _Tp>175struct indirectly_readable_traits<_Tp>176 : __cond_value_type<typename _Tp::value_type> {};177template <bool> struct _OrImpl;178template <> struct _OrImpl<true> {179 template <class _Res, class _First, class... _Rest>180 using _Result =181 typename _OrImpl<!bool(_First::value) && sizeof...(_Rest) != 0>::182 template _Result<_First, _Rest...>;183};184template <> struct _OrImpl<false> {185 template <class _Res, class...> using _Result = _Res;186};187template <class... _Args>188using _Or = typename _OrImpl<sizeof...(_Args) !=189 0>::template _Result<false_type, _Args...>;190template <class _Tp> using __with_reference = _Tp &;191template <class _Tp>192concept __can_reference = requires { typename __with_reference<_Tp>; };193template <class _Tp>194concept __dereferenceable = requires(_Tp &__t) {195 { *__t } -> __can_reference;196};197template <__dereferenceable _Tp>198using iter_reference_t = decltype(*std::declval<_Tp &>());199struct input_iterator_tag {};200struct forward_iterator_tag : public input_iterator_tag {};201struct bidirectional_iterator_tag : public forward_iterator_tag {};202struct random_access_iterator_tag : public bidirectional_iterator_tag {};203template <class _Iter> struct __iter_traits_cache;204template <class _Iter>205using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type;206struct __iter_concept_concept_test {207 template <class _Iter>208 using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept;209};210struct __iter_concept_category_test {211 template <class _Iter>212 using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category;213};214struct __iter_concept_random_fallback {215 template <class _Iter>216 using _Apply =217 __enable_if_t<__is_primary_template<iterator_traits<_Iter>>::value,218 random_access_iterator_tag>;219};220template <class _Iter, class _Tester>221struct __test_iter_concept : _IsValidExpansion<_Tester::template _Apply, _Iter>,222 _Tester {};223template <class _Iter> struct __iter_concept_cache {224 using type = _Or<__test_iter_concept<_Iter, __iter_concept_concept_test>,225 __test_iter_concept<_Iter, __iter_concept_category_test>,226 __test_iter_concept<_Iter, __iter_concept_random_fallback>>;227};228template <class _Iter>229using _ITER_CONCEPT =230 typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>;231template <class _Ip> struct iterator_traits {232 using __primary_template = iterator_traits;233};234template <class _Ip>235using iter_value_t = typename conditional_t<236 __is_primary_template<iterator_traits<remove_cvref_t<_Ip>>>::value,237 indirectly_readable_traits<remove_cvref_t<_Ip>>,238 iterator_traits<remove_cvref_t<_Ip>>>::value_type;239namespace ranges {240namespace __iter_move {241template <class _Tp>242concept __move_deref = requires(_Tp &&__t) {243 requires is_lvalue_reference_v<decltype(*__t)>;244};245struct __fn {246 template <class _Ip>247 requires __move_deref<_Ip>248 constexpr auto operator()(_Ip &&__i) const249 -> decltype(std::move(*std::forward<_Ip>(__i))) {250 return std::move(*std::forward<_Ip>(__i));251 }252 template <class _Ip>253 constexpr auto operator()(_Ip &&__i) const254 -> decltype(*std::forward<_Ip>(__i));255};256} // namespace __iter_move257inline namespace __cpo {258inline constexpr auto iter_move = __iter_move::__fn{};259}260} // namespace ranges261template <__dereferenceable _Tp>262 requires requires(_Tp &__t) {263 { ranges::iter_move(__t) } -> __can_reference;264 }265using iter_rvalue_reference_t =266 decltype(ranges::iter_move(std::declval<_Tp &>()));267template <class _Ptr, class = void> struct __pointer_traits_impl {};268template <class _Tp> inline constexpr bool is_pointer_v = __is_pointer(_Tp);269template <class _Ip>270concept input_or_output_iterator = requires(_Ip __i) {271 { *__i } -> __can_reference;272};273template <class _Sp, class _Ip>274concept sentinel_for = semiregular<_Sp> && input_or_output_iterator<_Ip> &&275 __weakly_equality_comparable_with<_Sp, _Ip>;276template <class _Ip>277concept input_iterator =278 input_or_output_iterator<_Ip> && requires {279 typename _ITER_CONCEPT<_Ip>;280 } && derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>;281namespace ranges {282namespace __begin {283struct __fn {284 template <class _Tp> constexpr auto operator()(_Tp &&__t) const {285 return static_cast<::std::__decay_t<decltype((__t.begin()))>>(__t.begin());286 }287};288} // namespace __begin289inline namespace __cpo {290inline constexpr auto begin = __begin::__fn{};291}292template <class _Tp>293using iterator_t = decltype(ranges::begin(std::declval<_Tp &>()));294namespace __end {295struct __fn {296 template <class _Tp> constexpr auto operator()(_Tp &&__t) const {}297};298} // namespace __end299inline namespace __cpo {300inline constexpr auto end = __end::__fn{};301}302} // namespace ranges303namespace ranges {304template <class _Tp>305concept range = requires(_Tp &__t) { ranges::end(__t); };306template <class _Tp>307concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;308template <range _Rp> using range_value_t = iter_value_t<iterator_t<_Rp>>;309} // namespace ranges310} // namespace __1311} // namespace std312constexpr void *operator new(std::size_t, void *__p) noexcept; // both-warning {{not defined}}313namespace std {314inline namespace __1 {315template <class _Tp, class... _Args,316 class = decltype(::new (std::declval<void *>())317 _Tp(std::declval<_Args>()...))>318constexpr _Tp *construct_at(_Tp *__location, _Args &&...__args) {319 return ::new (static_cast<void *>(__location)) _Tp(std::forward<_Args>(__args)...); // both-note {{here}}320}321enum class __element_count : size_t;322template <class _Tp, class _Up>323constexpr _Tp *__constexpr_memmove(_Tp *__dest, _Up *__src,324 __element_count __n) {325 size_t __count = static_cast<size_t>(__n);326 ::__builtin_memcpy(__dest, __src, __count * sizeof(_Tp));327 return __dest;328};329namespace ranges {330template <class _From, class _To>331concept __convertible_to_non_slicing =332 convertible_to<_From, _To>;333template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter>334class subrange {335private:336 _Iter __begin_ = _Iter();337 _Sent __end_ = _Sent();338 339public:340 constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter,341 _Sent __sent)342 : __begin_(std::move(__iter)), __end_(std::move(__sent)) {}343 constexpr _Iter begin() { return std::move(__begin_); }344 constexpr _Sent end() const;345};346template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>347subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;348} // namespace ranges349template <class _Tp> class allocator {350public:351 constexpr _Tp *allocate(size_t __n) {352 return static_cast<_Tp *>(::operator new(__n * sizeof(_Tp)));353 }354 constexpr void deallocate(_Tp *__p, size_t __n) noexcept {355 ::operator delete(__p);356 }357};358template <class _CharT> struct char_traits;359template <class _CharT, class _Traits = char_traits<_CharT>,360 class _Allocator = allocator<_CharT>>361class basic_string;362using string = basic_string<char>;363template <class _Iter>364class move_iterator {365private:366public:367 using iterator_type = _Iter;368 using value_type = iter_value_t<_Iter>;369 using reference = iter_rvalue_reference_t<_Iter>;370 constexpr explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {}371 constexpr move_iterator();372 constexpr reference operator*() const {373 return ranges::iter_move(__current_);374 }375 _Iter __current_;376};377namespace ranges {378template <class _T1> struct min_max_result {379 _T1 min;380};381template <class _T1> using minmax_result = min_max_result<_T1>;382struct __minmax {383 template <input_range _Range>384 constexpr ranges::minmax_result<range_value_t<_Range>>385 operator()(_Range &&__r) const {386 auto __first = ranges::begin(__r);387 using _ValueT = range_value_t<_Range>;388 ranges::minmax_result<_ValueT> __result = {*__first};389 return __result;390 }391};392inline namespace __cpo {393inline constexpr auto minmax = __minmax{};394}395} // namespace ranges396template <> struct char_traits<char> {397 using char_type = char;398 static constexpr int compare(const char_type *__lhs, const char_type *__rhs,399 size_t __count) noexcept {400 return __builtin_memcmp(__lhs, __rhs, __count);401 }402 static inline size_t constexpr length(const char_type *__s) noexcept {403 return __builtin_strlen(__s);404 }405 static inline constexpr char_type *406 copy(char_type *__s1, const char_type *__s2, size_t __n) noexcept {407 std::__constexpr_memmove(__s1, __s2, __element_count(__n));408 return __s1;409 }410};411template <class _CharT, class _Traits, class _Allocator> class basic_string {412 using traits_type = _Traits;413 using value_type = _CharT;414 using allocator_type = _Allocator;415 416private:417 struct __long {418 struct {419 unsigned __is_long_ : 1;420 unsigned __cap_ : sizeof(unsigned) * 8 - 1;421 };422 unsigned __size_;423 char *__data_;424 };425 struct __short {426 struct {427 unsigned char __is_long_ : 1;428 };429 };430 union __rep {431 __short __s;432 __long __l;433 };434 __rep __rep_;435 allocator_type __alloc_;436 437public:438 constexpr basic_string(const basic_string &__str) : __alloc_(__str.__alloc_) {439 __init_copy_ctor_external(__str.__rep_.__l.__data_,440 __str.__rep_.__l.__size_);441 }442 constexpr basic_string(basic_string &&__str)443 : __rep_(__str.__rep_), __alloc_(std::move(__str.__alloc_)) {444 __str.__rep_ = __rep();445 }446 constexpr basic_string(const _CharT *__s) {447 __init_copy_ctor_external(__s, traits_type::length(__s));448 }449 inline constexpr ~basic_string() {450 if (__is_long())451 __alloc_.deallocate(__rep_.__l.__data_, __rep_.__l.__cap_*2);452 }453 constexpr unsigned size() const noexcept { return __rep_.__l.__size_; }454 constexpr const value_type *data() const noexcept { return __rep_.__l.__data_; }455 456private:457 constexpr bool __is_long() const {458 if (__builtin_constant_p(__rep_.__l.__is_long_)) {459 return __rep_.__l.__is_long_;460 }461 return __rep_.__s.__is_long_;462 }463 static constexpr void __begin_lifetime(char *__begin, unsigned __n) {464 for (unsigned __i = 0; __i != __n; ++__i)465 std::construct_at(&__begin[__i]);466 }467 constexpr void __init_copy_ctor_external(const value_type *__s,468 unsigned __sz);469};470template <class _CharT, class _Traits, class _Allocator>471constexpr void472basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(473 const value_type *__s, unsigned __sz) {474 char *__p;475 auto __allocation = __alloc_.allocate(__sz + 1);476 __p = __allocation;477 __begin_lifetime(__p, __sz + 1);478 __rep_.__l.__data_ = __p;479 __rep_.__l.__cap_ = (__sz + 1) / 2;480 __rep_.__l.__is_long_ = true;481 __rep_.__l.__size_ = __sz;482 traits_type::copy(__p, __s, __sz + 1);483}484template <class _CharT, class _Traits, class _Allocator>485inline constexpr bool486operator==(const basic_string<_CharT, _Traits, _Allocator> &__lhs,487 const basic_string<_CharT, _Traits, _Allocator> &__rhs) noexcept {488 return _Traits::compare(__lhs.data(), __rhs.data(), __lhs.size()) == 0;489}490} // namespace __1491} // namespace std492template <class It> class cpp20_input_iterator {493 It it_;494 495public:496 using value_type = std::iter_value_t<It>;497 constexpr explicit cpp20_input_iterator(It it) : it_(it) {}498 constexpr decltype(auto) operator*() const { return *it_; }499 constexpr void operator++(int);500 friend constexpr It base(const cpp20_input_iterator &i) { return i.it_; }501};502template <class It> class sentinel_wrapper {503public:504 explicit sentinel_wrapper() = default;505 constexpr explicit sentinel_wrapper(const It &it) : base_(base(it)) {}506 constexpr bool operator==(const It &other) const;507 508private:509 decltype(base(std::declval<It>())) base_;510};511constexpr bool test_range() {512 const std::string str{513 "this long string will be dynamically "514 "allocatedasfajkshdfasdhjkfahjksdgfjkasdhkfgaksdgfhkasghjkdfgjhasdghjfgah"515 "jksdgjfhkasghjkdfghjasgjdfghasdghjkfgajksdgfgajsdfghjkgashjkdfghjasjdhkf"516 "gahjsdfghjkgashjdghjfkasghjkdfasgjkdhfgajkshdfgkjashdgfkjasghdfkjghasdkf"517 "hgaskdjghfasdfasdfasdfasdfasdf"};518 std::string a[] = {str};519 auto range = std::ranges::subrange(520 cpp20_input_iterator(std::move_iterator(a)),521 sentinel_wrapper(cpp20_input_iterator(std::move_iterator(a + 1))));522 auto ret = std::ranges::minmax(range);523 if (ret.min != str)524 __builtin_abort();525 return true;526}527static_assert(test_range());528