diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -422,6 +422,7 @@ __iterator/advance.h __iterator/back_insert_iterator.h __iterator/bounded_iter.h + __iterator/cpp17_iterator_concepts.h __iterator/common_iterator.h __iterator/concepts.h __iterator/counted_iterator.h diff --git a/libcxx/include/__algorithm/pstl_any_all_none_of.h b/libcxx/include/__algorithm/pstl_any_all_none_of.h --- a/libcxx/include/__algorithm/pstl_any_all_none_of.h +++ b/libcxx/include/__algorithm/pstl_any_all_none_of.h @@ -12,6 +12,7 @@ #include <__algorithm/pstl_find.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> +#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_execution_policy.h> @@ -36,6 +37,7 @@ enable_if_t, int> = 0> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of), [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { @@ -56,6 +58,7 @@ enable_if_t, int> = 0> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of), [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { @@ -78,6 +81,7 @@ enable_if_t, int> = 0> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of), [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) { diff --git a/libcxx/include/__algorithm/pstl_fill.h b/libcxx/include/__algorithm/pstl_fill.h --- a/libcxx/include/__algorithm/pstl_fill.h +++ b/libcxx/include/__algorithm/pstl_fill.h @@ -13,6 +13,7 @@ #include <__algorithm/pstl_for_each.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> +#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> @@ -36,6 +37,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI void fill(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill), [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { @@ -59,6 +61,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI void fill_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _SizeT __n, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_fill_n), [&](_ForwardIterator __g_first, _SizeT __g_n, const _Tp& __g_value) { diff --git a/libcxx/include/__algorithm/pstl_find.h b/libcxx/include/__algorithm/pstl_find.h --- a/libcxx/include/__algorithm/pstl_find.h +++ b/libcxx/include/__algorithm/pstl_find.h @@ -14,6 +14,7 @@ #include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> +#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> @@ -34,6 +35,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI _ForwardIterator find_if(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); using _Backend = typename __select_backend<_RawPolicy>::type; return std::__pstl_find_if<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__pred)); } @@ -48,6 +50,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI _ForwardIterator find_if_not(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find_if_not), [&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) { @@ -70,6 +73,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI _ForwardIterator find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_find), [&](_ForwardIterator __g_first, _ForwardIterator __g_last, const _Tp& __g_value) { diff --git a/libcxx/include/__algorithm/pstl_for_each.h b/libcxx/include/__algorithm/pstl_for_each.h --- a/libcxx/include/__algorithm/pstl_for_each.h +++ b/libcxx/include/__algorithm/pstl_for_each.h @@ -14,6 +14,7 @@ #include <__algorithm/pstl_backend.h> #include <__algorithm/pstl_frontend_dispatch.h> #include <__config> +#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> #include <__type_traits/is_execution_policy.h> #include <__type_traits/remove_cvref.h> @@ -35,6 +36,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI void for_each(_ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); using _Backend = typename __select_backend<_RawPolicy>::type; std::__pstl_for_each<_RawPolicy>(_Backend{}, std::move(__first), std::move(__last), std::move(__func)); } @@ -50,6 +52,7 @@ enable_if_t, int> = 0> _LIBCPP_HIDE_FROM_ABI void for_each_n(_ExecutionPolicy&& __policy, _ForwardIterator __first, _Size __size, _Function __func) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); return std::__pstl_frontend_dispatch( _LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_for_each_n), [&](_ForwardIterator __g_first, _Size __g_size, _Function __g_func) { diff --git a/libcxx/include/__algorithm/pstl_transform.h b/libcxx/include/__algorithm/pstl_transform.h --- a/libcxx/include/__algorithm/pstl_transform.h +++ b/libcxx/include/__algorithm/pstl_transform.h @@ -11,6 +11,7 @@ #include <__algorithm/pstl_backend.h> #include <__config> +#include <__iterator/cpp17_iterator_concepts.h> #include <__iterator/iterator_traits.h> #include <__type_traits/is_execution_policy.h> #include <__utility/terminate_on_exception.h> @@ -35,6 +36,9 @@ _ForwardIterator __last, _ForwardOutIterator __result, _UnaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first))); using _Backend = typename __select_backend<_RawPolicy>::type; return std::__pstl_transform<_RawPolicy>( _Backend{}, std::move(__first), std::move(__last), std::move(__result), std::move(__op)); @@ -54,6 +58,10 @@ _ForwardIterator2 __first2, _ForwardOutIterator __result, _BinaryOperation __op) { + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2); + _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardOutIterator); + _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(_ForwardOutIterator, decltype(__op(*__first1, *__first2))); using _Backend = typename __select_backend<_RawPolicy>::type; return std::__pstl_transform<_RawPolicy>( _Backend{}, std::move(__first1), std::move(__last1), std::move(__first2), std::move(__result), std::move(__op)); diff --git a/libcxx/include/__iterator/cpp17_iterator_concepts.h b/libcxx/include/__iterator/cpp17_iterator_concepts.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__iterator/cpp17_iterator_concepts.h @@ -0,0 +1,184 @@ +//===----------------------------------------------------------------------===// +// +// 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_CPP17_ITERATOR_CONCEPTS_H +#define _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H + +#include <__concepts/boolean_testable.h> +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_signed.h> +#include <__type_traits/is_void.h> +#include <__utility/as_const.h> +#include <__utility/forward.h> +#include <__utility/move.h> +#include <__utility/swap.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 20 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +concept __cpp17_move_constructible = is_move_constructible_v<_Tp>; + +template +concept __cpp17_copy_constructible = __cpp17_move_constructible<_Tp> && is_copy_constructible_v<_Tp>; + +template +concept __cpp17_move_assignable = requires(_Tp __lhs, _Tp __rhs) { + { __lhs = std::move(__rhs) } -> same_as<_Tp&>; +}; + +template +concept __cpp17_copy_assignable = __cpp17_move_assignable<_Tp> && requires(_Tp __lhs, _Tp __rhs) { + { __lhs = __rhs } -> same_as<_Tp&>; +}; + +template +concept __cpp17_destructible = requires(_Tp __v) { __v.~_Tp(); }; + +template +concept __cpp17_equality_comparable = requires(_Iter __lhs, _Iter __rhs) { + { __lhs == __rhs } -> __boolean_testable; + { std::as_const(__lhs) == __rhs } -> __boolean_testable; + { __lhs == std::as_const(__rhs) } -> __boolean_testable; + { std::as_const(__lhs) == std::as_const(__rhs) } -> __boolean_testable; +}; + +template +concept __cpp17_default_constructible = is_default_constructible_v<_Tp>; + +template +concept __cpp17_iterator = + __cpp17_copy_constructible<_Iter> && __cpp17_copy_assignable<_Iter> && __cpp17_destructible<_Iter> && + (is_signed_v<__iter_diff_t<_Iter>> || is_void_v<__iter_diff_t<_Iter>>)&&requires(_Iter __iter) { + { *__iter }; + { ++__iter } -> same_as<_Iter&>; + }; + +template +concept __cpp17_input_iterator = + __cpp17_iterator<_Iter> && __cpp17_equality_comparable<_Iter> && requires(_Iter __lhs, _Iter __rhs) { + { __lhs != __rhs } -> __boolean_testable; + { std::as_const(__lhs) != __rhs } -> __boolean_testable; + { __lhs != std::as_const(__rhs) } -> __boolean_testable; + { std::as_const(__lhs) != std::as_const(__rhs) } -> __boolean_testable; + + { *__lhs } -> same_as<__iter_reference<_Iter>>; + { *std::as_const(__lhs) } -> same_as<__iter_reference<_Iter>>; + + { ++__lhs } -> same_as<_Iter&>; + { (void)__lhs++ }; + { *__lhs++ }; + }; + +template +concept __cpp17_output_iterator = __cpp17_iterator<_Iter> && requires(_Iter __iter, _WriteTo __write) { + { *__iter = std::forward<_WriteTo>(__write) }; + { ++__iter } -> same_as<_Iter&>; + { __iter++ } -> convertible_to; + { *__iter++ = std::forward<_WriteTo>(__write) }; +}; + +template +concept __cpp17_forward_iterator = + __cpp17_input_iterator<_Iter> && __cpp17_default_constructible<_Iter> && requires(_Iter __iter) { + { __iter++ } -> convertible_to; + { *__iter++ } -> same_as<__iter_reference<_Iter>>; + }; + +template +concept __cpp17_bidirectional_iterator = __cpp17_forward_iterator<_Iter> && requires(_Iter __iter) { + { --__iter } -> same_as<_Iter&>; + { __iter-- } -> convertible_to; + { *__iter-- } -> same_as<__iter_reference<_Iter>>; +}; + +template +concept __cpp17_random_access_iterator = + __cpp17_bidirectional_iterator<_Iter> && requires(_Iter __iter, __iter_diff_t<_Iter> __n) { + { __iter += __n } -> same_as<_Iter&>; + + { __iter + __n } -> same_as<_Iter>; + { __n + __iter } -> same_as<_Iter>; + { std::as_const(__iter) + __n } -> same_as<_Iter>; + { __n + std::as_const(__iter) } -> same_as<_Iter>; + + { __iter -= __n } -> same_as<_Iter&>; + { __iter - __n } -> same_as<_Iter>; + { std::as_const(__iter) - __n } -> same_as<_Iter>; + + { __iter - __iter } -> same_as<__iter_diff_t<_Iter>>; + { std::as_const(__iter) - __iter } -> same_as<__iter_diff_t<_Iter>>; + { __iter - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; + { std::as_const(__iter) - std::as_const(__iter) } -> same_as<__iter_diff_t<_Iter>>; + + { __iter[__n] } -> convertible_to<__iter_reference<_Iter>>; + { std::as_const(__iter)[__n] } -> convertible_to<__iter_reference<_Iter>>; + + { __iter < __iter } -> __boolean_testable; + { std::as_const(__iter) < __iter } -> __boolean_testable; + { __iter < std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) < std::as_const(__iter) } -> __boolean_testable; + + { __iter > __iter } -> __boolean_testable; + { std::as_const(__iter) > __iter } -> __boolean_testable; + { __iter > std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) > std::as_const(__iter) } -> __boolean_testable; + + { __iter >= __iter } -> __boolean_testable; + { std::as_const(__iter) >= __iter } -> __boolean_testable; + { __iter >= std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) >= std::as_const(__iter) } -> __boolean_testable; + + { __iter <= __iter } -> __boolean_testable; + { std::as_const(__iter) <= __iter } -> __boolean_testable; + { __iter <= std::as_const(__iter) } -> __boolean_testable; + { std::as_const(__iter) <= std::as_const(__iter) } -> __boolean_testable; + }; + +_LIBCPP_END_NAMESPACE_STD + +# ifndef _LIBCPP_DISABLE_ITERATOR_CHECKS +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) static_assert(::std::__cpp17_input_iterator); +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t, write_t) \ + static_assert(::std::__cpp17_output_iterator); +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) static_assert(::std::__cpp17_forward_iterator); +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) \ + static_assert(::std::__cpp17_bidirectional_iterator); +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) \ + static_assert(::std::__cpp17_random_access_iterator); +# else +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) +# endif + +#else // _LIBCPP_STD_VER >= 20 + +# define _LIBCPP_REQUIRE_CPP17_INPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_OUTPUT_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_BIDIRECTIONAL_ITERATOR(iter_t) +# define _LIBCPP_REQUIRE_CPP17_RANDOM_ACCESS_ITERATOR(iter_t) + +#endif // _LIBCPP_STD_VER >= 20 + +#endif // _LIBCPP___ITERATOR_CPP17_ITERATOR_CONCEPTS_H diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1073,6 +1073,7 @@ export concepts.equality_comparable export type_traits.common_reference } + module check_iterators { private header "__iterator/check_iterators.h" } module counted_iterator { private header "__iterator/counted_iterator.h" } module data { private header "__iterator/data.h" } module default_sentinel { private header "__iterator/default_sentinel.h" } diff --git a/libcxx/include/sstream b/libcxx/include/sstream --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -232,15 +232,15 @@ public: // [stringbuf.cons] constructors: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_stringbuf() : __hm_(nullptr), __mode_(ios_base::in | ios_base::out) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION explicit basic_stringbuf(ios_base::openmode __wch) : __hm_(nullptr), __mode_(__wch) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION explicit basic_stringbuf(const string_type& __s, ios_base::openmode __wch = ios_base::in | ios_base::out) : __str_(__s.get_allocator()), __hm_(nullptr), __mode_(__wch) @@ -258,7 +258,7 @@ string_type str() const; void str(const string_type& __s); #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_string_view view() const noexcept; #endif @@ -269,7 +269,7 @@ int_type overflow (int_type __c = traits_type::eof()) override; pos_type seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out) override; - _LIBCPP_HIDE_FROM_ABI_VIRTUAL + _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION pos_type seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out) override { return seekoff(__sp, ios_base::beg, __wch); @@ -672,22 +672,22 @@ public: // [istringstream.cons] Constructors: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_istringstream() : basic_istream<_CharT, _Traits>(&__sb_), __sb_(ios_base::in) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION explicit basic_istringstream(ios_base::openmode __wch) : basic_istream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::in) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION explicit basic_istringstream(const string_type& __s, ios_base::openmode __wch = ios_base::in) : basic_istream<_CharT, _Traits>(&__sb_) , __sb_(__s, __wch | ios_base::in) { } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_istringstream(basic_istringstream&& __rhs) : basic_istream<_CharT, _Traits>(_VSTD::move(__rhs)) , __sb_(_VSTD::move(__rhs.__sb_)) @@ -701,27 +701,27 @@ __sb_ = _VSTD::move(__rhs.__sb_); return *this; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION void swap(basic_istringstream& __rhs) { basic_istream::swap(__rhs); __sb_.swap(__rhs.__sb_); } // [istringstream.members] Member functions: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_stringbuf* rdbuf() const { return const_cast*>(&__sb_); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION string_type str() const { return __sb_.str(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION void str(const string_type& __s) { __sb_.str(__s); } #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_string_view view() const noexcept { return __sb_.view(); } @@ -758,22 +758,22 @@ public: // [ostringstream.cons] Constructors: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_ostringstream() : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(ios_base::out) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION explicit basic_ostringstream(ios_base::openmode __wch) : basic_ostream<_CharT, _Traits>(&__sb_), __sb_(__wch | ios_base::out) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION explicit basic_ostringstream(const string_type& __s, ios_base::openmode __wch = ios_base::out) : basic_ostream<_CharT, _Traits>(&__sb_) , __sb_(__s, __wch | ios_base::out) { } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_ostringstream(basic_ostringstream&& __rhs) : basic_ostream<_CharT, _Traits>(_VSTD::move(__rhs)) , __sb_(_VSTD::move(__rhs.__sb_)) @@ -788,27 +788,27 @@ return *this; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION void swap(basic_ostringstream& __rhs) { basic_ostream::swap(__rhs); __sb_.swap(__rhs.__sb_); } // [ostringstream.members] Member functions: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_stringbuf* rdbuf() const { return const_cast*>(&__sb_); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION string_type str() const { return __sb_.str(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION void str(const string_type& __s) { __sb_.str(__s); } #if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION basic_string_view view() const noexcept { return __sb_.view(); } diff --git a/libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp b/libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Check that __cpp17_*_iterator concepts catch bad iterators + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// ADDITIONAL_COMPILE_FLAGS: -Wno-private-header + +#include <__iterator/cpp17_iterator_concepts.h> +#include + +struct missing_deref { + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + using value_type = int; + using reference = int&; + + missing_deref& operator++(); +}; + +struct missing_preincrement { + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + using value_type = int; + using reference = int&; + + int& operator*(); +}; + +template +struct valid_iterator { + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + using value_type = int; + using reference = int&; + + int& operator*() const; + Derived& operator++(); + Derived operator++(int); +}; + +struct not_move_constructible : valid_iterator { + not_move_constructible(const not_move_constructible&) = default; + not_move_constructible(not_move_constructible&&) = delete; + not_move_constructible& operator=(not_move_constructible&&) = default; + not_move_constructible& operator=(const not_move_constructible&) = default; +}; + +struct not_copy_constructible : valid_iterator { + not_copy_constructible(const not_copy_constructible&) = delete; + not_copy_constructible(not_copy_constructible&&) = default; + not_copy_constructible& operator=(not_copy_constructible&&) = default; + not_copy_constructible& operator=(const not_copy_constructible&) = default; +}; + +struct not_move_assignable : valid_iterator { + not_move_assignable(const not_move_assignable&) = default; + not_move_assignable(not_move_assignable&&) = default; + not_move_assignable& operator=(not_move_assignable&&) = delete; + not_move_assignable& operator=(const not_move_assignable&) = default; +}; + +struct not_copy_assignable : valid_iterator { + not_copy_assignable(const not_copy_assignable&) = default; + not_copy_assignable(not_copy_assignable&&) = default; + not_copy_assignable& operator=(not_copy_assignable&&) = default; + not_copy_assignable& operator=(const not_copy_assignable&) = delete; +}; + +struct diff_t_not_signed : valid_iterator { + using difference_type = unsigned; +}; + +void check_iterator_requirements() { + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{indirection requires pointer operand}} + + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{cannot increment value of type 'missing_preincrement'}} + + + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{because 'not_move_constructible' does not satisfy '__cpp17_move_constructible'}} + + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{because 'not_copy_constructible' does not satisfy '__cpp17_copy_constructible'}} + + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{because 'not_move_assignable' does not satisfy '__cpp17_copy_assignable'}} + + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expectted-note@*:* {{because 'not_copy_assignable' does not satisfy '__cpp17_copy_assignable'}} + + static_assert(std::__cpp17_iterator); // expected-error {{static assertion failed}} + // expectted-note@*:* {{'is_signed_v<__iter_diff_t >' evaluated to false}} +} + +struct not_equality_comparable : valid_iterator {}; +bool operator!=(not_equality_comparable, not_equality_comparable); + +struct not_unequality_comparable : valid_iterator {}; +bool operator==(not_unequality_comparable, not_unequality_comparable); +bool operator!=(not_unequality_comparable, not_unequality_comparable) = delete; + +void check_input_iterator_requirements() { + static_assert(std::__cpp17_input_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{'__lhs == __rhs' would be invalid: invalid operands to binary expression}} + + static_assert(std::__cpp17_input_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{'__lhs != __rhs' would be invalid: overload resolution selected deleted operator '!='}} +} + +struct not_default_constructible : valid_iterator { + not_default_constructible() = delete; +}; +bool operator==(not_default_constructible, not_default_constructible); +bool operator!=(not_default_constructible, not_default_constructible); + +void check_forward_iterator_requirements() { + static_assert(std::__cpp17_forward_iterator); // expected-error {{static assertion failed}} + // expected-note@*:* {{because 'not_default_constructible' does not satisfy '__cpp17_default_constructible'}} +} + +void check_bidirection_iterator_requirements() { + static_assert(!std::__cpp17_bidirectional_iterator<>) +}