diff options
Diffstat (limited to 'libcxx')
14 files changed, 421 insertions, 88 deletions
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 1a450218..5e8fe2e 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -68,6 +68,9 @@ Improvements and New Features reduced debug information. - The performance of ``std::find`` has been improved by up to 2x for integral types +- The ``std::distance`` and ``std::ranges::distance`` algorithms have been optimized for segmented iterators (e.g., + ``std::join_view`` iterators), reducing the complexity from ``O(n)`` to ``O(n / segment_size)``. Benchmarks show + performance improvements of over 1600x in favorable cases with large segment sizes (e.g., 1024). Deprecations and Removals ------------------------- diff --git a/libcxx/include/__cxx03/__bit_reference b/libcxx/include/__cxx03/__bit_reference index 76027e2..ac0005f 100644 --- a/libcxx/include/__cxx03/__bit_reference +++ b/libcxx/include/__cxx03/__bit_reference @@ -167,7 +167,7 @@ _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned( unsigned __clz = __bits_per_word - __first.__ctz_; difference_type __dn = std::min(static_cast<difference_type>(__clz), __n); __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + __storage_type __m = (__storage_type(~0) << __first.__ctz_) & (__storage_type(~0) >> (__clz - __dn)); __storage_type __b = *__first.__seg_ & __m; *__result.__seg_ &= ~__m; *__result.__seg_ |= __b; @@ -185,7 +185,7 @@ _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned( // do last word if (__n > 0) { __first.__seg_ += __nw; - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __m = __storage_type(~0) >> (__bits_per_word - __n); __storage_type __b = *__first.__seg_ & __m; *__result.__seg_ &= ~__m; *__result.__seg_ |= __b; @@ -210,11 +210,11 @@ _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( unsigned __clz_f = __bits_per_word - __first.__ctz_; difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n); __n -= __dn; - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __m = (__storage_type(~0) << __first.__ctz_) & (__storage_type(~0) >> (__clz_f - __dn)); __storage_type __b = *__first.__seg_ & __m; unsigned __clz_r = __bits_per_word - __result.__ctz_; __storage_type __ddn = std::min<__storage_type>(__dn, __clz_r); - __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + __m = (__storage_type(~0) << __result.__ctz_) & (__storage_type(~0) >> (__clz_r - __ddn)); *__result.__seg_ &= ~__m; if (__result.__ctz_ > __first.__ctz_) *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_); @@ -224,7 +224,7 @@ _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( __result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word); __dn -= __ddn; if (__dn > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __dn); + __m = __storage_type(~0) >> (__bits_per_word - __dn); *__result.__seg_ &= ~__m; *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn); __result.__ctz_ = static_cast<unsigned>(__dn); @@ -235,7 +235,7 @@ _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( // __first.__ctz_ == 0; // do middle words unsigned __clz_r = __bits_per_word - __result.__ctz_; - __storage_type __m = ~__storage_type(0) << __result.__ctz_; + __storage_type __m = __storage_type(~0) << __result.__ctz_; for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) { __storage_type __b = *__first.__seg_; *__result.__seg_ &= ~__m; @@ -246,17 +246,17 @@ _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned( } // do last word if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); + __m = __storage_type(~0) >> (__bits_per_word - __n); __storage_type __b = *__first.__seg_ & __m; __storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r)); - __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + __m = (__storage_type(~0) << __result.__ctz_) & (__storage_type(~0) >> (__clz_r - __dn)); *__result.__seg_ &= ~__m; *__result.__seg_ |= __b << __result.__ctz_; __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; __result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word); __n -= __dn; if (__n > 0) { - __m = ~__storage_type(0) >> (__bits_per_word - __n); + __m = __storage_type(~0) >> (__bits_per_word - __n); *__result.__seg_ &= ~__m; *__result.__seg_ |= __b >> __dn; __result.__ctz_ = static_cast<unsigned>(__n); diff --git a/libcxx/include/__cxx03/__verbose_abort b/libcxx/include/__cxx03/__verbose_abort index 4fcfffa..52d1297 100644 --- a/libcxx/include/__cxx03/__verbose_abort +++ b/libcxx/include/__cxx03/__verbose_abort @@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // This function should never be called directly from the code -- it should only be called through // the _LIBCPP_VERBOSE_ABORT macro. _LIBCPP_NORETURN _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_OVERRIDABLE_FUNC_VIS -_LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) void __libcpp_verbose_abort(const char* __format, ...); +_LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) void __libcpp_verbose_abort(const char* __format, ...) _NOEXCEPT; // _LIBCPP_VERBOSE_ABORT(format, args...) // diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 74923ddb..6b65e73 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -808,7 +808,7 @@ public: } { __node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args2)...); - if (size() + 1 > __bc * max_load_factor() || __bc == 0) { + if (size() + 1 > __bc * max_load_factor()) { __rehash_unique(std::max<size_type>(2 * __bc + !std::__is_hash_power2(__bc), size_type(__math::ceil(float(size() + 1) / max_load_factor())))); __bc = bucket_count(); diff --git a/libcxx/include/__iterator/distance.h b/libcxx/include/__iterator/distance.h index 1732aa5..9be9db0 100644 --- a/libcxx/include/__iterator/distance.h +++ b/libcxx/include/__iterator/distance.h @@ -10,41 +10,71 @@ #ifndef _LIBCPP___ITERATOR_DISTANCE_H #define _LIBCPP___ITERATOR_DISTANCE_H +#include <__algorithm/for_each_segment.h> #include <__config> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iterator_traits.h> +#include <__iterator/segmented_iterator.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/size.h> #include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> #include <__type_traits/remove_cvref.h> +#include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD -template <class _InputIter> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type -__distance(_InputIter __first, _InputIter __last, input_iterator_tag) { - typename iterator_traits<_InputIter>::difference_type __r(0); +#if _LIBCPP_STD_VER >= 20 +template <class _Iter> +using __iter_distance_t _LIBCPP_NODEBUG = std::iter_difference_t<_Iter>; +#else +template <class _Iter> +using __iter_distance_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type; +#endif + +template <class _InputIter, class _Sent> +inline _LIBCPP_HIDE_FROM_ABI +_LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_InputIter> __distance(_InputIter __first, _Sent __last) { + __iter_distance_t<_InputIter> __r(0); for (; __first != __last; ++__first) ++__r; return __r; } -template <class _RandIter> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_RandIter>::difference_type -__distance(_RandIter __first, _RandIter __last, random_access_iterator_tag) { +template <class _RandIter, __enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_RandIter> +__distance(_RandIter __first, _RandIter __last) { return __last - __first; } +#if _LIBCPP_STD_VER >= 20 +template <class _SegmentedIter, + __enable_if_t<!__has_random_access_iterator_category<_SegmentedIter>::value && + __is_segmented_iterator_v<_SegmentedIter>, + int> = 0> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 __iter_distance_t<_SegmentedIter> +__distance(_SegmentedIter __first, _SegmentedIter __last) { + __iter_distance_t<_SegmentedIter> __r(0); + std::__for_each_segment(__first, __last, [&__r](auto __lfirst, auto __llast) { + __r += std::__distance(__lfirst, __llast); + }); + return __r; +} +#endif // _LIBCPP_STD_VER >= 20 + template <class _InputIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 typename iterator_traits<_InputIter>::difference_type distance(_InputIter __first, _InputIter __last) { - return std::__distance(__first, __last, typename iterator_traits<_InputIter>::iterator_category()); + return std::__distance(__first, __last); } #if _LIBCPP_STD_VER >= 20 @@ -56,12 +86,7 @@ struct __distance { template <class _Ip, sentinel_for<_Ip> _Sp> requires(!sized_sentinel_for<_Sp, _Ip>) _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip __first, _Sp __last) const { - iter_difference_t<_Ip> __n = 0; - while (__first != __last) { - ++__first; - ++__n; - } - return __n; + return std::__distance(std::move(__first), std::move(__last)); } template <class _Ip, sized_sentinel_for<decay_t<_Ip>> _Sp> @@ -92,4 +117,6 @@ inline constexpr auto distance = __distance{}; _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ITERATOR_DISTANCE_H diff --git a/libcxx/include/__utility/cmp.h b/libcxx/include/__utility/cmp.h index 14dc0c1..68864e2 100644 --- a/libcxx/include/__utility/cmp.h +++ b/libcxx/include/__utility/cmp.h @@ -26,10 +26,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 +template <typename _Tp, typename _Ip> +concept __comparison_can_promote_to = + sizeof(_Tp) < sizeof(_Ip) || (sizeof(_Tp) == sizeof(_Ip) && __signed_integer<_Tp>); + template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up> _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_equal(_Tp __t, _Up __u) noexcept { if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) return __t == __u; + else if constexpr (__comparison_can_promote_to<_Tp, int> && __comparison_can_promote_to<_Up, int>) + return static_cast<int>(__t) == static_cast<int>(__u); + else if constexpr (__comparison_can_promote_to<_Tp, long long> && __comparison_can_promote_to<_Up, long long>) + return static_cast<long long>(__t) == static_cast<long long>(__u); else if constexpr (is_signed_v<_Tp>) return __t < 0 ? false : make_unsigned_t<_Tp>(__t) == __u; else @@ -45,6 +53,10 @@ template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up> _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_less(_Tp __t, _Up __u) noexcept { if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) return __t < __u; + else if constexpr (__comparison_can_promote_to<_Tp, int> && __comparison_can_promote_to<_Up, int>) + return static_cast<int>(__t) < static_cast<int>(__u); + else if constexpr (__comparison_can_promote_to<_Tp, long long> && __comparison_can_promote_to<_Up, long long>) + return static_cast<long long>(__t) < static_cast<long long>(__u); else if constexpr (is_signed_v<_Tp>) return __t < 0 ? true : make_unsigned_t<_Tp>(__t) < __u; else diff --git a/libcxx/test/benchmarks/iterators/distance.bench.cpp b/libcxx/test/benchmarks/iterators/distance.bench.cpp new file mode 100644 index 0000000..186ef79 --- /dev/null +++ b/libcxx/test/benchmarks/iterators/distance.bench.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#include <algorithm> +#include <cstddef> +#include <deque> +#include <iterator> +#include <ranges> +#include <vector> + +#include <benchmark/benchmark.h> + +int main(int argc, char** argv) { + auto std_distance = [](auto first, auto last) { return std::distance(first, last); }; + + // {std,ranges}::distance(std::deque) + { + auto bm = [](std::string name, auto distance) { + benchmark::RegisterBenchmark( + name, + [distance](auto& st) { + std::size_t const size = st.range(0); + std::deque<int> c(size, 1); + + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + auto result = distance(c.begin(), c.end()); + benchmark::DoNotOptimize(result); + } + }) + ->Arg(50) // non power-of-two + ->Arg(1024) + ->Arg(4096) + ->Arg(8192); + }; + bm.operator()("std::distance(deque<int>)", std_distance); + bm.operator()("rng::distance(deque<int>)", std::ranges::distance); + } + + // {std,ranges}::distance(std::join_view) + { + auto bm = []<class Container>(std::string name, auto distance, std::size_t seg_size) { + benchmark::RegisterBenchmark( + name, + [distance, seg_size](auto& st) { + std::size_t const size = st.range(0); + std::size_t const segments = (size + seg_size - 1) / seg_size; + Container c(segments); + for (std::size_t i = 0, n = size; i < segments; ++i, n -= seg_size) { + c[i].resize(std::min(seg_size, n)); + } + + auto view = c | std::views::join; + auto first = view.begin(); + auto last = view.end(); + + for ([[maybe_unused]] auto _ : st) { + benchmark::DoNotOptimize(c); + auto result = distance(first, last); + benchmark::DoNotOptimize(result); + } + }) + ->Arg(50) // non power-of-two + ->Arg(1024) + ->Arg(4096) + ->Arg(8192); + }; + bm.operator()<std::vector<std::vector<int>>>("std::distance(join_view(vector<vector<int>>))", std_distance, 256); + bm.operator()<std::vector<std::vector<int>>>( + "rng::distance(join_view(vector<vector<int>>)", std::ranges::distance, 256); + } + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + benchmark::Shutdown(); + return 0; +} diff --git a/libcxx/test/benchmarks/utility/cmp.bench.cpp b/libcxx/test/benchmarks/utility/cmp.bench.cpp new file mode 100644 index 0000000..1ed179a --- /dev/null +++ b/libcxx/test/benchmarks/utility/cmp.bench.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#include <utility> +#include "../CartesianBenchmarks.h" +#include "benchmark/benchmark.h" + +namespace { + +enum ValueType : size_t { + SChar, + UChar, + Short, + UShort, + Int, + UInt, + Long, + ULong, + LongLong, + ULongLong, +#ifndef TEST_HAS_NO_INT128 + Int128, + UInt128, +#endif +}; + +struct AllValueTypes : EnumValuesAsTuple<AllValueTypes, ValueType, 6> { + static constexpr const char* Names[] = { + "schar", + "uchar", + "short", + "ushort", + "int", + "uint", + "long", + "ulong", + "longlong", + "ulonglong", +#ifndef TEST_HAS_NO_INT128 + "int128", + "uint128" +#endif + }; +}; + +using TestType = + std::tuple< signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long +#ifndef TEST_HAS_NO_INT128 + , + __int128_t, + __uint128_t +#endif + >; + +template <typename TType, typename UType> +struct CmpEqual { + static void run(benchmark::State& state) { + using T = std::tuple_element_t<TType::value, TestType>; + using U = std::tuple_element_t<UType::value, TestType>; + + T x1 = T{127}, x2 = T{111}; + U y1 = U{123}, y2 = U{1}; + for (auto _ : state) { + benchmark::DoNotOptimize(x1); + benchmark::DoNotOptimize(x2); + benchmark::DoNotOptimize(y1); + benchmark::DoNotOptimize(y2); + benchmark::DoNotOptimize(std::cmp_equal(x1, y1)); + benchmark::DoNotOptimize(std::cmp_equal(y1, x1)); + benchmark::DoNotOptimize(std::cmp_equal(x1, x1)); + benchmark::DoNotOptimize(std::cmp_equal(y1, y1)); + + benchmark::DoNotOptimize(std::cmp_equal(x2, y2)); + benchmark::DoNotOptimize(std::cmp_equal(y2, x2)); + benchmark::DoNotOptimize(std::cmp_equal(x2, x2)); + benchmark::DoNotOptimize(std::cmp_equal(y2, y2)); + } + } + + static std::string name() { return "BM_CmpEqual" + TType::name() + UType::name(); } +}; + +template <typename TType, typename UType> +struct CmpLess { + static void run(benchmark::State& state) { + using T = std::tuple_element_t<TType::value, TestType>; + using U = std::tuple_element_t<UType::value, TestType>; + + T x1 = T{127}, x2 = T{111}; + U y1 = U{123}, y2 = U{1}; + for (auto _ : state) { + benchmark::DoNotOptimize(x1); + benchmark::DoNotOptimize(x2); + benchmark::DoNotOptimize(y1); + benchmark::DoNotOptimize(y2); + benchmark::DoNotOptimize(std::cmp_less(x1, y1)); + benchmark::DoNotOptimize(std::cmp_less(y1, x1)); + benchmark::DoNotOptimize(std::cmp_less(x1, x1)); + benchmark::DoNotOptimize(std::cmp_less(y1, y1)); + + benchmark::DoNotOptimize(std::cmp_less(x2, y2)); + benchmark::DoNotOptimize(std::cmp_less(y2, x2)); + benchmark::DoNotOptimize(std::cmp_less(x2, x2)); + benchmark::DoNotOptimize(std::cmp_less(y2, y2)); + } + } + + static std::string name() { return "BM_CmpLess" + TType::name() + UType::name(); } +}; + +} // namespace + +int main(int argc, char** argv) { + benchmark::Initialize(&argc, argv); + if (benchmark::ReportUnrecognizedArguments(argc, argv)) + return 1; + + makeCartesianProductBenchmark<CmpEqual, AllValueTypes, AllValueTypes>(); + makeCartesianProductBenchmark<CmpLess, AllValueTypes, AllValueTypes>(); + benchmark::RunSpecifiedBenchmarks(); + + return 0; +} diff --git a/libcxx/test/libcxx-03/assertions/customize_verbose_abort.link-time.pass.cpp b/libcxx/test/libcxx-03/assertions/customize_verbose_abort.link-time.pass.cpp index 390c6b6..3c7a2d4 100644 --- a/libcxx/test/libcxx-03/assertions/customize_verbose_abort.link-time.pass.cpp +++ b/libcxx/test/libcxx-03/assertions/customize_verbose_abort.link-time.pass.cpp @@ -12,9 +12,7 @@ // failures when back-deploying. // XFAIL: availability-verbose_abort-missing -// XFAIL: FROZEN-CXX03-HEADERS-FIXME - -#include <__verbose_abort> +#include <__cxx03/__verbose_abort> #include <cstdlib> void std::__libcpp_verbose_abort(char const*, ...) _NOEXCEPT { std::exit(EXIT_SUCCESS); } diff --git a/libcxx/test/libcxx-03/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx-03/language.support/support.dynamic/libcpp_deallocate.sh.cpp index 7ead65c..a9fe04f 100644 --- a/libcxx/test/libcxx-03/language.support/support.dynamic/libcpp_deallocate.sh.cpp +++ b/libcxx/test/libcxx-03/language.support/support.dynamic/libcpp_deallocate.sh.cpp @@ -21,8 +21,6 @@ // GCC doesn't support the aligned-allocation flags. // XFAIL: gcc -// XFAIL: FROZEN-CXX03-HEADERS-FIXME - // RUN: %{build} -faligned-allocation -fsized-deallocation // RUN: %{run} // RUN: %{build} -faligned-allocation -fno-sized-deallocation -DNO_SIZE @@ -40,7 +38,7 @@ TEST_DIAGNOSTIC_PUSH TEST_CLANG_DIAGNOSTIC_IGNORED("-Wprivate-header") -#include <__memory/aligned_alloc.h> +#include <__cxx03/__memory/aligned_alloc.h> TEST_DIAGNOSTIC_POP struct alloc_stats { @@ -138,42 +136,42 @@ void test_libcpp_dealloc() { std::size_t with_size_val = 2; { - std::__libcpp_deallocate_unsized<char>(static_cast<char*>(p), under_align_val); + std::__libcpp_deallocate_unsized(p, under_align_val); assert(stats.expect_plain()); } stats.reset(); #if defined(NO_SIZE) && defined(NO_ALIGN) { - std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val); + std::__libcpp_deallocate(p, with_size_val, over_align_val); assert(stats.expect_plain()); } stats.reset(); #elif defined(NO_SIZE) { - std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val); + std::__libcpp_deallocate(p, with_size_val, over_align_val); assert(stats.expect_align(over_align_val)); } stats.reset(); #elif defined(NO_ALIGN) { - std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val); + std::__libcpp_deallocate(p, with_size_val, over_align_val); assert(stats.expect_size(with_size_val)); } stats.reset(); #else { - std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), over_align_val); + std::__libcpp_deallocate(p, with_size_val, over_align_val); assert(stats.expect_size_align(with_size_val, over_align_val)); } stats.reset(); { - std::__libcpp_deallocate_unsized<char>(static_cast<char*>(p), over_align_val); + std::__libcpp_deallocate_unsized(p, over_align_val); assert(stats.expect_align(over_align_val)); } stats.reset(); { - std::__libcpp_deallocate<char>(static_cast<char*>(p), std::__element_count(with_size_val), under_align_val); + std::__libcpp_deallocate(p, with_size_val, under_align_val); assert(stats.expect_size(with_size_val)); } stats.reset(); diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp index 3c9cf9b..bede567 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp @@ -12,8 +12,6 @@ // constexpr OutIter // constexpr after C++17 // copy(InIter first, InIter last, OutIter result); -// XFAIL: FROZEN-CXX03-HEADERS-FIXME - #include <algorithm> #include <cassert> #include <vector> diff --git a/libcxx/test/std/iterators/iterator.primitives/iterator.operations/distance.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/iterator.operations/distance.pass.cpp index 13caeff..d92a44f 100644 --- a/libcxx/test/std/iterators/iterator.primitives/iterator.operations/distance.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/iterator.operations/distance.pass.cpp @@ -16,38 +16,73 @@ // Iter::difference_type // distance(Iter first, Iter last); // constexpr in C++17 -#include <iterator> +#include <array> #include <cassert> +#include <deque> +#include <iterator> +#include <vector> #include <type_traits> #include "test_macros.h" #include "test_iterators.h" template <class It> -TEST_CONSTEXPR_CXX17 -void check_distance(It first, It last, typename std::iterator_traits<It>::difference_type dist) -{ - typedef typename std::iterator_traits<It>::difference_type Difference; - static_assert(std::is_same<decltype(std::distance(first, last)), Difference>::value, ""); - assert(std::distance(first, last) == dist); +TEST_CONSTEXPR_CXX17 void check_distance(It first, It last, typename std::iterator_traits<It>::difference_type dist) { + typedef typename std::iterator_traits<It>::difference_type Difference; + static_assert(std::is_same<decltype(std::distance(first, last)), Difference>::value, ""); + assert(std::distance(first, last) == dist); } -TEST_CONSTEXPR_CXX17 bool tests() -{ - const char* s = "1234567890"; - check_distance(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10), 10); - check_distance(forward_iterator<const char*>(s), forward_iterator<const char*>(s+10), 10); - check_distance(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+10), 10); - check_distance(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+10), 10); - check_distance(s, s+10, 10); - return true; +#if TEST_STD_VER >= 20 +/*TEST_CONSTEXPR_CXX26*/ void test_deque() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr + using Container = std::deque<std::deque<double>>; + Container c; + auto view = c | std::views::join; + Container::difference_type n = 0; + for (std::size_t i = 0; i < 10; ++i) { + n += i; + c.push_back(Container::value_type(i)); + } + assert(std::distance(view.begin(), view.end()) == n); +} +#endif + +TEST_CONSTEXPR_CXX17 bool tests() { + const char* s = "1234567890"; + check_distance(cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s + 10), 10); + check_distance(forward_iterator<const char*>(s), forward_iterator<const char*>(s + 10), 10); + check_distance(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s + 10), 10); + check_distance(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s + 10), 10); + check_distance(s, s + 10, 10); + +#if TEST_STD_VER >= 20 + { + using Container = std::vector<std::vector<int>>; + Container c; + auto view = c | std::views::join; + Container::difference_type n = 0; + for (std::size_t i = 0; i < 10; ++i) { + n += i; + c.push_back(Container::value_type(i)); + } + assert(std::distance(view.begin(), view.end()) == n); + } + { + using Container = std::array<std::array<char, 3>, 10>; + Container c; + auto view = c | std::views::join; + assert(std::distance(view.begin(), view.end()) == 30); + } + if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr + test_deque(); +#endif + return true; } -int main(int, char**) -{ - tests(); +int main(int, char**) { + tests(); #if TEST_STD_VER >= 17 - static_assert(tests(), ""); + static_assert(tests(), ""); #endif - return 0; + return 0; } diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp index b4199b7..1b78489 100644 --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp @@ -15,18 +15,21 @@ // template<class I, sized_sentinel_for<decay_t<I>> S> // constexpr iter_difference_t<I> ranges::distance(I&& first, S last); // TODO: update when LWG3664 is resolved -#include <iterator> +#include <array> #include <cassert> +#include <deque> +#include <iterator> +#include <vector> #include "test_iterators.h" #include "test_macros.h" -template<class It, class Sent> +template <class It, class Sent> constexpr void test_unsized() { static_assert(std::sentinel_for<Sent, It> && !std::sized_sentinel_for<Sent, It>); - int a[3] = {1,2,3}; + int a[3] = {1, 2, 3}; { - It first = It(a); + It first = It(a); auto last = Sent(It(a)); assert(std::ranges::distance(first, last) == 0); assert(std::ranges::distance(It(a), last) == 0); @@ -36,7 +39,7 @@ constexpr void test_unsized() { } { auto check = [&a]<class ItQual, class SentQual> { - It first = It(a); + It first = It(a); Sent last = Sent(It(a + 3)); assert(std::ranges::distance(static_cast<ItQual>(first), static_cast<SentQual>(last)) == 3); }; @@ -61,13 +64,13 @@ constexpr void test_unsized() { } } -template<class It, class Sent> +template <class It, class Sent> constexpr void test_sized() { static_assert(std::sized_sentinel_for<Sent, It>); - int a[] = {1,2,3}; + int a[] = {1, 2, 3}; { auto check = [&a]<class ItQual, class SentQual> { - It first = It(a + 3); + It first = It(a + 3); Sent last = Sent(It(a)); assert(std::ranges::distance(static_cast<ItQual>(first), static_cast<SentQual>(last)) == -3); }; @@ -91,7 +94,7 @@ constexpr void test_sized() { check.template operator()<const It&&, const Sent&&>(); } { - It first = It(a); + It first = It(a); auto last = Sent(It(a)); assert(std::ranges::distance(first, last) == 0); assert(std::ranges::distance(It(a), last) == 0); @@ -100,7 +103,7 @@ constexpr void test_sized() { ASSERT_SAME_TYPE(decltype(std::ranges::distance(It(a), Sent(It(a)))), std::iter_difference_t<It>); } { - It first = It(a); + It first = It(a); auto last = Sent(It(a + 3)); assert(std::ranges::distance(first, last) == 3); assert(std::ranges::distance(It(a), last) == 3); @@ -110,13 +113,17 @@ constexpr void test_sized() { } struct StrideCounter { - int *it_; - int *inc_; - using value_type = int; + int* it_; + int* inc_; + using value_type = int; using difference_type = int; explicit StrideCounter(); - constexpr explicit StrideCounter(int *it, int *inc) : it_(it), inc_(inc) {} - constexpr auto& operator++() { ++it_; *inc_ += 1; return *this; } + constexpr explicit StrideCounter(int* it, int* inc) : it_(it), inc_(inc) {} + constexpr auto& operator++() { + ++it_; + *inc_ += 1; + return *this; + } StrideCounter operator++(int); int& operator*() const; bool operator==(StrideCounter) const; @@ -125,11 +132,11 @@ static_assert(std::forward_iterator<StrideCounter>); static_assert(!std::sized_sentinel_for<StrideCounter, StrideCounter>); struct SizedStrideCounter { - int *it_; - int *minus_; + int* it_; + int* minus_; using value_type = int; explicit SizedStrideCounter(); - constexpr explicit SizedStrideCounter(int *it, int *minus) : it_(it), minus_(minus) {} + constexpr explicit SizedStrideCounter(int* it, int* minus) : it_(it), minus_(minus) {} SizedStrideCounter& operator++(); SizedStrideCounter operator++(int); int& operator*() const; @@ -147,22 +154,34 @@ constexpr void test_stride_counting() { int a[] = {1, 2, 3}; int inc = 0; StrideCounter first(a, &inc); - StrideCounter last(a+3, nullptr); + StrideCounter last(a + 3, nullptr); std::same_as<int> auto result = std::ranges::distance(first, last); assert(result == 3); assert(inc == 3); } { - int a[] = {1, 2, 3}; + int a[] = {1, 2, 3}; int minus = 0; SizedStrideCounter first(a, &minus); - SizedStrideCounter last(a+3, nullptr); + SizedStrideCounter last(a + 3, nullptr); std::same_as<int> auto result = std::ranges::distance(first, last); assert(result == 3); assert(minus == 1); } } +/*TEST_CONSTEXPR_CXX26*/ void test_deque() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr + using Container = std::deque<std::deque<double>>; + Container c; + auto view = c | std::views::join; + Container::difference_type n = 0; + for (std::size_t i = 0; i < 10; ++i) { + n += i; + c.push_back(Container::value_type(i)); + } + assert(std::ranges::distance(view.begin(), view.end()) == n); +} + constexpr bool test() { { int a[] = {1, 2, 3}; @@ -197,7 +216,7 @@ constexpr bool test() { test_sized<contiguous_iterator<int*>, contiguous_iterator<int*>>(); { - using It = cpp20_input_iterator<int*>; // non-copyable, thus not a sentinel for itself + using It = cpp20_input_iterator<int*>; // non-copyable, thus not a sentinel for itself static_assert(!std::is_copy_constructible_v<It>); static_assert(!std::sentinel_for<It, It>); static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&>); @@ -206,10 +225,10 @@ constexpr bool test() { static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&&, It&&>); } { - using It = cpp20_input_iterator<int*>; // non-copyable - using Sent = sentinel_wrapper<It>; // not a sized sentinel + using It = cpp20_input_iterator<int*>; // non-copyable + using Sent = sentinel_wrapper<It>; // not a sized sentinel static_assert(std::sentinel_for<Sent, It> && !std::sized_sentinel_for<Sent, It>); - int a[] = {1,2,3}; + int a[] = {1, 2, 3}; Sent last = Sent(It(a + 3)); static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, Sent&>); static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, Sent&&>); @@ -217,7 +236,7 @@ constexpr bool test() { assert(std::ranges::distance(It(a), Sent(It(a + 3))) == 3); } { - using It = cpp17_input_iterator<int*>; // not a sentinel for itself + using It = cpp17_input_iterator<int*>; // not a sentinel for itself static_assert(!std::sentinel_for<It, It>); static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&>); static_assert(!std::is_invocable_v<decltype(std::ranges::distance), It&, It&&>); @@ -231,6 +250,26 @@ constexpr bool test() { static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int, int*>); static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int*, char*>); + { + using Container = std::vector<std::vector<int>>; + Container c; + auto view = c | std::views::join; + Container::difference_type n = 0; + for (std::size_t i = 0; i < 10; ++i) { + n += i; + c.push_back(Container::value_type(i)); + } + assert(std::ranges::distance(view.begin(), view.end()) == n); + } + { + using Container = std::array<std::array<char, 3>, 10>; + Container c; + auto view = c | std::views::join; + assert(std::ranges::distance(view.begin(), view.end()) == 30); + } + if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr + test_deque(); + return true; } diff --git a/libcxx/test/std/language.support/support.runtime/cstdalign.compile.pass.cpp b/libcxx/test/std/language.support/support.runtime/cstdalign.compile.pass.cpp index 69296df..d289ef6 100644 --- a/libcxx/test/std/language.support/support.runtime/cstdalign.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.runtime/cstdalign.compile.pass.cpp @@ -10,7 +10,7 @@ // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS -// XFAIL: FROZEN-CXX03-HEADERS-FIXME +// UNSUPPORTED: c++03 #include <cstdalign> |