diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv --- a/libcxx/docs/Status/RangesPaper.csv +++ b/libcxx/docs/Status/RangesPaper.csv @@ -77,7 +77,7 @@ [move.sentinel],,[predef.iterators],Unassigned,Not started [common.iterator],,"| [iterator.concepts] | [iterator.cust.swap] -| [iterator.cust.move]",Zoe Carver,Not started +| [iterator.cust.move]",Zoe Carver,`D103335 `_,✅ [default.sentinels],std::default_sentinel_t.,No dependencies,Unassigned,Not started [counted.iterator],,"| [iterator.concepts] | [iterator.cust.swap] diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -133,6 +133,7 @@ __iterator/access.h __iterator/advance.h __iterator/back_insert_iterator.h + __iterator/common_iterator.h __iterator/concepts.h __iterator/data.h __iterator/default_sentinel.h @@ -167,8 +168,10 @@ __memory/allocator_traits.h __memory/allocator.h __memory/auto_ptr.h + __memory/builtin_new_allocator.h __memory/compressed_pair.h __memory/construct_at.h + __memory/destruct_n.h __memory/pointer_safety.h __memory/pointer_traits.h __memory/raw_storage_iterator.h diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h --- a/libcxx/include/__algorithm/equal.h +++ b/libcxx/include/__algorithm/equal.h @@ -12,8 +12,8 @@ #include <__config> #include <__algorithm/comp.h> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> -#include // FIXME: replace with <__iterator/distance.h> when it lands #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h --- a/libcxx/include/__algorithm/equal_range.h +++ b/libcxx/include/__algorithm/equal_range.h @@ -15,7 +15,7 @@ #include <__algorithm/half_positive.h> #include <__algorithm/lower_bound.h> #include <__algorithm/upper_bound.h> -#include +#include <__iterator/distance.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h --- a/libcxx/include/__algorithm/inplace_merge.h +++ b/libcxx/include/__algorithm/inplace_merge.h @@ -18,8 +18,11 @@ #include <__algorithm/rotate.h> #include <__algorithm/upper_bound.h> #include <__iterator/iterator_traits.h> +#include <__iterator/reverse_iterator.h> +#include <__memory/destruct_n.h> +#include <__memory/temporary_buffer.h> +#include <__memory/unique_ptr.h> #include <__utility/swap.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/is_permutation.h b/libcxx/include/__algorithm/is_permutation.h --- a/libcxx/include/__algorithm/is_permutation.h +++ b/libcxx/include/__algorithm/is_permutation.h @@ -12,9 +12,9 @@ #include <__algorithm/comp.h> #include <__config> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> -#include // FIXME: replace with <__iterator/distance.h> when it lands #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/lower_bound.h b/libcxx/include/__algorithm/lower_bound.h --- a/libcxx/include/__algorithm/lower_bound.h +++ b/libcxx/include/__algorithm/lower_bound.h @@ -12,7 +12,8 @@ #include <__config> #include <__algorithm/comp.h> #include <__algorithm/half_positive.h> -#include +#include <__iterator/advance.h> +#include <__iterator/distance.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/partition_point.h b/libcxx/include/__algorithm/partition_point.h --- a/libcxx/include/__algorithm/partition_point.h +++ b/libcxx/include/__algorithm/partition_point.h @@ -11,7 +11,7 @@ #include <__config> #include <__algorithm/half_positive.h> -#include +#include <__iterator/distance.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/rotate.h b/libcxx/include/__algorithm/rotate.h --- a/libcxx/include/__algorithm/rotate.h +++ b/libcxx/include/__algorithm/rotate.h @@ -13,11 +13,11 @@ #include <__algorithm/move_backward.h> #include <__algorithm/swap_ranges.h> #include <__config> +#include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__iterator/prev.h> #include <__utility/swap.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/rotate_copy.h b/libcxx/include/__algorithm/rotate_copy.h --- a/libcxx/include/__algorithm/rotate_copy.h +++ b/libcxx/include/__algorithm/rotate_copy.h @@ -11,7 +11,6 @@ #include <__config> #include <__algorithm/copy.h> -#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/sample.h b/libcxx/include/__algorithm/sample.h --- a/libcxx/include/__algorithm/sample.h +++ b/libcxx/include/__algorithm/sample.h @@ -11,8 +11,8 @@ #include <__config> #include <__algorithm/min.h> +#include <__iterator/distance.h> #include <__random/uniform_int_distribution.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -15,8 +15,9 @@ #include <__algorithm/min_element.h> #include <__algorithm/partial_sort.h> #include <__algorithm/unwrap_iter.h> +#include <__memory/destruct_n.h> +#include <__memory/unique_ptr.h> #include <__utility/swap.h> -#include #include // swap #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h --- a/libcxx/include/__algorithm/stable_partition.h +++ b/libcxx/include/__algorithm/stable_partition.h @@ -12,8 +12,9 @@ #include <__config> #include <__algorithm/rotate.h> #include <__iterator/iterator_traits.h> +#include <__memory/destruct_n.h> +#include <__memory/unique_ptr.h> #include <__utility/swap.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -15,8 +15,9 @@ #include <__algorithm/inplace_merge.h> #include <__algorithm/sort.h> #include <__iterator/iterator_traits.h> +#include <__memory/destruct_n.h> +#include <__memory/unique_ptr.h> #include <__utility/swap.h> -#include #include // swap #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/unwrap_iter.h b/libcxx/include/__algorithm/unwrap_iter.h --- a/libcxx/include/__algorithm/unwrap_iter.h +++ b/libcxx/include/__algorithm/unwrap_iter.h @@ -10,7 +10,7 @@ #define _LIBCPP___ALGORITHM_UNWRAP_ITER_H #include <__config> -#include +#include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> #include diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h --- a/libcxx/include/__algorithm/upper_bound.h +++ b/libcxx/include/__algorithm/upper_bound.h @@ -12,7 +12,7 @@ #include <__config> #include <__algorithm/comp.h> #include <__algorithm/half_positive.h> -#include +#include <__iterator/distance.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -16,10 +16,10 @@ #include <__functional/unary_function.h> #include <__iterator/iterator_traits.h> #include <__memory/allocator_traits.h> +#include <__memory/builtin_new_allocator.h> #include <__memory/compressed_pair.h> #include <__memory/shared_ptr.h> #include -#include // TODO: replace with <__memory/__builtin_new_allocator.h> #include #include diff --git a/libcxx/include/__iterator/common_iterator.h b/libcxx/include/__iterator/common_iterator.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/common_iterator.h @@ -0,0 +1,210 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___ITERATOR_COMMON_ITERATOR_H +#define _LIBCPP___ITERATOR_COMMON_ITERATOR_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/readable_traits.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +template _Sent> + requires (!same_as<_Iter, _Sent> && copyable<_Iter>) +class common_iterator { + variant<_Iter, _Sent> __hold; + + class __proxy { + friend common_iterator; + + iter_value_t<_Iter> __value; + constexpr __proxy(iter_reference_t<_Iter>&& __x) + : __value(__x) {} + + public: + const iter_value_t<_Iter>* operator->() const { + return _VSTD::addressof(__value); + } + }; + + class __postfix_proxy { + friend common_iterator; + + iter_value_t<_Iter> __value; + constexpr __postfix_proxy(iter_reference_t<_Iter>&& __x) + : __value(__x) {} + + public: + const iter_value_t<_Iter>& operator*() const { + return __value; + } + }; + +public: + common_iterator() requires default_initializable<_Iter> = default; + + constexpr common_iterator(_Iter __i) : __hold(in_place_type<_Iter>, _VSTD::move(__i)) {} + constexpr common_iterator(_Sent __s) : __hold(in_place_type<_Sent>, _VSTD::move(__s)) {} + + template + requires convertible_to && convertible_to + constexpr common_iterator(const common_iterator<_I2, _S2>& __other) + : __hold(__other.__hold) {} + + template + requires convertible_to && convertible_to && + assignable_from && assignable_from + common_iterator& operator=(const common_iterator<_I2, _S2>& __other) { + __hold = __other.__hold; + } + + decltype(auto) operator*() { return *_VSTD::get<_Iter>(__hold); } + decltype(auto) operator*() const + requires __dereferenceable + { return *_VSTD::get<_Iter>(__hold); } + + decltype(auto) operator->() const + requires indirectly_readable && + (requires(const _Iter& __i) { __i.operator->(); } || + is_reference_v> || + constructible_from, iter_reference_t<_Iter>>) { + if constexpr (is_pointer_v<_Iter> || requires(const _Iter& __i) { __i.operator->(); }) { + return _VSTD::get<_Iter>(__hold); + } else if constexpr (is_reference_v>) { + auto&& __tmp = *_VSTD::get<_Iter>(__hold); + return _VSTD::addressof(__tmp); + } else { + return __proxy(*_VSTD::get<_Iter>(__hold)); + } + } + + common_iterator& operator++() { ++_VSTD::get<_Iter>(__hold); return *this; } + decltype(auto) operator++(int) { + if constexpr (forward_iterator<_Iter>) { + auto __tmp = *this; + ++*this; + return __tmp; + } else if constexpr (requires (_Iter& __i) { { *__i++ } -> __referenceable; } || + !(constructible_from, iter_reference_t<_Iter>> && + move_constructible>)) { + return _VSTD::get<_Iter>(__hold)++; + } else { + __postfix_proxy __p(**this); + ++*this; + return __p; + } + } + + template _S2> + requires sentinel_for<_Sent, _I2> + friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + if (__x.__hold.index() == __y.__hold.index()) + return true; + + if (__x.__hold.index() == 0) + return _VSTD::get<_Iter>(__x.__hold) == _VSTD::get<_Sent>(__y.__hold); + + return _VSTD::get<_Sent>(__x.__hold) == _VSTD::get<_Iter>(__y.__hold); + } + + template _S2> + requires sentinel_for<_Sent, _I2> && equality_comparable_with<_Iter, _I2> + friend bool operator==(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + if (__x.__hold.index() == 1 && __y.__hold.index() == 1) + return true; + + if (__x.__hold.index() == 0 && __y.__hold.index() == 0) + return _VSTD::get<_Iter>(__x.__hold) == _VSTD::get<_Iter>(__y.__hold); + + if (__x.__hold.index() == 0) + return _VSTD::get<_Iter>(__x.__hold) == _VSTD::get<_Sent>(__y.__hold); + + return _VSTD::get<_Sent>(__x.__hold) == _VSTD::get<_Iter>(__y.__hold); + } + + template _I2, sized_sentinel_for<_Iter> _S2> + requires sized_sentinel_for<_Sent, _I2> + friend iter_difference_t<_I2> operator-(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) { + if (__x.__hold.index() == 1 && __y.__hold.index() == 1) + return 0; + + if (__x.__hold.index() == 0 && __y.__hold.index() == 0) + return _VSTD::get<_Iter>(__x.__hold) - _VSTD::get<_Iter>(__y.__hold); + + if (__x.__hold.index() == 0) + return _VSTD::get<_Iter>(__x.__hold) - _VSTD::get<_Sent>(__y.__hold); + + return _VSTD::get<_Sent>(__x.__hold) - _VSTD::get<_Iter>(__y.__hold); + } + + friend iter_rvalue_reference_t<_Iter> iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(declval()))) + requires input_iterator<_Iter> + { return ranges::iter_move( _VSTD::get<_Iter>(__i.__hold)); } + + template _I2, class _S2> + friend void iter_swap(const common_iterator& __x, const common_iterator<_I2, _S2>& __y) + noexcept(noexcept(ranges::iter_swap(declval(), declval()))) + { return ranges::iter_swap( _VSTD::get<_Iter>(__x.__hold), _VSTD::get<_Iter>(__y.__hold)); } +}; + +template +struct incrementable_traits> { + using difference_type = iter_difference_t<_Iter>; +}; + +template +concept __denotes_forward_iter = + requires { + typename iterator_traits<_Iter>::iterator_category; + } && + derived_from::iterator_category, forward_iterator_tag>; + +template +concept __common_iter_has_ptr_op = requires(const common_iterator<_Iter, _Sent> __a) { + __a.operator->(); +}; + +template +struct iterator_traits> { + using iterator_concept = conditional_t, + forward_iterator_tag, + input_iterator_tag>; + using iterator_category = conditional_t<__denotes_forward_iter<_Iter>, + forward_iterator_tag, + input_iterator_tag>; + using pointer = conditional_t<__common_iter_has_ptr_op<_Iter, _Sent>, + decltype(declval>().operator->()), + void>; + using value_type = iter_value_t<_Iter>; + using difference_type = iter_difference_t<_Iter>; + using reference = iter_reference_t<_Iter>; +}; + + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ITERATOR_COMMON_ITERATOR_H diff --git a/libcxx/include/__memory/builtin_new_allocator.h b/libcxx/include/__memory/builtin_new_allocator.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__memory/builtin_new_allocator.h @@ -0,0 +1,74 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MEMORY_BUILTIN_NEW_ALLOCATOR_H +#define _LIBCPP___MEMORY_BUILTIN_NEW_ALLOCATOR_H + +#include <__config> +#include <__memory/unique_ptr.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __builtin_new_allocator -- A non-templated helper for allocating and +// deallocating memory using __builtin_operator_new and +// __builtin_operator_delete. It should be used in preference to +// `std::allocator` to avoid additional instantiations. +struct __builtin_new_allocator { + struct __builtin_new_deleter { + typedef void* pointer_type; + + _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) + : __size_(__size), __align_(__align) {} + + void operator()(void* p) const _NOEXCEPT { + _VSTD::__libcpp_deallocate(p, __size_, __align_); + } + + private: + size_t __size_; + size_t __align_; + }; + + typedef unique_ptr __holder_t; + + static __holder_t __allocate_bytes(size_t __s, size_t __align) { + return __holder_t(_VSTD::__libcpp_allocate(__s, __align), + __builtin_new_deleter(__s, __align)); + } + + static void __deallocate_bytes(void* __p, size_t __s, + size_t __align) _NOEXCEPT { + _VSTD::__libcpp_deallocate(__p, __s, __align); + } + + template + _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE + static __holder_t __allocate_type(size_t __n) { + return __allocate_bytes(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); + } + + template + _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE + static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { + __deallocate_bytes(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MEMORY_BUILTIN_NEW_ALLOCATOR_H diff --git a/libcxx/include/__memory/destruct_n.h b/libcxx/include/__memory/destruct_n.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__memory/destruct_n.h @@ -0,0 +1,67 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MEMORY_DESTRUCT_N_H +#define _LIBCPP___MEMORY_DESTRUCT_N_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __destruct_n +{ +private: + size_t __size_; + + template + _LIBCPP_INLINE_VISIBILITY void __process(_Tp* __p, false_type) _NOEXCEPT + {for (size_t __i = 0; __i < __size_; ++__i, ++__p) __p->~_Tp();} + + template + _LIBCPP_INLINE_VISIBILITY void __process(_Tp*, true_type) _NOEXCEPT + {} + + _LIBCPP_INLINE_VISIBILITY void __incr(false_type) _NOEXCEPT + {++__size_;} + _LIBCPP_INLINE_VISIBILITY void __incr(true_type) _NOEXCEPT + {} + + _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, false_type) _NOEXCEPT + {__size_ = __s;} + _LIBCPP_INLINE_VISIBILITY void __set(size_t, true_type) _NOEXCEPT + {} +public: + _LIBCPP_INLINE_VISIBILITY explicit __destruct_n(size_t __s) _NOEXCEPT + : __size_(__s) {} + + template + _LIBCPP_INLINE_VISIBILITY void __incr() _NOEXCEPT + {__incr(integral_constant::value>());} + + template + _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, _Tp*) _NOEXCEPT + {__set(__s, integral_constant::value>());} + + template + _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) _NOEXCEPT + {__process(__p, integral_constant::value>());} +}; + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MEMORY_DESTRUCT_N_H diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -5,6 +5,7 @@ #include <__config> #include <__utility/forward.h> #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -652,8 +652,6 @@ #include #include #include -#include // needed to provide swap_ranges. -#include #include #include #include diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -136,6 +136,10 @@ template concept indirectly_swappable = see below; // since C++20 +template S> + requires (!same_as && copyable) +class common_iterator; // since C++20 + template struct iterator // deprecated in C++17 @@ -564,6 +568,7 @@ #include <__iterator/access.h> #include <__iterator/advance.h> #include <__iterator/back_insert_iterator.h> +#include <__iterator/common_iterator.h> #include <__iterator/concepts.h> #include <__iterator/data.h> #include <__iterator/default_sentinel.h> diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -674,8 +674,10 @@ #include <__memory/allocator.h> #include <__memory/allocator_arg_t.h> #include <__memory/allocator_traits.h> +#include <__memory/builtin_new_allocator.h> #include <__memory/compressed_pair.h> #include <__memory/construct_at.h> +#include <__memory/destruct_n.h> #include <__memory/pointer_safety.h> #include <__memory/pointer_traits.h> #include <__memory/raw_storage_iterator.h> @@ -799,45 +801,6 @@ _VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp)); } -struct __destruct_n -{ -private: - size_t __size_; - - template - _LIBCPP_INLINE_VISIBILITY void __process(_Tp* __p, false_type) _NOEXCEPT - {for (size_t __i = 0; __i < __size_; ++__i, ++__p) __p->~_Tp();} - - template - _LIBCPP_INLINE_VISIBILITY void __process(_Tp*, true_type) _NOEXCEPT - {} - - _LIBCPP_INLINE_VISIBILITY void __incr(false_type) _NOEXCEPT - {++__size_;} - _LIBCPP_INLINE_VISIBILITY void __incr(true_type) _NOEXCEPT - {} - - _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, false_type) _NOEXCEPT - {__size_ = __s;} - _LIBCPP_INLINE_VISIBILITY void __set(size_t, true_type) _NOEXCEPT - {} -public: - _LIBCPP_INLINE_VISIBILITY explicit __destruct_n(size_t __s) _NOEXCEPT - : __size_(__s) {} - - template - _LIBCPP_INLINE_VISIBILITY void __incr() _NOEXCEPT - {__incr(integral_constant::value>());} - - template - _LIBCPP_INLINE_VISIBILITY void __set(size_t __s, _Tp*) _NOEXCEPT - {__set(__s, integral_constant::value>());} - - template - _LIBCPP_INLINE_VISIBILITY void operator()(_Tp* __p) _NOEXCEPT - {__process(__p, integral_constant::value>());} -}; - _LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space); // --- Helper for container swap -- @@ -912,52 +875,6 @@ > : true_type {}; -// __builtin_new_allocator -- A non-templated helper for allocating and -// deallocating memory using __builtin_operator_new and -// __builtin_operator_delete. It should be used in preference to -// `std::allocator` to avoid additional instantiations. -struct __builtin_new_allocator { - struct __builtin_new_deleter { - typedef void* pointer_type; - - _LIBCPP_CONSTEXPR explicit __builtin_new_deleter(size_t __size, size_t __align) - : __size_(__size), __align_(__align) {} - - void operator()(void* p) const _NOEXCEPT { - _VSTD::__libcpp_deallocate(p, __size_, __align_); - } - - private: - size_t __size_; - size_t __align_; - }; - - typedef unique_ptr __holder_t; - - static __holder_t __allocate_bytes(size_t __s, size_t __align) { - return __holder_t(_VSTD::__libcpp_allocate(__s, __align), - __builtin_new_deleter(__s, __align)); - } - - static void __deallocate_bytes(void* __p, size_t __s, - size_t __align) _NOEXCEPT { - _VSTD::__libcpp_deallocate(__p, __s, __align); - } - - template - _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE - static __holder_t __allocate_type(size_t __n) { - return __allocate_bytes(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); - } - - template - _LIBCPP_NODEBUG _LIBCPP_ALWAYS_INLINE - static void __deallocate_type(void* __p, size_t __n) _NOEXCEPT { - __deallocate_bytes(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); - } -}; - - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -539,8 +539,10 @@ module allocator_arg_t { header "__memory/allocator_arg_t.h" } module allocator_traits { header "__memory/allocator_traits.h" } module auto_ptr { header "__memory/auto_ptr.h" } + module builtin_new_allocator { header "__memory/builtin_new_allocator.h" } module compressed_pair { header "__memory/compressed_pair.h" } module construct_at { header "__memory/construct_at.h" } + module destruct_n { header "__memory/destruct_n.h" } module pointer_safety { header "__memory/pointer_safety.h" } module pointer_traits { header "__memory/pointer_traits.h" } module raw_storage_iterator { header "__memory/raw_storage_iterator.h" } diff --git a/libcxx/include/valarray b/libcxx/include/valarray --- a/libcxx/include/valarray +++ b/libcxx/include/valarray @@ -340,6 +340,7 @@ */ #include <__config> +#include <__memory/uninitialized_algorithms.h> #include #include #include diff --git a/libcxx/include/variant b/libcxx/include/variant --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -206,7 +206,7 @@ #include <__tuple> #include #include -#include +#include <__functional/hash.h> #include #include #include diff --git a/libcxx/include/vector b/libcxx/include/vector --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -276,6 +276,7 @@ #include <__debug> #include <__functional_base> #include <__iterator/wrap_iter.h> +#include <__iterator/move_iterator.h> #include <__split_buffer> #include <__utility/forward.h> #include diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/arrow.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// decltype(auto) operator->() const +// requires see below; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + // Case 2: http://eel.is/c++draft/iterators.common#common.iter.access-5.2 + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->() == buffer); + assert(commonIter2.operator->() == buffer); + } + + // Case 3: http://eel.is/c++draft/iterators.common#common.iter.access-5.3 + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*commonIter1.operator->().operator->() == 1); + assert(*commonIter2.operator->().operator->() == 1); + } + + // Case 3: http://eel.is/c++draft/iterators.common#common.iter.access-5.3 + { + auto iter1 = void_plus_plus_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*commonIter1.operator->().operator->() == 1); + assert(*commonIter2.operator->().operator->() == 1); + } + + // Case 1: http://eel.is/c++draft/iterators.common#common.iter.access-5.1 + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->().base() == buffer); + assert(commonIter2.operator->().base() == buffer); + } + + // Case 1: http://eel.is/c++draft/iterators.common#common.iter.access-5.1 + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->().base() == buffer); + assert(commonIter2.operator->().base() == buffer); + } + + // Case 1: http://eel.is/c++draft/iterators.common#common.iter.access-5.1 + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(commonIter1.operator->().base() == buffer); + assert(commonIter2.operator->().base() == buffer); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/assign.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/assign.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/assign.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// requires convertible_to && convertible_to && +// assignable_from && assignable_from +// common_iterator& operator=(const common_iterator& x); + +#include +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(cpp17_input_iterator(buffer + 1)); + + assert(*commonIter1 == 1); + assert(*commonIter2 == 2); + assert(commonIter1 != commonIter2); + + commonIter1 = commonIter2; + + assert(*commonIter1 == 2); + assert(*commonIter2 == 2); + assert(commonIter1 == commonIter2); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(forward_iterator(buffer + 1)); + + assert(*commonIter1 == 1); + assert(*commonIter2 == 2); + assert(commonIter1 != commonIter2); + + commonIter1 = commonIter2; + + assert(*commonIter1 == 2); + assert(*commonIter2 == 2); + assert(commonIter1 == commonIter2); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + auto commonIter2 = std::common_iterator>(iter1 + 1); + auto commonSent2 = std::common_iterator>(sentinel_type{buffer + 7}); + + assert(*commonIter1 == 1); + assert(*commonIter2 == 2); + assert(commonIter1 != commonIter2); + + commonIter1 = commonIter2; + + assert(*commonIter1 == 2); + assert(*commonIter2 == 2); + assert(commonIter1 == commonIter2); + + assert(std::ranges::next(commonIter1, 6) != commonSent1); + assert(std::ranges::next(commonIter1, 6) == commonSent2); + + commonSent1 = commonSent2; + + assert(std::ranges::next(commonIter1, 6) == commonSent1); + assert(std::ranges::next(commonIter1, 6) == commonSent2); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/ctor.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/ctor.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/ctor.pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// constexpr common_iterator() requires default_initializable = default; +// constexpr common_iterator(I i); +// constexpr common_iterator(S s); +// template +// requires convertible_to && convertible_to +// constexpr common_iterator(const common_iterator& x); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +struct ConvertibleToForwardIter { + int *ptr; + + constexpr operator forward_iterator() { return forward_iterator(ptr); } +}; + +template +concept ValidCommonIterator = requires { + typename std::common_iterator; +}; + +template +concept ConvCtorEnabled = requires(I2 ci) { + std::common_iterator(ci); +}; + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + static_assert( std::is_default_constructible_v>>); + static_assert(!std::is_default_constructible_v, sentinel_type>>); + + // Not copyable: + static_assert(!ValidCommonIterator, sentinel_type>); + // Same iter and sent: + static_assert(!ValidCommonIterator, cpp17_input_iterator>); + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + assert(commonIter1 != commonSent1); + } + + // Conversion constructor: + { + ConvertibleToForwardIter conv{buffer}; + auto commonIter = std::common_iterator, sentinel_type>(conv); + assert(*commonIter == 1); + + static_assert(ConvCtorEnabled, sentinel_type, ConvertibleToForwardIter>); + static_assert(!ConvCtorEnabled, sentinel_type, random_access_iterator>); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/deref.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/deref.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/deref.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// decltype(auto) operator*(); +// decltype(auto) operator*() const +// requires dereferenceable; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto iter2 = simple_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto iter2 = value_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto iter2 = cpp17_input_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto iter2 = forward_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto iter2 = random_access_iterator(buffer); + const auto commonIter2 = std::common_iterator>(iter1); + + assert(*iter1 == 1); + assert(*commonIter1 == 1); + + assert(*iter2 == 1); + assert(*commonIter2 == 1); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/eq.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/eq.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template S2> +// requires sentinel_for +// friend bool operator==( +// const common_iterator& x, const common_iterator& y); +// template S2> +// requires sentinel_for && equality_comparable_with +// friend bool operator==( +// const common_iterator& x, const common_iterator& y); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + const auto commonIter2 = std::common_iterator>(iter1); + const auto commonSent2 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(commonIter1 != commonSent1); + assert(commonIter2 != commonSent2); + + for (auto i = 1; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_move.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_move.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_move.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// friend iter_rvalue_reference_t iter_move(const common_iterator& i) +// noexcept(noexcept(ranges::iter_move(declval()))) +// requires input_iterator; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + assert(std::ranges::iter_move(commonIter1) == 1); + ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + assert(std::ranges::iter_move(commonIter1) == 1); + ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + assert(std::ranges::iter_move(commonIter1) == 1); + ASSERT_SAME_TYPE(decltype(std::ranges::iter_move(commonIter1)), int&&); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_swap.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_swap.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iter_swap.pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template I2, class S2> +// friend void iter_swap(const common_iterator& x, const common_iterator& y) +// noexcept(noexcept(ranges::iter_swap(declval(), declval()))); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(iter1); + for (auto i = 0; i < 4; ++i) ++commonIter2; + assert(*commonIter2 == 5); + std::ranges::iter_swap(commonIter1, commonIter2); + assert(*commonIter1 == 5); + assert(*commonIter2 == 1); + std::ranges::iter_swap(commonIter2, commonIter1); + } + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(iter1); + for (auto i = 0; i < 4; ++i) ++commonIter2; + assert(*commonIter2 == 5); + std::ranges::iter_swap(commonIter1, commonIter2); + assert(*commonIter1 == 5); + assert(*commonIter2 == 1); + std::ranges::iter_swap(commonIter2, commonIter1); + } + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonIter2 = std::common_iterator>(iter1); + for (auto i = 0; i < 4; ++i) ++commonIter2; + assert(*commonIter2 == 5); + std::ranges::iter_swap(commonIter1, commonIter2); + assert(*commonIter1 == 5); + assert(*commonIter2 == 1); + std::ranges::iter_swap(commonIter2, commonIter1); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/iterator_traits.compile.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template +// struct iterator_traits>; + +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + { + using Iter = simple_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + } + { + using Iter = value_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + // Note: IterTraits::pointer == __proxy. + static_assert(!std::same_as); + static_assert(std::same_as); + } + { + using Iter = cpp17_input_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); // TODO: is this right? + static_assert(std::same_as); + } + { + using Iter = forward_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + } + { + using Iter = random_access_iterator; + using CommonIter = std::common_iterator>; + using IterTraits = std::iterator_traits; + + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + } +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/minus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/minus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/minus.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// template I2, sized_sentinel_for S2> +// requires sized_sentinel_for +// friend iter_difference_t operator-( +// const common_iterator& x, const common_iterator& y); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sized_sentinel_type{buffer + 8}); + assert(commonIter1 - commonSent1 == -8); + assert(commonSent1 - commonIter1 == 8); + assert(commonIter1 - commonIter1 == 0); + assert(commonSent1 - commonSent1 == 0); +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/plus_plus.pass.cpp b/libcxx/test/std/iterators/predef.iterators/iterators.common/plus_plus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/plus_plus.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// common_iterator& operator++(); +// decltype(auto) operator++(int); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +struct Incomplete; + +void test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + // Reference: http://eel.is/c++draft/iterators.common#common.iter.nav-5 + // Case 2: can-reference + { + auto iter1 = simple_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + // Case 2: can-reference + { + auto iter1 = value_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + // Case 3: postfix-proxy + { + auto iter1 = void_plus_plus_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + // Case 2: where this is not referencable or move constructible + { + auto iter1 = value_type_not_move_constructible_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + commonIter1++; + // Note: operator++ returns void. + // assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*commonIter1 == i); + commonIter1++; + } + assert(commonIter1 == commonSent1); + } + + // Case 2: can-reference + { + auto iter1 = cpp17_input_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + // Case 1: forward_iterator + { + auto iter1 = forward_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } + + // Case 1: forward_iterator + { + auto iter1 = random_access_iterator(buffer); + auto commonIter1 = std::common_iterator>(iter1); + auto commonSent1 = std::common_iterator>(sentinel_type{buffer + 8}); + + assert(*(commonIter1++) == 1); + assert(*commonIter1 == 2); + assert(*(++commonIter1) == 3); + assert(*commonIter1 == 3); + + for (auto i = 3; commonIter1 != commonSent1; ++i) { + assert(*(commonIter1++) == i); + } + assert(commonIter1 == commonSent1); + } +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/iterators.common/types.h b/libcxx/test/std/iterators/predef.iterators/iterators.common/types.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/iterators.common/types.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H +#define TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H + +#include "test_macros.h" +#include "test_iterators.h" + +template +class simple_iterator +{ + It it_; + +public: + typedef std::input_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + constexpr It base() const {return it_;} + + simple_iterator() = default; + explicit constexpr simple_iterator(It it) : it_(it) {} + + constexpr reference operator*() const {return *it_;} + + constexpr simple_iterator& operator++() {++it_; return *this;} + constexpr simple_iterator operator++(int) + {simple_iterator tmp(*this); ++(*this); return tmp;} +}; + +template +class value_iterator +{ + It it_; + +public: + typedef std::input_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + constexpr It base() const {return it_;} + + value_iterator() = default; + explicit constexpr value_iterator(It it) : it_(it) {} + + constexpr value_type operator*() const {return std::move(*it_);} + + constexpr value_iterator& operator++() {++it_; return *this;} + constexpr value_iterator operator++(int) + {value_iterator tmp(*this); ++(*this); return tmp;} +}; + +template +class void_plus_plus_iterator +{ + It it_; + +public: + typedef std::input_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + constexpr It base() const {return it_;} + + void_plus_plus_iterator() = default; + explicit constexpr void_plus_plus_iterator(It it) : it_(it) {} + + constexpr value_type operator*() const {return std::move(*it_);} + + constexpr void_plus_plus_iterator& operator++() {++it_; return *this;} + constexpr void operator++(int) {++(*this);} +}; + +// Not referenceable, constructible, and not move constructible. +template +class value_type_not_move_constructible_iterator +{ + It it_; + +public: + template + struct hold { + T value_; + hold(T v) : value_(v) {} + hold(const hold&) = delete; + hold(hold&&) = delete; + }; + + typedef std::input_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type underlying_value_type; + typedef hold value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + constexpr It base() const {return it_;} + + value_type_not_move_constructible_iterator() = default; + explicit constexpr value_type_not_move_constructible_iterator(It it) : it_(it) {} + + constexpr underlying_value_type operator*() const {return std::move(*it_);} + + constexpr value_type_not_move_constructible_iterator& operator++() {++it_; return *this;} + constexpr void operator++(int) {++(*this);} +}; + +template +struct sentinel_type { + T base; + + template + friend constexpr bool operator==(const sentinel_type& lhs, const U& rhs) { return lhs.base == rhs.base(); } + template + friend constexpr bool operator==(const U& lhs, const sentinel_type& rhs) { return lhs.base() == rhs.base; } +}; + +template +struct sized_sentinel_type { + T base; + + template + friend constexpr bool operator==(const sized_sentinel_type& lhs, const U& rhs) { return lhs.base - rhs.base(); } + template + friend constexpr bool operator==(const U& lhs, const sized_sentinel_type& rhs) { return lhs.base() - rhs.base; } + template + friend constexpr auto operator- (const sized_sentinel_type& lhs, const U& rhs) { return lhs.base - rhs.base(); } + template + friend constexpr auto operator- (const U& lhs, const sized_sentinel_type& rhs) { return lhs.base() - rhs.base; } +}; + +#endif // TEST_STD_RANGES_ITERATORS_PREDEF_ITERATORS_ITERATORS_COMMON_TYPES_H diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -161,6 +161,59 @@ return !(x == y); } +template +class non_default_constructible_iterator +{ + It it_; + + template friend class non_default_constructible_iterator; +public: + typedef std::forward_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + TEST_CONSTEXPR_CXX14 It base() const {return it_;} + + non_default_constructible_iterator() = delete; + + explicit TEST_CONSTEXPR_CXX14 non_default_constructible_iterator(It it) : it_(it) {} + template + TEST_CONSTEXPR_CXX14 non_default_constructible_iterator(const non_default_constructible_iterator& u) :it_(u.it_) {} + + TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;} + TEST_CONSTEXPR_CXX14 pointer operator->() const {return it_;} + + TEST_CONSTEXPR_CXX14 non_default_constructible_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 non_default_constructible_iterator operator++(int) + {non_default_constructible_iterator tmp(*this); ++(*this); return tmp;} + + friend TEST_CONSTEXPR_CXX14 bool operator==(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y) + {return x.it_ == y.it_;} + friend TEST_CONSTEXPR_CXX14 bool operator!=(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y) + {return !(x == y);} + + template + void operator,(T const &) DELETE_FUNCTION; +}; + +template +inline +bool TEST_CONSTEXPR_CXX14 +operator==(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y) +{ + return x.base() == y.base(); +} + +template +inline +bool TEST_CONSTEXPR_CXX14 +operator!=(const non_default_constructible_iterator& x, const non_default_constructible_iterator& y) +{ + return !(x == y); +} + template class bidirectional_iterator {