aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/testsuite')
-rw-r--r--libstdc++-v3/testsuite/17_intro/names.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/constrained.cc30
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_move/constrained.cc29
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc35
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc129
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc7
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc125
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc116
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc130
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc133
-rw-r--r--libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc5
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_map/1.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc22
-rw-r--r--libstdc++-v3/testsuite/23_containers/flat_set/1.cc20
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc6
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc5
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/priority_queue/cons_from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/queue/cons_from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/stack/cons_from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc7
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc6
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/format.cc72
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/capacity/114945.cc36
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc5
-rw-r--r--libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc5
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc57
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/dangling_ref.cc3
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/lwg4154_neg.cc10
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/id/output.cc30
-rw-r--r--libstdc++-v3/testsuite/lib/prune.exp3
-rw-r--r--libstdc++-v3/testsuite/std/format/debug.cc833
-rw-r--r--libstdc++-v3/testsuite/std/format/debug_nonunicode.cc5
-rw-r--r--libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc2
-rw-r--r--libstdc++-v3/testsuite/std/format/formatter/requirements.cc14
-rw-r--r--libstdc++-v3/testsuite/std/format/functions/format.cc19
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/adaptors.cc156
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/feature_test.cc9
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/format_kind.cc94
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc13
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/formatter.cc171
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/map.cc210
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/sequence.cc323
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/string.cc290
-rw-r--r--libstdc++-v3/testsuite/std/format/tuple.cc352
-rw-r--r--libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc13
-rw-r--r--libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/cons/43820_neg.cc3
-rw-r--r--libstdc++-v3/testsuite/util/debug/unordered_checks.h152
-rw-r--r--libstdc++-v3/testsuite/util/replacement_memory_operators.h8
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.cc4
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_iterators.h7
98 files changed, 4151 insertions, 104 deletions
diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc
index 4458325..f67818d 100644
--- a/libstdc++-v3/testsuite/17_intro/names.cc
+++ b/libstdc++-v3/testsuite/17_intro/names.cc
@@ -142,6 +142,10 @@
#define try_emplace (
#endif
+#if __cplusplus < 202002L
+#define ranges (
+#endif
+
// These clash with newlib so don't use them.
# define __lockable cannot be used as an identifier
# define __null_sentinel cannot be used as an identifier
diff --git a/libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc b/libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc
index 7f6cefa..a079d98 100644
--- a/libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc
+++ b/libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc
@@ -4,7 +4,7 @@
#ifndef __cpp_lib_constrained_equality
# error "Feature-test macro for constrained_equality missing in <expected>"
-#elif __cpp_lib_constrained_equality < 202411L // TODO: use final value
+#elif __cpp_lib_constrained_equality < 202411L
# error "Feature-test macro for constrained_equality has wrong value"
#endif
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 af3b733..5dff0da 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
@@ -178,12 +178,40 @@ test03()
void
test_pr101587()
{
- short in[1];
+ 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());
+
+ // iterator that has an integer-like class type for difference_type
+ struct Iter
+ {
+ using value_type = long;
+ using difference_type = std::ranges::__detail::__max_diff_type;
+
+ long& operator*() const { return *p; }
+
+ Iter& operator++() { ++p; return *this; }
+ Iter operator++(int) { return Iter{p++}; }
+
+ difference_type operator-(Iter i) const { return p - i.p; }
+ bool operator==(const Iter&) const = default;
+
+ long* p = nullptr;
+ };
+ static_assert(std::sized_sentinel_for<Iter, Iter>);
+
+ std::ranges::subrange<Iter> rmax(Iter{out+0}, Iter{out+1});
+ // Check with integer-like class type for output range:
+ std::ranges::uninitialized_copy(in, rmax);
+ std::ranges::uninitialized_copy_n(in+0, 1, rmax.begin(), rmax.end());
+
+ int to[1];
+ // And for input range:
+ std::ranges::uninitialized_copy(rmax, to);
+ std::ranges::uninitialized_copy_n(rmax.begin(), 1, to+0, to+1);
}
int
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 fe82d1f1..3e81244 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
@@ -188,12 +188,39 @@ test03()
void
test_pr101587()
{
- short in[1];
+ 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());
+
+ struct Iter
+ {
+ using value_type = long;
+ using difference_type = std::ranges::__detail::__max_diff_type;
+
+ long& operator*() const { return *p; }
+
+ Iter& operator++() { ++p; return *this; }
+ Iter operator++(int) { return Iter{p++}; }
+
+ difference_type operator-(Iter i) const { return p - i.p; }
+ bool operator==(const Iter&) const = default;
+
+ long* p = nullptr;
+ };
+ static_assert(std::sized_sentinel_for<Iter, Iter>);
+
+ std::ranges::subrange<Iter> rmax(Iter{out+0}, Iter{out+1});
+ // Check with integer-like class type for output range:
+ std::ranges::uninitialized_move(in, rmax);
+ std::ranges::uninitialized_move_n(in+0, 1, rmax.begin(), rmax.end());
+
+ int to[1];
+ // And for input range:
+ std::ranges::uninitialized_copy(rmax, to);
+ std::ranges::uninitialized_copy_n(rmax.begin(), 1, to+0, to+1);
}
int
diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc
index 48628a9..18d47d2 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc
@@ -61,4 +61,4 @@ test03()
// { dg-error "tuple index must be in range" "" { target *-*-* } 0 }
// { dg-prune-output "no type named 'type' in .*_Nth_type" }
-// { dg-prune-output "pack index is out of range" }
+// { dg-prune-output "pack index '.' is out of range" }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
new file mode 100644
index 0000000..301ca5d
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
@@ -0,0 +1,35 @@
+// { dg-do compile }
+
+// Bug 119748
+// string(InputIterator, InputIterator) rejects volatile charT* as iterator
+
+#ifndef TEST_CHAR_TYPE
+#define TEST_CHAR_TYPE char
+#endif
+
+#include <string>
+#include <testsuite_iterators.h>
+
+typedef TEST_CHAR_TYPE C;
+
+volatile C vs[42] = {};
+std::basic_string<C> s(vs+0, vs+42);
+#ifdef __cpp_lib_containers_ranges
+std::basic_string<C> s2(std::from_range, vs);
+#endif
+
+using namespace __gnu_test;
+
+test_container<volatile C, input_iterator_wrapper> input_cont(vs);
+std::basic_string<C> s3(input_cont.begin(), input_cont.end());
+
+test_container<volatile C, forward_iterator_wrapper> fwd_cont(vs);
+std::basic_string<C> s4(fwd_cont.begin(), fwd_cont.end());
+
+#ifdef __cpp_lib_containers_ranges
+test_input_range<volatile C> input_range(vs);
+std::basic_string<C> s5(std::from_range, input_range);
+
+test_forward_range<volatile C> fwd_range(vs);
+std::basic_string<C> s6(std::from_range, fwd_range);
+#endif
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc
new file mode 100644
index 0000000..6331050
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/from_range.cc
@@ -0,0 +1,129 @@
+// { dg-do run { target c++23 } }
+
+#include <string>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <string>"
+#endif
+
+#include <span>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
+
+void
+test_deduction_guide(char* p)
+{
+ __gnu_test::test_input_range<char> r(nullptr, nullptr);
+ std::basic_string v(std::from_range, r);
+ static_assert(std::is_same_v<decltype(v), std::string>);
+
+ using Alloc = __gnu_test::SimpleAllocator<char>;
+ Alloc alloc;
+ std::basic_string v2(std::from_range, r, alloc);
+ static_assert(std::is_same_v<decltype(v2), std::basic_string<char, std::char_traits<char>, Alloc>>);
+
+ __gnu_test::test_input_range<wchar_t> wr(nullptr, nullptr);
+ std::basic_string w(std::from_range, wr);
+ static_assert(std::is_same_v<decltype(w), std::wstring>);
+
+ using WAlloc = __gnu_test::SimpleAllocator<wchar_t>;
+ WAlloc walloc;
+ std::basic_string w2(std::from_range, wr, walloc);
+ static_assert(std::is_same_v<decltype(w2), std::basic_string<wchar_t, std::char_traits<wchar_t>, WAlloc>>);
+}
+
+template<typename Range, typename Alloc>
+constexpr void
+do_test(Alloc alloc)
+{
+ // The basic_string's value_type.
+ using V = typename std::allocator_traits<Alloc>::value_type;
+ using CT = std::char_traits<V>;
+
+ // The range's value_type.
+ using T = std::ranges::range_value_t<Range>;
+ T a[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
+
+ auto eq = [](const std::basic_string<V, CT, 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::basic_string<V, CT, Alloc> v0(std::from_range, Range(a, a+0));
+ VERIFY( v0.empty() );
+ VERIFY( v0.get_allocator() == Alloc() );
+
+ std::basic_string<V, CT, Alloc> v4(std::from_range, Range(a, a+4));
+ VERIFY( eq(v4, {a, 4}) );
+ VERIFY( v4.get_allocator() == Alloc() );
+
+ std::basic_string<V, CT, Alloc> v9(std::from_range, Range(a, a+9), alloc);
+ VERIFY( eq(v9, {a, 9}) );
+ VERIFY( v9.get_allocator() == alloc );
+
+ std::basic_string<V, CT, Alloc> v20(std::from_range, Range(a, a+20), alloc);
+ VERIFY( eq(v20, {a, 20}) );
+ VERIFY( v20.get_allocator() == alloc );
+}
+
+template<typename Range>
+void
+do_test_a()
+{
+ do_test<Range>(std::allocator<char>());
+ do_test<Range>(__gnu_test::uneq_allocator<char>(42));
+ do_test<Range>(std::allocator<wchar_t>());
+ do_test<Range>(__gnu_test::uneq_allocator<wchar_t>(42));
+}
+
+bool
+test_ranges()
+{
+ using namespace __gnu_test;
+
+ do_test_a<test_forward_range<char>>();
+ do_test_a<test_forward_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, forward_iterator_wrapper>>();
+
+ do_test_a<test_input_range<char>>();
+ do_test_a<test_input_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper>>();
+
+ do_test_a<test_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper_nocopy>>();
+
+ // Not lvalue-convertible to char
+ struct C {
+ C(char v) : val(v) { }
+ operator char() && { return val; }
+ bool operator==(char b) const { return b == val; }
+ char val;
+ };
+ using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
+ do_test<rvalue_input_range>(std::allocator<char>());
+
+ return true;
+}
+
+constexpr bool
+test_constexpr()
+{
+#if _GLIBCXX_USE_CXX11_ABI
+ // XXX: this doesn't test the non-forward_range code paths are constexpr.
+ do_test<std::string_view>(std::allocator<char>());
+#endif // _GLIBCXX_USE_CXX11_ABI
+ return true;
+}
+
+int main()
+{
+ test_ranges();
+ static_assert( test_constexpr() );
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
new file mode 100644
index 0000000..7d3ba10
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc
@@ -0,0 +1,7 @@
+// { dg-do compile }
+
+// Bug 119748
+// string(InputIterator, InputIterator) rejects volatile charT* as iterator
+
+#define TEST_CHAR_TYPE wchar_t
+#include "../char/119748.cc"
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc
new file mode 100644
index 0000000..6c0bc0c
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/append_range.cc
@@ -0,0 +1,125 @@
+// { dg-do run { target c++23 } }
+
+#include <span>
+#include <string>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename Range, typename Alloc>
+constexpr void
+do_test()
+{
+ // The vector's value_type.
+ using V = typename std::allocator_traits<Alloc>::value_type;
+ using CT = std::char_traits<V>;
+
+ // The range's value_type.
+ using T = std::ranges::range_value_t<Range>;
+ T a[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
+
+ auto eq = [](const std::basic_string<V, CT, 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;
+ };
+
+ Range r4(a, a+4);
+ Range r5(a+4, a+9);
+ Range r11(a+9, a+20);
+
+ std::basic_string<V, CT, Alloc> v;
+ v.append_range(r4);
+ VERIFY( eq(v, {a, 4}) );
+ v.append_range(r5);
+ VERIFY( eq(v, {a, 9}) );
+
+ std::basic_string<V, CT, Alloc> const s = v;
+ v.append_range(r11);
+ VERIFY( eq(v, a) );
+ v.append_range(Range(a, a));
+ VERIFY( eq(v, a) );
+ v.clear();
+ v.append_range(Range(a, a));
+ VERIFY( v.empty() );
+}
+
+template<typename Range>
+void
+do_test_a()
+{
+ do_test<Range, std::allocator<char>>();
+ do_test<Range, __gnu_test::SimpleAllocator<char>>();
+ do_test<Range, std::allocator<wchar_t>>();
+ do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
+}
+
+bool
+test_ranges()
+{
+ using namespace __gnu_test;
+
+ do_test_a<test_forward_range<char>>();
+ do_test_a<test_forward_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, forward_iterator_wrapper>>();
+
+ do_test_a<test_input_range<char>>();
+ do_test_a<test_input_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper>>();
+
+ do_test_a<test_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper_nocopy>>();
+
+ // Not lvalue-convertible to char
+ struct C {
+ C(char v) : val(v) { }
+ operator char() && { return val; }
+ bool operator==(char b) const { return b == val; }
+ char val;
+ };
+ using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
+ do_test<rvalue_input_range, std::allocator<char>>();
+
+ return true;
+}
+
+void
+test_overlapping()
+{
+ std::string const s = "1234abcd";
+
+ std::string c = s;
+ c.append_range(std::string_view(c));
+ VERIFY( c == "1234abcd1234abcd" );
+
+ c = s;
+ c.append_range(std::string_view(c).substr(4, 4));
+ VERIFY( c == "1234abcdabcd" );
+
+ c = s;
+ c.reserve(12);
+ c.append_range(std::string_view(c).substr(0, 4));
+ VERIFY( c == "1234abcd1234" );
+}
+
+constexpr bool
+test_constexpr()
+{
+#if _GLIBCXX_USE_CXX11_ABI
+ // XXX: this doesn't test the non-forward_range code paths are constexpr.
+ do_test<std::string_view, std::allocator<char>>();
+#endif // _GLIBCXX_USE_CXX11_ABI
+ return true;
+}
+
+int main()
+{
+ test_ranges();
+ test_overlapping();
+ static_assert( test_constexpr() );
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc
new file mode 100644
index 0000000..310c8bc
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/assign_range.cc
@@ -0,0 +1,116 @@
+// { dg-do run { target c++23 } }
+
+#include <vector>
+#include <span>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <testsuite_allocator.h>
+
+template<typename Range, typename Alloc>
+constexpr void
+do_test()
+{
+ // The vector's value_type.
+ using V = typename std::allocator_traits<Alloc>::value_type;
+ using CT = std::char_traits<V>;
+
+ // The range's value_type.
+ using T = std::ranges::range_value_t<Range>;
+ T a[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
+
+ auto eq = [](const std::basic_string<V, CT, 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::basic_string<V, CT, Alloc> v;
+ v.assign_range(Range(a, a));
+ VERIFY( v.empty() );
+ v.assign_range(Range(a, a+4));
+ VERIFY( eq(v, {a, 4}) );
+ v.assign_range(Range(a, a+9));
+ VERIFY( eq(v, {a, 9}) );
+ std::basic_string<V, CT, Alloc> const s = v;
+ v.assign_range(Range(a, a+20));
+ VERIFY( eq(v, {a, 20}) );
+}
+
+template<typename Range>
+void
+do_test_a()
+{
+ do_test<Range, std::allocator<char>>();
+ do_test<Range, __gnu_test::SimpleAllocator<char>>();
+ do_test<Range, std::allocator<wchar_t>>();
+ do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
+}
+
+bool
+test_ranges()
+{
+ using namespace __gnu_test;
+
+ do_test_a<test_forward_range<char>>();
+ do_test_a<test_forward_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, forward_iterator_wrapper>>();
+
+ do_test_a<test_input_range<char>>();
+ do_test_a<test_input_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper>>();
+
+ do_test_a<test_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper_nocopy>>();
+
+ // Not lvalue-convertible to char
+ struct C {
+ C(char v) : val(v) { }
+ operator char() && { return val; }
+ bool operator==(char b) const { return b == val; }
+ char val;
+ };
+ using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
+ do_test<rvalue_input_range, std::allocator<char>>();
+
+ return true;
+}
+
+void
+test_overlapping()
+{
+ std::string const s = "1234abcd";
+
+ std::string c = s;
+ c.assign_range(std::string_view(c));
+ VERIFY( c == "1234abcd" );
+
+ c = s;
+ c.assign_range(std::string_view(c).substr(4, 4));
+ VERIFY( c == "abcd" );
+
+ c = s;
+ c.assign_range(std::string_view(c).substr(0, 4));
+ VERIFY( c == "1234" );
+}
+
+constexpr bool
+test_constexpr()
+{
+#if _GLIBCXX_USE_CXX11_ABI
+ // XXX: this doesn't test the non-forward_range code paths are constexpr.
+ do_test<std::string_view, std::allocator<char>>();
+#endif // _GLIBCXX_USE_CXX11_ABI
+ return true;
+}
+
+int main()
+{
+ test_ranges();
+ test_overlapping();
+ static_assert( test_constexpr() );
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc
new file mode 100644
index 0000000..4fead32
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/insert/insert_range.cc
@@ -0,0 +1,130 @@
+// { dg-do run { target c++23 } }
+
+#include <span>
+#include <string>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename Range, typename Alloc>
+constexpr void
+do_test()
+{
+ // The vector's value_type.
+ using V = typename std::allocator_traits<Alloc>::value_type;
+ using CT = std::char_traits<V>;
+
+ // The range's value_type.
+ using T = std::ranges::range_value_t<Range>;
+ T a[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
+
+ auto eq = [](const std::basic_string<V, CT, 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::basic_string<V, CT, Alloc> v;
+ auto it = v.insert_range(v.end(), Range(a, a));
+ VERIFY( v.empty() );
+ VERIFY( it == v.begin() );
+ it = v.insert_range(v.end(), Range(a, a+4));
+ VERIFY( eq(v, {a, 4}) );
+ VERIFY( it == v.begin() );
+ it = v.insert_range(v.end(), Range(a+4, a+9));
+ VERIFY( eq(v, {a, 9}) );
+ VERIFY( it == v.begin()+4 );
+
+ std::basic_string<V, CT, Alloc> s = v;
+ it = v.insert_range(v.end(), Range(a+9, a+20));
+ VERIFY( eq(v, {a, 20}) );
+ VERIFY( it == v.begin()+9 );
+
+ v = std::basic_string<V, CT, Alloc>();
+ it = v.insert_range(v.begin(), Range(a, a+5));
+ VERIFY( it == v.begin() );
+ s = v;
+ it = v.insert_range(v.begin() + 5, Range(a+5, a+20));
+ VERIFY( eq(v, {a, 20}) );
+ VERIFY( it == v.begin()+5 );
+}
+
+template<typename Range>
+void
+do_test_a()
+{
+ do_test<Range, std::allocator<char>>();
+ do_test<Range, __gnu_test::SimpleAllocator<char>>();
+ do_test<Range, std::allocator<wchar_t>>();
+ do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
+}
+
+bool
+test_ranges()
+{
+ using namespace __gnu_test;
+
+ do_test_a<test_forward_range<char>>();
+ do_test_a<test_forward_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, forward_iterator_wrapper>>();
+
+ do_test_a<test_input_range<char>>();
+ do_test_a<test_input_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper>>();
+
+ do_test_a<test_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper_nocopy>>();
+
+ // Not lvalue-convertible to char
+ struct C {
+ C(char v) : val(v) { }
+ operator char() && { return val; }
+ bool operator==(char b) const { return b == val; }
+ char val;
+ };
+ using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
+ do_test<rvalue_input_range, std::allocator<char>>();
+
+ return true;
+}
+
+void
+test_overlapping()
+{
+ std::string const s = "1234abcd";
+
+ std::string c = s;
+ c.insert_range(c.end(), std::string_view(c));
+ VERIFY( c == "1234abcd1234abcd" );
+
+ c = s;
+ c.insert_range(c.begin()+4, std::string_view(c).substr(4, 4));
+ VERIFY( c == "1234abcdabcd" );
+
+ c = s;
+ c.reserve(12);
+ c.insert_range(c.begin()+2, std::string_view(c).substr(0, 4));
+ VERIFY( c == "12123434abcd" );
+}
+
+constexpr bool
+test_constexpr()
+{
+#if _GLIBCXX_USE_CXX11_ABI
+ // XXX: this doesn't test the non-forward_range code paths are constexpr.
+ do_test<std::string_view, std::allocator<char>>();
+#endif // _GLIBCXX_USE_CXX11_ABI
+ return true;
+}
+
+int main()
+{
+ test_ranges();
+ test_overlapping();
+ static_assert( test_constexpr() );
+}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc
new file mode 100644
index 0000000..9acf11a
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/replace_with_range.cc
@@ -0,0 +1,133 @@
+// { dg-do run { target c++23 } }
+
+#include <span>
+#include <string>
+#include <testsuite_allocator.h>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+template<typename Range, typename Alloc>
+constexpr void
+do_test()
+{
+ // The vector's value_type.
+ using V = typename std::allocator_traits<Alloc>::value_type;
+ using CT = std::char_traits<V>;
+
+ // The range's value_type.
+ using T = std::ranges::range_value_t<Range>;
+ T a[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
+
+ auto eq = [](const std::basic_string<V, CT, 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::basic_string<V, CT, Alloc> v;
+ v.replace_with_range(v.end(), v.end(), Range(a, a));
+ VERIFY( v.empty() );
+ v.replace_with_range(v.end(), v.end(), Range(a, a+4));
+ VERIFY( eq(v, {a, 4}) );
+ v.replace_with_range(v.end(), v.end(), Range(a+4, a+9));
+ VERIFY( eq(v, {a, 9}) );
+ std::basic_string<V, CT, Alloc> s = v;
+ v.replace_with_range(v.end(), v.end(), Range(a+9, a+20));
+ VERIFY( eq(v, {a, 20}) );
+
+ v.replace_with_range(v.begin()+10, v.begin()+20, Range(a+5, a+10));
+ VERIFY( v.size() == 15 );
+ v.replace_with_range(v.begin(), v.begin()+10, Range(a, a+5));
+ VERIFY( eq(v, {a, 10}) );
+
+ s = v;
+ v.replace_with_range(v.begin(), v.begin()+4, Range(a, a+8));
+ VERIFY( v.size() == 14 );
+ v.replace_with_range(v.begin()+8, v.begin()+12, Range(a+8, a+16));
+ VERIFY( v.size() == 18 );
+ v.replace_with_range(v.begin()+16, v.begin()+18, Range(a+16, a+20));
+ VERIFY( eq(v, {a, 20}) );
+}
+
+template<typename Range>
+void
+do_test_a()
+{
+ do_test<Range, std::allocator<char>>();
+ do_test<Range, __gnu_test::SimpleAllocator<char>>();
+ do_test<Range, std::allocator<wchar_t>>();
+ do_test<Range, __gnu_test::SimpleAllocator<wchar_t>>();
+}
+
+bool
+test_ranges()
+{
+ using namespace __gnu_test;
+
+ do_test_a<test_forward_range<char>>();
+ do_test_a<test_forward_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, forward_iterator_wrapper>>();
+
+ do_test_a<test_input_range<char>>();
+ do_test_a<test_input_sized_range<char>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper>>();
+
+ do_test_a<test_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range<char, input_iterator_wrapper_nocopy>>();
+ do_test_a<test_sized_range_sized_sent<char, input_iterator_wrapper_nocopy>>();
+
+ // Not lvalue-convertible to char
+ struct C {
+ C(char v) : val(v) { }
+ operator char() && { return val; }
+ bool operator==(char b) const { return b == val; }
+ char val;
+ };
+ using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
+ do_test<rvalue_input_range, std::allocator<char>>();
+
+ return true;
+}
+
+void
+test_overlapping()
+{
+ std::string const s = "1234abcd";
+
+ std::string c = s;
+ c.replace_with_range(c.end(), c.end(), std::string_view(c));
+ VERIFY( c == "1234abcd1234abcd" );
+
+ c = s;
+ c.replace_with_range(c.begin(), c.begin()+4, std::string_view(c).substr(4, 4));
+ VERIFY( c == "abcdabcd" );
+
+ c = s;
+ c.replace_with_range(c.begin()+2, c.begin()+4, std::string_view(c).substr(0, 4));
+ VERIFY( c == "121234abcd" );
+
+ c = s;
+ c.replace_with_range(c.begin()+2, c.begin()+2, std::string_view(c).substr(0, 4));
+ VERIFY( c == "12123434abcd" );
+}
+
+constexpr bool
+test_constexpr()
+{
+#if _GLIBCXX_USE_CXX11_ABI
+ // XXX: this doesn't test the non-forward_range code paths are constexpr.
+ do_test<std::string_view, std::allocator<char>>();
+#endif // _GLIBCXX_USE_CXX11_ABI
+ return true;
+}
+
+int main()
+{
+ test_ranges();
+ test_overlapping();
+ static_assert( test_constexpr() );
+}
diff --git a/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc b/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc
index a34b2ae..24aba99 100644
--- a/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc
+++ b/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc
@@ -18,7 +18,6 @@
// <http://www.gnu.org/licenses/>.
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 0 }
-// { dg-error "invalid 'static_cast'" "" { target c++98_only } 0 }
#include <locale>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
index 7cb6707..4dbf405 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
@@ -1,4 +1,6 @@
// { dg-do run { target c++11 } }
+// { dg-require-effective-target std_allocator_new }
+// { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } }
// 2010-01-08 Paolo Carlini <paolo.carlini@oracle.com>
@@ -19,18 +21,42 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#include <vector>
+#include <deque>
#include <testsuite_hooks.h>
+#include <replacement_memory_operators.h>
// libstdc++/42573
void test01()
{
- std::vector<int> d(100);
- d.push_back(1);
- d.push_back(1);
- // VERIFY( d.size() < d.capacity() );
+ using namespace std;
+ __gnu_test::counter::reset();
+
+ const size_t buf_size = _GLIBCXX_STD_C::__deque_buf_size(sizeof(size_t));
+ deque<size_t> d;
+ for (size_t i = 0; i != buf_size; ++i)
+ d.push_back(i);
+
+ // No shrink if 1st buffer is full, create some front capacity.
+ d.pop_front();
+
+ // 1 node array allocation + 2 node allocation = 3.
+ VERIFY( __gnu_test::counter::count() == 3 );
+ VERIFY( __gnu_test::counter::get()._M_increments == 3 );
+
d.shrink_to_fit();
- // VERIFY( d.size() == d.capacity() );
+
+ // No reallocation if no exception support, shrink_to_fit is then a
+ // no-op.
+#if __cpp_exceptions
+ // 1 node array allocation + 1 node allocation = 2.
+ const int expected_count = 2;
+ const int expected_increments = 2;
+#else
+ const int expected_count = 3;
+ const int expected_increments = 0;
+#endif
+ VERIFY( __gnu_test::counter::count() == expected_count );
+ VERIFY( __gnu_test::counter::get()._M_increments == 3 + expected_increments );
}
int main()
diff --git a/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc
index 96e994d..48fd196 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/cons/from_range.cc
@@ -1,6 +1,11 @@
// { dg-do run { target c++23 } }
#include <deque>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <deque>"
+#endif
+
#include <span>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
index d9d88c4..4fd33f6 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
@@ -1,4 +1,5 @@
// { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
#include <flat_map>
diff --git a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
index ff180bf..ea0d4b4 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
@@ -1,4 +1,5 @@
// { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
#include <flat_map>
#include <deque>
diff --git a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc
index dc3cecd..7d9a33c 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc
@@ -214,6 +214,27 @@ void test07()
#endif
}
+void
+test08()
+{
+ // PR libstdc++/119620 -- flat_set::emplace always constructs element on the stack
+ static int copy_counter;
+ struct A {
+ A() { }
+ A(const A&) { ++copy_counter; }
+ A& operator=(const A&) { ++copy_counter; return *this; }
+ auto operator<=>(const A&) const = default;
+ };
+ std::vector<A> v;
+ v.reserve(2);
+ std::flat_multiset<A> s(std::move(v));
+ A a;
+ s.emplace(a);
+ VERIFY( copy_counter == 1 );
+ s.emplace(a);
+ VERIFY( copy_counter == 2 );
+}
+
int
main()
{
@@ -225,4 +246,5 @@ main()
test05();
test06();
test07();
+ test08();
}
diff --git a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc
index 90f5855..ed24fab 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc
@@ -229,6 +229,25 @@ void test07()
#endif
}
+void
+test08()
+{
+ // PR libstdc++/119620 -- flat_set::emplace always constructs element on the stack
+ static int copy_counter;
+ struct A {
+ A() { }
+ A(const A&) { ++copy_counter; }
+ A& operator=(const A&) { ++copy_counter; return *this; }
+ auto operator<=>(const A&) const = default;
+ };
+ std::flat_set<A> s;
+ A a;
+ s.emplace(a);
+ VERIFY( copy_counter == 1 );
+ s.emplace(a);
+ VERIFY( copy_counter == 1 );
+}
+
int
main()
{
@@ -240,4 +259,5 @@ main()
test05();
test06();
test07();
+ test08();
}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc
index 2f2ea2a..d18195e 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc
@@ -26,6 +26,5 @@ test01()
}
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
// { dg-prune-output "rebind_alloc" }
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc
index 65b378e..aa70105 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc
@@ -1,11 +1,15 @@
// { dg-do run { target c++23 } }
#include <forward_list>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <forward_list>"
+#endif
+
#include <span>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
#include <testsuite_allocator.h>
-
void
test_deduction_guide(long* p)
{
diff --git a/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc
index 8b2e075..cc51705 100644
--- a/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc
@@ -26,5 +26,4 @@ test01()
}
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
diff --git a/libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc
index 31448b9..107ad74 100644
--- a/libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc
@@ -1,6 +1,11 @@
// { dg-do run { target c++23 } }
#include <list>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <list>"
+#endif
+
#include <span>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc
index c740471..9935f44 100644
--- a/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <map>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <map>"
+#endif
+
+#include <algorithm>
#include <ranges>
#include <span>
#include <testsuite_allocator.h>
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc
index 3e456f5..4a8ea9f 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <map>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <map>"
+#endif
+
+#include <algorithm>
#include <ranges>
#include <span>
#include <testsuite_allocator.h>
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc
index f0786cf..3cc0658 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc
@@ -29,7 +29,6 @@ test01()
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
// { dg-error "comparison object must be invocable" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
// { dg-prune-output "no match for call" }
// { dg-prune-output "invalid conversion" }
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/multiset/cons/from_range.cc
index 43821ca..cdba7eb 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/from_range.cc
@@ -1,8 +1,13 @@
// { dg-do run { target c++23 } }
+#include <set>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <set>"
+#endif
+
#include <algorithm>
#include <ranges>
-#include <set>
#include <span>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/cons_from_range.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/cons_from_range.cc
index 977ef98..87e404b 100644
--- a/libstdc++-v3/testsuite/23_containers/priority_queue/cons_from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/cons_from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <queue>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <queue>"
+#endif
+
+#include <algorithm>
#include <ranges>
#include <span>
#include <testsuite_allocator.h>
diff --git a/libstdc++-v3/testsuite/23_containers/queue/cons_from_range.cc b/libstdc++-v3/testsuite/23_containers/queue/cons_from_range.cc
index c21f52c..039d084 100644
--- a/libstdc++-v3/testsuite/23_containers/queue/cons_from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/queue/cons_from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <list>
#include <queue>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <queue>"
+#endif
+
+#include <list>
#include <span>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc
index e8dec72..fe38d1a 100644
--- a/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc
@@ -29,7 +29,6 @@ test01()
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
// { dg-error "comparison object must be invocable" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
// { dg-prune-output "no match for call" }
// { dg-prune-output "invalid conversion" }
diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/set/cons/from_range.cc
index 869326f..efde05d 100644
--- a/libstdc++-v3/testsuite/23_containers/set/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/cons/from_range.cc
@@ -1,8 +1,13 @@
// { dg-do run { target c++23 } }
+#include <set>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <set>"
+#endif
+
#include <algorithm>
#include <ranges>
-#include <set>
#include <span>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/23_containers/stack/cons_from_range.cc b/libstdc++-v3/testsuite/23_containers/stack/cons_from_range.cc
index e957d0c..2ee52e1 100644
--- a/libstdc++-v3/testsuite/23_containers/stack/cons_from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/stack/cons_from_range.cc
@@ -1,8 +1,13 @@
// { dg-do run { target c++23 } }
+#include <stack>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <span>"
+#endif
+
#include <ranges>
#include <span>
-#include <stack>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
index 6d1da5b..36efc2d 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <unordered_map>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <unordered_map>"
+#endif
+
+#include <algorithm>
#include <span>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc
new file mode 100644
index 0000000..09870a7
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_arrow_operator
+ <std::unordered_map<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc
new file mode 100644
index 0000000..7bfe3a8
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_const_conversion
+ <std::unordered_map<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc
new file mode 100644
index 0000000..d3b671b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_assignment
+ <std::unordered_map<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc
new file mode 100644
index 0000000..d609671
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_construction
+ <std::unordered_map<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc
new file mode 100644
index 0000000..8d2ed6b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_assignment
+ <std::unordered_map<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc
new file mode 100644
index 0000000..dd9b7dc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_construction
+ <std::unordered_map<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc
index 7fbc453..2596798 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc
@@ -22,7 +22,7 @@
void test01()
{
- std::unordered_multimap<int, int> um;
+ std::unordered_map<int, int> um;
um.max_load_factor(-1.0f);
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
index 2ca93d3..b551df4 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <unordered_map>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <unordered_map>"
+#endif
+
+#include <algorithm>
#include <ranges>
#include <span>
#include <testsuite_allocator.h>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc
index ff787cf..b2d67fb 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc
@@ -22,8 +22,8 @@
void test01()
{
- std::unordered_map<int, int> um;
- const std::unordered_map<int, int>& cum = um;
+ std::unordered_multimap<int, int> um;
+ const std::unordered_multimap<int, int>& cum = um;
cum.begin(um.bucket_count());
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc
index b5ddb18..4d5cb84 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc
@@ -22,7 +22,7 @@
void test01()
{
- std::unordered_map<int, int> um;
+ std::unordered_multimap<int, int> um;
um.bucket_size(um.bucket_count());
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc
index 5ba1da5..654d409 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc
@@ -22,7 +22,7 @@
void test01()
{
- std::unordered_map<int, int> um;
+ std::unordered_multimap<int, int> um;
um.cbegin(um.bucket_count());
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc
index 031be37..f7149d4 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc
@@ -22,7 +22,7 @@
void test01()
{
- std::unordered_map<int, int> um;
+ std::unordered_multimap<int, int> um;
um.cend(um.bucket_count());
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc
index d412fcf..fd0f981 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc
@@ -22,7 +22,7 @@
void test01()
{
- std::unordered_map<int, int> um;
+ std::unordered_multimap<int, int> um;
um.end(um.bucket_count());
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc
index 0115351..0c3f86c 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc
@@ -22,8 +22,8 @@
void test01()
{
- std::unordered_map<int, int> um;
- const std::unordered_map<int, int>& cum = um;
+ std::unordered_multimap<int, int> um;
+ const std::unordered_multimap<int, int>& cum = um;
cum.end(um.bucket_count());
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc
new file mode 100644
index 0000000..8b23020
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_arrow_operator
+ <std::unordered_multimap<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc
new file mode 100644
index 0000000..62c0280
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_const_conversion
+ <std::unordered_multimap<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc
new file mode 100644
index 0000000..9ac5b35
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_assignment
+ <std::unordered_multimap<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc
new file mode 100644
index 0000000..4140272
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_construction
+ <std::unordered_multimap<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc
new file mode 100644
index 0000000..32c847c
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_assignment
+ <std::unordered_multimap<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc
new file mode 100644
index 0000000..124b9ec
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_map>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_construction
+ <std::unordered_multimap<int, int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc
index 2596798..7fbc453 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc
@@ -22,7 +22,7 @@
void test01()
{
- std::unordered_map<int, int> um;
+ std::unordered_multimap<int, int> um;
um.max_load_factor(-1.0f);
}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
index 45c3848..d44598d 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <unordered_set>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <unordered_set>"
+#endif
+
+#include <algorithm>
#include <ranges>
#include <span>
#include <testsuite_allocator.h>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc
new file mode 100644
index 0000000..1677b20
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_arrow_operator
+ <std::unordered_multiset<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc
new file mode 100644
index 0000000..0d64a41
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_const_conversion
+ <std::unordered_multiset<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc
new file mode 100644
index 0000000..b0d7b9f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_assignment
+ <std::unordered_multiset<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc
new file mode 100644
index 0000000..fa9c5ee
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_construction
+ <std::unordered_multiset<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc
new file mode 100644
index 0000000..b25fedc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_assignment
+ <std::unordered_multiset<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc
new file mode 100644
index 0000000..8b855b2
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_construction
+ <std::unordered_multiset<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc
index 0806045..8259be8 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc
@@ -1,7 +1,12 @@
// { dg-do run { target c++23 } }
-#include <algorithm>
#include <unordered_set>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <unordered_set>"
+#endif
+
+#include <algorithm>
#include <span>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc
new file mode 100644
index 0000000..f62ed6b
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_arrow_operator
+ <std::unordered_set<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc
new file mode 100644
index 0000000..839f9ae
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_const_conversion
+ <std::unordered_set<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc
new file mode 100644
index 0000000..377019f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_assignment
+ <std::unordered_set<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc
new file mode 100644
index 0000000..1f7e6dd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_copy_construction
+ <std::unordered_set<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc
new file mode 100644
index 0000000..d16a154
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_assignment
+ <std::unordered_set<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc
new file mode 100644
index 0000000..d878abf
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc
@@ -0,0 +1,17 @@
+// { dg-do run { target c++11 xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <unordered_set>
+#include <debug/unordered_checks.h>
+
+void test01()
+{
+ __gnu_test::invalid_local_iterator_move_construction
+ <std::unordered_set<int>>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
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 37f0ecf..339c06bd 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
@@ -1,5 +1,11 @@
// { dg-do run { target c++23 } }
+#include <unordered_set>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <unordered_set>"
+#endif
+
#include <vector>
#include <span>
#include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc
new file mode 100644
index 0000000..eb24b66
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc
@@ -0,0 +1,72 @@
+// { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
+
+#include <format>
+#include <vector>
+#include <testsuite_hooks.h>
+
+static_assert(!std::formattable<std::vector<bool>::reference, int>);
+static_assert(!std::formattable<std::vector<bool>::reference, char32_t>);
+
+template<typename... Args>
+bool
+is_format_string_for(const char* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_format_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+void
+test_format_string()
+{
+ std::vector<bool> v(1, true);
+ VERIFY( !is_format_string_for("{:?}", v[0]) );
+ VERIFY( !is_format_string_for("{:P}", v[0]) );
+
+ // width needs to be integer type
+ VERIFY( !is_format_string_for("{:{}}", v[0], 1.0f) );
+}
+
+template<typename _CharT>
+void
+test_output()
+{
+ std::basic_string<_CharT> res;
+ size_t size = 0;
+ std::vector<bool> v{true, false};
+
+ res = std::format(WIDEN("{}"), v[0]);
+ VERIFY( res == WIDEN("true") );
+
+ res = std::format(WIDEN("{:s}"), v[1]);
+ VERIFY( res == WIDEN("false") );
+
+ res = std::format(WIDEN("{:d} {:#B} {:#o} {:#x}"), v[0], v[1], v[0], v[1]);
+ VERIFY( res == WIDEN("1 0B0 01 0x0") );
+
+ res = std::format(WIDEN("{:{}}"), v[0], 6);
+ VERIFY( res == WIDEN("true ") );
+
+ res = std::format(WIDEN("{:=^#7X}"), v[1]);
+ VERIFY( res == WIDEN("==0X0==") );
+
+ res = std::format(WIDEN("{}"), v);
+ VERIFY( res == WIDEN("[true, false]") );
+
+ res = std::format(WIDEN("{::d}"), v);
+ VERIFY( res == WIDEN("[1, 0]") );
+}
+
+int main()
+{
+ test_format_string();
+ test_output<char>();
+ test_output<wchar_t>();
+}
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/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
index ed2e3ca..7a62645 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
@@ -1,6 +1,11 @@
// { dg-do run { target c++23 } }
#include <vector>
+
+#if __cpp_lib_containers_ranges != 202202L
+# error "Feature-test macro __cpp_lib_containers_ranges has wrong value in <vector>"
+#endif
+
#include <span>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
diff --git a/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc b/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc
index 0b18616..e2fbf7d 100644
--- a/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc
+++ b/libstdc++-v3/testsuite/24_iterators/indirect_callable/projected.cc
@@ -22,12 +22,7 @@
template<typename T>
using PI = std::projected<T, std::identity>;
-#if __GLIBCXX__
-// Verify our projected<I, identity> optimization.
-static_assert(std::same_as<PI<int*>, int*>);
-#else
static_assert(std::same_as<PI<int*>::value_type, int>);
-#endif
static_assert(std::same_as<decltype(*std::declval<const PI<int*>&>()), int&>);
struct X
diff --git a/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc b/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc
new file mode 100644
index 0000000..5a812ec
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc
@@ -0,0 +1,57 @@
+// { dg-do run { target c++23 } }
+
+// LWG 3899.
+// co_yielding elements of an lvalue generator is unnecessarily inefficient
+
+#include <generator>
+#include <memory_resource>
+#include <testsuite_hooks.h>
+
+struct memory_resource : std::pmr::memory_resource
+{
+ std::size_t count = 0;
+
+ void* do_allocate(std::size_t n, std::size_t a) override
+ {
+ count += n;
+ return std::pmr::new_delete_resource()->allocate(n, a);
+ }
+
+ void do_deallocate(void* p, std::size_t n, std::size_t a) override
+ {
+ return std::pmr::new_delete_resource()->deallocate(p, n, a);
+ }
+
+ bool do_is_equal(const std::pmr::memory_resource& mr) const noexcept override
+ { return this == &mr; }
+};
+
+std::pmr::generator<int>
+f(std::allocator_arg_t, std::pmr::polymorphic_allocator<>, int init)
+{
+ co_yield init + 0;
+ co_yield init + 1;
+}
+
+std::pmr::generator<int>
+g(std::allocator_arg_t, std::pmr::polymorphic_allocator<> alloc)
+{
+ auto gen = f(std::allocator_arg, alloc, 0);
+ auto gen2 = f(std::allocator_arg, alloc, 2);
+ co_yield std::ranges::elements_of(std::move(gen), alloc);
+ co_yield std::ranges::elements_of(gen2, alloc);
+}
+
+int
+main()
+{
+ std::size_t counts[4];
+ memory_resource mr;
+ for (auto d : g(std::allocator_arg , &mr))
+ counts[d] = mr.count;
+ VERIFY(counts[0] != 0);
+ // No allocations after the first one:
+ VERIFY(counts[1] == counts[0]);
+ VERIFY(counts[2] == counts[0]);
+ VERIFY(counts[3] == counts[0]);
+}
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/dangling_ref.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/dangling_ref.cc
index 51c6ade..8cc3f78 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/dangling_ref.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/dangling_ref.cc
@@ -8,6 +8,5 @@ int f();
std::packaged_task<const int&()> task(f);
// { dg-error "dangling reference" "" { target { c++14_down } } 0 }
// { dg-error "reference to temporary" "" { target { c++14_down } } 0 }
-// { dg-error "no matching function" "" { target c++17 } 0 }
-// { dg-error "enable_if" "" { target c++17 } 0 }
// { dg-error "static assertion failed" "" { target c++17 } 0 }
+// { dg-error "note: .*std::is_invocable_r" "" { target c++17 } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/lwg4154_neg.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/lwg4154_neg.cc
index 6ba1bb1..b3413c2 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/lwg4154_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/lwg4154_neg.cc
@@ -12,16 +12,16 @@ struct F {
// Mandates: is_invocable_r_v<R, decay_t<F>&, ArgTypes...> is true.
const F f;
-std::packaged_task<void()> p(f); // { dg-error "here" "" { target c++17 } }
-// { dg-error "static assertion failed" "" { target c++17 } 0 }
-// { dg-error "invoke_r" "" { target *-*-* } 0 }
-// { dg-prune-output "enable_if<false" }
+std::packaged_task<void()> p(f); // { dg-error "here" }
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+// { dg-error "note: .*std::is_invocable_r_v<void, " "" { target c++17 } 0 }
// Only callable as rvalue
struct Frv {
int* operator()() && { return 0; }
};
-std::packaged_task<int*()> p2(Frv{}); // { dg-error "here" "" { target c++17 } }
+std::packaged_task<int*()> p2(Frv{}); // { dg-error "here" }
+// { dg-error "note: .*std::is_invocable_r_v<int., " "" { target c++17 } 0 }
// Only callable as non-const lvalue
struct Fnc {
diff --git a/libstdc++-v3/testsuite/30_threads/thread/id/output.cc b/libstdc++-v3/testsuite/30_threads/thread/id/output.cc
index 94a6ff0..3d1dd38 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/id/output.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/id/output.cc
@@ -118,8 +118,38 @@ test02()
VERIFY( ws1.length() == len );
#endif
+ out.str("");
+ out << i;
+ s1 = out.str();
+ len = s1.size();
+ out.str("");
+
+ // with width
+ s2 = std::format("{0:{1}}", i, len + 2);
+ VERIFY( s2 == (" " + s1) );
+ // with align + width
+ s2 = std::format("{0:>{1}}", i, len + 2);
+ VERIFY( s2 == (" " + s1) );
+ s2 = std::format("{0:<{1}}", i, len + 2);
+ VERIFY( s2 == (s1 + " ") );
+ // with fill-and-align + width
+ s2 = std::format("{0:x^{1}}", i, len + 5);
+ VERIFY( s2 == ("xx" + s1 + "xxx") );
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ static_assert( std::is_default_constructible_v<std::formatter<std::thread::id, wchar_t>> );
+ ws1 = std::format(L"{}", i);
+ VERIFY( ws1.length() == len );
+#endif
+
t1.join();
t2.join();
+
+ static_assert( std::formattable<std::thread::id, char> );
+ static_assert( std::formattable<std::thread::id, wchar_t> );
+ static_assert( !std::formattable<std::thread::id, char16_t> );
+ static_assert( !std::formattable<std::thread::id, int> );
+
#elif __cplusplus >= 202302L
# error "Feature-test macro for formatters has wrong value in <thread>"
#endif
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/debug.cc b/libstdc++-v3/testsuite/std/format/debug.cc
new file mode 100644
index 0000000..d3402f8
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/debug.cc
@@ -0,0 +1,833 @@
+// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32LE -DUNICODE_ENC" { target le } }
+// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32BE -DUNICODE_ENC" { target be } }
+// { dg-do run { target c++23 } }
+// { dg-add-options no_pch }
+// { dg-timeout-factor 2 }
+
+#include <format>
+#include <testsuite_hooks.h>
+
+std::string
+fdebug(char t)
+{ return std::format("{:?}", t); }
+
+std::wstring
+fdebug(wchar_t t)
+{ return std::format(L"{:?}", t); }
+
+std::string
+fdebug(std::string_view t)
+{ return std::format("{:?}", t); }
+
+std::wstring
+fdebug(std::wstring_view t)
+{ return std::format(L"{:?}", t); }
+
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template<typename _CharT>
+void
+test_basic_escapes()
+{
+ std::basic_string<_CharT> res;
+
+ const auto tab = WIDEN("\t");
+ res = fdebug(tab);
+ VERIFY( res == WIDEN(R"("\t")") );
+ res = fdebug(tab[0]);
+ VERIFY( res == WIDEN(R"('\t')") );
+
+ const auto nline = WIDEN("\n");
+ res = fdebug(nline);
+ VERIFY( res == WIDEN(R"("\n")") );
+ res = fdebug(nline[0]);
+ VERIFY( res == WIDEN(R"('\n')") );
+
+ const auto carret = WIDEN("\r");
+ res = fdebug(carret);
+ VERIFY( res == WIDEN(R"("\r")") );
+ res = fdebug(carret[0]);
+ VERIFY( res == WIDEN(R"('\r')") );
+
+ const auto bslash = WIDEN("\\");
+ res = fdebug(bslash);
+ VERIFY( res == WIDEN(R"("\\")") );
+ res = fdebug(bslash[0]);
+ VERIFY( res == WIDEN(R"('\\')") );
+
+ const auto quote = WIDEN("\"");
+ res = fdebug(quote);
+ VERIFY( res == WIDEN(R"("\"")") );
+ res = fdebug(quote[0]);
+ VERIFY( res == WIDEN(R"('"')") );
+
+ const auto apos = WIDEN("\'");
+ res = fdebug(apos);
+ VERIFY( res == WIDEN(R"("'")") );
+ res = fdebug(apos[0]);
+ VERIFY( res == WIDEN(R"('\'')") );
+}
+
+template<typename _CharT>
+void
+test_ascii_escapes()
+{
+ std::basic_string<_CharT> res;
+
+ const auto in = WIDEN("\x10 abcde\x7f\t0123");
+ res = fdebug(in);
+ VERIFY( res == WIDEN(R"("\u{10} abcde\u{7f}\t0123")") );
+ res = fdebug(in[0]);
+ VERIFY( res == WIDEN(R"('\u{10}')") );
+ res = fdebug(in[1]);
+ VERIFY( res == WIDEN(R"(' ')") );
+ res = fdebug(in[2]);
+ VERIFY( res == WIDEN(R"('a')") );
+}
+
+template<typename _CharT>
+void
+test_extended_ascii()
+{
+ std::basic_string<_CharT> res;
+
+ const auto in = WIDEN("Åëÿ");
+ res = fdebug(in);
+ VERIFY( res == WIDEN(R"("Åëÿ")") );
+
+ static constexpr bool __test_characters
+#if UNICODE_ENC
+ = sizeof(_CharT) >= 2;
+#else // ISO8859-1
+ = true;
+#endif // UNICODE_ENC
+
+ if constexpr (__test_characters)
+ {
+ res = fdebug(in[0]);
+ VERIFY( res == WIDEN(R"('Ã…')") );
+ res = fdebug(in[1]);
+ VERIFY( res == WIDEN(R"('ë')") );
+ res = fdebug(in[2]);
+ VERIFY( res == WIDEN(R"('ÿ')") );
+ }
+}
+
+template<typename _CharT>
+void
+test_unicode_escapes()
+{
+#if UNICODE_ENC
+ std::basic_string<_CharT> res;
+
+ const auto in = WIDEN(
+ "\u008a" // Cc, Control, Line Tabulation Set,
+ "\u00ad" // Cf, Format, Soft Hyphen
+ "\u1d3d" // Lm, Modifier letter, Modifier Letter Capital Ou
+ "\u00a0" // Zs, Space Separator, No-Break Space (NBSP)
+ "\u2029" // Zp, Paragraph Separator, Paragraph Separator
+ "\U0001f984" // So, Other Symbol, Unicorn Face
+ );
+ const auto out = WIDEN("\""
+ R"(\u{8a})"
+ R"(\u{ad})"
+ "\u1d3d"
+ R"(\u{a0})"
+ R"(\u{2029})"
+ "\U0001f984"
+ "\"");
+
+ res = fdebug(in);
+ VERIFY( res == out );
+
+ if constexpr (sizeof(_CharT) >= 2)
+ {
+ res = fdebug(in[0]);
+ VERIFY( res == WIDEN(R"('\u{8a}')") );
+ res = fdebug(in[1]);
+ VERIFY( res == WIDEN(R"('\u{ad}')") );
+ res = fdebug(in[2]);
+ VERIFY( res == WIDEN("'\u1d3d'") );
+ res = fdebug(in[3]);
+ VERIFY( res == WIDEN(R"('\u{a0}')") );
+ res = fdebug(in[4]);
+ VERIFY( res == WIDEN(R"('\u{2029}')") );
+ }
+
+ if constexpr (sizeof(_CharT) >= 4)
+ {
+ res = fdebug(in[5]);
+ VERIFY( res == WIDEN("'\U0001f984'") );
+ }
+#endif // UNICODE_ENC
+}
+
+template<typename _CharT>
+void
+test_grapheme_extend()
+{
+#if UNICODE_ENC
+ std::basic_string<_CharT> res;
+
+ const auto vin = WIDEN("o\u0302\u0323");
+ res = fdebug(vin);
+ VERIFY( res == WIDEN("\"o\u0302\u0323\"") );
+
+ std::basic_string_view<_CharT> in = WIDEN("\t\u0302\u0323");
+ res = fdebug(in);
+ VERIFY( res == WIDEN(R"("\t\u{302}\u{323}")") );
+
+ res = fdebug(in.substr(1));
+ VERIFY( res == WIDEN(R"("\u{302}\u{323}")") );
+
+ if constexpr (sizeof(_CharT) >= 2)
+ {
+ res = fdebug(in[1]);
+ VERIFY( res == WIDEN(R"('\u{302}')") );
+ }
+#endif // UNICODE_ENC
+}
+
+template<typename _CharT>
+void
+test_replacement_char()
+{
+#if UNICODE_ENC
+ std::basic_string<_CharT> repl = WIDEN("\uFFFD");
+ std::basic_string<_CharT> res = fdebug(repl);
+ VERIFY( res == WIDEN("\"\uFFFD\"") );
+
+ repl = WIDEN("\uFFFD\uFFFD");
+ res = fdebug(repl);
+ VERIFY( res == WIDEN("\"\uFFFD\uFFFD\"") );
+#endif // UNICODE_ENC
+}
+
+void
+test_ill_formed_utf8_seq()
+{
+#if UNICODE_ENC
+ std::string_view seq = "\xf0\x9f\xa6\x84"; // \U0001F984
+ std::string res;
+
+ res = fdebug(seq);
+ VERIFY( res == "\"\U0001F984\"" );
+
+ res = fdebug(seq.substr(1));
+ VERIFY( res == R"("\x{9f}\x{a6}\x{84}")" );
+
+ res = fdebug(seq.substr(2));
+ VERIFY( res == R"("\x{a6}\x{84}")" );
+
+ res = fdebug(seq[0]);
+ VERIFY( res == R"('\x{f0}')" );
+ res = fdebug(seq.substr(0, 1));
+ VERIFY( res == R"("\x{f0}")" );
+
+ res = fdebug(seq[1]);
+ VERIFY( res == R"('\x{9f}')" );
+ res = fdebug(seq.substr(1, 1));
+ VERIFY( res == R"("\x{9f}")" );
+
+ res = fdebug(seq[2]);
+ VERIFY( res == R"('\x{a6}')" );
+ res = fdebug(seq.substr(2, 1));
+ VERIFY( res == R"("\x{a6}")" );
+
+ res = fdebug(seq[3]);
+ VERIFY( res == R"('\x{84}')" );
+ res = fdebug(seq.substr(3, 1));
+ VERIFY( res == R"("\x{84}")" );
+#endif // UNICODE_ENC
+}
+
+void
+test_ill_formed_utf32()
+{
+#if UNICODE_ENC
+ std::wstring res;
+
+ wchar_t ic1 = static_cast<wchar_t>(0xff'ffff);
+ res = fdebug(ic1);
+ VERIFY( res == LR"('\x{ffffff}')" );
+
+ std::wstring is1(1, ic1);
+ res = fdebug(is1);
+ VERIFY( res == LR"("\x{ffffff}")" );
+
+ wchar_t ic2 = static_cast<wchar_t>(0xffff'ffff);
+ res = fdebug(ic2);
+ VERIFY( res == LR"('\x{ffffffff}')" );
+
+ std::wstring is2(1, ic2);
+ res = fdebug(is2);
+ VERIFY( res == LR"("\x{ffffffff}")" );
+#endif // UNICODE_ENC
+}
+
+template<typename _CharT>
+void
+test_fill()
+{
+ std::basic_string<_CharT> res;
+
+ std::basic_string_view<_CharT> in = WIDEN("a\t\x10\u00ad");
+ res = std::format(WIDEN("{:10?}"), in.substr(0, 1));
+ VERIFY( res == WIDEN(R"("a" )") );
+
+ res = std::format(WIDEN("{:->10?}"), in.substr(1, 1));
+ VERIFY( res == WIDEN(R"(------"\t")") );
+
+ res = std::format(WIDEN("{:+<10?}"), in.substr(2, 1));
+ VERIFY( res == WIDEN(R"("\u{10}"++)") );
+
+
+ res = std::format(WIDEN("{:10?}"), in[0]);
+ VERIFY( res == WIDEN(R"('a' )") );
+
+ res = std::format(WIDEN("{:->10?}"), in[1]);
+ VERIFY( res == WIDEN(R"(------'\t')") );
+
+ res = std::format(WIDEN("{:+<10?}"), in[2]);
+ VERIFY( res == WIDEN(R"('\u{10}'++)") );
+
+#if UNICODE_ENC
+ res = std::format(WIDEN("{:=^10?}"), in.substr(3));
+ VERIFY( res == WIDEN(R"(="\u{ad}"=)") );
+
+ // width is 2
+ std::basic_string_view<_CharT> in2 = WIDEN("\u1100");
+ res = std::format(WIDEN("{:*^10?}"), in2);
+ VERIFY( res == WIDEN("***\"\u1100\"***") );
+
+ if constexpr (sizeof(_CharT) >= 2)
+ {
+ res = std::format(WIDEN("{:=^10?}"), in[3]);
+ VERIFY( res == WIDEN(R"(='\u{ad}'=)") );
+
+ res = std::format(WIDEN("{:*^10?}"), in2[0]);
+ VERIFY( res == WIDEN("***'\u1100'***") );
+ }
+#endif // UNICODE_ENC
+}
+
+template<typename _CharT>
+void
+test_prec()
+{
+ std::basic_string<_CharT> res;
+ // with ? escpaed presentation is copied to ouput, same as source
+
+ std::basic_string_view<_CharT> in = WIDEN("a\t\x10\u00ad");
+ res = std::format(WIDEN("{:.2?}"), in.substr(0, 1));
+ VERIFY( res == WIDEN(R"("a)") );
+
+ res = std::format(WIDEN("{:.4?}"), in.substr(1, 1));
+ VERIFY( res == WIDEN(R"("\t")") );
+
+ res = std::format(WIDEN("{:.5?}"), in.substr(2, 1));
+ VERIFY( res == WIDEN(R"("\u{1)") );
+
+#if UNICODE_ENC
+ res = std::format(WIDEN("{:.10?}"), in.substr(3));
+ VERIFY( res == WIDEN(R"("\u{ad}")") );
+
+ std::basic_string_view<_CharT> in2 = WIDEN("\u1100");
+ res = std::format(WIDEN("{:.3?}"), in2);
+ VERIFY( res == WIDEN("\"\u1100") );
+#endif // UNICODE_ENC
+}
+
+bool strip_quote(std::string_view& v)
+{
+ if (!v.starts_with('"'))
+ return false;
+ v.remove_prefix(1);
+ return true;
+}
+
+bool strip_quotes(std::string_view& v)
+{
+ if (!v.starts_with('"') || !v.ends_with('"'))
+ return false;
+ v.remove_prefix(1);
+ v.remove_suffix(1);
+ return true;
+}
+
+bool strip_prefix(std::string_view& v, size_t n, char c)
+{
+ size_t pos = v.find_first_not_of(c);
+ if (pos == std::string_view::npos)
+ pos = v.size();
+ if (pos != n)
+ return false;
+ v.remove_prefix(n);
+ return true;
+}
+
+void test_padding()
+{
+ std::string res;
+ std::string_view resv;
+
+ // width and size are 26
+ std::string in = "abcdefghijklmnopqrstuvwxyz";
+ in += in; // width and size are 52
+ in += in; // width and size are 104
+ in += in; // width and size are 208
+ in += in; // width and size are 416
+ std::string_view inv = in;
+
+ resv = res = std::format("{}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.500}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.400}", in);
+ VERIFY( resv == inv.substr(0, 400) );
+
+ resv = res = std::format("{:.200}", in);
+ VERIFY( resv == inv.substr(0, 200) );
+
+ resv = res = std::format("{:.10}", in);
+ VERIFY( resv == inv.substr(0, 10) );
+
+ resv = res = std::format("{:.0}", in);
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>20}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>20.500}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>20.400}", in);
+ VERIFY( resv == inv.substr(0, 400) );
+
+ resv = res = std::format("{:*>20.200}", in);
+ VERIFY( resv == inv.substr(0, 200) );
+
+ resv = res = std::format("{:*>20.10}", in);
+ VERIFY( strip_prefix(resv, 10, '*') );
+ VERIFY( resv == inv.substr(0, 10) );
+
+ resv = res = std::format("{:*>20.0}", in);
+ VERIFY( strip_prefix(resv, 20, '*') );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>450}", in);
+ VERIFY( strip_prefix(resv, 34, '*') );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>450.500}", in);
+ VERIFY( strip_prefix(resv, 34, '*') );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>450.420}", in);
+ VERIFY( strip_prefix(resv, 34, '*') );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>450.400}", in);
+ VERIFY( strip_prefix(resv, 50, '*') );
+ VERIFY( resv == inv.substr(0, 400) );
+
+ resv = res = std::format("{:*>450.200}", in);
+ VERIFY( strip_prefix(resv, 250, '*') );
+ VERIFY( resv == inv.substr(0, 200) );
+
+ resv = res = std::format("{:*>450.10}", in);
+ VERIFY( strip_prefix(resv, 440, '*') );
+ VERIFY( resv == inv.substr(0, 10) );
+
+ resv = res = std::format("{:*>450.0}", in);
+ VERIFY( strip_prefix(resv, 450, '*') );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.500?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.400?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 399) );
+
+ resv = res = std::format("{:.200?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 199) );
+
+ resv = res = std::format("{:.10?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 9) );
+
+ resv = res = std::format("{:.1?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:.0?}", in);
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>20?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>20.500?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>20.400?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 399) );
+
+ resv = res = std::format("{:*>20.200?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 199) );
+
+ resv = res = std::format("{:*>20.10?}", in);
+ VERIFY( strip_prefix(resv, 10, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 9) );
+
+ resv = res = std::format("{:*>20.1?}", in);
+ VERIFY( strip_prefix(resv, 19, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>20.0?}", in);
+ VERIFY( strip_prefix(resv, 20, '*') );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>450?}", in);
+ VERIFY( strip_prefix(resv, 32, '*') );
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>450.500?}", in);
+ VERIFY( strip_prefix(resv, 32, '*') );
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>450.420?}", in);
+ VERIFY( strip_prefix(resv, 32, '*') );
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>450.400?}", in);
+ VERIFY( strip_prefix(resv, 50, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 399) );
+
+ resv = res = std::format("{:*>450.200?}", in);
+ VERIFY( strip_prefix(resv, 250, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 199) );
+
+ resv = res = std::format("{:*>450.10?}", in);
+ VERIFY( strip_prefix(resv, 440, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 9) );
+
+ resv = res = std::format("{:*>450.1?}", in);
+ VERIFY( strip_prefix(resv, 449, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>450.0?}", in);
+ VERIFY( strip_prefix(resv, 450, '*') );
+ VERIFY( resv == "" );
+
+#if UNICODE_ENC
+ // width is 3, size is 15
+ in = "o\u0302\u0323i\u0302\u0323u\u0302\u0323";
+ in += in; // width is 6, size is 30
+ in += in; // width is 12, size is 60
+ in += in; // width is 24, size is 120
+ in += in; // width is 48, size is 240
+ in += in; // width is 96, size is 480
+ in += in; // width is 192, size is 960
+ inv = in;
+
+ resv = res = std::format("{:}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.200}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.96}", in);
+ VERIFY( resv == inv.substr(0, 480) );
+
+ resv = res = std::format("{:.12}", in);
+ VERIFY( resv == inv.substr(0, 60) );
+
+ resv = res = std::format("{:.3}", in);
+ VERIFY( resv == inv.substr(0, 15) );
+
+ resv = res = std::format("{:.0}", in);
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>10}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>10.200}", in);
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>10.96}", in);
+ VERIFY( resv == inv.substr(0, 480) );
+
+ resv = res = std::format("{:*>10.12}", in);
+ VERIFY( resv == inv.substr(0, 60) );
+
+ resv = res = std::format("{:*>10.3}", in);
+ VERIFY( strip_prefix(resv, 7, '*') );
+ VERIFY( resv == inv.substr(0, 15) );
+
+ resv = res = std::format("{:*>10.0}", in);
+ VERIFY( strip_prefix(resv, 10, '*') );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>240s}", in);
+ VERIFY( strip_prefix(resv, 48, '*') );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>240.200s}", in);
+ VERIFY( strip_prefix(resv, 48, '*') );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>240.96s}", in);
+ VERIFY( strip_prefix(resv, 144, '*') );
+ VERIFY( resv == inv.substr(0, 480) );
+
+ resv = res = std::format("{:*>240.12}", in);
+ VERIFY( strip_prefix(resv, 228, '*') );
+ VERIFY( resv == inv.substr(0, 60) );
+
+ resv = res = std::format("{:*>240.3s}", in);
+ VERIFY( strip_prefix(resv, 237, '*') );
+ VERIFY( resv == inv.substr(0, 15) );
+
+ resv = res = std::format("{:*>240.0s}", in);
+ VERIFY( strip_prefix(resv, 240, '*') );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.200?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:.97?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 480) );
+
+ resv = res = std::format("{:.13?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 60) );
+
+ resv = res = std::format("{:.4?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 15) );
+
+ resv = res = std::format("{:.1?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:.0?}", in);
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>10?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>10.200?}", in);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>10.97?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 480) );
+
+ resv = res = std::format("{:*>10.13?}", in);
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 60) );
+
+ resv = res = std::format("{:*>10.4?}", in);
+ VERIFY( strip_prefix(resv, 6, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 15) );
+
+ resv = res = std::format("{:*>10.1?}", in);
+ VERIFY( strip_prefix(resv, 9, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>10.0?}", in);
+ VERIFY( strip_prefix(resv, 10, '*') );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>240?}", in);
+ VERIFY( strip_prefix(resv, 46, '*') );
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>240.200?}", in);
+ VERIFY( strip_prefix(resv, 46, '*') );
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == inv );
+
+ resv = res = std::format("{:*>240.97?}", in);
+ VERIFY( strip_prefix(resv, 143, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 480) );
+
+ resv = res = std::format("{:*>240.13?}", in);
+ VERIFY( strip_prefix(resv, 227, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 60) );
+
+ resv = res = std::format("{:*>240.4?}", in);
+ VERIFY( strip_prefix(resv, 236, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == inv.substr(0, 15) );
+
+ resv = res = std::format("{:*>240.1?}", in);
+ VERIFY( strip_prefix(resv, 239, '*') );
+ VERIFY( strip_quote(resv) );
+ VERIFY( resv == "" );
+
+ resv = res = std::format("{:*>240.0?}", in);
+ VERIFY( strip_prefix(resv, 240, '*') );
+ VERIFY( resv == "" );
+#endif // UNICODE_ENC
+}
+
+void test_char_as_wchar()
+{
+ std::wstring res;
+
+ res = std::format(L"{:?}", 'a');
+ VERIFY( res == LR"('a')" );
+
+ res = std::format(L"{:?}", '\t');
+ VERIFY( res == LR"('\t')" );
+
+ res = std::format(L"{:+<10?}", '\x10');
+ VERIFY( res == LR"('\u{10}'++)" );
+}
+
+template<typename T>
+struct DebugWrapper
+{
+ T val;
+};
+
+template<typename T, typename CharT>
+struct std::formatter<DebugWrapper<T>, CharT>
+{
+ constexpr std::basic_format_parse_context<CharT>::iterator
+ parse(std::basic_format_parse_context<CharT>& pc)
+ {
+ auto out = under.parse(pc);
+ under.set_debug_format();
+ return out;
+ }
+
+ template<typename Out>
+ Out format(DebugWrapper<T> const& t,
+ std::basic_format_context<Out, CharT>& fc) const
+ { return under.format(t.val, fc); }
+
+private:
+ std::formatter<T, CharT> under;
+};
+
+template<typename _CharT, typename StrT>
+void
+test_formatter_str()
+{
+ _CharT buf[]{ 'a', 'b', 'c', 0 };
+ DebugWrapper<StrT> in{ buf };
+ std::basic_string<_CharT> res = std::format(WIDEN("{:?}"), in );
+ VERIFY( res == WIDEN(R"("abc")") );
+}
+
+template<typename _CharT>
+void
+test_formatter_arr()
+{
+ std::basic_string<_CharT> res;
+
+ DebugWrapper<_CharT[3]> in3{ 'a', 'b', 'c' };
+ res = std::format(WIDEN("{:?}"), in3 );
+ VERIFY( res == WIDEN(R"("abc")") );
+
+ // We print all characters, including null-terminator
+ DebugWrapper<_CharT[4]> in4{ 'a', 'b', 'c', 0 };
+ res = std::format(WIDEN("{:?}"), in4 );
+ VERIFY( res == WIDEN(R"("abc\u{0}")") );
+}
+
+template<typename _CharT, typename SrcT>
+void
+test_formatter_char()
+{
+ DebugWrapper<SrcT> in{ 'a' };
+ std::basic_string<_CharT> res = std::format(WIDEN("{:?}"), in);
+ VERIFY( res == WIDEN(R"('a')") );
+}
+
+template<typename CharT>
+void
+test_formatters()
+{
+ test_formatter_char<CharT, CharT>();
+ test_formatter_str<CharT, CharT*>();
+ test_formatter_str<CharT, const CharT*>();
+ test_formatter_str<CharT, std::basic_string<CharT>>();
+ test_formatter_str<CharT, std::basic_string_view<CharT>>();
+ test_formatter_arr<CharT>();
+}
+
+void
+test_formatters_c()
+{
+ test_formatters<char>();
+ test_formatters<wchar_t>();
+ test_formatter_char<wchar_t, char>();
+}
+
+int main()
+{
+ test_basic_escapes<char>();
+ test_basic_escapes<wchar_t>();
+ test_ascii_escapes<char>();
+ test_ascii_escapes<wchar_t>();
+ test_extended_ascii<char>();
+ test_extended_ascii<wchar_t>();
+
+ test_unicode_escapes<char>();
+ test_unicode_escapes<wchar_t>();
+ test_grapheme_extend<char>();
+ test_grapheme_extend<wchar_t>();
+ test_replacement_char<char>();
+ test_replacement_char<wchar_t>();
+ test_ill_formed_utf8_seq();
+ test_ill_formed_utf32();
+
+ test_fill<char>();
+ test_fill<wchar_t>();
+ test_prec<char>();
+ test_prec<wchar_t>();
+
+ test_padding();
+
+ test_formatters_c();
+}
diff --git a/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc b/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc
new file mode 100644
index 0000000..2ac7e75
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc
@@ -0,0 +1,5 @@
+// { dg-options "-fexec-charset=ISO8859-1" }
+// { dg-do run { target c++23 } }
+// { dg-add-options no_pch }
+
+#include "debug.cc"
diff --git a/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc b/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
index ff5f075..07e63af 100644
--- a/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
+++ b/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
@@ -4,6 +4,7 @@
// LWG 3944. Formatters converting sequences of char to sequences of wchar_t
#include <format>
+#include <vector>
void test_lwg3944()
{
@@ -14,7 +15,6 @@ void test_lwg3944()
std::format(L"{}",cstr); // { dg-error "here" }
// Ill-formed in C++20
- // In C++23 they give L"['h', 'e', 'l', 'l', 'o']"
std::format(L"{}", "hello"); // { dg-error "here" }
std::format(L"{}", std::string_view("hello")); // { dg-error "here" }
std::format(L"{}", std::string("hello")); // { dg-error "here" }
diff --git a/libstdc++-v3/testsuite/std/format/formatter/requirements.cc b/libstdc++-v3/testsuite/std/format/formatter/requirements.cc
index 416b9a8..1c9a0a5 100644
--- a/libstdc++-v3/testsuite/std/format/formatter/requirements.cc
+++ b/libstdc++-v3/testsuite/std/format/formatter/requirements.cc
@@ -70,12 +70,14 @@ test_specializations() // [format.formatter.spec]
// LWG 3833. Remove specialization
// template<size_t N> struct formatter<const charT[N], charT>
- using Farr = std::format_context::formatter_type<const char[1]>;
- static_assert( ! std::is_default_constructible_v<Farr> );
- static_assert( ! std::is_copy_constructible_v<Farr> );
- static_assert( ! std::is_move_constructible_v<Farr> );
- static_assert( ! std::is_copy_assignable_v<Farr> );
- static_assert( ! std::is_move_assignable_v<Farr> );
+ // Formatter is only expected to be instantiated with only cv-unqual types
+ // and attempting to instantiate this specialization is ill-formed
+ // using Farr = std::format_context::formatter_type<const char[1]>;
+ // static_assert( ! std::is_default_constructible_v<Farr> );
+ // static_assert( ! std::is_copy_constructible_v<Farr> );
+ // static_assert( ! std::is_move_constructible_v<Farr> );
+ // static_assert( ! std::is_copy_assignable_v<Farr> );
+ // static_assert( ! std::is_move_assignable_v<Farr> );
}
int main()
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 7fc4201..93c33b4 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -370,6 +370,18 @@ test_wchar()
// P2909R4 Fix formatting of code units as integers (Dude, where’s my char?)
s = std::format(L"{:d} {:d}", wchar_t(-1), char(-1));
VERIFY( s.find('-') == std::wstring::npos );
+
+ auto ws = std::format(L"{:L}", 0.5);
+ VERIFY( ws == L"0.5" );
+ // The default C locale.
+ std::locale cloc = std::locale::classic();
+ // PR libstdc++/119671 use-after-free formatting floating-point to wstring
+ ws = std::format(cloc, L"{:L}", 0.5);
+ VERIFY( ws == L"0.5" );
+ // A locale with no name, but with the same facets as the C locale.
+ std::locale locx(cloc, &std::use_facet<std::ctype<char>>(cloc));
+ ws = std::format(locx, L"{:L}", 0.5);
+ VERIFY( ws == L"0.5" );
}
void
@@ -501,9 +513,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/ranges/adaptors.cc b/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
new file mode 100644
index 0000000..daa73aa
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
@@ -0,0 +1,156 @@
+// { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
+
+#include <format>
+#include <queue>
+#include <stack>
+#include <testsuite_hooks.h>
+
+template<typename... Args>
+bool
+is_format_string_for(const char* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_format_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template<template<typename Tp> class Adaptor>
+void
+test_format_string()
+{
+ Adaptor<int> q;
+ VERIFY( !is_format_string_for("{:?}", q) );
+ VERIFY( !is_format_string_for("{:P}", q) );
+
+ // width needs to be integer type
+ VERIFY( !is_format_string_for("{:{}}", q, 1.0f) );
+}
+
+struct NoFormat
+{
+ friend auto operator<=>(NoFormat, NoFormat) = default;
+};
+
+struct MutFormat
+{
+ MutFormat() = default;
+ MutFormat(int p) : x(p) {}
+
+ int x;
+ friend auto operator<=>(MutFormat, MutFormat) = default;
+};
+
+template<typename CharT>
+struct std::formatter<MutFormat, CharT>
+ : std::formatter<int, CharT>
+{
+ template<typename Out>
+ Out format(MutFormat& mf, basic_format_context<Out, CharT>& ctx) const
+ { return std::formatter<int, CharT>::format(mf.x, ctx); }
+};
+
+template<typename T>
+struct NotFormattableCont : std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template<typename T>
+constexpr auto std::format_kind<NotFormattableCont<T>>
+ = std::range_format::disabled;
+
+template<typename _CharT,
+ template<typename Tp, typename Cont = std::vector<Tp>> class Adaptor>
+void
+test_output()
+{
+ const std::vector<int> v{3, 2, 1};
+ std::basic_string<_CharT> res;
+ Adaptor<int, std::vector<int>> q(std::from_range, v);
+
+ res = std::format(WIDEN("{}"), q);
+ VERIFY( res == WIDEN("[3, 2, 1]") );
+
+ res = std::format(WIDEN("{}"), std::as_const(q));
+ VERIFY( res == WIDEN("[3, 2, 1]") );
+
+ res = std::format(WIDEN("{:n:#x}"), q);
+ VERIFY( res == WIDEN("0x3, 0x2, 0x1") );
+
+ res = std::format(WIDEN("{:=^23:#04x}"), q);
+ VERIFY( res == WIDEN("==[0x03, 0x02, 0x01]===") );
+
+ // Sequence output is always used
+ Adaptor<_CharT, std::basic_string<_CharT>> qs(
+ std::from_range,
+ std::basic_string_view<_CharT>(WIDEN("321")));
+
+ res = std::format(WIDEN("{}"), qs);
+ VERIFY( res == WIDEN("['3', '2', '1']") );
+
+ res = std::format(WIDEN("{::}"), std::as_const(qs));
+ VERIFY( res == WIDEN("[3, 2, 1]") );
+
+ res = std::format(WIDEN("{:?s}"), qs);
+ VERIFY( res == WIDEN(R"("321")") );
+
+ Adaptor<int, std::deque<int>> qd(std::from_range, v);
+
+ res = std::format(WIDEN("{}"), qd);
+ VERIFY( res == WIDEN("[3, 2, 1]") );
+
+ res = std::format(WIDEN("{}"), std::as_const(qd));
+ VERIFY( res == WIDEN("[3, 2, 1]") );
+
+ Adaptor<MutFormat> mq(std::from_range, v);
+
+ res = std::format(WIDEN("{}"), mq);
+ VERIFY( res == WIDEN("[3, 2, 1]") );
+
+ static_assert(!std::formattable<const Adaptor<MutFormat>, _CharT>);
+
+ static_assert(!std::formattable<Adaptor<NoFormat>, _CharT>);
+ static_assert(!std::formattable<const Adaptor<NoFormat>, _CharT>);
+
+ // Formatter check if container is formattable, not container elements.
+ static_assert(!std::formattable<Adaptor<int, NotFormattableCont<int>>, _CharT>);
+}
+
+template<template<typename Tp, typename Cont = std::vector<Tp>> class Adaptor>
+void
+test_adaptor()
+{
+ test_format_string<Adaptor>();
+ test_output<char, Adaptor>();
+ test_output<wchar_t, Adaptor>();
+
+ static_assert(!std::formattable<Adaptor<int>, int>);
+ static_assert(!std::formattable<Adaptor<int>, char32_t>);
+}
+
+template<typename _CharT>
+void
+test_compare()
+{
+ const std::vector<int> v{3, 2, 1};
+ std::basic_string<_CharT> res;
+ std::priority_queue<int, std::vector<int>, std::greater<>> q(
+ std::from_range, v);
+
+ res = std::format(WIDEN("{}"), q);
+ VERIFY( res == WIDEN("[1, 2, 3]") );
+}
+
+int main()
+{
+ test_adaptor<std::queue>();
+ test_adaptor<std::priority_queue>();
+ test_compare<char>();
+}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/feature_test.cc b/libstdc++-v3/testsuite/std/format/ranges/feature_test.cc
new file mode 100644
index 0000000..80d2cea
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/feature_test.cc
@@ -0,0 +1,9 @@
+// { dg-do preprocess { target c++23 } }
+
+#include <format>
+
+#ifndef __cpp_lib_format_ranges
+# error "Feature-test macro __cpp_lib_format_ranges missing in <format>"
+#elif __cpp_lib_format_ranges != 202207L
+# error "Feature-test macro __cpp_lib_format_ranges has wrong value in <format>"
+#endif
diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
new file mode 100644
index 0000000..14b9ff2
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
@@ -0,0 +1,94 @@
+// { dg-do run { target c++23 } }
+
+#include <deque>
+#include <flat_map>
+#include <flat_set>
+#include <format>
+#include <list>
+#include <map>
+#include <set>
+#include <testsuite_hooks.h>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+static_assert( std::format_kind<std::vector<int>> == std::range_format::sequence );
+static_assert( std::format_kind<std::deque<int>> == std::range_format::sequence );
+static_assert( std::format_kind<std::list<int>> == std::range_format::sequence );
+
+static_assert( std::format_kind<std::set<int>> == std::range_format::set );
+static_assert( std::format_kind<std::multiset<int>> == std::range_format::set );
+static_assert( std::format_kind<std::unordered_set<int>> == std::range_format::set );
+static_assert( std::format_kind<std::unordered_multiset<int>> == std::range_format::set );
+static_assert( std::format_kind<std::flat_set<int>> == std::range_format::set );
+static_assert( std::format_kind<std::flat_multiset<int>> == std::range_format::set );
+
+static_assert( std::format_kind<std::map<int, int>> == std::range_format::map );
+static_assert( std::format_kind<std::multimap<int, int>> == std::range_format::map );
+static_assert( std::format_kind<std::unordered_map<int, int>> == std::range_format::map );
+static_assert( std::format_kind<std::unordered_multimap<int, int>> == std::range_format::map );
+static_assert( std::format_kind<std::flat_map<int, int>> == std::range_format::map );
+static_assert( std::format_kind<std::flat_multimap<int, int>> == std::range_format::map );
+
+template<typename T>
+struct MyVec : std::vector<T>
+{};
+
+static_assert( std::format_kind<MyVec<int>> == std::range_format::sequence );
+
+template<typename T>
+struct MySet : std::vector<T>
+{
+ using key_type = T;
+};
+
+static_assert( std::format_kind<MySet<int>> == std::range_format::set );
+
+template<typename T>
+struct MyMap : std::vector<T>
+{
+ using key_type = T;
+ using mapped_type = int;
+};
+
+static_assert( std::format_kind<MyMap<std::pair<int, int>>> == std::range_format::map );
+static_assert( std::format_kind<MyMap<std::tuple<int, int>>> == std::range_format::map );
+static_assert( std::format_kind<MyMap<int>> == std::range_format::set );
+
+template<typename T, std::range_format rf>
+struct CustFormat : std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template<typename T, std::range_format rf>
+constexpr auto std::format_kind<CustFormat<T, rf>> = rf;
+
+void test_override()
+{
+ CustFormat<int, std::range_format::disabled> disabledf;
+ static_assert( !std::formattable<decltype(disabledf), char> );
+
+ CustFormat<int, std::range_format::sequence> seqf{1, 2, 3};
+ VERIFY( std::format("{}", seqf) == "[1, 2, 3]" );
+
+ CustFormat<int, std::range_format::set> setf{1, 2, 3};
+ VERIFY( std::format("{}", setf) == "{1, 2, 3}" );
+
+ // TODO test map once formatter for pair is implenented
+
+ CustFormat<char, std::range_format::string> stringf{'a', 'b', 'c', 'd'};
+ VERIFY( std::format("{}", stringf) == "abcd" );
+ // Support precision as string do
+ VERIFY( std::format("{:.2}", stringf) == "ab" );
+
+ CustFormat<char, std::range_format::debug_string> debugf{'a', 'b', 'c', 'd'};
+ VERIFY( std::format("{}", debugf) == R"("abcd")" );
+ // Support precision as string do
+ VERIFY( std::format("{:.3}", debugf) == R"("ab)" );
+}
+
+int main()
+{
+ test_override();
+}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc
new file mode 100644
index 0000000..bf8619d
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++23 } }
+
+// C++23 22.14.7.1 [format.range.fmtkind] p1: A program that instantiates
+// the primary template of format_kind is ill-formed.
+
+#include <format>
+
+template<auto> struct Tester { };
+
+Tester<std::format_kind<const int(&)[1]>> t; // { dg-error "here" }
+
+// { dg-error "use of 'std::format_kind" "" { target *-*-* } 0 }
+// { dg-error "primary_template_not_defined" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
new file mode 100644
index 0000000..00ce9f6
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
@@ -0,0 +1,171 @@
+// { dg-do run { target c++23 } }
+
+#include <flat_map>
+#include <format>
+#include <testsuite_hooks.h>
+#include <vector>
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template<typename T,
+ template<typename, typename> class Formatter = std::range_formatter>
+struct MyVector : std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template<typename T,
+ template<typename, typename> class Formatter,
+ typename CharT>
+struct std::formatter<MyVector<T, Formatter>, CharT>
+{
+ constexpr formatter() noexcept
+ {
+ using _CharT = CharT;
+ _formatter.set_brackets(WIDEN("<"), WIDEN(">"));
+ _formatter.set_separator(WIDEN("; "));
+ }
+
+ constexpr std::basic_format_parse_context<CharT>::iterator
+ parse(std::basic_format_parse_context<CharT>& pc)
+ { return _formatter.parse(pc); }
+
+ template<typename Out>
+ typename std::basic_format_context<Out, CharT>::iterator
+ format(const MyVector<T, Formatter>& mv,
+ std::basic_format_context<Out, CharT>& fc) const
+ { return _formatter.format(mv, fc); }
+
+private:
+ Formatter<T, CharT> _formatter;
+};
+
+template<typename _CharT, template<typename, typename> class Formatter>
+void
+test_default()
+{
+ MyVector<int, Formatter> vec{1, 2, 3};
+ std::basic_string<_CharT> res;
+
+ res = std::format(WIDEN("{}"), vec);
+ VERIFY( res == WIDEN("<1; 2; 3>") );
+ res = std::format(WIDEN("{:}"), vec);
+ VERIFY( res == WIDEN("<1; 2; 3>") );
+ res = std::format(WIDEN("{:n}"), vec);
+ VERIFY( res == WIDEN("1; 2; 3") );
+
+ res = std::format(WIDEN("{:3}"), vec);
+ VERIFY( res == WIDEN("<1; 2; 3>") );
+
+ res = std::format(WIDEN("{:10}"), vec);
+ VERIFY( res == WIDEN("<1; 2; 3> ") );
+
+ res = std::format(WIDEN("{:{}}"), vec, 10);
+ VERIFY( res == WIDEN("<1; 2; 3> ") );
+
+ res = std::format(WIDEN("{1:{0}}"), 10, vec);
+ VERIFY( res == WIDEN("<1; 2; 3> ") );
+
+ res = std::format(WIDEN("{:10n}"), vec);
+ VERIFY( res == WIDEN("1; 2; 3 ") );
+
+ res = std::format(WIDEN("{:*<11}"), vec);
+ VERIFY( res == WIDEN("<1; 2; 3>**") );
+
+ res = std::format(WIDEN("{:->12}"), vec);
+ VERIFY( res == WIDEN("---<1; 2; 3>") );
+
+ res = std::format(WIDEN("{:=^13}"), vec);
+ VERIFY( res == WIDEN("==<1; 2; 3>==") );
+
+ res = std::format(WIDEN("{:=^13n}"), vec);
+ VERIFY( res == WIDEN("===1; 2; 3===") );
+
+ res = std::format(WIDEN("{::#x}"), vec);
+ VERIFY( res == WIDEN("<0x1; 0x2; 0x3>") );
+
+ res = std::format(WIDEN("{:|^25n:#05x}"), vec);
+ VERIFY( res == WIDEN("|||0x001; 0x002; 0x003|||") );
+
+ // ':' is start of the format string for element
+ res = std::format(WIDEN("{::^+4}"), vec);
+ VERIFY( res == WIDEN("< +1 ; +2 ; +3 >") );
+}
+
+template<typename _CharT, template<typename, typename> class Formatter>
+void
+test_override()
+{
+ MyVector<_CharT, Formatter> vc{'a', 'b', 'c', 'd'};
+ MyVector<std::pair<int, int>, Formatter> vp{{1, 11}, {2, 21}};
+ std::basic_string<_CharT> res;
+
+ res = std::format(WIDEN("{:s}"), vc);
+ VERIFY( res == WIDEN("abcd") );
+ res = std::format(WIDEN("{:?s}"), vc);
+ VERIFY( res == WIDEN("\"abcd\"") );
+ res = std::format(WIDEN("{:+^6s}"), vc);
+ VERIFY( res == WIDEN("+abcd+") );
+
+ res = std::format(WIDEN("{:m}"), vp);
+ VERIFY( res == WIDEN("{1: 11, 2: 21}") );
+ res = std::format(WIDEN("{:=^20m}"), vp);
+ VERIFY( res == WIDEN("==={1: 11, 2: 21}===") );
+}
+
+template<template<typename, typename> class Formatter>
+void test_outputs()
+{
+ test_default<char, Formatter>();
+ test_default<wchar_t, Formatter>();
+ test_override<char, Formatter>();
+ test_override<wchar_t, Formatter>();
+}
+
+void
+test_nested()
+{
+ MyVector<MyVector<int>> v
+ {
+ {1, 2},
+ {11, 12}
+ };
+
+ std::string res = std::format("{}", v);
+ VERIFY( res == "<<1; 2>; <11; 12>>" );
+
+ res = std::format("{:+^18:n:02}", v);
+ VERIFY( res == "+<01; 02; 11; 12>+" );
+}
+
+struct MyFlatMap : std::flat_map<int, int>
+{
+ using std::flat_map<int, int>::flat_map;
+};
+
+template<typename CharT>
+struct std::formatter<MyFlatMap, CharT>
+ // This cannot apply format BitVector const&, because formatted type would
+ // be std::pair<int const&, int const&>, and formatter for
+ // pair<int const&, int> cannot format it.
+ : std::range_formatter<MyFlatMap::reference>
+{};
+
+void test_const_ref_type_mismatch()
+{
+ MyFlatMap m{{1, 11}, {2, 22}};
+ std::string res = std::format("{:m}", m);
+ VERIFY( res == "{1: 11, 2: 22}" );
+}
+
+template<typename T, typename CharT>
+using VectorFormatter = std::formatter<std::vector<T>, CharT>;
+
+int main()
+{
+ test_outputs<std::range_formatter>();
+ test_outputs<VectorFormatter>();
+ test_nested();
+ test_const_ref_type_mismatch();
+}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/map.cc b/libstdc++-v3/testsuite/std/format/ranges/map.cc
new file mode 100644
index 0000000..1838480
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/map.cc
@@ -0,0 +1,210 @@
+// { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
+
+#include <flat_map>
+#include <format>
+#include <list>
+#include <map>
+#include <span>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <vector>
+
+struct NotFormattable
+{
+ friend auto operator<=>(NotFormattable, NotFormattable) = default;
+};
+
+static_assert( !std::formattable<std::map<int, NotFormattable>, char> );
+static_assert( !std::formattable<std::map<NotFormattable, int>, wchar_t> );
+
+template<typename... Args>
+bool
+is_format_string_for(const char* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_format_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename... Args>
+bool
+is_format_string_for(const wchar_t* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_wformat_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename Rg, typename CharT>
+bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
+{
+ using V = std::remove_cvref_t<std::ranges::range_reference_t<Rg>>;
+ std::range_formatter<V, CharT> fmt;
+ std::basic_format_parse_context<CharT> pc(spec);
+ try {
+ (void)fmt.parse(pc);
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+void
+test_format_string()
+{
+ // only pair<T, U> amd tuple<T, U> value types are supported
+ VERIFY( !is_range_formatter_spec_for("m", std::vector<int>()) );
+ VERIFY( !is_format_string_for("{:m}", std::vector<int>()) );
+ VERIFY( !is_range_formatter_spec_for("m", std::vector<std::tuple<int, int, int>>()) );
+ VERIFY( !is_format_string_for("{:m}", std::vector<std::tuple<int, int, int>>()) );
+
+ // invalid format stringss
+ VERIFY( !is_range_formatter_spec_for("?m", std::vector<std::pair<int, int>>()) );
+ VERIFY( !is_format_string_for("{:?m}", std::vector<std::pair<int, int>>()) );
+ VERIFY( !is_range_formatter_spec_for("m:", std::vector<std::pair<int, int>>()) );
+ VERIFY( !is_format_string_for("{:m:}", std::vector<std::pair<int, int>>()) );
+
+ // precision is not supported
+ VERIFY( !is_range_formatter_spec_for(".10m", std::vector<std::pair<int, int>>()) );
+ VERIFY( !is_format_string_for("{:.10m}", std::vector<std::pair<int, int>>()) );
+ VERIFY( !is_format_string_for("{:.{}m}", std::vector<std::pair<int, int>>(), 10) );
+
+ // width needs to be integer type
+ VERIFY( !is_format_string_for("{:{}m}", std::vector<std::pair<int, int>>(), 1.0f) );
+}
+
+template<typename _CharT, typename Range>
+void test_output(bool mapIsDefault)
+{
+ using Sv = std::basic_string_view<_CharT>;
+ using Pt = std::ranges::range_value_t<Range>;
+ using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pt>>;
+ using St = std::remove_cvref_t<std::tuple_element_t<1, Pt>>;
+ auto makeRange = [](std::span<Pt> s) {
+ return Range(s.data(), s.data() + s.size());
+ };
+
+ std::basic_string<_CharT> res;
+ size_t size = 0;
+
+ Ft f1[]{1, 2, 3};
+ St s1[]{11, 22, 33};
+ Pt v1[]{{f1[0], s1[0]}, {f1[1], s1[1]}, {f1[2], s1[2]}};
+
+ res = std::format(WIDEN("{}"), makeRange(v1));
+ if (mapIsDefault)
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}") );
+ else
+ VERIFY( res == WIDEN("[(1, 11), (2, 22), (3, 33)]") );
+
+ res = std::format(WIDEN("{:m}"), makeRange(v1));
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}") );
+ res = std::format(WIDEN("{:nm}"), makeRange(v1));
+ VERIFY( res == WIDEN("1: 11, 2: 22, 3: 33") );
+
+ res = std::format(WIDEN("{:3m}"), makeRange(v1));
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}") );
+
+ res = std::format(WIDEN("{:25m}"), makeRange(v1));
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33} ") );
+
+ res = std::format(WIDEN("{:{}m}"), makeRange(v1), 25);
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33} ") );
+
+ res = std::format(WIDEN("{1:{0}m}"), 25, makeRange(v1));
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33} ") );
+
+ res = std::format(WIDEN("{:25nm}"), makeRange(v1));
+ VERIFY( res == WIDEN("1: 11, 2: 22, 3: 33 ") );
+
+ res = std::format(WIDEN("{:*<23m}"), makeRange(v1));
+ VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}**") );
+
+ res = std::format(WIDEN("{:->24m}"), makeRange(v1));
+ VERIFY( res == WIDEN("---{1: 11, 2: 22, 3: 33}") );
+
+ res = std::format(WIDEN("{:=^25m}"), makeRange(v1));
+ VERIFY( res == WIDEN("=={1: 11, 2: 22, 3: 33}==") );
+
+ res = std::format(WIDEN("{:=^25nm}"), makeRange(v1));
+ VERIFY( res == WIDEN("===1: 11, 2: 22, 3: 33===") );
+
+ size = std::formatted_size(WIDEN("{:m}"), makeRange(v1));
+ VERIFY( size == Sv(WIDEN("{1: 11, 2: 22, 3: 33}")).size() );
+
+ size = std::formatted_size(WIDEN("{:3m}"), makeRange(v1));
+ VERIFY( size == Sv(WIDEN("{1: 11, 2: 22, 3: 33}")).size() );
+
+ size = std::formatted_size(WIDEN("{:25m}"), makeRange(v1));
+ VERIFY( size == 25 );
+}
+
+template<class Range>
+void test_output_c(bool mapIsDefault = false)
+{
+ test_output<char, Range>(mapIsDefault);
+ test_output<wchar_t, Range>(mapIsDefault);
+}
+
+template<template<typename> class RangeT>
+void test_output_pc()
+{
+ test_output_c<RangeT<std::pair<int, int>>>();
+ test_output_c<RangeT<std::pair<const int, int>>>();
+ test_output_c<RangeT<std::tuple<const int&, int&>>>();
+}
+
+void
+test_outputs()
+{
+ using namespace __gnu_test;
+ test_output_c<std::map<int, int>>(true);
+ test_output_c<std::flat_map<int, int>>(true);
+
+ test_output_pc<std::vector>();
+ test_output_pc<std::list>();
+ test_output_pc<std::span>();
+
+ test_output_pc<test_forward_range>();
+ test_output_pc<test_input_range>();
+ test_output_pc<test_input_range_nocopy>();
+}
+
+void
+test_nested()
+{
+ std::vector<std::map<int, std::string>> vm{
+ {{1, "one"}, {2, "two"}},
+ {{1, "jeden"}, {2, "dwa"}},
+ };
+ std::string res;
+
+ res = std::format("{}", vm);
+ VERIFY( res == R"([{1: "one", 2: "two"}, {1: "jeden", 2: "dwa"}])" );
+ res = std::format("{:n:n}", vm);
+ VERIFY( res == R"(1: "one", 2: "two", 1: "jeden", 2: "dwa")" );
+
+ std::map<std::string, std::vector<std::string>> mv{
+ {"english", {"zero", "one", "two"}},
+ {"polish", {"zero", "jeden", "dwa"}},
+ };
+ res = std::format("{}", mv);
+ VERIFY( res == R"({"english": ["zero", "one", "two"], "polish": ["zero", "jeden", "dwa"]})" );
+}
+
+int main()
+{
+ test_format_string();
+ test_outputs();
+ test_nested();
+}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
new file mode 100644
index 0000000..75fe4c1
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
@@ -0,0 +1,323 @@
+// { dg-do run { target c++23 } }
+// { dg-options "-fexec-charset=UTF-8" }
+// { dg-timeout-factor 2 }
+
+#include <array>
+#include <format>
+#include <list>
+#include <ranges>
+#include <span>
+#include <string>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <vector>
+
+struct NotFormattable
+{};
+
+static_assert(!std::formattable<std::vector<NotFormattable>, char>);
+static_assert(!std::formattable<std::span<NotFormattable>, wchar_t>);
+
+template<typename... Args>
+bool
+is_format_string_for(const char* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_format_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename... Args>
+bool
+is_format_string_for(const wchar_t* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_wformat_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename Rg, typename CharT>
+bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
+{
+ using V = std::remove_cvref_t<std::ranges::range_reference_t<Rg>>;
+ std::range_formatter<V, CharT> fmt;
+ std::basic_format_parse_context<CharT> pc(spec);
+ try {
+ (void)fmt.parse(pc);
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+void
+test_format_string()
+{
+ // invalid format spec 'p'
+ VERIFY( !is_range_formatter_spec_for("p", std::vector<int>()) );
+ VERIFY( !is_format_string_for("{:p}", std::vector<int>()) );
+ VERIFY( !is_range_formatter_spec_for("np", std::vector<int>()) );
+ VERIFY( !is_format_string_for("{:np}", std::vector<int>()) );
+
+ // width needs to be integer type
+ VERIFY( !is_format_string_for("{:{}}", std::vector<int>(), 1.0f) );
+
+ // element format needs to be valid
+ VERIFY( !is_range_formatter_spec_for(":p", std::vector<int>()) );
+ VERIFY( !is_format_string_for("{::p}", std::vector<int>()) );
+ VERIFY( !is_range_formatter_spec_for("n:p", std::vector<int>()) );
+ VERIFY( !is_format_string_for("{:n:p}", std::vector<int>()) );
+}
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template<typename _CharT, typename Range, typename Storage>
+void test_output()
+{
+ using Sv = std::basic_string_view<_CharT>;
+ using T = std::ranges::range_value_t<Range>;
+ auto makeRange = [](Storage& s) -> Range {
+ if constexpr (std::is_same_v<std::remove_cvref_t<Range>, Storage>)
+ return s;
+ else
+ return Range(std::ranges::data(s),
+ std::ranges::data(s) + std::ranges::size(s));
+ };
+
+ std::basic_string<_CharT> res;
+ size_t size = 0;
+
+ Storage v1{1, 2, 3};
+ res = std::format(WIDEN("{}"), makeRange(v1));
+ VERIFY( res == WIDEN("[1, 2, 3]") );
+ res = std::format(WIDEN("{:}"), makeRange(v1));
+ VERIFY( res == WIDEN("[1, 2, 3]") );
+ res = std::format(WIDEN("{:n}"), makeRange(v1));
+ VERIFY( res == WIDEN("1, 2, 3") );
+
+ res = std::format(WIDEN("{:3}"), makeRange(v1));
+ VERIFY( res == WIDEN("[1, 2, 3]") );
+
+ res = std::format(WIDEN("{:10}"), makeRange(v1));
+ VERIFY( res == WIDEN("[1, 2, 3] ") );
+
+ res = std::format(WIDEN("{:{}}"), makeRange(v1), 10);
+ VERIFY( res == WIDEN("[1, 2, 3] ") );
+
+ res = std::format(WIDEN("{1:{0}}"), 10, makeRange(v1));
+ VERIFY( res == WIDEN("[1, 2, 3] ") );
+
+ res = std::format(WIDEN("{:10n}"), makeRange(v1));
+ VERIFY( res == WIDEN("1, 2, 3 ") );
+
+ res = std::format(WIDEN("{:*<11}"), makeRange(v1));
+ VERIFY( res == WIDEN("[1, 2, 3]**") );
+
+ res = std::format(WIDEN("{:->12}"), makeRange(v1));
+ VERIFY( res == WIDEN("---[1, 2, 3]") );
+
+ res = std::format(WIDEN("{:=^13}"), makeRange(v1));
+ VERIFY( res == WIDEN("==[1, 2, 3]==") );
+
+ res = std::format(WIDEN("{:=^13n}"), makeRange(v1));
+ VERIFY( res == WIDEN("===1, 2, 3===") );
+
+ res = std::format(WIDEN("{::#x}"), makeRange(v1));
+ VERIFY( res == WIDEN("[0x1, 0x2, 0x3]") );
+
+ res = std::format(WIDEN("{:|^25n:#05x}"), makeRange(v1));
+ VERIFY( res == WIDEN("|||0x001, 0x002, 0x003|||") );
+
+ // ':' is start of the format string for element
+ res = std::format(WIDEN("{::^+04}"), makeRange(v1));
+ VERIFY( res == WIDEN("[ +1 , +2 , +3 ]") );
+
+ size = std::formatted_size(WIDEN("{:}"), makeRange(v1));
+ VERIFY( size == Sv(WIDEN("[1, 2, 3]")).size() );
+
+ size = std::formatted_size(WIDEN("{:3}"), makeRange(v1));
+ VERIFY( size == Sv(WIDEN("[1, 2, 3]")).size() );
+
+ size = std::formatted_size(WIDEN("{:10}"), makeRange(v1));
+ VERIFY( size == 10 );
+
+ size = std::formatted_size(WIDEN("{:|^25n:#05x}"), makeRange(v1));
+ VERIFY( size == 25 );
+}
+
+template<typename Cont>
+void test_output_cont()
+{
+ test_output<char, Cont&, Cont>();
+ test_output<wchar_t, Cont const&, Cont>();
+}
+
+template<typename View>
+void test_output_view()
+{
+ test_output<char, View, int[3]>();
+ test_output<wchar_t, View, int[3]>();
+}
+
+void
+test_outputs()
+{
+ using namespace __gnu_test;
+ test_output_cont<std::vector<int>>();
+ test_output_cont<std::list<int>>();
+ test_output_cont<std::array<int, 3>>();
+
+ test_output_view<std::span<int>>();
+ test_output_view<std::ranges::subrange<int*>>();
+ test_output_view<test_forward_range<int>>();
+ test_output_view<test_input_range<int>>();
+ test_output_view<test_input_range_nocopy<int>>();
+
+ test_output_view<std::span<const int>>();
+ test_output_view<std::ranges::subrange<const int*>>();
+ test_output_view<test_forward_range<const int>>();
+}
+
+void
+test_nested()
+{
+ std::vector<std::vector<int>> v
+ {
+ {1, 2},
+ {11, 12}
+ };
+
+ std::string res = std::format("{}", v);
+ VERIFY( res == "[[1, 2], [11, 12]]" );
+
+ res = std::format("{:+^18:n:02}", v);
+ VERIFY( res == "+[01, 02, 11, 12]+" );
+}
+
+bool strip_quote(std::string_view& v)
+{
+ if (!v.starts_with('"'))
+ return false;
+ v.remove_prefix(1);
+ return true;
+}
+
+bool strip_prefix(std::string_view& v, std::string_view expected, bool quoted = false)
+{
+ if (quoted && !strip_quote(v))
+ return false;
+ if (!v.starts_with(expected))
+ return false;
+ v.remove_prefix(expected.size());
+ if (quoted && !strip_quote(v))
+ return false;
+ return true;
+}
+
+bool strip_squares(std::string_view& v)
+{
+ if (!v.starts_with('[') || !v.ends_with(']'))
+ return false;
+ v.remove_prefix(1);
+ v.remove_suffix(1);
+ return true;
+}
+
+bool strip_prefix(std::string_view& v, size_t n, char c)
+{
+ size_t pos = v.find_first_not_of(c);
+ if (pos == std::string_view::npos)
+ pos = v.size();
+ if (pos != n)
+ return false;
+ v.remove_prefix(n);
+ return true;
+}
+
+void test_padding()
+{
+ std::string res;
+ std::string_view resv;
+
+ // width is 3, size is 15
+ std::string in = "o\u0302\u0323i\u0302\u0323u\u0302\u0323";
+ in += in; // width is 6, size is 30
+ in += in; // width is 12, size is 60
+ in += in; // width is 24, size is 120
+ in += in; // width is 48, size is 240
+ // width is 192, size is 960
+ std::vector<std::string> const vs{in, in, in, in};
+
+ auto const check_elems = [=](std::string_view& v, bool quoted)
+ {
+ VERIFY( strip_prefix(v, in, quoted) );
+ VERIFY( strip_prefix(v, ", ", false) );
+ VERIFY( strip_prefix(v, in, quoted) );
+ VERIFY( strip_prefix(v, ", ", false) );
+ VERIFY( strip_prefix(v, in, quoted) );
+ VERIFY( strip_prefix(v, ", ", false) );
+ VERIFY( strip_prefix(v, in, quoted) );
+ return v.empty();
+ };
+
+ resv = res = std::format("{}", vs);
+ VERIFY( strip_squares(resv) );
+ VERIFY( check_elems(resv, true) );
+
+ resv = res = std::format("{:n}", vs);
+ VERIFY( check_elems(resv, true) );
+
+ resv = res = std::format("{::}", vs);
+ VERIFY( strip_squares(resv) );
+ VERIFY( check_elems(resv, false) );
+
+ resv = res = std::format("{:n:}", vs);
+ VERIFY( check_elems(resv, false) );
+
+ resv = res = std::format("{:*>10}", vs);
+ VERIFY( strip_squares(resv) );
+ VERIFY( check_elems(resv, true) );
+
+ resv = res = std::format("{:*>10n}", vs);
+ VERIFY( check_elems(resv, true) );
+
+ resv = res = std::format("{:*>10:}", vs);
+ VERIFY( strip_squares(resv) );
+ VERIFY( check_elems(resv, false) );
+
+ resv = res = std::format("{:*>10n:}", vs);
+ VERIFY( check_elems(resv, false) );
+
+ resv = res = std::format("{:*>240}", vs);
+ VERIFY( strip_prefix(resv, 32, '*') );
+ VERIFY( strip_squares(resv) );
+ VERIFY( check_elems(resv, true) );
+
+ resv = res = std::format("{:*>240n}", vs);
+ VERIFY( strip_prefix(resv, 34, '*') );
+ VERIFY( check_elems(resv, true) );
+
+ resv = res = std::format("{:*>240:}", vs);
+ VERIFY( strip_prefix(resv, 40, '*') );
+ VERIFY( strip_squares(resv) );
+ VERIFY( check_elems(resv, false) );
+
+ resv = res = std::format("{:*>240n:}", vs);
+ VERIFY( strip_prefix(resv, 42, '*') );
+ VERIFY( check_elems(resv, false) );
+}
+
+int main()
+{
+ test_format_string();
+ test_outputs();
+ test_nested();
+ test_padding();
+}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/string.cc b/libstdc++-v3/testsuite/std/format/ranges/string.cc
new file mode 100644
index 0000000..cebdd53
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/string.cc
@@ -0,0 +1,290 @@
+// { dg-do run { target c++23 } }
+// { dg-options "-fexec-charset=UTF-8" }
+// { dg-timeout-factor 2 }
+
+#include <format>
+#include <forward_list>
+#include <span>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+#include <vector>
+
+template<typename... Args>
+bool
+is_format_string_for(const char* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_format_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename... Args>
+bool
+is_format_string_for(const wchar_t* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_wformat_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename Rg, typename CharT>
+bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
+{
+ using V = std::remove_cvref_t<std::ranges::range_reference_t<Rg>>;
+ std::range_formatter<V, CharT> fmt;
+ std::basic_format_parse_context<CharT> pc(spec);
+ try {
+ (void)fmt.parse(pc);
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+void
+test_format_string()
+{
+ // only CharT value types are supported
+ VERIFY( !is_range_formatter_spec_for(L"s", std::vector<char>()) );
+ VERIFY( !is_format_string_for(L"{:s}", std::vector<char>()) );
+ VERIFY( !is_range_formatter_spec_for(L"s", std::vector<char>()) );
+ VERIFY( !is_format_string_for(L"{:s}", std::vector<char>()) );
+ VERIFY( !is_range_formatter_spec_for("s", std::vector<int>()) );
+ VERIFY( !is_format_string_for("{:s}", std::vector<int>()) );
+
+ // invalid format stringss
+ VERIFY( !is_range_formatter_spec_for("?", std::vector<char>()) );
+ VERIFY( !is_format_string_for("{:?}", std::vector<char>()) );
+ VERIFY( !is_range_formatter_spec_for("ns", std::vector<char>()) );
+ VERIFY( !is_format_string_for("{:ns}", std::vector<char>()) );
+ VERIFY( !is_range_formatter_spec_for("s:", std::vector<char>()) );
+ VERIFY( !is_format_string_for("{:s:}", std::vector<char>()) );
+
+ // precision is not supported, even for s
+ VERIFY( !is_range_formatter_spec_for(".10s", std::vector<char>()) );
+ VERIFY( !is_format_string_for("{:.10s}", std::vector<char>()) );
+ VERIFY( !is_format_string_for("{:.{}s}", std::vector<char>(), 10) );
+
+ // width needs to be integer type
+ VERIFY( !is_format_string_for("{:{}s}", std::vector<char>(), 1.0f) );
+}
+
+template<typename Range>
+void test_output()
+{
+ using _CharT = std::ranges::range_value_t<Range>;
+ auto makeRange = [](std::basic_string<_CharT>& s) {
+ return Range(s.data(), s.data() + s.size());
+ };
+ std::basic_string<_CharT> res;
+ size_t size = 0;
+
+ std::basic_string<_CharT> s1 = WIDEN("abcd");
+ res = std::format(WIDEN("{}"), makeRange(s1));
+ VERIFY( res == WIDEN("['a', 'b', 'c', 'd']") );
+
+ res = std::format(WIDEN("{::}"), makeRange(s1));
+ VERIFY( res == WIDEN("[a, b, c, d]") );
+
+ res = std::format(WIDEN("{:s}"), makeRange(s1));
+ VERIFY( res == WIDEN("abcd") );
+
+ res = std::format(WIDEN("{:?s}"), makeRange(s1));
+ VERIFY( res == WIDEN(R"("abcd")") );
+
+ res = std::format(WIDEN("{:3s}"), makeRange(s1));
+ VERIFY( res == WIDEN("abcd") );
+
+ res = std::format(WIDEN("{:7s}"), makeRange(s1));
+ VERIFY( res == WIDEN("abcd ") );
+
+ res = std::format(WIDEN("{:{}s}"), makeRange(s1), 7);
+ VERIFY( res == WIDEN("abcd ") );
+
+ res = std::format(WIDEN("{1:{0}s}"), 7, makeRange(s1));
+ VERIFY( res == WIDEN("abcd ") );
+
+ res = std::format(WIDEN("{:*>6s}"), makeRange(s1));
+ VERIFY( res == WIDEN("**abcd") );
+
+ res = std::format(WIDEN("{:-<5s}"), makeRange(s1));
+ VERIFY( res == WIDEN("abcd-") );
+
+ res = std::format(WIDEN("{:=^8s}"), makeRange(s1));
+ VERIFY( res == WIDEN("==abcd==") );
+
+ std::basic_string<_CharT> s2(512, static_cast<_CharT>('a'));
+ res = std::format(WIDEN("{:=^8s}"), makeRange(s2));
+ VERIFY( res == s2 );
+
+ size = std::formatted_size(WIDEN("{:s}"), makeRange(s1));
+ VERIFY( size == 4 );
+
+ size = std::formatted_size(WIDEN("{:3s}"), makeRange(s1));
+ VERIFY( size == 4 );
+
+ size = std::formatted_size(WIDEN("{:7s}"), makeRange(s1));
+ VERIFY( size == 7 );
+
+ size = std::formatted_size(WIDEN("{:s}"), makeRange(s2));
+ VERIFY( size == 512 );
+}
+
+template<typename CharT>
+struct cstr_view
+{
+ cstr_view() = default;
+ explicit cstr_view(CharT* f, CharT* l)
+ : ptr(f)
+ { VERIFY(!*l); }
+
+ struct sentinel
+ {
+ friend constexpr
+ bool operator==(CharT const* ptr, sentinel) noexcept
+ { return !*ptr; }
+ };
+
+ constexpr
+ CharT* begin() const noexcept
+ { return ptr; };
+ static constexpr
+ sentinel end() noexcept
+ { return {}; }
+
+private:
+ CharT* ptr = "";
+};
+
+template<typename CharT>
+void
+test_outputs()
+{
+ using namespace __gnu_test;
+ test_output<std::vector<CharT>>();
+ test_output<std::span<CharT>>();
+ test_output<cstr_view<CharT>>();
+
+ test_output<test_forward_range<CharT>>();
+ test_output<test_forward_sized_range<CharT>>();
+
+ test_output<test_input_range<CharT>>();
+ test_output<test_input_sized_range<CharT>>();
+
+ test_output<test_range_nocopy<CharT, input_iterator_wrapper_nocopy>>();
+ test_output<test_sized_range<CharT, input_iterator_wrapper_nocopy>>();
+
+ test_output<std::span<const CharT>>();
+ test_output<cstr_view<const CharT>>();
+ test_output<test_forward_range<const CharT>>();
+
+ static_assert(!std::formattable<std::span<volatile CharT>, CharT>);
+ static_assert(!std::formattable<std::span<const volatile CharT>, CharT>);
+}
+
+void
+test_nested()
+{
+ std::string_view s1 = "str1";
+ std::string_view s2 = "str2";
+
+ std::vector<std::string> vs;
+ vs.emplace_back(s1);
+ vs.emplace_back(s2);
+
+ VERIFY( std::format("{}", vs) == R"(["str1", "str2"])" );
+ VERIFY( std::format("{:}", vs) == R"(["str1", "str2"])" );
+ VERIFY( std::format("{::?}", vs) == R"(["str1", "str2"])" );
+ VERIFY( std::format("{::}", vs) == R"([str1, str2])" );
+
+ std::vector<std::vector<char>> vv;
+ vv.emplace_back(s1.begin(), s1.end());
+ vv.emplace_back(s2.begin(), s2.end());
+ std::string_view escaped = R"([['s', 't', 'r', '1'], ['s', 't', 'r', '2']])";
+
+ VERIFY( std::format("{}", vv) == escaped );
+ VERIFY( std::format("{:}", vv) == escaped );
+ VERIFY( std::format("{::}", vv) == escaped );
+ VERIFY( std::format("{:::?}", vv) == escaped );
+ VERIFY( std::format("{:::}", vv) == R"([[s, t, r, 1], [s, t, r, 2]])" );
+ VERIFY( std::format("{::s}", vv) == R"([str1, str2])" );
+ VERIFY( std::format("{::?s}", vv) == R"(["str1", "str2"])" );
+}
+
+bool strip_quotes(std::string_view& v)
+{
+ if (!v.starts_with('"') || !v.ends_with('"'))
+ return false;
+ v.remove_prefix(1);
+ v.remove_suffix(1);
+ return true;
+}
+
+bool strip_prefix(std::string_view& v, size_t n, char c)
+{
+ size_t pos = v.find_first_not_of(c);
+ if (pos == std::string_view::npos)
+ pos = v.size();
+ if (pos != n)
+ return false;
+ v.remove_prefix(n);
+ return true;
+}
+
+
+void test_padding()
+{
+ std::string res;
+ std::string_view resv;
+
+ // width is 3, size is 15
+ std::string in = "o\u0302\u0323i\u0302\u0323u\u0302\u0323";
+ in += in; // width is 6, size is 30
+ in += in; // width is 12, size is 60
+ in += in; // width is 24, size is 120
+ in += in; // width is 48, size is 240
+ in += in; // width is 96, size is 480
+ in += in; // width is 192, size is 960
+
+ std::forward_list<char> lc(std::from_range, in);
+
+ resv = res = std::format("{:s}", lc);
+ VERIFY( resv == in );
+
+ resv = res = std::format("{:*>10s}", lc);
+ VERIFY( resv == in );
+
+ resv = res = std::format("{:*>240s}", lc);
+ VERIFY( strip_prefix(resv, 48, '*') );
+ VERIFY( resv == in );
+
+ resv = res = std::format("{:?s}", lc);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == in );
+
+ resv = res = std::format("{:*>10?s}", lc);
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == in );
+
+ resv = res = std::format("{:*>240?s}", lc);
+ VERIFY( strip_prefix(resv, 46, '*') );
+ VERIFY( strip_quotes(resv) );
+ VERIFY( resv == in );
+}
+
+int main()
+{
+ test_format_string();
+ test_outputs<char>();
+ test_outputs<wchar_t>();
+ test_nested();
+}
diff --git a/libstdc++-v3/testsuite/std/format/tuple.cc b/libstdc++-v3/testsuite/std/format/tuple.cc
new file mode 100644
index 0000000..ff0359b
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/tuple.cc
@@ -0,0 +1,352 @@
+// { dg-do run { target c++23 } }
+// { dg-options "-fexec-charset=UTF-8" }
+// { dg-timeout-factor 2 }
+
+#include <format>
+#include <string>
+#include <testsuite_hooks.h>
+#include <tuple>
+#include <utility>
+
+struct NotFormattable
+{};
+
+static_assert( !std::formattable<std::pair<int, NotFormattable>, char> );
+static_assert( !std::formattable<std::tuple<int, NotFormattable, int>, wchar_t> );
+
+template<typename... Args>
+bool
+is_format_string_for(const char* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_format_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+template<typename... Args>
+bool
+is_format_string_for(const wchar_t* str, Args&&... args)
+{
+ try {
+ (void) std::vformat(str, std::make_wformat_args(args...));
+ return true;
+ } catch (const std::format_error&) {
+ return false;
+ }
+}
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+void
+test_format_string()
+{
+ // invalid format stringss
+ VERIFY( !is_format_string_for("{:p}", std::tuple<>()) );
+ VERIFY( !is_format_string_for("{:nm}", std::tuple<>()) );
+
+ // 'm' is only valid for 2 elemenst
+ VERIFY( !is_format_string_for("{:m}", std::tuple<>()) );
+ VERIFY( !is_format_string_for("{:m}", std::tuple<int, int, int>()) );
+
+ // element specifier is not supported
+ VERIFY( !is_format_string_for("{::}", std::tuple<>()) );
+
+ // precision is not supported
+ VERIFY( !is_format_string_for("{:.10}", std::tuple<>()) );
+
+ // width needs to be integer type
+ VERIFY( !is_format_string_for("{:{}}", std::tuple<>(), 1.0f) );
+}
+
+template<typename _CharT>
+void test_multi()
+{
+ using Sv = std::basic_string_view<_CharT>;
+ using Str = std::basic_string<_CharT>;
+
+ std::basic_string<_CharT> res;
+ std::size_t size = 0;
+ std::tuple<int, Str, float> t1(1, WIDEN("test"), 2.1);
+
+ res = std::format(WIDEN("{}"), t1);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1))") );
+ res = std::format(WIDEN("{:}"), t1);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1))") );
+ res = std::format(WIDEN("{:n}"), t1);
+ VERIFY( res == WIDEN(R"(1, "test", 2.1)") );
+
+ res = std::format(WIDEN("{:3}"), t1);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1))") );
+
+ res = std::format(WIDEN("{:20}"), t1);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1) )") );
+
+ res = std::format(WIDEN("{:{}}"), t1, 20);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1) )") );
+
+ res = std::format(WIDEN("{1:{0}}"), 20, t1);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1) )") );
+
+ res = std::format(WIDEN("{:^>17}"), t1);
+ VERIFY( res == WIDEN(R"(^(1, "test", 2.1))") );
+
+ res = std::format(WIDEN("{:$<18}"), t1);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1)$$)") );
+
+ res = std::format(WIDEN("{:+^19}"), t1);
+ VERIFY( res == WIDEN(R"(+(1, "test", 2.1)++)") );
+
+ res = std::format(WIDEN("{:|^19n}"), t1);
+ VERIFY( res == WIDEN(R"(||1, "test", 2.1|||)") );
+
+ size = std::formatted_size(WIDEN("{}"), t1);
+ VERIFY( size == Sv(WIDEN(R"((1, "test", 2.1))")).size() );
+
+ size = std::formatted_size(WIDEN("{:3}"), t1);
+ VERIFY( size == Sv(WIDEN(R"((1, "test", 2.1))")).size() );
+
+ size = std::formatted_size(WIDEN("{:20}"), t1);
+ VERIFY( size == 20 );
+
+ std::tuple<int&, Str&, float&> t2 = t1;
+ res = std::format(WIDEN("{}"), t2);
+ VERIFY( res == WIDEN(R"((1, "test", 2.1))") );
+
+ std::tuple<int, int, int, int> t3(1, 2, 3, 4);
+ res = std::format(WIDEN("{}"), t3);
+ VERIFY( res == WIDEN(R"((1, 2, 3, 4))") );
+
+}
+
+template<typename _CharT, typename Tuple>
+void test_empty()
+{
+ std::basic_string<_CharT> res;
+
+ Tuple e1;
+ res = std::format(WIDEN("{}"), e1);
+ VERIFY( res == WIDEN(R"(())") );
+
+ res = std::format(WIDEN("{:}"), e1);
+ VERIFY( res == WIDEN(R"(())") );
+
+ res = std::format(WIDEN("{:n}"), e1);
+ VERIFY( res == WIDEN(R"()") );
+
+ res = std::format(WIDEN("{:^>6}"), e1);
+ VERIFY( res == WIDEN(R"(^^^^())") );
+}
+
+template<typename _CharT, typename Pair>
+void test_pair()
+{
+ using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pair>>;
+ using St = std::remove_cvref_t<std::tuple_element_t<1, Pair>>;
+
+ std::basic_string<_CharT> res;
+
+ Ft f1 = 1;
+ St s1 = WIDEN("abc");
+ Pair p1(f1, s1);
+
+ res = std::format(WIDEN("{}"), p1);
+ VERIFY( res == WIDEN(R"((1, "abc"))") );
+
+ res = std::format(WIDEN("{:}"), p1);
+ VERIFY( res == WIDEN(R"((1, "abc"))") );
+
+ res = std::format(WIDEN("{:m}"), p1);
+ VERIFY( res == WIDEN(R"(1: "abc")") );
+
+ res = std::format(WIDEN("{:|^12m}"), p1);
+ VERIFY( res == WIDEN(R"(||1: "abc"||)") );
+}
+
+template<typename CharT, template<typename, typename> class PairT>
+void test_pair_e()
+{
+ test_pair<CharT, PairT<int, std::basic_string<CharT>>>();
+ test_pair<CharT, PairT<int, const CharT*>>();
+ test_pair<CharT, PairT<const int, std::basic_string<CharT>>>();
+ test_pair<CharT, PairT<int&, std::basic_string<CharT>&>>();
+ test_pair<CharT, PairT<const int&, const std::basic_string<CharT>&>>();
+}
+
+template<typename Pair>
+struct MyPair : Pair
+{
+ using Pair::Pair;
+};
+
+template<typename Pair, typename CharT>
+struct std::formatter<MyPair<Pair>, CharT>
+{
+ constexpr formatter() noexcept
+ {
+ using _CharT = CharT;
+ _formatter.set_brackets(WIDEN("<"), WIDEN(">"));
+ _formatter.set_separator(WIDEN("; "));
+ }
+
+ constexpr std::basic_format_parse_context<CharT>::iterator
+ parse(std::basic_format_parse_context<CharT>& pc)
+ { return _formatter.parse(pc); }
+
+ template<typename Out>
+ typename std::basic_format_context<Out, CharT>::iterator
+ format(const MyPair<Pair>& mp,
+ std::basic_format_context<Out, CharT>& fc) const
+ { return _formatter.format(mp, fc); }
+
+private:
+ std::formatter<Pair, CharT> _formatter;
+};
+
+template<typename _CharT, template<typename, typename> class PairT>
+void test_custom()
+{
+ std::basic_string<_CharT> res;
+ MyPair<PairT<int, const _CharT*>> c1(1, WIDEN("abc"));
+
+ res = std::format(WIDEN("{}"), c1);
+ VERIFY( res == WIDEN(R"(<1; "abc">)") );
+
+ res = std::format(WIDEN("{:}"), c1);
+ VERIFY( res == WIDEN(R"(<1; "abc">)") );
+
+ res = std::format(WIDEN("{:n}"), c1);
+ VERIFY( res == WIDEN(R"(1; "abc")") );
+
+ res = std::format(WIDEN("{:m}"), c1);
+ VERIFY( res == WIDEN(R"(1: "abc")") );
+
+ res = std::format(WIDEN("{:|^14}"), c1);
+ VERIFY( res == WIDEN(R"(||<1; "abc">||)") );
+}
+
+template<typename CharT>
+void test_outputs()
+{
+ test_multi<CharT>();
+ test_empty<CharT, std::tuple<>>();
+ test_pair_e<CharT, std::pair>();
+ test_pair_e<CharT, std::tuple>();
+ test_custom<CharT, std::pair>();
+ test_custom<CharT, std::tuple>();
+}
+
+void test_nested()
+{
+ std::string res;
+ std::tuple<std::tuple<>, std::pair<int, std::string>> tt{{}, {1, "abc"}};
+
+ res = std::format("{}", tt);
+ VERIFY( res == R"(((), (1, "abc")))" );
+ res = std::format("{:n}", tt);
+ VERIFY( res == R"((), (1, "abc"))" );
+ res = std::format("{:m}", tt);
+ VERIFY( res == R"((): (1, "abc"))" );
+}
+
+bool strip_quote(std::string_view& v)
+{
+ if (!v.starts_with('"'))
+ return false;
+ v.remove_prefix(1);
+ return true;
+}
+
+bool strip_prefix(std::string_view& v, std::string_view expected, bool quoted = false)
+{
+ if (quoted && !strip_quote(v))
+ return false;
+ if (!v.starts_with(expected))
+ return false;
+ v.remove_prefix(expected.size());
+ if (quoted && !strip_quote(v))
+ return false;
+ return true;
+}
+
+bool strip_parens(std::string_view& v)
+{
+ if (!v.starts_with('(') || !v.ends_with(')'))
+ return false;
+ v.remove_prefix(1);
+ v.remove_suffix(1);
+ return true;
+}
+
+bool strip_prefix(std::string_view& v, size_t n, char c)
+{
+ size_t pos = v.find_first_not_of(c);
+ if (pos == std::string_view::npos)
+ pos = v.size();
+ if (pos != n)
+ return false;
+ v.remove_prefix(n);
+ return true;
+}
+
+void test_padding()
+{
+ std::string res;
+ std::string_view resv;
+
+ // width is 3, size is 15
+ std::string in = "o\u0302\u0323i\u0302\u0323u\u0302\u0323";
+ in += in; // width is 6, size is 30
+ in += in; // width is 12, size is 60
+ in += in; // width is 24, size is 120
+ in += in; // width is 48, size is 240
+ // width is 192, size is 960
+ auto const ts = std::make_tuple(in, in, in, in);
+
+ auto const check_elems = [=](std::string_view& v)
+ {
+ VERIFY( strip_prefix(v, in, true) );
+ VERIFY( strip_prefix(v, ", ", false) );
+ VERIFY( strip_prefix(v, in, true) );
+ VERIFY( strip_prefix(v, ", ", false) );
+ VERIFY( strip_prefix(v, in, true) );
+ VERIFY( strip_prefix(v, ", ", false) );
+ VERIFY( strip_prefix(v, in, true) );
+ return v.empty();
+ };
+
+ resv = res = std::format("{}", ts);
+ VERIFY( strip_parens(resv) );
+ VERIFY( check_elems(resv) );
+
+ resv = res = std::format("{:n}", ts);
+ VERIFY( check_elems(resv) );
+
+ resv = res = std::format("{:*>10}", ts);
+ VERIFY( strip_parens(resv) );
+ VERIFY( check_elems(resv) );
+
+ resv = res = std::format("{:*>10n}", ts);
+ VERIFY( check_elems(resv) );
+
+ resv = res = std::format("{:*>240}", ts);
+ VERIFY( strip_prefix(resv, 32, '*') );
+ VERIFY( strip_parens(resv) );
+ VERIFY( check_elems(resv) );
+
+ resv = res = std::format("{:*>240n}", ts);
+ VERIFY( strip_prefix(resv, 34, '*') );
+ VERIFY( check_elems(resv) );
+}
+
+int main()
+{
+ test_format_string();
+ test_outputs<char>();
+ test_outputs<wchar_t>();
+ test_nested();
+ test_padding();
+}
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc
index 3f1f8eb..5ccf47d 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc
@@ -69,10 +69,23 @@ test03()
auto r2 = views::as_const(views::all(v));
}
+void
+test04()
+{
+ // PR libstdc++/115046 - meta-recursion with join_view and as_const_view
+ int x[3] = {1,2,3};
+ auto v = x
+ | views::chunk(3)
+ | views::transform(views::as_const)
+ | views::join;
+ VERIFY( ranges::equal(v, x) );
+}
+
int
main()
{
static_assert(test01());
static_assert(test02());
test03();
+ test04();
}
diff --git a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/cons/43820_neg.cc
index 7b5ede4..03fad14 100644
--- a/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/cons/43820_neg.cc
+++ b/libstdc++-v3/testsuite/tr1/2_general_utilities/shared_ptr/cons/43820_neg.cc
@@ -39,9 +39,6 @@ void test01()
// { dg-error "incomplete" "" { target *-*-* } 600 }
}
-// { dg-error "-Wdelete-incomplete" "" { target c++26 } 283 }
-// { dg-error "-Wdelete-incomplete" "" { target c++26 } 305 }
-
// Ignore additional diagnostic given with -Wsystem-headers:
// { dg-prune-output "has incomplete type" }
// { dg-prune-output "possible problem detected" }
diff --git a/libstdc++-v3/testsuite/util/debug/unordered_checks.h b/libstdc++-v3/testsuite/util/debug/unordered_checks.h
index d01ee82..785aeb4 100644
--- a/libstdc++-v3/testsuite/util/debug/unordered_checks.h
+++ b/libstdc++-v3/testsuite/util/debug/unordered_checks.h
@@ -65,28 +65,36 @@ namespace __gnu_test
template<typename _Tp>
struct KeyExtractor
{
- static _Tp get_key(const _Tp& val)
+ static const _Tp& get_key(const _Tp& val)
{ return val; }
};
template<typename _Tp1, typename _Tp2>
- struct KeyExtractor<std::pair<const _Tp1, _Tp2>>
+ struct KeyExtractor<std::pair<_Tp1, _Tp2>>
{
- static _Tp1 get_key(const std::pair<const _Tp1, _Tp2>& val)
+ static const _Tp1& get_key(const std::pair<_Tp1, _Tp2>& val)
{ return val.first; }
};
template<typename _Tp>
- void use_erased_local_iterator()
+ void fill_container(_Tp& c)
{
typedef _Tp cont_type;
typedef typename cont_type::value_type cont_val_type;
typedef typename CopyableValueType<cont_val_type>::value_type val_type;
generate_unique<val_type> gu;
- cont_type c;
for (size_t i = 0; i != 5; ++i)
c.insert(gu.build());
+ }
+
+ template<typename _Tp>
+ void use_erased_local_iterator()
+ {
+ typedef _Tp cont_type;
+ typedef typename cont_type::value_type cont_val_type;
+ cont_type c;
+ fill_container(c);
typename cont_type::local_iterator it, end;
for (size_t i = 0; i != c.bucket_count(); ++i)
@@ -96,22 +104,18 @@ namespace __gnu_test
if (it != end)
break;
}
- typename cont_type::key_type key = KeyExtractor<cont_val_type>::get_key(*it);
+
+ const auto& key = KeyExtractor<cont_val_type>::get_key(*it);
c.erase(key);
VERIFY( it != end );
}
template<typename _Tp>
- void use_invalid_local_iterator()
+ typename _Tp::local_iterator
+ fill_and_get_local_iterator(_Tp& c)
{
typedef _Tp cont_type;
- typedef typename cont_type::value_type cont_val_type;
- typedef typename CopyableValueType<cont_val_type>::value_type val_type;
- generate_unique<val_type> gu;
-
- cont_type c;
- for (size_t i = 0; i != 5; ++i)
- c.insert(gu.build());
+ fill_container(c);
typename cont_type::local_iterator it;
for (size_t i = 0; i != c.bucket_count(); ++i)
@@ -120,22 +124,107 @@ namespace __gnu_test
if (it != c.end(i))
break;
}
- cont_val_type val = *it;
+
+ return it;
+ }
+
+ template<typename _Tp>
+ void use_invalid_local_iterator()
+ {
+ typedef _Tp cont_type;
+ cont_type c;
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
c.clear();
VERIFY( *it == val );
}
template<typename _Tp>
- void invalid_local_iterator_pre_increment()
+ void invalid_local_iterator_arrow_operator()
{
typedef _Tp cont_type;
- typedef typename cont_type::value_type cont_val_type;
- typedef typename CopyableValueType<cont_val_type>::value_type val_type;
- generate_unique<val_type> gu;
+ cont_type c;
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
+ c.clear();
+ VERIFY( *it.operator->() == val );
+ }
+ template<typename _Tp>
+ void invalid_local_iterator_copy_construction()
+ {
+ typedef _Tp cont_type;
cont_type c;
- for (size_t i = 0; i != 5; ++i)
- c.insert(gu.build());
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
+ c.clear();
+ typename cont_type::local_iterator lit(it);
+ VERIFY( *lit == val );
+ }
+
+ template<typename _Tp>
+ void invalid_local_iterator_move_construction()
+ {
+ typedef _Tp cont_type;
+ cont_type c;
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
+ c.clear();
+ typename cont_type::local_iterator lit(std::move(it));
+ VERIFY( *lit == val );
+ }
+
+ template<typename _Tp>
+ void invalid_local_iterator_copy_assignment()
+ {
+ typedef _Tp cont_type;
+ cont_type c;
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
+ c.clear();
+ typename cont_type::local_iterator lit;
+ lit = it;
+ VERIFY( *lit == val );
+ }
+
+ template<typename _Tp>
+ void invalid_local_iterator_move_assignment()
+ {
+ typedef _Tp cont_type;
+ cont_type c;
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
+ c.clear();
+ typename cont_type::local_iterator lit;
+ lit = std::move(it);
+ VERIFY( *lit == val );
+ }
+
+ template<typename _Tp>
+ void invalid_local_iterator_const_conversion()
+ {
+ typedef _Tp cont_type;
+ cont_type c;
+ auto it = fill_and_get_local_iterator(c);
+
+ const auto& val = *it;
+ c.clear();
+ typename cont_type::const_local_iterator clit(it);
+ VERIFY( *clit == val );
+ }
+
+ template<typename _Tp>
+ void invalid_local_iterator_pre_increment()
+ {
+ typedef _Tp cont_type;
+ cont_type c;
+ fill_container(c);
auto lit = c.begin(0);
for (size_t i = 0; i != 6; ++i)
@@ -146,13 +235,8 @@ namespace __gnu_test
void invalid_local_iterator_post_increment()
{
typedef _Tp cont_type;
- typedef typename cont_type::value_type cont_val_type;
- typedef typename CopyableValueType<cont_val_type>::value_type val_type;
- generate_unique<val_type> gu;
-
cont_type c;
- for (size_t i = 0; i != 5; ++i)
- c.insert(gu.build());
+ fill_container(c);
auto lit = c.begin(0);
for (size_t i = 0; i != 6; ++i)
@@ -163,13 +247,8 @@ namespace __gnu_test
void invalid_local_iterator_compare()
{
typedef _Tp cont_type;
- typedef typename cont_type::value_type cont_val_type;
- typedef typename CopyableValueType<cont_val_type>::value_type val_type;
- generate_unique<val_type> gu;
-
cont_type c;
- for (size_t i = 0; i != 5; ++i)
- c.insert(gu.build());
+ fill_container(c);
typename cont_type::local_iterator it1, it2;
size_t i;
@@ -194,13 +273,8 @@ namespace __gnu_test
void invalid_local_iterator_range()
{
typedef _Tp cont_type;
- typedef typename cont_type::value_type cont_val_type;
- typedef typename CopyableValueType<cont_val_type>::value_type val_type;
- generate_unique<val_type> gu;
-
cont_type c;
- for (size_t i = 0; i != 5; ++i)
- c.insert(gu.build());
+ fill_container(c);
typename cont_type::local_iterator it, end;
for (size_t i = 0; i != c.bucket_count(); ++i)
diff --git a/libstdc++-v3/testsuite/util/replacement_memory_operators.h b/libstdc++-v3/testsuite/util/replacement_memory_operators.h
index 2516cd2..69afa77 100644
--- a/libstdc++-v3/testsuite/util/replacement_memory_operators.h
+++ b/libstdc++-v3/testsuite/util/replacement_memory_operators.h
@@ -36,8 +36,12 @@ namespace __gnu_test
~counter() THROW (counter_error)
{
+#if __cpp_exceptions
if (_M_throw && _M_count != 0)
throw counter_error();
+#else
+ VERIFY( !_M_throw || _M_count == 0 );
+#endif
}
static void
@@ -133,8 +137,12 @@ void* operator new(std::size_t size) THROW(std::bad_alloc)
{
std::printf("operator new is called \n");
void* p = std::malloc(size);
+#if __cpp_exceptions
if (!p)
throw std::bad_alloc();
+#else
+ VERIFY( p );
+#endif
__gnu_test::counter::increment();
return p;
}
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index 1b4044c..90cda2f 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -258,8 +258,8 @@ check_version(symbol& test, bool added)
test.version_status = symbol::incompatible;
// Check that added symbols are added in the latest pre-release version.
- bool latestp = (test.version_name == "GLIBCXX_3.4.34"
- || test.version_name == "CXXABI_1.3.16"
+ bool latestp = (test.version_name == "GLIBCXX_3.4.35"
+ || test.version_name == "CXXABI_1.3.17"
|| test.version_name == "CXXABI_FLOAT128"
|| test.version_name == "CXXABI_TM_1");
if (added && !latestp)
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index 0df6dcc..74a8739 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -610,12 +610,10 @@ namespace __gnu_test
test_container(T* _first, T* _last) : bounds(_first, _last)
{ }
-#if __cplusplus >= 201103L
template<std::size_t N>
explicit
- test_container(T (&arr)[N]) : test_container(arr, arr+N)
+ test_container(T (&arr)[N]) : bounds(arr, arr+N)
{ }
-#endif
ItType<T>
it(int pos)
@@ -894,6 +892,9 @@ namespace __gnu_test
using test_input_range
= test_range<T, input_iterator_wrapper>;
template<typename T>
+ using test_input_range_nocopy
+ = test_range_nocopy<T, input_iterator_wrapper_nocopy>;
+ template<typename T>
using test_output_range
= test_range<T, output_iterator_wrapper>;