diff options
Diffstat (limited to 'libstdc++-v3/testsuite')
35 files changed, 1406 insertions, 8 deletions
diff --git a/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc b/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc index 9491bbc..a84c110 100644 --- a/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc +++ b/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc @@ -1,5 +1,5 @@ // { dg-do link } -// { dg-require-static-libstdcxx } +// { dg-require-static-libstdcxx "" } // { dg-require-sharedlib "" } // { dg-require-effective-target fpic } // { dg-options "-shared -fPIC -static-libgcc -static-libstdc++" } diff --git a/libstdc++-v3/testsuite/17_intro/static.cc b/libstdc++-v3/testsuite/17_intro/static.cc index ab0cf27..26b34c8 100644 --- a/libstdc++-v3/testsuite/17_intro/static.cc +++ b/libstdc++-v3/testsuite/17_intro/static.cc @@ -1,5 +1,5 @@ // { dg-do run { target c++11 } } -// { dg-require-static-libstdcxx } +// { dg-require-static-libstdcxx "" } // { dg-options "-static-libstdc++" } // Copyright (C) 2012-2025 Free Software Foundation, Inc. diff --git a/libstdc++-v3/testsuite/18_support/type_info/110572.cc b/libstdc++-v3/testsuite/18_support/type_info/110572.cc index f727653..5a05078 100644 --- a/libstdc++-v3/testsuite/18_support/type_info/110572.cc +++ b/libstdc++-v3/testsuite/18_support/type_info/110572.cc @@ -1,6 +1,6 @@ // { dg-options "-static-libstdc++" } // { dg-do link } -// { dg-require-static-libstdcxx } +// { dg-require-static-libstdcxx "" } // { dg-require-cpp-feature-test __cpp_rtti } #include <typeinfo> diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc index e0589e3..af3b733 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc @@ -175,6 +175,17 @@ test03() } } +void +test_pr101587() +{ + short in[1]; + __gnu_test::test_contiguous_range r(in); // difference_type is integer-like + long out[1]; + std::span<long> o(out); // difference_type is ptrdiff_t + ranges::uninitialized_copy(r, o); + ranges::uninitialized_copy_n(ranges::begin(r), 0, o.begin(), o.end()); +} + int main() { @@ -188,4 +199,6 @@ main() test02<false>(); test02<true>(); + + test_pr101587(); } diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc index 4c858e1..fe82d1f1 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc @@ -185,6 +185,17 @@ test03() } } +void +test_pr101587() +{ + short in[1]; + __gnu_test::test_contiguous_range r(in); // difference_type is integer-like + long out[1]; + std::span<long> o(out); // difference_type is ptrdiff_t + ranges::uninitialized_move(r, o); + ranges::uninitialized_move_n(ranges::begin(r), 0, o.begin(), o.end()); +} + int main() { @@ -198,4 +209,6 @@ main() test02<false>(); test02<true>(); + + test_pr101587(); } diff --git a/libstdc++-v3/testsuite/20_util/to_chars/4.cc b/libstdc++-v3/testsuite/20_util/to_chars/4.cc index 3d76d56..65abfaa 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/4.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/4.cc @@ -17,7 +17,7 @@ // { dg-do link { target c++17 } } // { dg-require-effective-target ieee_floats } -// { dg-require-static-libstdcxx } +// { dg-require-static-libstdcxx "" } // { dg-additional-options "-static-libstdc++" } // Verify the Ryu symbol generic_to_chars doesn't inadvertently leak into diff --git a/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/119545.cc b/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/119545.cc new file mode 100644 index 0000000..3a65ef5 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/comparison_operators/119545.cc @@ -0,0 +1,24 @@ +// { dg-do compile { target c++11 } } +// Bug libstdc++/119545 +// tuple::operator==()'s help lambda does not specify return type as bool + +#include <tuple> + +void +test_pr119545() +{ + struct Bool { + Bool() = default; + Bool(const Bool&) = delete; + operator bool() const { return true; } + }; + + static Bool b; + + struct Object { + const Bool& operator==(const Object&) const { return b; } + }; + + std::tuple<Object> t; + (void) (t == t); +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc new file mode 100644 index 0000000..96e994d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc @@ -0,0 +1,117 @@ +// { dg-do run { target c++23 } } + +#include <deque> +#include <span> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_allocator.h> + +void +test_deduction_guide(long* p) +{ + __gnu_test::test_input_range<long> r(p, p); + std::deque d(std::from_range, r); + static_assert(std::is_same_v<decltype(d), std::deque<long>>); + + using Alloc = __gnu_test::SimpleAllocator<long>; + Alloc alloc; + std::deque d2(std::from_range, r, alloc); + static_assert(std::is_same_v<decltype(d2), std::deque<long, Alloc>>); +} + +template<typename Range, typename Alloc> +constexpr void +do_test(Alloc alloc) +{ + // The deque's value_type. + using V = typename std::allocator_traits<Alloc>::value_type; + + // The range's value_type. + using T = std::ranges::range_value_t<Range>; + T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14}; + + auto eq = [](const std::deque<V, Alloc>& l, std::span<T> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + if (l[i] != r[i]) + return false; + return true; + }; + + std::deque<V, Alloc> d0(std::from_range, Range(a, a+0)); + VERIFY( d0.empty() ); + VERIFY( d0.get_allocator() == Alloc() ); + + std::deque<V, Alloc> d4(std::from_range, Range(a, a+4)); + VERIFY( eq(d4, {a, 4}) ); + VERIFY( d4.get_allocator() == Alloc() ); + + std::deque<V, Alloc> d8(std::from_range, Range(a, a+8)); + VERIFY( eq(d8, {a, 8}) ); + VERIFY( d8.get_allocator() == Alloc() ); + + std::deque<V, Alloc> d9(std::from_range, Range(a, a+14), alloc); + VERIFY( eq(d9, {a, 14}) ); + VERIFY( d9.get_allocator() == alloc ); +} + +struct EightInBuf +{ + EightInBuf(int x) : elems{x} + { } + +private: + int elems[512 / (sizeof(int) * 8)]; + + friend constexpr bool operator==(EightInBuf const& lhs, int rhs) + { return lhs.elems[0] == rhs; } +}; + + +template<typename Range> +void +do_test_a() +{ + do_test<Range>(std::allocator<int>()); + do_test<Range>(__gnu_test::uneq_allocator<int>(42)); + do_test<Range>(std::allocator<EightInBuf>()); +} + +bool +test_ranges() +{ + using namespace __gnu_test; + + do_test_a<test_forward_range<int>>(); + do_test_a<test_forward_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + + do_test_a<test_input_range<int>>(); + do_test_a<test_input_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + + do_test_a<test_range_nocopy<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + + do_test_a<test_forward_range<short>>(); + do_test_a<test_input_range<short>>(); + + // Not lvalue-convertible to int + struct C { + C(int v) : val(v) { } + operator int() && { return val; } + bool operator==(int b) const { return b == val; } + int val; + }; + using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; + do_test<rvalue_input_range>(std::allocator<int>()); + + return true; +} + +int main() +{ + test_ranges(); +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/append_range.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/append_range.cc new file mode 100644 index 0000000..e46711c --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/append_range.cc @@ -0,0 +1,128 @@ +// { dg-do run { target c++23 } } + +#include <deque> +#include <span> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_allocator.h> + +template<typename Range, typename Alloc> +constexpr void +do_test() +{ + // The deque's value_type. + using V = typename std::allocator_traits<Alloc>::value_type; + + // The range's value_type. + using T = std::ranges::range_value_t<Range>; + T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14}; + + auto eq = [](const std::deque<V, Alloc>& l, std::span<T> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + if (l[i] != r[i]) + return false; + return true; + }; + + V const* p[std::size(a)]{}; + auto stable = [](const std::deque<V, Alloc>& l, std::span<V const*> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + { + if (r[i] == nullptr) + r[i] = &l[i]; + else if (&l[i] != r[i]) + return false; + } + return true; + }; + + std::deque<V, Alloc> d; + d.append_range(Range(a, a)); + VERIFY( d.empty() ); + d.append_range(Range(a, a+4)); + VERIFY( eq(d, {a, 4}) ); + VERIFY( stable(d, {p, 4} ) ); + d.append_range(Range(a+4, a+8)); + VERIFY( eq(d, {a, 8}) ); + VERIFY( stable(d, {p, 8}) ); + d.append_range(Range(a+8, a+14)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + std::ranges::fill(p, nullptr); + d.append_range(Range(a, a+4)); + VERIFY( eq(d, {a, 4}) ); + VERIFY( stable(d, {p, 4} ) ); + d.append_range(Range(a+4, a+14)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + std::ranges::fill(p, nullptr); + d.append_range(Range(a, a+14)); + VERIFY( eq(d, a) ); +} + +struct EightInBuf +{ + EightInBuf(int x) : elems{x} + { } + +private: + int elems[512 / (sizeof(int) * 8)]; + + friend constexpr bool operator==(EightInBuf const& lhs, int rhs) + { return lhs.elems[0] == rhs; } +}; + +template<typename Range> +void +do_test_a() +{ + do_test<Range, std::allocator<int>>(); + do_test<Range, __gnu_test::SimpleAllocator<int>>(); + do_test<Range, std::allocator<EightInBuf>>(); +} + +bool +test_ranges() +{ + using namespace __gnu_test; + + do_test_a<test_forward_range<int>>(); + do_test_a<test_forward_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + + do_test_a<test_input_range<int>>(); + do_test_a<test_input_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + + do_test_a<test_range_nocopy<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + + do_test_a<test_forward_range<short>>(); + do_test_a<test_input_range<short>>(); + + // Not lvalue-convertible to int + struct C { + C(int v) : val(v) { } + operator int() && { return val; } + bool operator==(int b) const { return b == val; } + int val; + }; + using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; + do_test<rvalue_input_range, std::allocator<int>>(); + + return true; +} + +int main() +{ + test_ranges(); +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/assign/assign_range.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/assign/assign_range.cc new file mode 100644 index 0000000..0cfdd3b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/assign/assign_range.cc @@ -0,0 +1,109 @@ +// { dg-do run { target c++23 } } + +#include <deque> +#include <span> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_allocator.h> + +template<typename Range, typename Alloc> +constexpr void +do_test() +{ + // The deque's value_type. + using V = typename std::allocator_traits<Alloc>::value_type; + + // The range's value_type. + using T = std::ranges::range_value_t<Range>; + T a[]{1,2,3,4,5,6,7,8,9}; + + auto eq = [](const std::deque<V, Alloc>& l, std::span<T> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + if (l[i] != r[i]) + return false; + return true; + }; + + // assign to empty deque + std::deque<V, Alloc> d; + d.assign_range(Range(a, a)); + VERIFY( d.empty() ); + d.assign_range(Range(a, a+4)); + VERIFY( eq(d, {a, 4}) ); + d.clear(); + d.assign_range(Range(a, a+9)); + VERIFY( eq(d, a) ); + d.clear(); + d.assign_range(Range(a, a+4)); + VERIFY( eq(d, {a, 4}) ); + d.clear(); + d.assign_range(Range(a, a+9)); + VERIFY( eq(d, a) ); + + + // assign to non-empty deque + d.assign_range(Range(a, a+4)); // smaller than size() + VERIFY( eq(d, {a, 4}) ); + d.assign_range(Range(a, a+9)); // larger than size() + VERIFY( eq(d, a) ); + d.resize(1); + d.assign_range(Range(a, a+4)); // larger than size() + VERIFY( eq(d, {a, 4}) ); + d.clear(); + d.resize(4); + d.assign_range(Range(a, a+4)); // equal to size() + VERIFY( eq(d, {a, 4}) ); + d.shrink_to_fit(); + d.assign_range(Range(a, a+9)); + VERIFY( eq(d, a) ); + d.assign_range(Range(a, a)); + VERIFY( d.empty() ); +} + +template<typename Range> +void +do_test_a() +{ + do_test<Range, std::allocator<int>>(); + do_test<Range, __gnu_test::SimpleAllocator<int>>(); +} + +bool +test_ranges() +{ + using namespace __gnu_test; + + do_test_a<test_forward_range<int>>(); + do_test_a<test_forward_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + + do_test_a<test_input_range<int>>(); + do_test_a<test_input_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + + do_test_a<test_range_nocopy<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + + do_test_a<test_forward_range<short>>(); + do_test_a<test_input_range<short>>(); + + // Not lvalue-convertible to int + struct C { + C(int v) : val(v) { } + operator int() && { return val; } + bool operator==(int b) const { return b == val; } + int val; + }; + using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; + do_test<rvalue_input_range, std::allocator<int>>(); + + return true; +} + +int main() +{ + test_ranges(); +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/insert/insert_range.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/insert/insert_range.cc new file mode 100644 index 0000000..75cd430 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/insert/insert_range.cc @@ -0,0 +1,142 @@ +// { dg-do run { target c++23 } } + +#include <deque> +#include <span> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_allocator.h> + +template<typename Range, typename Alloc> +constexpr void +do_test() +{ + // The deque's value_type. + using V = typename std::allocator_traits<Alloc>::value_type; + + // The range's value_type. + using T = std::ranges::range_value_t<Range>; + T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14}; + + auto eq = [](const std::deque<V, Alloc>& l, std::span<T> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + if (l[i] != r[i]) + return false; + return true; + }; + + V const* p[std::size(a)]{}; + auto stable = [](const std::deque<V, Alloc>& l, std::span<V const*> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + { + if (r[i] == nullptr) + r[i] = &l[i]; + else if (&l[i] != r[i]) + return false; + } + return true; + }; + + std::deque<V, Alloc> d; + d.insert_range(d.begin(), Range(a, a)); + VERIFY( d.empty() ); + d.insert_range(d.begin(), Range(a+12, a+14)); + VERIFY( eq(d, {a+12, 2}) ); + VERIFY( stable(d, {p+12, 2}) ); + d.insert_range(d.begin(), Range(a+8,a+12)); + VERIFY( eq(d, {a+8, 6}) ); + VERIFY( stable(d, {p+8, 6}) ); + d.insert_range(d.begin(), Range(a, a+8)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + std::ranges::fill(p, nullptr); + d.insert_range(d.end(), Range(a, a)); + VERIFY( d.empty() ); + d.insert_range(d.end(), Range(a, a+4)); + VERIFY( eq(d, {a, a+4}) ); + VERIFY( stable(d, {p, 4} ) ); + d.insert_range(d.end(), Range(a+4, a+14)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + auto it = d.insert_range(d.begin(), Range(a, a+4)); + VERIFY( it == d.begin() ); + it = d.insert_range(d.end(), Range(a+8, a+14)); + VERIFY( it == d.begin() + 4 ); + it = d.insert_range(d.begin() + 4, Range(a+4, a+8)); + VERIFY( it == d.begin() + 4 ); + VERIFY( eq(d, a) ); + + d.clear(); + it = d.insert_range(d.end(), Range(a+10, a+14)); + VERIFY( it == d.begin() ); + it = d.insert_range(d.begin(), Range(a, a+6)); + VERIFY( it == d.begin() ); + it = d.insert_range(d.begin() + 6, Range(a+6, a+10)); + VERIFY( it == d.begin() + 6 ); + VERIFY( eq(d, a) ); +} + +struct EightInBuf +{ + EightInBuf(int x) : elems{x} + { } + +private: + int elems[512 / (sizeof(int) * 8)]; + + friend constexpr bool operator==(EightInBuf const& lhs, int rhs) + { return lhs.elems[0] == rhs; } +}; + +template<typename Range> +void +do_test_a() +{ + do_test<Range, std::allocator<int>>(); + do_test<Range, __gnu_test::SimpleAllocator<int>>(); + do_test<Range, std::allocator<EightInBuf>>(); +} + +bool +test_ranges() +{ + using namespace __gnu_test; + + do_test_a<test_forward_range<int>>(); + do_test_a<test_forward_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + + do_test_a<test_input_range<int>>(); + do_test_a<test_input_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + + do_test_a<test_range_nocopy<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + + do_test_a<test_forward_range<short>>(); + do_test_a<test_input_range<short>>(); + + // Not lvalue-convertible to int + struct C { + C(int v) : val(v) { } + operator int() && { return val; } + bool operator==(int b) const { return b == val; } + int val; + }; + using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; + do_test<rvalue_input_range, std::allocator<int>>(); + + return true; +} +int main() +{ + test_ranges(); +} diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/prepend_range.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/prepend_range.cc new file mode 100644 index 0000000..4258bee --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/prepend_range.cc @@ -0,0 +1,140 @@ +// { dg-do run { target c++23 } } + +#include <deque> +#include <span> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_allocator.h> + +template<typename Range, typename Alloc> +constexpr void +do_test() +{ + // The deque's value_type. + using V = typename std::allocator_traits<Alloc>::value_type; + + // The range's value_type. + using T = std::ranges::range_value_t<Range>; + T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14}; + + auto eq = [](const std::deque<V, Alloc>& l, std::span<T> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + if (l[i] != r[i]) + return false; + return true; + }; + + V const* p[std::size(a)]{}; + auto stable = [](const std::deque<V, Alloc>& l, std::span<V const*> r) { + if (l.size() != r.size()) + return false; + for (auto i = 0u; i < l.size(); ++i) + { + if (r[i] == nullptr) + r[i] = &l[i]; + else if (&l[i] != r[i]) + return false; + } + return true; + }; + + std::deque<V, Alloc> d; + d.prepend_range(Range(a, a)); + VERIFY( d.empty() ); + d.prepend_range(Range(a+8, a+14)); + VERIFY( eq(d, {a+8, 6}) ); + VERIFY( stable(d, {p+8, 6}) ); + d.prepend_range(Range(a+4, a+8)); + VERIFY( eq(d, {a+4, 10}) ); + VERIFY( stable(d, {p+4, 10}) ); + d.prepend_range(Range(a, a+4)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + std::ranges::fill(p, nullptr); + d.prepend_range(Range(a+12, a+14)); + VERIFY( eq(d, {a+12, 2}) ); + VERIFY( stable(d, {p+12, 2}) ); + d.prepend_range(Range(a+8,a+12)); + VERIFY( eq(d, {a+8, 6}) ); + VERIFY( stable(d, {p+8, 6}) ); + d.prepend_range(Range(a, a+8)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + std::ranges::fill(p, nullptr); + d.prepend_range(Range(a+12, a+14)); + VERIFY( eq(d, {a+12, 2}) ); + VERIFY( stable(d, {p+12, 2}) ); + d.prepend_range(Range(a, a+12)); + VERIFY( eq(d, a) ); + VERIFY( stable(d, p) ); + + d.clear(); + d.prepend_range(Range(a, a+14)); + VERIFY( eq(d, a) ); +} + +struct EightInBuf +{ + EightInBuf(int x) : elems{x} + { } + +private: + int elems[512 / (sizeof(int) * 8)]; + + friend constexpr bool operator==(EightInBuf const& lhs, int rhs) + { return lhs.elems[0] == rhs; } +}; + + +template<typename Range> +void +do_test_a() +{ + do_test<Range, std::allocator<int>>(); + do_test<Range, __gnu_test::SimpleAllocator<int>>(); + do_test<Range, std::allocator<EightInBuf>>(); +} + +bool +test_ranges() +{ + using namespace __gnu_test; + + do_test_a<test_forward_range<int>>(); + do_test_a<test_forward_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, forward_iterator_wrapper>>(); + + do_test_a<test_input_range<int>>(); + do_test_a<test_input_sized_range<int>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper>>(); + + do_test_a<test_range_nocopy<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range<int, input_iterator_wrapper_nocopy>>(); + do_test_a<test_sized_range_sized_sent<int, input_iterator_wrapper_nocopy>>(); + + do_test_a<test_forward_range<short>>(); + do_test_a<test_input_range<short>>(); + + // Not lvalue-convertible to int + struct C { + C(int v) : val(v) { } + operator int() && { return val; } + bool operator==(int b) const { return b == val; } + int val; + }; + using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; + do_test<rvalue_input_range, std::allocator<int>>(); + + return true; +} + +int main() +{ + test_ranges(); +} diff --git a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc index 910f5dc..dc3cecd 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc @@ -143,6 +143,77 @@ test06() VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); } +template<typename T> +struct NoInsertRange : std::vector<T> +{ + using std::vector<T>::vector; + + template<typename It, typename R> + void insert_range(typename std::vector<T>::const_iterator, R&&) = delete; +}; + +struct NoCatIterator { + using difference_type = int; + using value_type = int; + + NoCatIterator() : v(0) {} + NoCatIterator(int x) : v(x) {} + + int operator*() const + { return v; } + + NoCatIterator& operator++() + { + ++v; + return *this; + } + + NoCatIterator operator++(int) + { + ++v; + return NoCatIterator(v-1); + } + + bool operator==(const NoCatIterator& rhs) const + { return v == rhs.v; } + +private: + int v; +}; + +template<> +struct std::iterator_traits<NoCatIterator> { + using difference_type = int; + using value_type = int; + using iterator_concept = std::input_iterator_tag; + // no iterator_category, happens also for common_iterator +}; + +void test07() +{ + std::flat_multiset<int> s; + std::flat_multiset<int, std::less<int>, NoInsertRange<int>> s2; + + auto r = std::ranges::subrange<NoCatIterator>(1, 6); + s.insert_range(r); + VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); + s2.insert_range(r); + VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); + +#ifdef __SIZEOF_INT128__ + // PR libstdc++/119415 - flat_foo::insert_range cannot handle common ranges + // on c++20 only iterators + auto r2 = std::views::iota(__int128(1), __int128(6)); + s.clear(); + s.insert_range(r2); + VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); + + s2.clear(); + s2.insert_range(r2); + VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); +#endif +} + int main() { @@ -153,4 +224,5 @@ main() test04(); test05(); test06(); + test07(); } diff --git a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc index f0eaac9..90f5855 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc @@ -158,6 +158,77 @@ test06() VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); } +template<typename T> +struct NoInsertRange : std::vector<T> +{ + using std::vector<T>::vector; + + template<typename It, typename R> + void insert_range(typename std::vector<T>::const_iterator, R&&) = delete; +}; + +struct NoCatIterator { + using difference_type = int; + using value_type = int; + + NoCatIterator() : v(0) {} + NoCatIterator(int x) : v(x) {} + + int operator*() const + { return v; } + + NoCatIterator& operator++() + { + ++v; + return *this; + } + + NoCatIterator operator++(int) + { + ++v; + return NoCatIterator(v-1); + } + + bool operator==(const NoCatIterator& rhs) const + { return v == rhs.v; } + +private: + int v; +}; + +template<> +struct std::iterator_traits<NoCatIterator> { + using difference_type = int; + using value_type = int; + using iterator_concept = std::input_iterator_tag; + // no iterator_category, happens also for common_iterator +}; + +void test07() +{ + std::flat_set<int> s; + std::flat_set<int, std::less<int>, NoInsertRange<int>> s2; + + auto r = std::ranges::subrange<NoCatIterator>(1, 6); + s.insert_range(r); + VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); + s2.insert_range(r); + VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); + +#ifdef __SIZEOF_INT128__ + // PR libstdc++/119415 - flat_foo::insert_range cannot handle common ranges + // on c++20 only iterators + auto r2 = std::views::iota(__int128(1), __int128(6)); + s.clear(); + s.insert_range(r2); + VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) ); + + s2.clear(); + s2.insert_range(r2); + VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) ); +#endif +} + int main() { @@ -168,4 +239,5 @@ main() test04(); test05(); test06(); + test07(); } diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/110498.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/110498.cc new file mode 100644 index 0000000..f848edc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/110498.cc @@ -0,0 +1,18 @@ +// { dg-options "-O3 -Werror=array-bounds -fno-assume-sane-operators-new-delete" } +// { dg-do compile } + +// Bug libstdc++/110498 +// Spurious warnings stringop-overflow and array-bounds copying data as bytes +// into vector::reserve + +#include <vector> + +void f(std::vector<bool>& v) +{ + // Warning emitted when set to any number in the range [1,64]. + const std::size_t reserve_size = 30; + + v.reserve(reserve_size); + v.push_back(0); +} + diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/114758.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/114758.cc new file mode 100644 index 0000000..c56d50a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/capacity/114758.cc @@ -0,0 +1,12 @@ +// { dg-options "-O3 -Werror=stringop-overread -fno-assume-sane-operators-new-delete" } +// { dg-do compile } + +// Bug libstdc++/114758 The layout of a std::vector<bool> reports a warning + +#include <vector> + +void pr114758(std::vector<bool>& v) +{ + v.resize(3); + v = std::vector<bool>(3, false); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc index f531e7f..37f0ecf 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc @@ -71,7 +71,7 @@ test_ranges() bool val; }; using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>; - do_test<rvalue_input_range>(std::allocator<int>()); + do_test<rvalue_input_range>(std::allocator<bool>()); return true; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc index a35ed0f..43a698f 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc @@ -83,6 +83,57 @@ test_constexpr() { // XXX: this doesn't test the non-forward_range code paths are constexpr. do_test<std::span<short>, std::allocator<bool>>(); + + // Some basic tests for overlapping ranges in constant expressions. + using I = std::vector<bool>::iterator; + + struct InputRange + { + struct Sent { I end; }; + + struct Iter + { + using value_type = bool; + using difference_type = int; + constexpr explicit Iter(I i) : i(i) { } + constexpr Iter& operator++() { ++i; return *this; } + constexpr Iter operator++(int) { auto i = *this; ++i; return i; } + constexpr int operator*() const { return *i; } + constexpr bool operator==(const Iter&) const = default; + constexpr bool operator==(const Sent& s) const { return i == s.end; } + I i; + }; + + Iter iter; + Sent sent; + + constexpr InputRange(I f, I l) : iter{f}, sent{l} { } + constexpr Iter begin() const { return iter; } + constexpr Sent end() const { return sent; } + }; + static_assert( std::ranges::input_range<InputRange> ); + static_assert( ! std::ranges::forward_range<InputRange> ); + + std::vector<bool> vec(5); + + // Test overlapping input ranges + vec.resize(vec.capacity()); + vec.append_range(InputRange(vec.begin(), vec.begin() + 3)); // no capacity + vec.reserve(vec.capacity() + 2); + vec.append_range(InputRange(vec.begin(), vec.begin() + 4)); // some capacity + vec.reserve(vec.capacity() + 6); + vec.append_range(InputRange(vec.begin(), vec.begin() + 5)); // enough capacity + + using R = std::ranges::subrange<I>; + + // Test overlapping forward ranges + vec.resize(vec.capacity()); + vec.append_range(R(vec.begin(), vec.begin() + 3)); // no capacity + vec.reserve(vec.size() + 2); + vec.append_range(R(vec.begin(), vec.begin() + 4)); // some capacity + vec.reserve(vec.size() + 6); + vec.append_range(R(vec.begin(), vec.begin() + 5)); // enough capacity + return true; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/114945.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/114945.cc new file mode 100644 index 0000000..daafc59 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/114945.cc @@ -0,0 +1,36 @@ +// { dg-options "-O2 -Werror=stringop-overflow -Werror=array-bounds" } +// { dg-do compile { target c++11 } } + +// Bug libstdc++/114945 +// Sporadic std::vector::resize() -Wstringop-overflow or -Warray-bounds warning + +#include <stdint.h> +#include <vector> +template <typename a> struct b { + void resize(std::size_t c) { d.resize(c); } + template <typename e> void f(a, e); + std::vector<char> d; +}; +#include <regex> +std::regex g; +uint64_t h; +uint32_t i; +struct s { + enum class j : size_t; + void k(); + using l = b<j>; + std::vector<l> m; +}; +enum class s::j : size_t { n }; +void o() { g = ""; } +void s::k() { + l p; + auto q = uint32_t(), r = uint32_t(); + if (h) + r = i; + b<size_t> t; + if (q || r) + p.f(j::n, 5); + t.resize(4); + m.push_back(p); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/108487.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/108487.cc new file mode 100644 index 0000000..13f2c47 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/108487.cc @@ -0,0 +1,24 @@ +// { dg-do run { target c++20 } } +// Bug libstdc++/108487 +// ~20-30x slowdown in populating std::vector from std::ranges::iota_view + +#include <ranges> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +void +test_pr108487() +{ + using __gnu_test::tracker_allocator; + using __gnu_test::tracker_allocator_counter; + auto r = std::ranges::iota_view{0, 20}; + tracker_allocator_counter::reset(); + std::vector<int, tracker_allocator<int>> v{r.begin(), r.end()}; + const std::size_t bytes = v.capacity() * sizeof(v.front()); + VERIFY( tracker_allocator_counter::get_allocation_count() == bytes ); +} + +int main() +{ + test_pr108487(); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc index 5725cd2..be097e2 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc @@ -82,16 +82,181 @@ test_ranges() return true; } +void +test_overlapping() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + + struct X { + unsigned* p; + constexpr X(int i = 0) : p(new unsigned(i)) { } + constexpr X(const X& m) : p(new unsigned(*m.p)) { } + constexpr X(X&& m) noexcept : p(m.p) { m.p = nullptr; } + constexpr ~X() { delete p; } + }; + + std::vector<X> vec; + unsigned size = 5; + vec.reserve(size); + for (unsigned i = 0; i < size; ++i) + vec.emplace_back(i); + + // Append an input range that overlaps with vec. + { + __gnu_test::test_input_range<X> r(vec.data(), vec.data() + size); + vec.append_range(r); + VERIFY( vec.size() == 2 * size ); + for (unsigned i = 0; i < size; ++i) + { + VERIFY( *vec[i].p == i ); + VERIFY( *vec[i+size].p == i ); + } + } + + size = vec.size() - 2; + vec.resize(size); + for (unsigned i = 0; i < size; ++i) + *vec[i].p = i; + + // Repeat with unused capacity in the vector. + { + __gnu_test::test_input_range<X> r(vec.data(), vec.data() + size); + vec.append_range(r); + VERIFY( vec.size() == 2 * size ); + for (unsigned i = 0; i < size; ++i) + { + VERIFY( *vec[i].p == i ); + VERIFY( *vec[i+size].p == i ); + } + } + + size = vec.size() - 2; + vec.resize(size); + for (unsigned i = 0; i < size; ++i) + *vec[i].p = i; + + // Repeat with input range that doesn't overlap full vector. + { + __gnu_test::test_input_range<X> r(vec.data() + 1, vec.data() + 4); + vec.append_range(r); + VERIFY( vec.size() == size + 3 ); + for (unsigned i = 0; i < size; ++i) + { + VERIFY( *vec[i].p == i ); + if (i < 3) + VERIFY( *vec[i+size].p == i+1 ); + } + } + + size = 5; + vec.resize(size); + for (unsigned i = 0; i < size; ++i) + *vec[i].p = i; + + // Append a forward range that overlaps with vec. + { + __gnu_test::test_forward_range<X> r(vec.data(), vec.data() + size); + vec.append_range(r); + VERIFY( vec.size() == 2 * size ); + for (unsigned i = 0; i < size; ++i) + { + VERIFY( *vec[i].p == i ); + VERIFY( *vec[i+size].p == i ); + } + } + + size = vec.size() - 2; + vec.resize(size); + for (unsigned i = 0; i < size; ++i) + *vec[i].p = i; + + // Repeat with insufficient unused capacity in the vector. + { + __gnu_test::test_forward_range<X> r(vec.data(), vec.data() + size); + vec.append_range(r); + VERIFY( vec.size() == 2 * size ); + for (unsigned i = 0; i < size; ++i) + { + VERIFY( *vec[i].p == i ); + VERIFY( *vec[i+size].p == i ); + } + } + + size = vec.size() / 2; + vec.resize(size); + + // Repeat with sufficient unused capacity in the vector. + { + __gnu_test::test_forward_range<X> r(vec.data(), vec.data() + size); + vec.append_range(r); + VERIFY( vec.size() == 2 * size ); + for (unsigned i = 0; i < size; ++i) + { + VERIFY( *vec[i].p == i ); + VERIFY( *vec[i+size].p == i ); + } + } +} + constexpr bool test_constexpr() { // XXX: this doesn't test the non-forward_range code paths are constexpr. do_test<std::span<short>, std::allocator<int>>(); + + // Some basic tests for overlapping ranges in constant expressions. + struct InputRange + { + struct Sent { const void* end; }; + + struct Iter + { + using value_type = int; + using difference_type = int; + constexpr explicit Iter(int* p) : ptr(p) { } + constexpr Iter& operator++() { ++ptr; return *this; } + constexpr Iter operator++(int) { auto i = *this; ++ptr; return i; } + constexpr int operator*() const { return *ptr; } + constexpr bool operator==(const Iter&) const = default; + constexpr bool operator==(const Sent& s) const { return ptr == s.end; } + int* ptr; + }; + + Iter iter; + Sent sent; + + constexpr InputRange(int* f, int* l) : iter{f}, sent{l} { } + constexpr Iter begin() const { return iter; } + constexpr Sent end() const { return sent; } + }; + static_assert( std::ranges::input_range<InputRange> ); + static_assert( ! std::ranges::forward_range<InputRange> ); + + std::vector<int> vec(5); + + // Test overlapping input ranges + vec.resize(vec.capacity()); + vec.append_range(InputRange(vec.data(), vec.data() + 3)); // no capacity + vec.reserve(vec.capacity() + 2); + vec.append_range(InputRange(vec.data(), vec.data() + 4)); // some capacity + vec.reserve(vec.capacity() + 6); + vec.append_range(InputRange(vec.data(), vec.data() + 5)); // enough capacity + + // Test overlapping forward ranges + vec.resize(vec.capacity()); + vec.append_range(std::span<int>(vec)); // no capacity + vec.reserve(vec.size() + 2); + vec.append_range(std::span<int>(vec).subspan(1, 4)); // some capacity + vec.reserve(vec.size() + 6); + vec.append_range(std::span<int>(vec).subspan(1, 5)); // enough capacity + return true; } int main() { test_ranges(); + test_overlapping(); static_assert( test_constexpr() ); } diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/117983.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/117983.cc new file mode 100644 index 0000000..e6027a6 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/117983.cc @@ -0,0 +1,17 @@ +// { dg-options "-O3 -Werror=stringop-overflow" } +// { dg-do compile } + +// PR libstdc++/117983 +// -Wstringop-overflow false positive for __builtin_memmove from vector::insert + +#include <vector> + +typedef std::vector<unsigned char> bytes; + +void push(bytes chunk, bytes& data) { + if (data.empty()) { + data.swap(chunk); + } else { + data.insert(data.end(), chunk.begin(), chunk.end()); + } +} diff --git a/libstdc++-v3/testsuite/24_iterators/common_iterator/101527.cc b/libstdc++-v3/testsuite/24_iterators/common_iterator/101527.cc new file mode 100644 index 0000000..0a2a5e8 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/common_iterator/101527.cc @@ -0,0 +1,14 @@ +// { dg-do compile { target c++20 } } + +// PR libstdc++/101527 +// implementation of std::common_iterator and std::counted_iterator's +// operator== seems to be wrong + +#include <iterator> + +bool test_pr101527() +{ + std::common_iterator<int*, std::unreachable_sentinel_t> it1; + std::common_iterator<const int*, std::unreachable_sentinel_t> it2; + return it1 == it2; +} diff --git a/libstdc++-v3/testsuite/24_iterators/counted_iterator/101527.cc b/libstdc++-v3/testsuite/24_iterators/counted_iterator/101527.cc new file mode 100644 index 0000000..51c6e99 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/counted_iterator/101527.cc @@ -0,0 +1,14 @@ +// { dg-do compile { target c++20 } } + +// PR libstdc++/101527 +// implementation of std::common_iterator and std::counted_iterator's +// operator== seems to be wrong + +#include <iterator> + +bool test_pr101527() +{ + std::counted_iterator<int*> it1; + std::counted_iterator<const int*> it2; + return it1 == it2; +} diff --git a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc index 341bd5b..8737574 100644 --- a/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc +++ b/libstdc++-v3/testsuite/24_iterators/customization_points/iter_move.cc @@ -157,9 +157,20 @@ test_pr106612() static_assert( std::same_as<decltype(std::ranges::iter_move(I3{})), F> ); } +void +test_pr119469() +{ + // rvalue references to function types are weird. + using F = int(); + static_assert( std::same_as<std::iter_rvalue_reference_t<F>, F&> ); + static_assert( std::same_as<std::iter_rvalue_reference_t<F&>, F&> ); + static_assert( std::same_as<std::iter_rvalue_reference_t<F&&>, F&> ); +} + int main() { test01(); test_adl(); + test_pr119469(); } diff --git a/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc b/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc index 5000b18..072dd07 100644 --- a/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc +++ b/libstdc++-v3/testsuite/25_algorithms/headers/algorithm/synopsis.cc @@ -349,6 +349,7 @@ namespace std partition(_BIter, _BIter, _Predicate); template<typename _BIter, typename _Predicate> + _GLIBCXX26_CONSTEXPR _BIter stable_partition(_BIter, _BIter, _Predicate); @@ -458,10 +459,12 @@ namespace std merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); template<typename _BIter> + _GLIBCXX26_CONSTEXPR void inplace_merge(_BIter, _BIter, _BIter); template<typename _BIter, typename _Compare> + _GLIBCXX26_CONSTEXPR void inplace_merge(_BIter, _BIter, _BIter, _Compare); diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constexpr.cc new file mode 100644 index 0000000..0bc4ed4 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constexpr.cc @@ -0,0 +1,72 @@ +// { dg-do compile { target c++26 } } + +#include <algorithm> +#include <array> +#include <functional> +#include <utility> + +// returns a pair [array, index of partitioning point] +constexpr auto +create_array() +{ + return std::make_pair( + std::to_array({0, 2, 2, 2, 4, 6, 1, 2, 3, 3, 4, 4, 5}), + 6); +} + +constexpr bool +test01() +{ + auto [ar, index] = create_array(); + std::inplace_merge(ar.begin(), ar.begin() + index, ar.end()); + return std::is_sorted(ar.begin(), ar.end()); +} + +static_assert(test01()); + +constexpr bool +test02() +{ + auto [ar, index] = create_array(); + auto index_it = ar.begin() + index; + std::reverse(ar.begin(), index_it); + std::reverse(index_it, ar.end()); + std::inplace_merge(ar.begin(), index_it, ar.end(), std::greater<>()); + return std::is_sorted(ar.begin(), ar.end(), std::greater<>()); +} + +static_assert(test02()); + +constexpr bool +test03() +{ + auto [ar, index] = create_array(); + std::ranges::inplace_merge(ar, ar.begin() + index); + return std::ranges::is_sorted(ar); +} + +static_assert(test03()); + +constexpr bool +test04() +{ + auto [ar, index] = create_array(); + auto index_it = ar.begin() + index; + std::ranges::reverse(ar.begin(), index_it); + std::ranges::reverse(index_it, ar.end()); + std::ranges::inplace_merge(ar, index_it, std::ranges::greater()); + return std::ranges::is_sorted(ar, std::ranges::greater()); +} + +static_assert(test04()); + +constexpr bool +test05() +{ + auto [ar, index] = create_array(); + auto proj = [](int i) { return -i; }; + std::ranges::inplace_merge(ar, ar.begin() + index, std::ranges::greater(), proj); + return std::ranges::is_sorted(ar, std::ranges::greater(), proj); +} + +static_assert(test05()); diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_partition/constexpr.cc b/libstdc++-v3/testsuite/25_algorithms/stable_partition/constexpr.cc new file mode 100644 index 0000000..8decc93 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_partition/constexpr.cc @@ -0,0 +1,44 @@ +// { dg-do compile { target c++26 } } + +#include <algorithm> +#include <array> + +constexpr auto +create_array() +{ + return std::to_array({0, 10, 1, 2, 3, 3, 4, -1, -2, -4, 5, 6}); +} + +constexpr bool +test01() +{ + auto ar = create_array(); + auto pred = [](int i) { return i % 2 == 0; }; + std::stable_partition(ar.begin(), ar.end(), pred); + return std::is_partitioned(ar.begin(), ar.end(), pred); +} + +static_assert(test01()); + +constexpr bool +test02() +{ + auto ar = create_array(); + auto pred = [](int i) { return i % 2 == 0; }; + std::ranges::stable_partition(ar, pred); + return std::ranges::is_partitioned(ar, pred); +} + +static_assert(test02()); + +constexpr bool +test03() +{ + auto ar = create_array(); + auto pred = [](int i) { return i % 2 == 0; }; + auto proj = [](int i) { return i + 1; }; + std::ranges::stable_partition(ar, pred, proj); + return std::ranges::is_partitioned(ar, pred, proj); +} + +static_assert(test03()); diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc index c302d9a..289bef6 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy.cc @@ -228,6 +228,23 @@ test_pr99290() remove_all(dir); } +void +test_pr118699() +{ + auto dir = __gnu_test::nonexistent_path(); + fs::create_directories(dir/"a"); + fs::create_directories(dir/"c"); + std::ofstream{dir/"a/b.txt"} << "b"; + std::ofstream{dir/"a/bb.txt"} << "bb"; + + fs::copy(dir/"a/b.txt", dir/"c"); + auto ec = make_error_code(std::errc::invalid_argument); + fs::copy(dir/"a/bb.txt", dir/"c", ec); + VERIFY( !ec ); + + remove_all(dir); +} + int main() { @@ -237,4 +254,5 @@ main() test04(); test05(); test_pr99290(); + test_pr118699(); } diff --git a/libstdc++-v3/testsuite/lib/prune.exp b/libstdc++-v3/testsuite/lib/prune.exp index 416e851..a9a2993 100644 --- a/libstdc++-v3/testsuite/lib/prune.exp +++ b/libstdc++-v3/testsuite/lib/prune.exp @@ -77,6 +77,9 @@ proc libstdc++-dg-prune { system text } { # Ignore harmless warnings from Xcode 4+. regsub -all "(^|\n)\[^\n\]*ld: warning: could not create compact unwind for\[^\n\]*" $text "" text + # Ignore duplicate path warnings from Xcode 16+. + regsub -all "(^|\n)\[^\n\]*ld: warning: duplicate -rpath\[^\n\]*" $text "" text + # Ignore dsymutil warning (tool bug is actually in the linker) regsub -all "(^|\n)\[^\n\]*could not find object file symbol for symbol\[^\n\]*" $text "" text diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc index 7fc4201..000f267 100644 --- a/libstdc++-v3/testsuite/std/format/functions/format.cc +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc @@ -501,9 +501,14 @@ test_unicode() { // Similar to sC example in test_std_examples, but not from the standard. // Verify that the character "🤡" has estimated field width 2, - // rather than estimated field width equal to strlen("🤡"), which would be 4. + // rather than estimated field width equal to strlen("🤡"), which would be 4, + // or just width 1 for single character. std::string sC = std::format("{:*<3}", "🤡"); VERIFY( sC == "🤡*" ); + std::wstring wsC = std::format(L"{:*<3}", L"🤡"); + VERIFY( wsC == L"🤡*" ); + wsC = std::format(L"{:*<3}", L'🤡'); + VERIFY( wsC == L"🤡*" ); // Verify that "£" has estimated field width 1, not strlen("£") == 2. std::string sL = std::format("{:*<3}", "£"); diff --git a/libstdc++-v3/testsuite/std/format/string_neg.cc b/libstdc++-v3/testsuite/std/format/string_neg.cc index d596314..09cc9a2 100644 --- a/libstdc++-v3/testsuite/std/format/string_neg.cc +++ b/libstdc++-v3/testsuite/std/format/string_neg.cc @@ -6,5 +6,5 @@ auto s = std::format(" {9} "); // { dg-error "call to consteval function" } // { dg-error "invalid.arg.id" "" { target *-*-* } 0 } struct X { }; -std::format_string<X> str(""); // dg-error "here" } +std::format_string<X> str(""); // { dg-error "here" } // { dg-error "std::formatter must be specialized" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/std/ranges/conv/lwg4229.cc b/libstdc++-v3/testsuite/std/ranges/conv/lwg4229.cc new file mode 100644 index 0000000..780ed1f --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/conv/lwg4229.cc @@ -0,0 +1,18 @@ +// { dg-do compile { target c++23 } } + +// LWG 4229 std::ranges::to with union return type + +#include <ranges> + +union U +{ + template<std::ranges::input_range R> U(std::from_range_t, R&&) { } + + int i; +}; + +void +test_lwg4229(std::ranges::subrange<int*> r) +{ + U u = std::ranges::to<U>(r); +} diff --git a/libstdc++-v3/testsuite/std/time/format/pr119517.cc b/libstdc++-v3/testsuite/std/time/format/pr119517.cc new file mode 100644 index 0000000..37bff86 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/format/pr119517.cc @@ -0,0 +1,43 @@ +// { dg-do compile { target c++23 } } + +#include <chrono> +#include <format> + +static_assert( std::formattable<std::chrono::weekday, char> ); +static_assert( std::formattable<std::chrono::weekday, wchar_t> ); +static_assert( !std::formattable<std::chrono::weekday, char16_t> ); + +static_assert( std::formattable<std::chrono::sys_days, char> ); +static_assert( std::formattable<std::chrono::sys_days, wchar_t> ); +static_assert( !std::formattable<std::chrono::sys_days, char16_t> ); + +static_assert( !std::formattable<std::chrono::seconds, int> ); + +static_assert( !std::formattable<std::chrono::day, int> ); +static_assert( !std::formattable<std::chrono::month, int> ); +static_assert( !std::formattable<std::chrono::year, int> ); +static_assert( !std::formattable<std::chrono::weekday, int> ); +static_assert( !std::formattable<std::chrono::weekday_indexed, int> ); +static_assert( !std::formattable<std::chrono::weekday_last, int> ); +static_assert( !std::formattable<std::chrono::month_day, int> ); +static_assert( !std::formattable<std::chrono::month_day_last, int> ); +static_assert( !std::formattable<std::chrono::month_weekday, int> ); +static_assert( !std::formattable<std::chrono::month_weekday_last, int> ); +static_assert( !std::formattable<std::chrono::year_month_day, int> ); +static_assert( !std::formattable<std::chrono::year_month_day_last, int> ); +static_assert( !std::formattable<std::chrono::year_month_weekday, int> ); +static_assert( !std::formattable<std::chrono::year_month_weekday_last, int> ); +static_assert( !std::formattable<std::chrono::hh_mm_ss<std::chrono::seconds>, int> ); + +static_assert( !std::formattable<std::chrono::sys_seconds, int> ); +static_assert( !std::formattable<std::chrono::utc_seconds, int> ); +static_assert( !std::formattable<std::chrono::tai_seconds, int> ); +static_assert( !std::formattable<std::chrono::gps_seconds, int> ); +static_assert( !std::formattable<std::chrono::local_seconds, int> ); +static_assert( !std::formattable<std::chrono::file_time<std::chrono::seconds>, int> ); +#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI +static_assert( !std::formattable<std::chrono::zoned_seconds, int> ); + +static_assert( !std::formattable<std::chrono::sys_info, int> ); +static_assert( !std::formattable<std::chrono::local_info, int> ); +#endif diff --git a/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc b/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc index 3968be3..fe86602 100644 --- a/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc +++ b/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc @@ -1,7 +1,7 @@ // { dg-do run { target c++20 } } // { dg-require-effective-target tzdb } // { dg-require-effective-target cxx11_abi } -// { dg-require-static-libstdcxx } +// { dg-require-static-libstdcxx "" } // { dg-additional-options "-static-libstdc++" } #include <chrono> |