aboutsummaryrefslogtreecommitdiff
path: root/libcxx
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/docs/ReleaseNotes/22.rst3
-rw-r--r--libcxx/include/__cxx03/__bit_reference18
-rw-r--r--libcxx/include/__cxx03/__verbose_abort2
-rw-r--r--libcxx/include/__hash_table2
-rw-r--r--libcxx/include/__iterator/distance.h55
-rw-r--r--libcxx/include/__utility/cmp.h12
-rw-r--r--libcxx/test/benchmarks/iterators/distance.bench.cpp84
-rw-r--r--libcxx/test/benchmarks/utility/cmp.bench.cpp139
-rw-r--r--libcxx/test/libcxx-03/assertions/customize_verbose_abort.link-time.pass.cpp4
-rw-r--r--libcxx/test/libcxx-03/language.support/support.dynamic/libcpp_deallocate.sh.cpp18
-rw-r--r--libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp2
-rw-r--r--libcxx/test/std/iterators/iterator.primitives/iterator.operations/distance.pass.cpp77
-rw-r--r--libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp91
-rw-r--r--libcxx/test/std/language.support/support.runtime/cstdalign.compile.pass.cpp2
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>