diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -35,6 +35,10 @@ __mutex_base __node_handle __nullptr + __ranges/begin.h + __ranges/cbegin.h + __ranges/cend.h + __ranges/end.h __ranges/enable_borrowed_range.h __split_buffer __sso_allocator @@ -149,6 +153,7 @@ random ranges ratio + ranges regex scoped_allocator semaphore diff --git a/libcxx/include/__ranges/begin.h b/libcxx/include/__ranges/begin.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/begin.h @@ -0,0 +1,109 @@ +// -*- C++ -*- +//===------------------------ __ranges/begin.h ----------------------------===// +// +// 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___RANGES_BEGIN_H +#define _LIBCPP___RANGES_BEGIN_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/enable_borrowed_range.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) + +// clang-format off + +namespace ranges { + template + concept __can_borrow = + is_lvalue_reference_v<_Tp> || enable_borrowed_range >; + + template + concept __is_complete = requires { sizeof(_Tp); }; +} // namespace ranges + +// [range.access.begin] +namespace ranges::__begin { + template + concept __member_begin = + __can_borrow<_Tp> && + requires(_Tp&& __t) { + { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).begin()) } -> input_or_output_iterator; + }; + + void begin(auto&) = delete; + void begin(const auto&) = delete; + + template + concept __unqualified_begin = + !__member_begin<_Tp> && + __can_borrow<_Tp> && + __class_or_enum > && + requires(_Tp && __t) { + { _VSTD::__decay_copy(begin(_VSTD::forward<_Tp>(__t))) } -> input_or_output_iterator; + }; + + struct __fn { + template + [[nodiscard]] constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept { + constexpr bool __complete = __is_complete >; + if constexpr (__complete) { // used to disable cryptic diagnostic + return __t + 0; + } + else { + static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly an arrays of an incomplete types."); + } + } + + template + requires __member_begin<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(__t.begin()))) + { + return __t.begin(); + } + + template + requires __unqualified_begin<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(begin(__t)))) + { + return begin(__t); + } + + void operator()(auto&&) const = delete; + }; +} // namespace ranges::__begin + +namespace ranges::inline __cpo { + inline constexpr auto begin = __begin::__fn{}; +} // namespace ranges::__cpo + +namespace ranges { + template + using iterator_t = decltype(ranges::begin(declval<_Tp&>())); +} // namespace ranges + +// clang-format off + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_BEGIN_H diff --git a/libcxx/include/__ranges/cbegin.h b/libcxx/include/__ranges/cbegin.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/cbegin.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===----------------------- __ranges/cbegin.h ----------------------------===// +// +// 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___RANGES_CBEGIN_H +#define _LIBCPP___RANGES_CBEGIN_H + +#include <__config> +#include <__ranges/begin.h> +#include +#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) + +// clang-format off + +// [range.access.cbegin] +namespace ranges::__cbegin { + struct __fn { + template + requires invocable + [[nodiscard]] constexpr auto operator()(_Tp& __t) const + noexcept(noexcept(ranges::begin(_VSTD::as_const(__t)))) + { + return ranges::begin(_VSTD::as_const(__t)); + } + + template + requires is_rvalue_reference_v<_Tp> && invocable + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t)))) + { + return ranges::begin(static_cast<_Tp const&&>(__t)); + } + }; +} // namespace ranges::__cbegin + +namespace ranges::inline __cpo { + inline constexpr auto cbegin = __cbegin::__fn{}; +} // namespace ranges::__cpo + +// clang-format off + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_CBEGIN_H diff --git a/libcxx/include/__ranges/cend.h b/libcxx/include/__ranges/cend.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/cend.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===----------------------- __ranges/cend.h ------------------------------===// +// +// 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___RANGES_CEND_H +#define _LIBCPP___RANGES_CEND_H + +#include <__config> +#include <__ranges/end.h> +#include +#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) + +// clang-format off + +// [range.access.cend] +namespace ranges::__cend { + struct __fn { + template + requires invocable + [[nodiscard]] constexpr auto operator()(_Tp& __t) const + noexcept(noexcept(ranges::end(_VSTD::as_const(__t)))) + { + return ranges::end(_VSTD::as_const(__t)); + } + + template + requires is_rvalue_reference_v<_Tp> && invocable + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t)))) + { + return ranges::end(static_cast<_Tp const&&>(__t)); + } + }; +} // namespace ranges::__cend + +namespace ranges::inline __cpo { + inline constexpr auto cend = __cend::__fn{}; +} // namespace ranges::__cpo + +// clang-format on + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_CEND_H diff --git a/libcxx/include/__ranges/end.h b/libcxx/include/__ranges/end.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/end.h @@ -0,0 +1,100 @@ +// -*- C++ -*- +//===------------------------ __ranges/end.h ------------------------------===// +// +// 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___RANGES_END_H +#define _LIBCPP___RANGES_END_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/begin.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) + +// clang-format off + +// [range.access.end] +namespace ranges::__end { + template + concept __member_end = + __can_borrow<_Tp> && + requires(_Tp&& __t) { + typename iterator_t<_Tp>; + { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for >; + }; + + void end(auto&) = delete; + void end(const auto&) = delete; + + template + concept __unqualified_end = + !__member_end<_Tp> && + __can_borrow<_Tp> && + __class_or_enum > && + requires(_Tp && __t) { + typename iterator_t<_Tp>; + { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for >; + }; + + class __fn { + public: + template + [[nodiscard]] constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept { + constexpr bool __complete = __is_complete >; + if constexpr (__complete) { // used to disable cryptic diagnostic + return __t + _Np; + } + else { + static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly an arrays of an incomplete types."); + } + } + + template + requires __member_end<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(__t.end()))) + { + return _VSTD::forward<_Tp>(__t).end(); + } + + template + requires __unqualified_end<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(end(__t)))) + { + return end(__t); + } + + void operator()(auto&&) const = delete; + }; +} // namespace ranges::__end + +namespace ranges::inline __cpo { + inline constexpr auto end = __end::__fn{}; +} // namespace ranges::__cpo + +// clang-format off + +#undef _LIBCPP_NOEXCEPT_RETURN + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_END_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -411,6 +411,9 @@ } module ranges { header "ranges" + export compare + export initializer_list + export iterator export * } module ratio { diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -17,15 +17,30 @@ #include // see [iterator.synopsis] namespace std::ranges { + inline namespace unspecified { + // [range.access], range access + inline constexpr unspecified begin = unspecified; + inline constexpr unspecified end = unspecified; + inline constexpr unspecified cbegin = unspecified; + inline constexpr unspecified cend = unspecified; + } + // [range.range], ranges template inline constexpr bool enable_borrowed_range = false; + + template + using iterator_t = decltype(ranges::begin(declval())); } */ #include <__config> +#include <__ranges/begin.h> +#include <__ranges/cbegin.h> +#include <__ranges/cend.h> #include <__ranges/enable_borrowed_range.h> +#include <__ranges/end.h> #include // Required by the standard. #include // Required by the standard. #include // Required by the standard. diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -2814,6 +2814,9 @@ inline _LIBCPP_INLINE_VISIBILITY typename decay<_Tp>::type __decay_copy(_Tp&& __t) +#if _LIBCPP_STD_VER > 17 +noexcept(is_nothrow_convertible_v<_Tp, remove_reference_t<_Tp>>) +#endif { return _VSTD::forward<_Tp>(__t); } diff --git a/libcxx/test/libcxx/ranges/range.access/access.h b/libcxx/test/libcxx/ranges/range.access/access.h new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.access/access.h @@ -0,0 +1,364 @@ +//===----------------------------------------------------------------------===// +// +// 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 LIBCXX_TEST_LIBCXX_RANGES_RANGE_ACCESS_ACCESS_H +#define LIBCXX_TEST_LIBCXX_RANGES_RANGE_ACCESS_ACCESS_H + +#include + +struct bad_lvalue_range_unqualified { + int begin(bad_lvalue_range_unqualified&); + int begin(bad_lvalue_range_unqualified const&); + int end(bad_lvalue_range_unqualified&); + int end(bad_lvalue_range_unqualified const&); +}; + +struct bad_lvalue_range_preferred { + int begin(); + int begin() const; + int end(); + int end() const; + + int begin(bad_lvalue_range_preferred&); + int begin(bad_lvalue_range_preferred const&); + int end(bad_lvalue_range_preferred&); + int end(bad_lvalue_range_preferred const&); +}; + +struct bad_lvalue_range_private_members { + friend int begin(bad_lvalue_range_private_members&); + friend int begin(bad_lvalue_range_private_members const&); + friend int end(bad_lvalue_range_private_members&); + friend int end(bad_lvalue_range_private_members const&); + +private: + int* begin(); + int const* begin() const; + int* end(); + int const* end() const; +}; + +struct rvalue_range_members_bad_return { + int begin() &&; + int begin() const&&; + int end() &&; + int end() const&&; +}; + +// An otherwise okay "range", except that it isn't borrowable, and thus can't be accessed as an +// rvalue +struct rvalue_range_members_not_borrowable { + int* begin() &&; + int const* begin() const&&; + int* end() &&; + int const* end() const&&; +}; + +struct rvalue_range_unqualified_bad_return { + friend int begin(rvalue_range_unqualified_bad_return&&); + friend int begin(rvalue_range_unqualified_bad_return const&&); + friend int end(rvalue_range_unqualified_bad_return&&); + friend int end(rvalue_range_unqualified_bad_return const&&); +}; + +struct rvalue_range_preferred_bad_return { + int begin(); + int begin() const; + int end(); + int end() const; + + friend int begin(rvalue_range_preferred_bad_return&&); + friend int begin(rvalue_range_preferred_bad_return const&&); + friend int end(rvalue_range_preferred_bad_return&&); + friend int end(rvalue_range_preferred_bad_return const&&); +}; + +struct rvalue_range_private_members_bad_return { + friend int begin(rvalue_range_private_members_bad_return&&); + friend int begin(rvalue_range_private_members_bad_return const&&); + friend int end(rvalue_range_private_members_bad_return&&); + friend int end(rvalue_range_private_members_bad_return const&&); + +private: + int* begin(); + int const* begin() const; + int* end(); + int const* end() const; +}; + +// An otherwise okay "range", except that it isn't borrowable, and thus can't be accessed as an +// rvalue +struct rvalue_range_unqualified_not_borrowable { + friend int* begin(rvalue_range_unqualified_not_borrowable&&); + friend int const* begin(rvalue_range_unqualified_not_borrowable const&&); + friend int* end(rvalue_range_unqualified_not_borrowable&&); + friend int const* end(rvalue_range_unqualified_not_borrowable const&&); +}; + +// An otherwise okay "range", except that it isn't borrowable, and thus can't be accessed as an +// rvalue +struct rvalue_range_preferred_not_borrowable { + int* begin() &&; + int const* begin() const&&; + int* end() &&; + int const* end() const&&; + + friend int* begin(rvalue_range_preferred_not_borrowable&&); + friend int const* begin(rvalue_range_preferred_not_borrowable const&&); + friend int* end(rvalue_range_preferred_not_borrowable&&); + friend int const* end(rvalue_range_preferred_not_borrowable const&&); +}; + +// An otherwise okay "range", except that it isn't borrowable, and thus can't be accessed as an +// rvalue +struct rvalue_range_private_members_not_borrowable { + friend int* begin(rvalue_range_private_members_not_borrowable&&); + friend int const* begin(rvalue_range_private_members_not_borrowable const&&); + friend int* end(rvalue_range_private_members_not_borrowable&&); + friend int const* end(rvalue_range_private_members_not_borrowable const&&); + +private: + int* begin(); + int const* begin() const; + int* end(); + int const* end() const; +}; + +#define CHECK_BAD_ACCESS(cpo) \ + template \ + [[nodiscard]] constexpr bool faulty_##cpo() { \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + \ + static_assert(!std::invocable); \ + static_assert(!std::invocable); \ + static_assert(!std::invocable); \ + static_assert(!std::invocable); \ + return true; \ + } \ + \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + static_assert(faulty_##cpo()); \ + \ + namespace std::ranges { \ + struct dummy { \ + friend void cpo() {} \ + }; \ + } \ + static_assert(faulty_##cpo()) + +struct sentinel { + bool operator==(int*) const; +}; + +struct lvalue_range_with_members { + int* begin() &; + int* begin() const&; + sentinel end() &; + sentinel end() const&; +}; + +struct lvalue_range_with_members_and_unqualified_friends : lvalue_range_with_members { + friend int* begin(lvalue_range_with_members_and_unqualified_friends& x); + friend int* begin(lvalue_range_with_members_and_unqualified_friends const& x); + friend sentinel end(lvalue_range_with_members_and_unqualified_friends& x); + friend sentinel end(lvalue_range_with_members_and_unqualified_friends const& x); +}; + +struct rvalue_range_with_members { + int* begin(); + int* begin() const; + sentinel end(); + sentinel end() const; +}; + +template <> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +struct rvalue_range_with_members_and_unqualified_friends : rvalue_range_with_members { + friend int* begin(rvalue_range_with_members_and_unqualified_friends&& x); + friend int* begin(rvalue_range_with_members_and_unqualified_friends const&& x); + friend sentinel end(rvalue_range_with_members_and_unqualified_friends&& x); + friend sentinel end(rvalue_range_with_members_and_unqualified_friends const&& x); +}; + +template <> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +#define CHECK_MEMBER_CPO(cpo) \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo); \ + \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo); \ + static_assert(std::ranges::__##cpo::__member_##cpo) + +struct unqualified_lvalue_range { + friend int* begin(unqualified_lvalue_range& x); + friend int* begin(unqualified_lvalue_range const& x); + friend sentinel end(unqualified_lvalue_range& x); + friend sentinel end(unqualified_lvalue_range const& x); +}; + +struct unqualified_lvalue_range_preferred { + int begin(); + int begin() const; + int end(); + int end() const; + + friend int* begin(unqualified_lvalue_range_preferred& x); + friend int* begin(unqualified_lvalue_range_preferred const& x); + friend sentinel end(unqualified_lvalue_range_preferred& x); + friend sentinel end(unqualified_lvalue_range_preferred const& x); +}; + +class unqualified_lvalue_range_private_members { +public: + friend int* begin(unqualified_lvalue_range_private_members& x); + friend int* begin(unqualified_lvalue_range_private_members const& x); + friend sentinel end(unqualified_lvalue_range_private_members& x); + friend sentinel end(unqualified_lvalue_range_private_members const& x); + +private: + int* begin() noexcept; + int* begin() const; + sentinel end(); + sentinel end() const; +}; + +class unqualified_rvalue_range { +public: + friend int* begin(unqualified_rvalue_range& x); + friend int* begin(unqualified_rvalue_range const& x); + friend sentinel end(unqualified_rvalue_range& x); + friend sentinel end(unqualified_rvalue_range const& x); + + friend int* begin(unqualified_rvalue_range&& x); + friend int* begin(unqualified_rvalue_range const&& x); + friend sentinel end(unqualified_rvalue_range&& x); + friend sentinel end(unqualified_rvalue_range const&& x); +}; + +template <> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +class unqualified_rvalue_range_preferred { +public: + int begin(); + int begin() const; + int end(); + int end() const; + + friend int* begin(unqualified_rvalue_range_preferred& x); + friend int* begin(unqualified_rvalue_range_preferred const& x); + friend sentinel end(unqualified_rvalue_range_preferred& x); + friend sentinel end(unqualified_rvalue_range_preferred const& x); + + friend int* begin(unqualified_rvalue_range_preferred&& x); + friend int* begin(unqualified_rvalue_range_preferred const&& x); + friend sentinel end(unqualified_rvalue_range_preferred&& x); + friend sentinel end(unqualified_rvalue_range_preferred const&& x); +}; + +template <> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +class unqualified_rvalue_range_private_members { +public: + friend int* begin(unqualified_rvalue_range_private_members& x); + friend int* begin(unqualified_rvalue_range_private_members const& x); + friend sentinel end(unqualified_rvalue_range_private_members& x); + friend sentinel end(unqualified_rvalue_range_private_members const& x); + + friend int* begin(unqualified_rvalue_range_private_members&& x); + friend int* begin(unqualified_rvalue_range_private_members const&& x); + friend sentinel end(unqualified_rvalue_range_private_members&& x); + friend sentinel end(unqualified_rvalue_range_private_members const&& x); + +private: + int* begin() noexcept; + int* begin() const; + sentinel end() noexcept; + sentinel end() const; +}; + +template <> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +#define CHECK_UNQUALIFIED_CPO(cpo) \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__unqualified_##cpo); \ + \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo); \ + static_assert(!std::ranges::__##cpo::__member_##cpo && \ + std::ranges::__##cpo::__unqualified_##cpo) + +#endif // LIBCXX_TEST_LIBCXX_RANGES_RANGE_ACCESS_ACCESS_H diff --git a/libcxx/test/libcxx/ranges/range.access/range.access.begin/begin.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.access/range.access.begin/begin.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.access/range.access.begin/begin.compile.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified begin; + +#include + +#include "../access.h" + +CHECK_BAD_ACCESS(begin); +CHECK_MEMBER_CPO(begin); +CHECK_UNQUALIFIED_CPO(begin); diff --git a/libcxx/test/libcxx/ranges/range.access/range.access.begin/incomplete.compile.verify.cpp b/libcxx/test/libcxx/ranges/range.access/range.access.begin/incomplete.compile.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.access/range.access.begin/incomplete.compile.verify.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified begin; + +#include + +#include + +// clang-format off +template +requires(!std::invocable) +void f() {} +// clang-format on + +void test() { + struct incomplete; + f(); + // expected-error@__ranges/begin.h:* {{"`std::ranges::begin` is SFINAE-unfriendly an arrays of an incomplete types."}} + // expected-error@-2 {{no matching function for call to 'f'}} + + // This is okay because calling `std::ranges::end` on any rvalue is ill-formed. + f(); +} diff --git a/libcxx/test/libcxx/ranges/range.access/range.access.end/end.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.access/range.access.end/end.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.access/range.access.end/end.compile.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified end; + +#include + +#include "../access.h" + +CHECK_BAD_ACCESS(end); +CHECK_MEMBER_CPO(end); +CHECK_UNQUALIFIED_CPO(end); diff --git a/libcxx/test/libcxx/ranges/range.access/range.access.end/incomplete.compile.verify.cpp b/libcxx/test/libcxx/ranges/range.access/range.access.end/incomplete.compile.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.access/range.access.end/incomplete.compile.verify.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified end; + +#include + +#include + +// clang-format off +template +requires(!std::invocable) +void f() {} +// clang-format on + +void test() { + struct incomplete; + f(); + // expected-error@__ranges/begin.h:* {{"`std::ranges::begin` is SFINAE-unfriendly an arrays of an incomplete types."}} + // expected-error@__ranges/end.h:* {{"`std::ranges::end` is SFINAE-unfriendly an arrays of an incomplete types."}} + // expected-error@-3 {{no matching function for call to 'f'}} + + // This is okay because calling `std::ranges::end` on any rvalue is ill-formed. + f(); +} diff --git a/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// map + +#include + +#include +#include + +using range = std::map; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// multimap + +#include + +#include +#include + +using range = std::multimap; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// multiset + +#include + +#include +#include + +using range = std::multiset; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// set + +#include + +#include +#include + +using range = std::set; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// array + +#include + +#include +#include + +using range = std::array; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// deque + +#include + +#include +#include + +using range = std::deque; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// forward_list + +#include + +#include +#include + +using range = std::forward_list; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// list + +#include + +#include +#include + +using range = std::list; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// vector + +#include + +#include +#include + +using range = std::vector; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// vector + +#include + +#include +#include + +using range = std::vector; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unordered_map + +#include + +#include +#include + +using range = std::unordered_map; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unordered_multimap + +#include + +#include +#include + +using range = std::unordered_multimap; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unordered_multiset + +#include + +#include +#include + +using range = std::unordered_multiset; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unordered_multiset + +#include + +#include +#include + +using range = std::unordered_set; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// span + +#include + +#include +#include + +using range = std::span; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// directory_iterator, recursive_directory_iterator + +#include "filesystem_include.h" + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, fs::directory_iterator>); +static_assert(std::same_as, fs::directory_iterator>); +static_assert(std::same_as, fs::recursive_directory_iterator>); +static_assert(std::same_as, fs::recursive_directory_iterator>); diff --git a/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// path + +#include "filesystem_include.h" + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, fs::path::iterator>); +static_assert(std::same_as, fs::path::const_iterator>); diff --git a/libcxx/test/std/ranges/range.access/array_access.h b/libcxx/test/std/ranges/range.access/array_access.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/array_access.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_ARRAY_ACCESS_H +#define LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_ARRAY_ACCESS_H + +#include + +#include + +#include "test_macros.h" + +class dummy { +public: + [[nodiscard]] constexpr int* begin() noexcept { return &second_; } + + [[nodiscard]] constexpr int end() noexcept { return first_; } + +private: + int first_ = 0; + int second_ = 54; +}; + +#define CHECK_ARRAY_ACCESS(cpo) \ + static_assert(!std::invocable); \ + static_assert(!std::invocable); \ + \ + template \ + [[nodiscard]] constexpr bool check_array() { \ + static_assert(std::invocable); \ + static_assert(std::is_nothrow_invocable_v); \ + \ + T array[size]{}; \ + return std::ranges::cpo(array) == std::cpo(array); \ + } \ + \ + int main(int, char**) { \ + CONSTEXPR_ASSERT(check_array()); \ + CONSTEXPR_ASSERT(check_array()); \ + CONSTEXPR_ASSERT(check_array()); \ + return 0; \ + } + +#endif // LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_ARRAY_ACCESS_H diff --git a/libcxx/test/std/ranges/range.access/member_access.h b/libcxx/test/std/ranges/range.access/member_access.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/member_access.h @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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 LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_MEMBER_ACCESS_H +#define LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_MEMBER_ACCESS_H +#include + +#include +#include +#include +#include + +#include "test_macros.h" + +#define RESULT_IS_ITERATOR std::input_or_output_iterator +#define RESULT_IS_SENTINEL std::sentinel_for > +#define RESULT_IS_POINTER std::is_pointer_v + +// `cpo` can be any customisation point object in [range.access]. +// `base_cpo` can't be a CPO defined in terms of another CPO (e.g. cbegin) and it must be the "base" +// of `cpo` if the parameters are different. +// E.g. CHECK_MEMBER_ACCESS(begin, begin, RESULT_IS_ITERATOR) // okay +// E.g. CHECK_MEMBER_ACCESS(cdata, data, RESULT_IS_POINTER) // okay: `cdata` is implemented in terms of `data` +// E.g. CHECK_MEMBER_ACCESS(end, cend, RESULT_IS_SENTINEL) // invalid: `end` isn't implemented in terms of `cend` +// E.g. CHECK_MEMBER_ACCESS(rbegin, begin, RESULT_IS_REVERSE_ITERATOR) // invalid: `rbegin` isn't related to `begin` +#define CHECK_MEMBER_ACCESS(cpo, base_cpo, check_result_type) \ + static_assert(std::invocable&>); \ + static_assert(std::invocable const&>); \ + \ + static_assert(!std::invocable&&>); \ + static_assert(!std::invocable const&&>); \ + \ + template \ + constexpr bool member_##cpo() { \ + using result_type = std::invoke_result_t; \ + static_assert(check_result_type); \ + static_assert(noexcept(std::ranges::cpo(std::declval())) == noexcept(std::declval().base_cpo())); \ + \ + if (not std::is_constant_evaluated()) { \ + auto r = R(100, typename std::remove_cvref_t::value_type()); \ + assert(std::ranges::cpo(r) == r.base_cpo()); \ + } \ + return true; \ + } \ + \ + int main(int, char**) { \ + member_##cpo >(); \ + member_##cpo const>(); \ + CONSTEXPR_ASSERT(member_##cpo >()); \ + CONSTEXPR_ASSERT(member_##cpo const>()); \ + return 0; \ + } + +#endif // LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_MEMBER_ACCESS_H diff --git a/libcxx/test/std/ranges/range.access/range.access.begin/array_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.begin/array_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.begin/array_access.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified begin; +#include + +#include "../array_access.h" + +CHECK_ARRAY_ACCESS(begin); diff --git a/libcxx/test/std/ranges/range.access/range.access.begin/member_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.begin/member_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.begin/member_access.pass.cpp @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified begin; +#include "../member_access.h" + +CHECK_MEMBER_ACCESS(begin, begin, RESULT_IS_ITERATOR) diff --git a/libcxx/test/std/ranges/range.access/range.access.begin/unqualified_lookup.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.begin/unqualified_lookup.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.begin/unqualified_lookup.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified begin; +#include + +#include "../unqualified_lookup_access.h" + +static_assert(!noexcept(std::ranges::begin(std::declval()))); +static_assert(noexcept(std::ranges::begin(std::declval()))); +CHECK_UNQUALIFIED_LOOKUP_ACCESS(begin, begin) diff --git a/libcxx/test/std/ranges/range.access/range.access.cbegin/array_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.cbegin/array_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.cbegin/array_access.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified cbegin; +#include + +#include "../array_access.h" + +CHECK_ARRAY_ACCESS(cbegin); diff --git a/libcxx/test/std/ranges/range.access/range.access.cbegin/member_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.cbegin/member_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.cbegin/member_access.pass.cpp @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified cbegin; +#include "../member_access.h" + +CHECK_MEMBER_ACCESS(cbegin, begin, RESULT_IS_ITERATOR) diff --git a/libcxx/test/std/ranges/range.access/range.access.cbegin/unqualified_lookup.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.cbegin/unqualified_lookup.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.cbegin/unqualified_lookup.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified cbegin; +#include + +#include "../unqualified_lookup_access.h" + +static_assert(noexcept(std::ranges::cbegin(std::declval()))); +static_assert(noexcept(std::ranges::cbegin(std::declval()))); +CHECK_UNQUALIFIED_LOOKUP_ACCESS(cbegin, begin) diff --git a/libcxx/test/std/ranges/range.access/range.access.cend/array_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.cend/array_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.cend/array_access.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified cend; +#include + +#include "../array_access.h" + +CHECK_ARRAY_ACCESS(cend); diff --git a/libcxx/test/std/ranges/range.access/range.access.cend/member_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.cend/member_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.cend/member_access.pass.cpp @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified cend; +#include "../member_access.h" + +CHECK_MEMBER_ACCESS(cend, end, RESULT_IS_SENTINEL) diff --git a/libcxx/test/std/ranges/range.access/range.access.cend/unqualified_lookup.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.cend/unqualified_lookup.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.cend/unqualified_lookup.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified cend; +#include + +#include "../unqualified_lookup_access.h" + +static_assert(noexcept(std::ranges::cend(std::declval()))); +static_assert(noexcept(std::ranges::cend(std::declval()))); +CHECK_UNQUALIFIED_LOOKUP_ACCESS(cend, end) diff --git a/libcxx/test/std/ranges/range.access/range.access.end/array_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.end/array_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.end/array_access.pass.cpp @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified end; +#include + +#include "../array_access.h" + +CHECK_ARRAY_ACCESS(end); diff --git a/libcxx/test/std/ranges/range.access/range.access.end/member_access.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.end/member_access.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.end/member_access.pass.cpp @@ -0,0 +1,17 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified end; +#include "../member_access.h" + +CHECK_MEMBER_ACCESS(end, end, RESULT_IS_SENTINEL) diff --git a/libcxx/test/std/ranges/range.access/range.access.end/unqualified_lookup.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.end/unqualified_lookup.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.end/unqualified_lookup.pass.cpp @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// unspecified end; +#include + +#include "../unqualified_lookup_access.h" + +static_assert(!noexcept(std::ranges::end(std::declval()))); +static_assert(noexcept(std::ranges::end(std::declval()))); +CHECK_UNQUALIFIED_LOOKUP_ACCESS(end, end) diff --git a/libcxx/test/std/ranges/range.access/unqualified_lookup_access.h b/libcxx/test/std/ranges/range.access/unqualified_lookup_access.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/unqualified_lookup_access.h @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_UNQUALIFIED_LOOKUP_ACCESS_H +#define LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_UNQUALIFIED_LOOKUP_ACCESS_H + +#include + +#include +#include +#include + +#include "test_macros.h" + +struct unqualified_lookup_access { + std::array data; + + [[nodiscard]] constexpr friend auto begin(unqualified_lookup_access& x) { return x.data.begin(); } + + [[nodiscard]] constexpr friend auto begin(unqualified_lookup_access const& x) noexcept { return x.data.begin(); } + + [[nodiscard]] constexpr friend auto end(unqualified_lookup_access& x) { return x.data.end(); } + + [[nodiscard]] constexpr friend auto end(unqualified_lookup_access const& x) noexcept { return x.data.end(); } +}; + +#define CHECK_UNQUALIFIED_LOOKUP_ACCESS(cpo, base_cpo) \ + [[nodiscard]] constexpr bool check_unqualified_lookup() { \ + auto r1 = unqualified_lookup_access(); \ + assert(std::ranges::cpo(r1) == r1.data.base_cpo()); \ + assert(std::ranges::cpo(r1) == std::as_const(r1.data).base_cpo()); \ + auto r2 = unqualified_lookup_access(); \ + assert(std::ranges::cpo(r1) != std::ranges::cpo(r2)); \ + assert(std::ranges::cpo(std::as_const(r1)) != std::ranges::cpo(std::as_const(r2))); \ + return true; \ + } \ + \ + int main(int, char**) { \ + CONSTEXPR_ASSERT(check_unqualified_lookup()); \ + return 0; \ + } + +#endif // #ifndef LIBCXX_TEST_STD_RANGES_RANGE_ACCESS_UNQUALIFIED_LOOKUP_ACCESS_H diff --git a/libcxx/test/std/ranges/range.range/iterator_t.compile.pass.cpp b/libcxx/test/std/ranges/range.range/iterator_t.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.range/iterator_t.compile.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// template +// using iterator_t = decltype(ranges::begin(declval())); + +#include + +#include + +#include "test_range.h" + +namespace stdr = std::ranges; + +static_assert(std::same_as >, input_iterator >); +static_assert(std::same_as const>, input_iterator >); + +static_assert(std::same_as >, input_iterator >); + +static_assert(std::same_as >, input_iterator >); +static_assert(std::same_as const>, input_iterator >); + +static_assert(std::same_as >, input_iterator >); diff --git a/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/re/re.results/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// match_results + +#include + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, std::cmatch::iterator>); +static_assert(std::same_as, std::cmatch::const_iterator>); diff --git a/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/basic.string/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// string + +#include + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, std::string::iterator>); +static_assert(std::same_as, std::string::const_iterator>); diff --git a/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/string.view/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// XFAIL: msvc && clang + +// string_view + +#include + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, std::string_view::iterator>); +static_assert(std::same_as, std::string_view::const_iterator>); diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -289,12 +289,17 @@ #if TEST_STD_VER < 11 #define ASSERT_NOEXCEPT(...) #define ASSERT_NOT_NOEXCEPT(...) +#define CONSTEXPR_ASSERT(...) assert((__VA_ARGS__)) #else #define ASSERT_NOEXCEPT(...) \ static_assert(noexcept(__VA_ARGS__), "Operation must be noexcept") #define ASSERT_NOT_NOEXCEPT(...) \ static_assert(!noexcept(__VA_ARGS__), "Operation must NOT be noexcept") + +#define CONSTEXPR_ASSERT(...) \ + static_assert(__VA_ARGS__); \ + assert((__VA_ARGS__)) #endif /* Macros for testing libc++ specific behavior and extensions */ diff --git a/libcxx/test/support/test_range.h b/libcxx/test/support/test_range.h new file mode 100644 --- /dev/null +++ b/libcxx/test/support/test_range.h @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 LIBCXX_TEST_SUPPORT_TEST_RANGE_H +#define LIBCXX_TEST_SUPPORT_TEST_RANGE_H + +#include +#include + +#include "test_iterators.h" + +#ifdef _LIBCPP_HAS_NO_RANGES +#error "test/suppoort/test_range.h" can only be included in builds supporting ranges +#endif + +struct sentinel { + bool operator==(std::input_or_output_iterator auto) const; +}; + +// clang-format off +template