[gcc r15-8296] libstdc++: Support maps deduction from_range of tuples.

2025-03-19 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:d50171bc07006dfb56cae487d72913e5d2567716

commit r15-8296-gd50171bc07006dfb56cae487d72913e5d2567716
Author: Tomasz Kamiński 
Date:   Wed Mar 19 11:42:50 2025 +0100

libstdc++: Support maps deduction from_range of tuples.

This implements part of LWG4223 that enables deduction for maps types
(map, unordered_map, flat_map and non-unique equivalent) from
(from_range, rg, ...) arguments, where rg is range of tuple
or other pair-like.

libstdc++-v3/ChangeLog:

* include/bits/ranges_base.h (__detail::__range_key_type):
Replace RV::first_type with tuple_element_t<0, RV>.
(__detail::__range_mapped_type) Replace RV::second_type
with tuple_element_t<1, RV>.
* testsuite/23_containers/flat_map/1.cc: New tests.
* testsuite/23_containers/flat_multimap/1.cc: New tests.
* testsuite/23_containers/map/cons/from_range.cc: New tests.
* testsuite/23_containers/multimap/cons/from_range.cc: New tests.
* testsuite/23_containers/unordered_map/cons/from_range.cc: New 
tests.
* testsuite/23_containers/unordered_multimap/cons/from_range.cc:
New tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h| 10 +++-
 libstdc++-v3/testsuite/23_containers/flat_map/1.cc | 61 
 .../testsuite/23_containers/flat_multimap/1.cc | 65 ++
 .../testsuite/23_containers/map/cons/from_range.cc |  8 ++-
 .../23_containers/multimap/cons/from_range.cc  |  8 ++-
 .../23_containers/unordered_map/cons/from_range.cc |  8 ++-
 .../unordered_multimap/cons/from_range.cc  | 12 +++-
 7 files changed, 158 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index c9687c256e99..13bfbb3795bf 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -41,6 +41,10 @@
 #include 
 #include 
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include  // for tuple_element_t
+#endif
+
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpedantic" // __int128
 
@@ -1093,13 +1097,15 @@ namespace __detail
   = ranges::input_range<_Rg>
  && convertible_to, _Tp>;
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 4223. Deduction guides for maps are mishandling tuples and references
   template
 using __range_key_type
-  = remove_const_t::first_type>;
+  = remove_const_t>>;
 
   template
 using __range_mapped_type
-  = typename ranges::range_value_t<_Range>::second_type;
+  = tuple_element_t<1, ranges::range_value_t<_Range>>;
 
   // The allocator's value_type for map-like containers.
   template
diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
index 00254dc2ee62..d9d88c4df6ec 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
@@ -11,6 +11,67 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+
+struct Gt {
+  template
+  bool operator()(T const& l, U const & r) const
+  { return l > r; }
+};
+
+void
+test_deduction_guide()
+{
+  __gnu_test::test_input_range> r(0, 0);
+  std::flat_map it1(r.begin(), r.begin());
+  static_assert(std::is_same_v>);
+  std::flat_map fr1(std::from_range, r);
+  static_assert(std::is_same_v>);
+
+  Gt cmp;
+  std::flat_map it2(r.begin(), r.begin(), cmp);
+  static_assert(std::is_same_v>);
+  std::flat_map fr2(std::from_range, r, cmp);
+  static_assert(std::is_same_v>);
+
+  using Alloc = __gnu_test::SimpleAllocator>;
+  Alloc alloc;
+  // No matching deduction guide
+  // std::flat_map it3(r.begin(), r.begin(), alloc);
+  std::flat_map fr3(std::from_range, r, alloc);
+  static_assert(std::is_same_v<
+ decltype(fr3),
+ std::flat_map,
+  std::vector>,
+  std::vector>>>);
+
+  // No matching deduction guide
+  // std::flat_map it4(r.begin(), r.begin(), cmp, alloc);
+  std::flat_map fr4(std::from_range, r, cmp, alloc);
+  static_assert(std::is_same_v<
+ decltype(fr4),
+ std::flat_map>,
+  std::vector>>>);
+
+  // LWG4223: deduces flat_map, which in turn instantiates
+  // std::vector that is ill-formed.
+  // __gnu_test::test_input_range> r2(0, 0);
+  // std::flat_map it5(r2.begin(), r2.begin());
+  // std::flat_map fr5(std::from_range, r2);
+
+  // LWG4223: deduces flat_map
+  //__gnu_test::test_input_range> r3(0, 0);
+  // std::flat_map it6(r3.begin(), r3.begin());
+  // std::flat_map fr6(std::from_range, r3);
+
+  __gnu_test::test_input_range> r4(0, 0);
+  std::flat_map it7(r4.begin(), r4.begin());
+  static_assert(std::is_same_v>);
+  std::flat_map fr7(std::from_range, r4);
+  static_assert(std::is_same_v>);
+}
 
 template class KeyContainer, template class 
Mapped

[gcc r15-8467] libstdc++: Add from_range_t constructors to debug unordered containers

2025-03-20 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:7cc40201a135112824e44edeeb29017151652402

commit r15-8467-g7cc40201a135112824e44edeeb29017151652402
Author: Tomasz Kamiński 
Date:   Thu Mar 20 12:08:00 2025 +0100

libstdc++: Add from_range_t constructors to debug unordered containers

libstdc++-v3/ChangeLog:

* include/debug/unordered_map (unordered_map): Add from_range
constructors and deduction guides.
(unordered_multimap): Likewise.
* include/debug/unordered_set (unordered_set): Add from_range
constructors and deduction guides.
(unordered_multiset): Likewise.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/debug/unordered_map | 141 +++
 libstdc++-v3/include/debug/unordered_set | 131 
 2 files changed, 272 insertions(+)

diff --git a/libstdc++-v3/include/debug/unordered_map 
b/libstdc++-v3/include/debug/unordered_map
index eb9590ac8e7e..16d4a4a98e0d 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -201,6 +201,34 @@ namespace __debug
   : unordered_map(__l, __n, __hf, key_equal(), __a)
   { }
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  template<__detail::__container_compatible_range _Rg>
+   unordered_map(from_range_t, _Rg&& __rg,
+ size_type __n = 0,
+ const hasher& __hf = hasher(),
+ const key_equal& __eql = key_equal(),
+ const allocator_type& __a = allocator_type())
+   : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __eql, __a)
+{ }
+
+  template<__detail::__container_compatible_range _Rg>
+   unordered_map(from_range_t, _Rg&& __rg, const allocator_type& __a)
+   : _Base(from_range, std::forward<_Rg>(__rg), __a)
+{ }
+
+  template<__detail::__container_compatible_range _Rg>
+   unordered_map(from_range_t, _Rg&& __rg, size_type __n,
+ const allocator_type& __a)
+   : _Base(from_range, std::forward<_Rg>(__rg), __n, __a)
+{ }
+
+  template<__detail::__container_compatible_range _Rg>
+   unordered_map(from_range_t, _Rg&& __rg, size_type __n,
+ const hasher& __hf, const allocator_type& __a)
+   : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __a)
+{ }
+#endif
+
   ~unordered_map() = default;
 
   unordered_map&
@@ -841,6 +869,47 @@ namespace __debug
  _Hash, _Allocator)
 -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  template>,
+  __not_allocator_like _Pred = 
equal_to<__detail::__range_key_type<_Rg>>,
+  __allocator_like _Allocator =
+allocator<__detail::__range_to_alloc_type<_Rg>>>
+unordered_map(from_range_t, _Rg&&, unordered_map::size_type = {},
+ _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
+-> unordered_map<__detail::__range_key_type<_Rg>,
+__detail::__range_mapped_type<_Rg>,
+_Hash, _Pred, _Allocator>;
+
+  template
+unordered_map(from_range_t, _Rg&&, unordered_map::size_type,
+ _Allocator)
+-> unordered_map<__detail::__range_key_type<_Rg>,
+__detail::__range_mapped_type<_Rg>,
+hash<__detail::__range_key_type<_Rg>>,
+equal_to<__detail::__range_key_type<_Rg>>,
+_Allocator>;
+
+  template
+unordered_map(from_range_t, _Rg&&, _Allocator)
+-> unordered_map<__detail::__range_key_type<_Rg>,
+__detail::__range_mapped_type<_Rg>,
+hash<__detail::__range_key_type<_Rg>>,
+equal_to<__detail::__range_key_type<_Rg>>,
+_Allocator>;
+
+  template
+unordered_map(from_range_t, _Rg&&, unordered_map::size_type,
+ _Hash, _Allocator)
+-> unordered_map<__detail::__range_key_type<_Rg>,
+__detail::__range_mapped_type<_Rg>,
+_Hash, equal_to<__detail::__range_key_type<_Rg>>,
+_Allocator>;
+#endif
 #endif
 
   template= 23
+  template<__detail::__container_compatible_range _Rg>
+   unordered_multimap(from_range_t, _Rg&& __rg,
+  size_type __n = 0,
+  const hasher& __hf = hasher(),
+  const key_equal& __eql = key_equal(),
+  const allocator_type& __a = allocator_type())
+   : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __eql, __a)
+{ }
+
+  template<__detail::__container_compatible_range _Rg>
+   unordered_multimap(from_range_t, _Rg&& __rg, const allocator_type& __a)
+   : _Base(from_range, std::forward<_Rg>(__rg), __a)
+{ }
+
+  template<__detail::__c

[gcc r15-8255] libstdc++: Add P1206R7 from_range members to unordered maps [PR111055]

2025-03-18 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:453d42046c461a8aa8ed68a88b94dac2d4dde73b

commit r15-8255-g453d42046c461a8aa8ed68a88b94dac2d4dde73b
Author: Tomasz Kamiński 
Date:   Tue Mar 18 11:08:19 2025 +0100

libstdc++: Add P1206R7 from_range members to unordered maps [PR111055]

This is another piece of P1206R7, adding new members to std::unordered_map
and std::unordered_multimap.

PR libstdc++/111055

libstdc++-v3/ChangeLog:

* include/bits/unordered_map.h (unordered_map): Define from_range
constructors and insert_range member.
(unordered_multimap): Likewise.
* testsuite/23_containers/unordered_multimap/cons/from_range.cc:
New test.
* 
testsuite/23_containers/unordered_multimap/modifiers/insert_range.cc:
New test.
* testsuite/23_containers/unordered_map/cons/from_range.cc:
New test.
* testsuite/23_containers/unordered_map/modifiers/insert_range.cc:
New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/unordered_map.h  | 203 ++
 .../23_containers/unordered_map/cons/from_range.cc | 232 
 .../unordered_map/modifiers/insert_range.cc|  79 +++
 .../unordered_multimap/cons/from_range.cc  | 238 +
 .../unordered_multimap/modifiers/insert_range.cc   |  76 +++
 5 files changed, 828 insertions(+)

diff --git a/libstdc++-v3/include/bits/unordered_map.h 
b/libstdc++-v3/include/bits/unordered_map.h
index 9f205f7521d3..5c9304871907 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -34,6 +34,9 @@
 #include 
 #include  // hash
 #include // equal_to
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include  // ranges::begin, ranges::distance etc.
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -274,6 +277,42 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : unordered_map(__l, __n, __hf, key_equal(), __a)
   { }
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   *  @brief  Builds an %unordered_map from a range.
+   *  @since C++23
+   *  @param  __rg An input range of elements that can be converted to
+   *   the maps's value type.
+   *  @param __n  Minimal initial number of buckets.
+   *  @param __hf  A hash functor.
+   *  @param __eql  A key equality functor.
+   *  @param  __a  An allocator object.
+   *
+   *  Create an %unordered_map consisting of copies of the elements in the
+   *  range. This is linear in N (where N is `std::ranges::size(__rg)`).
+   */
+   template<__detail::__container_compatible_range _Rg>
+unordered_map(from_range_t, _Rg&& __rg,
+  size_type __n = 0,
+  const hasher& __hf = hasher(),
+  const key_equal& __eql = key_equal(),
+  const allocator_type& __a = allocator_type())
+ : _M_h(__n, __hf, __eql, __a)
+ { insert_range(std::forward<_Rg>(__rg)); }
+
+   template<__detail::__container_compatible_range _Rg>
+unordered_map(from_range_t, _Rg&& __rg, size_type __n,
+  const allocator_type& __a)
+ : _M_h(__n, hasher(), key_equal(), __a)
+ { insert_range(std::forward<_Rg>(__rg)); }
+
+   template<__detail::__container_compatible_range _Rg>
+unordered_map(from_range_t, _Rg&& __rg, size_type __n,
+  const hasher& __hf, const allocator_type& __a)
+ : _M_h(__n, __hf, key_equal(), __a)
+ { insert_range(std::forward<_Rg>(__rg)); }
+#endif
+
   /// Copy assignment operator.
   unordered_map&
   operator=(const unordered_map&) = default;
@@ -635,6 +674,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   insert(initializer_list __l)
   { _M_h.insert(__l); }
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   *  @brief Inserts a range of elements.
+   *  @since C++23
+   *  @param  __rg An input range of elements that can be converted to
+   *   the map's value type.
+   */
+  template<__detail::__container_compatible_range _Rg>
+   void
+   insert_range(_Rg&& __rg)
+   {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+   _M_h.emplace(*__first);
+   }
+#endif
 
 #ifdef __glibcxx_unordered_map_try_emplace // >= C++17 && HOSTED
   /**
@@ -1228,6 +1284,47 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  _Hash, _Allocator)
 -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  template>,
+  __not_allocator_like _Pred = 
equal_to<__detail::__range_key_type<_Rg>>,
+  __allocator_like _Allocator =

[gcc r15-8251] libstdc++: Add P1206R7 from_range members to ordered maps [PR111055]

2025-03-18 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:8744d53db1b6816586dac102942c00c105524172

commit r15-8251-g8744d53db1b6816586dac102942c00c105524172
Author: Tomasz Kamiński 
Date:   Fri Mar 14 16:04:11 2025 +0100

libstdc++: Add P1206R7 from_range members to ordered maps [PR111055]

This is another piece of P1206R7, adding new members to std::map
and std::multimap.

PR libstdc++/111055

libstdc++-v3/ChangeLog:

* include/bits/ranges_base.h (__detail::__range_to_alloc_type):
Define.
* include/bits/stl_multimap.h: (inser_range)
(multimap(from_range_t, _Rg&&, const _Compare&, const _Alloc&))
(multimap(from_range_t, _Rg&&, const _Alloc&)): Define.
* include/bits/stl_map.h: (map(from_range_t, _Rg&&, const _Alloc&)) 
i
(map(from_range_t, _Rg&&, const _Compare&, const _Alloc&), 
insert_range):
Define.
* testsuite/23_containers/multimap/cons/from_range.cc: New test.
* 
testsuite/23_containers/multimap/modifiers/insert/insert_range.cc: New test.
* testsuite/23_containers/map/cons/from_range.cc: New test.
* testsuite/23_containers/map/modifiers/insert/insert_range.cc: New 
test.

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h|   8 ++
 libstdc++-v3/include/bits/stl_map.h|  59 
 libstdc++-v3/include/bits/stl_multimap.h   |  60 
 .../testsuite/23_containers/map/cons/from_range.cc | 155 +
 .../map/modifiers/insert/insert_range.cc   | 102 ++
 .../23_containers/multimap/cons/from_range.cc  | 155 +
 .../multimap/modifiers/insert/insert_range.cc  |  99 +
 7 files changed, 638 insertions(+)

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index 516d04afdab2..c9687c256e99 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -1083,6 +1083,9 @@ namespace ranges
   inline constexpr from_range_t from_range{};
 
 /// @cond undocumented
+  template
+struct pair;
+
 namespace __detail
 {
   template
@@ -1097,6 +1100,11 @@ namespace __detail
   template
 using __range_mapped_type
   = typename ranges::range_value_t<_Range>::second_type;
+
+  // The allocator's value_type for map-like containers.
+  template
+using __range_to_alloc_type
+  = pair, __range_mapped_type<_Range>>;
 }
 /// @endcond
 #endif
diff --git a/libstdc++-v3/include/bits/stl_map.h 
b/libstdc++-v3/include/bits/stl_map.h
index d2d0b524cceb..9381a7930af7 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -62,6 +62,9 @@
 #include 
 #include 
 #endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include  // ranges::begin, ranges::distance etc.
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -305,6 +308,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(__comp, _Pair_alloc_type(__a))
{ _M_t._M_insert_range_unique(__first, __last); }
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   * @brief Builds a %map from a range.
+   * @since C++23
+   */
+  template<__detail::__container_compatible_range _Rg>
+   map(from_range_t, _Rg&& __rg,
+   const _Compare& __comp,
+   const _Alloc& __a = _Alloc())
+   : _M_t(__comp, _Pair_alloc_type(__a))
+   { insert_range(std::forward<_Rg>(__rg)); }
+
+  /// Allocator-extended range constructor.
+  template<__detail::__container_compatible_range _Rg>
+   map(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
+   : _M_t(_Pair_alloc_type(__a))
+   { insert_range(std::forward<_Rg>(__rg)); }
+#endif
+
+
 #if __cplusplus >= 201103L
   /**
*  The dtor only erases the elements, and note that if the elements
@@ -880,6 +903,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   { insert(__list.begin(), __list.end()); }
 #endif
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   *  @brief Inserts a range of elements.
+   *  @since C++23
+   *  @param  __rg An input range of elements that can be converted to
+   *   the map's value type.
+   */
+  template<__detail::__container_compatible_range _Rg>
+   void
+   insert_range(_Rg&& __rg)
+   {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+   insert(*__first);
+   }
+#endif
+
   /**
*  @brief Attempts to insert a std::pair into the %map.
*  @param  __position  An iterator that serves as a hint as to where the
@@ -1495,6 +1536,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 map(initializer_list>, _Allocator)
 -> map<_Key, _Tp, less<_Key>, _Allocator>;
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  template>,
+  __allocator_like _Alloc =
+

[gcc r14-11523] libstdc++: Fix handling of field width for wide strings and characters [PR119593]

2025-04-04 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:ad1b71fc2882c14271ebf2bbaf216cceaa88c76a

commit r14-11523-gad1b71fc2882c14271ebf2bbaf216cceaa88c76a
Author: Tomasz Kamiński 
Date:   Thu Apr 3 10:23:45 2025 +0200

libstdc++: Fix handling of field width for wide strings and characters 
[PR119593]

This patch corrects handling of UTF-32LE and UTF32-BE in
__unicode::__literal_encoding_is_unicode<_CharT>, so they are
recognized as unicode and functions produces correct result for wchar_t.

Use `__unicode::__field_width` to compute the estimated witdh
of the charcter for unicode wide encoding.

PR libstdc++/119593

libstdc++-v3/ChangeLog:

* include/bits/unicode.h
(__unicode::__literal_encoding_is_unicode<_CharT>):
Corrected handing for UTF-16 and UTF-32 with "LE" or "BE" suffix.
* include/std/format (__formatter_str::_S_character_width):
Define.
(__formatter_str::_S_character_width): Updated passed char
length.
* testsuite/std/format/functions/format.cc: Test for wchar_t.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/unicode.h   |  2 ++
 libstdc++-v3/include/std/format   | 16 +++-
 libstdc++-v3/testsuite/std/format/functions/format.cc |  8 ++--
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/bits/unicode.h 
b/libstdc++-v3/include/bits/unicode.h
index 4b408948d722..eee3b7e37609 100644
--- a/libstdc++-v3/include/bits/unicode.h
+++ b/libstdc++-v3/include/bits/unicode.h
@@ -1039,6 +1039,8 @@ inline namespace __v15_1_0
  string_view __s(__enc);
  if (__s.ends_with("//"))
__s.remove_suffix(2);
+ if (__s.ends_with("LE") || __s.ends_with("BE"))
+   __s.remove_suffix(2);
  return __s == "16" || __s == "32";
}
}
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index f64947a0e293..15bded87c9cd 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1184,12 +1184,26 @@ namespace __format
  _M_spec);
}
 
+  [[__gnu__::__always_inline__]]
+  static size_t
+  _S_character_width(_CharT __c)
+  {
+   // N.B. single byte cannot encode charcter of width greater than 1
+   if constexpr (sizeof(_CharT) > 1u && 
+   __unicode::__literal_encoding_is_unicode<_CharT>())
+ return __unicode::__field_width(__c);
+   else
+ return 1u;
+  }
+
   template
typename basic_format_context<_Out, _CharT>::iterator
_M_format_character(_CharT __c,
  basic_format_context<_Out, _CharT>& __fc) const
{
- return __format::__write_padded_as_spec({&__c, 1u}, 1, __fc, _M_spec);
+ return __format::__write_padded_as_spec({&__c, 1u},
+ _S_character_width(__c),
+ __fc, _M_spec);
}
 
   template
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc 
b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 78cc1ab482ad..97eb0957e5e1 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -497,9 +497,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}", "£");
@@ -513,7 +518,6 @@ test_unicode()
   std::string sP = std::format("{:1.1} {:*<1.1}", "£", "🤡");
   VERIFY( sP == "£ *" );
   sP = std::format("{:*<2.1} {:*<2.1}", "£", "🤡");
-  VERIFY( sP == "£* **" );
 
   // Verify field width handling for extended grapheme clusters,
   // and that a cluster gets output as a single item, not truncated.


[gcc r15-8922] libstdc++: Add P1206R7 range operations to std::deque [PR111055]

2025-03-26 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:157c14a387fc880b31e9e42deb6960b3143d3c2d

commit r15-8922-g157c14a387fc880b31e9e42deb6960b3143d3c2d
Author: Tomasz Kamiński 
Date:   Fri Mar 21 09:03:54 2025 +0100

libstdc++: Add P1206R7 range operations to std::deque [PR111055]

This is another piece of P1206R7, adding from_range constructor, 
append_range,
prepend_range, insert_range, and assign_range members to std::deque.

For append_front of input non-sized range, we are emplacing element at the 
front and
then reverse inserted elements. This does not existing elements, and 
properly handle
aliasing ranges.

For insert_range, the handling of insertion in the middle of input-only 
ranges
that are sized could be optimized, we still insert nodes one-by-one in such 
case.
For forward and stronger ranges, we reduce them to common_range case, by 
computing
the iterator when computing the distance. This is slightly suboptimal, as 
it require
range to be iterated for non-common forward ranges that are sized, but 
reduces
number of instantiations.

This patch extract _M_range_prepend, _M_range_append helper functions that 
accepts
(iterator, sentinel) pair. This all used in all standard modes.

PR libstdc++/111055

libstdc++-v3/ChangeLog:

* include/bits/deque.tcc (deque::prepend_range, deque::append_range)
(deque::insert_range, __advance_dist): Define.
(deque::_M_range_prepend, deque::_M_range_append):
Extract from _M_range_insert_aux for _ForwardIterator(s).
* include/bits/stl_deque.h (deque::assign_range): Define.
(deque::prepend_range, deque::append_range, deque::insert_range):
Declare.
(deque(from_range_t, _Rg&&, const allocator_type&)): Define 
constructor
and deduction guide.
* include/debug/deque (deque::prepend_range, deque::append_range)
(deque::assign_range):  Define.
(deque(from_range_t, _Rg&&, const allocator_type&)): Define 
constructor
and deduction guide.
* testsuite/23_containers/deque/cons/from_range.cc: New test.
* testsuite/23_containers/deque/modifiers/append_range.cc: New test.
* testsuite/23_containers/deque/modifiers/assign/assign_range.cc:
New test.
* testsuite/23_containers/deque/modifiers/prepend_range.cc: New 
test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/deque.tcc| 229 ++---
 libstdc++-v3/include/bits/stl_deque.h  | 111 ++
 libstdc++-v3/include/debug/deque   |  51 +
 .../23_containers/deque/cons/from_range.cc | 117 +++
 .../23_containers/deque/modifiers/append_range.cc  | 128 
 .../deque/modifiers/assign/assign_range.cc | 109 ++
 .../deque/modifiers/insert/insert_range.cc | 142 +
 .../23_containers/deque/modifiers/prepend_range.cc | 140 +
 8 files changed, 996 insertions(+), 31 deletions(-)

diff --git a/libstdc++-v3/include/bits/deque.tcc 
b/libstdc++-v3/include/bits/deque.tcc
index fcbecca55b4f..87ea1cebdaa3 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -583,6 +583,51 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
 }
 
+  template 
+template 
+  void
+  deque<_Tp, _Alloc>::
+  _M_range_prepend(_InputIterator __first, _Sentinel __last,
+ size_type __n)
+  {
+iterator __new_start = _M_reserve_elements_at_front(__n);
+__try
+  {
+std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
+__new_start, _M_get_Tp_allocator());
+this->_M_impl._M_start = __new_start;
+  }
+__catch(...)
+  {
+_M_destroy_nodes(__new_start._M_node,
+ this->_M_impl._M_start._M_node);
+__throw_exception_again;
+  }
+  }
+
+  template 
+template 
+  void
+  deque<_Tp, _Alloc>::
+  _M_range_append(_InputIterator __first, _Sentinel __last,
+ size_type __n)
+ {
+   iterator __new_finish = _M_reserve_elements_at_back(__n);
+   __try
+   {
+ std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
+ this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ this->_M_impl._M_finish = __new_finish;
+   }
+  __catch(...)
+   {
+ _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
+  __new_finish._M_node + 1);
+ __throw_exception_again;
+   }
+ }
+
   template 
 template 
   void
@@ -605,38

[gcc r15-9380] libstdc++: Define __cpp_lib_containers_ranges in appropriate headers [PR111055]

2025-04-11 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:ae54d8cb51eb5cc1f5a3d319cc1840d2e9bfcbfc

commit r15-9380-gae54d8cb51eb5cc1f5a3d319cc1840d2e9bfcbfc
Author: Tomasz Kamiński 
Date:   Fri Mar 21 12:55:48 2025 +0100

libstdc++: Define __cpp_lib_containers_ranges in appropriate headers 
[PR111055]

This is final piece of P1206R7, adding a feature test macros,
as range constructors and member operations are now implemented for
all containers and adaptors.

For consistency with the proposal, all new container operations and
helpers are now defined if __glibcxx_containers_ranges, instead
of __glibcxx_ranges_to_container.

PR libstdc++/111055

libstdc++-v3/ChangeLog:

* include/bits/version.def (containers_ranges): Define.
* include/bits/version.h: Regenerate.
* include/bits/ranges_base.h 
(__detail::__container_compatible_range)
(__detail::__range_to_alloc_type, __detail::__range_mapped_type)
(__detail::__range_key_type): Depend on __glibcxx_containers_ranges
instead of __glibcxx_ranges_to_container.
* include/bits/basic_string.h: Replace 
__glibcxx_ranges_to_container with
__glibcxx_containers_ranges.
* include/bits/cow_string.h: Likewise.
* include/bits/deque.tcc: Likewise.
* include/bits/forward_list.h: Likewise.
* include/bits/stl_bvector.h: Likewise.
* include/bits/stl_deque.h: Likewise.
* include/bits/stl_list.h: Likewise.
* include/bits/stl_map.h: Likewise.
* include/bits/stl_multimap.h: Likewise.
* include/bits/stl_multiset.h: Likewise.
* include/bits/stl_queue.h: Likewise.
* include/bits/stl_set.h: Likewise.
* include/bits/stl_stack.h: Likewise.
* include/bits/stl_vector.h: Likewise.
* include/bits/unordered_map.h: Likewise.
* include/bits/unordered_set.h: Likewise.
* include/bits/vector.tcc: Likewise.
* include/debug/deque: Likewise.
* include/debug/forward_list: Likewise.
* include/debug/list: Likewise.
* include/debug/map.h: Likewise.
* include/debug/multimap.h: Likewise.
* include/debug/multiset.h: Likewise.
* include/debug/set.h: Likewise.
* include/debug/unordered_map: Likewise.
* include/debug/unordered_set: Likewise.
* include/debug/vector: Likewise.
* include/std/deque: Provide __cpp_lib_containers_ranges.
* include/std/forward_list: Likewise.
* include/std/list: Likewise.
* include/std/map: Likewise.
* include/std/queue: Likewise.
* include/std/set: Likewise.
* include/std/stack: Likewise.
* include/std/string: Likewise.
* include/std/unordered_map: Likewise.
* include/std/unordered_set: Likewise.
* include/std/vector: Likewise.
* testsuite/21_strings/basic_string/cons/from_range.cc: Test for 
value
__cpp_lib_containers_ranges.
* testsuite/23_containers/deque/cons/from_range.cc: Likewise.
* testsuite/23_containers/forward_list/cons/from_range.cc: Likewise.
* testsuite/23_containers/list/cons/from_range.cc: Likewise.
* testsuite/23_containers/map/cons/from_range.cc: Likewise.
* testsuite/23_containers/multimap/cons/from_range.cc: Likewise.
* testsuite/23_containers/multiset/cons/from_range.cc: Likewise.
* testsuite/23_containers/priority_queue/cons_from_range.cc: 
Likewise.
* testsuite/23_containers/queue/cons_from_range.cc: Likewise.
* testsuite/23_containers/set/cons/from_range.cc: Likewise.
* testsuite/23_containers/stack/cons_from_range.cc: Likewise.
* testsuite/23_containers/unordered_map/cons/from_range.cc: 
Likewise.
* testsuite/23_containers/unordered_multimap/cons/from_range.cc: 
Likewise.
* testsuite/23_containers/unordered_multiset/cons/from_range.cc: 
Likewise.
* testsuite/23_containers/unordered_set/cons/from_range.cc: 
Likewise.
* testsuite/23_containers/vector/bool/cons/from_range.cc: Likewise.
* testsuite/23_containers/vector/cons/from_range.cc: Likewise.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/basic_string.h | 16 
 libstdc++-v3/include/bits/cow_string.h   | 10 +-
 libstdc++-v3/include/bits/deque.tcc  |  4 ++--
 libstdc++-v3/include/bits/forward_list.h | 20 ++--
 libstdc++-v3/include/bits/ranges_base.h  |  4 +++-
 libstdc++-v3/include/bits/stl_bvector.h  |  8 
 libstdc++-v3/include/bits/stl_deque.h   

[gcc r15-9520] libstdc++: Fix constification in range_formatter::format [PR109162]

2025-04-16 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:aef87975224b0a4b5b103f241fd366b0e3a21360

commit r15-9520-gaef87975224b0a4b5b103f241fd366b0e3a21360
Author: Tomasz Kamiński 
Date:   Wed Apr 16 13:39:04 2025 +0200

libstdc++: Fix constification in range_formatter::format [PR109162]

The _Rg is deduced to lvalue reference for the lvalue arguments,
and in such case __format::__maybe_const_range<_Rg, _CharT> is always _Rg
(adding const to reference does not change behavior).

Now we correctly check if _Range = remove_reference_t<_Rg> is const
formattable range, furthermore as range_formatter can only format
ranges of values of type (possibly const) _Tp, we additional check if the
remove_cvref_t> is _Tp.

The range_reference_t and range_reference_t have different
types (modulo remove_cvref_t) for std::vector (::reference and bool)
or flat_map (pair and pair).

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/std/format (range_formatter::format): Format const range,
only if reference type is not changed.
* testsuite/std/format/ranges/formatter.cc: New tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/format| 11 ---
 .../testsuite/std/format/ranges/formatter.cc   | 22 ++
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index b1455977c65f..27253f50ea8d 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -5634,9 +5634,14 @@ namespace __format
typename basic_format_context<_Out, _CharT>::iterator
format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const
{
- using __maybe_const_range
-   = __format::__maybe_const_range<_Rg, _CharT>;
- return _M_format<__maybe_const_range>(__rg, __fc);
+ using _Range = remove_reference_t<_Rg>;
+ if constexpr (__format::__const_formattable_range<_Range, _CharT>)
+ {
+   using _CRef = ranges::range_reference_t;
+   if constexpr (same_as, _Tp>)
+ return _M_format(__rg, __fc);
+ }
+ return _M_format(__rg, __fc);
}
 
 private:
diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc 
b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
index a4f5d9210ddf..00ce9f6dd0cd 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
@@ -1,5 +1,6 @@
 // { dg-do run { target c++23 } }
 
+#include 
 #include 
 #include 
 #include 
@@ -138,6 +139,26 @@ test_nested()
   VERIFY( res == "+<01; 02; 11; 12>+" );
 }
 
+struct MyFlatMap : std::flat_map
+{
+  using std::flat_map::flat_map;
+};
+
+template
+struct std::formatter
+  // This cannot apply format BitVector const&, because formatted type would
+  // be std::pair, and formatter for
+  // pair cannot format it.
+  : std::range_formatter
+{};
+
+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
 using VectorFormatter = std::formatter, CharT>;
 
@@ -146,4 +167,5 @@ int main()
   test_outputs();
   test_outputs();
   test_nested();
+  test_const_ref_type_mismatch();
 }


[gcc r16-16] libstdc++: Clarify that _S_ prefix is be used for static member functions.

2025-04-18 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:6808f74b4f07decb3727624f0e62e7c57ae87022

commit r16-16-g6808f74b4f07decb3727624f0e62e7c57ae87022
Author: Tomasz Kamiński 
Date:   Fri Apr 18 09:38:32 2025 +0200

libstdc++: Clarify that _S_ prefix is be used for static member functions.

libstdc++-v3/ChangeLog:

* doc/xml/manual/appendix_contributing.xml: Add 'and functions'.

Diff:
---
 libstdc++-v3/doc/xml/manual/appendix_contributing.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml 
b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
index ac607fcfad41..b9245453497b 100644
--- a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
+++ b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml
@@ -895,7 +895,7 @@ indicate a place that may require attention for 
multi-thread safety.
 
   Examples:  _M_num_elements  _M_initialize ()
 
-  Static data members, constants, and enumerations: 
_S_.*
+  Static data and function members, constants, and enumerations: 
_S_.*
 
   Examples: _S_max_elements  _S_default_value


[gcc r16-66] libstdc++: Increase timeouts for format and flat_maps tests

2025-04-22 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:45cd8a836fbe310401b714ab676697b0772caf93

commit r16-66-g45cd8a836fbe310401b714ab676697b0772caf93
Author: Tomasz Kamiński 
Date:   Fri Apr 18 16:43:08 2025 +0200

libstdc++: Increase timeouts for format and flat_maps tests

Test for format parse format string and compile time,
flat_maps ones test all functionality in single test file.

libstdc++-v3/ChangeLog:

* testsuite/23_containers/flat_map/1.cc: Add dg-timeout-factor 2.
* testsuite/23_containers/flat_multimap/1.cc: Likewise.
* testsuite/std/format/ranges/map.cc: Likewise.
* testsuite/std/format/ranges/sequence.cc: Likewise.
* testsuite/std/format/ranges/string.cc: Likewise.

Diff:
---
 libstdc++-v3/testsuite/23_containers/flat_map/1.cc  | 1 +
 libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc | 1 +
 libstdc++-v3/testsuite/std/format/ranges/map.cc | 1 +
 libstdc++-v3/testsuite/std/format/ranges/sequence.cc| 1 +
 libstdc++-v3/testsuite/std/format/ranges/string.cc  | 1 +
 5 files changed, 5 insertions(+)

diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
index d9d88c4df6ec..4fd33f616f78 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 
 
diff --git a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
index ff180bf1bdf5..ea0d4b41e9fb 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 
 #include 
diff --git a/libstdc++-v3/testsuite/std/format/ranges/map.cc 
b/libstdc++-v3/testsuite/std/format/ranges/map.cc
index 34c5ed554b8b..1838480e2cf4 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/map.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/map.cc
@@ -1,4 +1,5 @@
 // { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
 
 #include 
 #include 
diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc 
b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
index 61fc68ea252d..f05f6ec1e1ca 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
@@ -1,4 +1,5 @@
 // { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
 
 #include 
 #include 
diff --git a/libstdc++-v3/testsuite/std/format/ranges/string.cc 
b/libstdc++-v3/testsuite/std/format/ranges/string.cc
index 7f59f59dda39..cf39aa66e071 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/string.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/string.cc
@@ -1,4 +1,5 @@
 // { dg-do run { target c++23 } }
+// { dg-timeout-factor 2 }
 
 #include 
 #include 


[gcc r16-183] libstdc++: Fix mingw build by using _M_span [PR119970]

2025-04-28 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:1be88e43f3e93e85bef9499de905fa72d8596e7d

commit r16-183-g1be88e43f3e93e85bef9499de905fa72d8596e7d
Author: Tomasz Kamiński 
Date:   Mon Apr 28 08:53:59 2025 +0200

libstdc++: Fix mingw build by using _M_span [PR119970]

The r16-142-g01e5ef3e8b9128 chagned return type of _Str_sink::view()
to basic_string_view<_CharT>. The mutable access is provided by _M_span
function, that is now used for mingw path.

PR libstdc++/119970

libstdc++-v3/ChangeLog:

* include/std/ostream (vprint_unicode) [_WIN32 && !__CYGWIN__]: Call
_Str_sink::_M_span instead of view.
* include/std/print (vprint_unicode) [_WIN32 && !__CYGWIN__]: Call
_Str_sink::_M_span instead of view.

Diff:
---
 libstdc++-v3/include/std/ostream | 2 +-
 libstdc++-v3/include/std/print   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index 644e568e8829..3a0a0d35df1d 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -193,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
__format::_Str_sink __buf;
std::vformat_to(__buf.out(), __os.getloc(), __fmt, __args);
-   auto __out = __buf.view();
+   auto __out = __buf._M_span();
 
void* __open_terminal(streambuf*);
error_code __write_to_terminal(void*, span);
diff --git a/libstdc++-v3/include/std/print b/libstdc++-v3/include/std/print
index ea1aaac43892..92dbe118fc31 100644
--- a/libstdc++-v3/include/std/print
+++ b/libstdc++-v3/include/std/print
@@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #else
 __format::_Str_sink __buf;
 std::vformat_to(__buf.out(), __fmt, __args);
-auto __out = __buf.view();
+auto __out = __buf._M_span();
 
 void* __open_terminal(FILE*);
 error_code __write_to_terminal(void*, span);


[gcc r16-181] libstdc++: Implement missing allocator-aware constructors for unordered containers.

2025-04-28 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:1ecd95ea1e0b36e289061262639460d6dc5fd209

commit r16-181-g1ecd95ea1e0b36e289061262639460d6dc5fd209
Author: Tomasz Kamiński 
Date:   Tue Mar 18 16:10:48 2025 +0100

libstdc++: Implement missing allocator-aware constructors for unordered 
containers.

This patch implements remainder of LWG2713 (after r15-8293-g64f5c854597759)
by adding missing allocator aware version of unordered associative 
containers
constructors accepting pair of iterators or initializer_list, and 
corresponding
deduction guides.

libstdc++-v3/ChangeLog:

* include/bits/unordered_map.h (unordered_map):
Define constructors accepting:
(_InputIterator, _InputIterator, const allocator_type&),
(initializer_list, const allocator_type&),
(unordered_multimap): Likewise.
* include/debug/unordered_map (unordered_map): Likewise.
(unordered_multimap): Likewise.
* include/bits/unordered_set.h (unordered_set):
Define constructors and deduction guide accepting:
(_InputIterator, _InputIterator, const allocator_type&),
(initializer_list, const allocator_type&),
(unordered_multiset): Likewise.
* include/debug/unordered_set (unordered_set): Likewise.
(unordered_multiset): Likewise.
* testsuite/23_containers/unordered_map/cons/66055.cc: New tests.
* testsuite/23_containers/unordered_map/cons/deduction.cc: New 
tests.
* testsuite/23_containers/unordered_multimap/cons/66055.cc: New 
tests.
* testsuite/23_containers/unordered_multimap/cons/deduction.cc: New
tests.
* testsuite/23_containers/unordered_multiset/cons/66055.cc: New 
tests.
* testsuite/23_containers/unordered_multiset/cons/deduction.cc: New
tests.
* testsuite/23_containers/unordered_set/cons/66055.cc: New tests.
* testsuite/23_containers/unordered_set/cons/deduction.cc: New 
tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/unordered_map.h  | 30 +
 libstdc++-v3/include/bits/unordered_set.h  | 71 ++
 libstdc++-v3/include/debug/unordered_map   | 22 +++
 libstdc++-v3/include/debug/unordered_set   | 54 
 .../23_containers/unordered_map/cons/66055.cc  | 11 ++--
 .../23_containers/unordered_map/cons/deduction.cc  | 28 +
 .../23_containers/unordered_multimap/cons/66055.cc | 10 +--
 .../unordered_multimap/cons/deduction.cc   | 34 +++
 .../23_containers/unordered_multiset/cons/66055.cc | 10 +--
 .../unordered_multiset/cons/deduction.cc   | 28 +
 .../23_containers/unordered_set/cons/66055.cc  | 10 +--
 .../23_containers/unordered_set/cons/deduction.cc  | 28 +
 12 files changed, 320 insertions(+), 16 deletions(-)

diff --git a/libstdc++-v3/include/bits/unordered_map.h 
b/libstdc++-v3/include/bits/unordered_map.h
index 5bc58e849ffa..fc07ffc998ca 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -251,6 +251,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : unordered_map(__n, __hf, key_equal(), __a)
   { }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2713. More missing allocator-extended constructors for unordered 
containers
+  template
+   unordered_map(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a)
+   : unordered_map(__first, __last, 0, hasher(), key_equal(), __a)
+   { }
+
   template
unordered_map(_InputIterator __first, _InputIterator __last,
  size_type __n,
@@ -271,6 +279,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : unordered_map(__l, __n, hasher(), key_equal(), __a)
   { }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2713. More missing allocator-extended constructors for unordered 
containers
+  unordered_map(initializer_list __l,
+   const allocator_type& __a)
+  : unordered_map(__l, 0, hasher(), key_equal(), __a)
+  { }
+
   unordered_map(initializer_list __l,
size_type __n, const hasher& __hf,
const allocator_type& __a)
@@ -1504,6 +1519,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   : unordered_multimap(__n, __hf, key_equal(), __a)
   { }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2713. More missing allocator-extended constructors for unordered 
containers
+  template
+   unordered_multimap(_InputIterator __first, _InputIterator __last,
+  const allocator_type& __a)
+   : unordered_multimap(__first, __last, 0, hasher(), key_equal(), __a)
+   { }
+
   template
unordered_multimap(_InputIterator __first, _InputIterator __last,
  

[gcc r16-182] libstdc++: Strip reference and cv-qual in range deduction guides for maps.

2025-04-28 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:4794340cd257ece0d197f041812c34c5ac5d50a1

commit r16-182-g4794340cd257ece0d197f041812c34c5ac5d50a1
Author: Tomasz Kamiński 
Date:   Thu Mar 20 09:02:03 2025 +0100

libstdc++: Strip reference and cv-qual in range deduction guides for maps.

This implements part of LWG4223 that adjust the deduction guides for maps 
types
(map, unordered_map, flat_map and non-unique equivalent) from "range"
(std::from_range, iterator pair), such that referience and cv qualification 
are
stripped from the element of the pair-like value_type.

In combination with r15-8296-gd50171bc07006d, the LWG4223 is fully 
implemented now.

libstdc++-v3/ChangeLog:

* include/bits/ranges_base.h (__detail::__range_key_type):
Replace remove_const_t with remove_cvref_t.
(__detail::__range_mapped_type): Apply remove_cvref_t.
* include/bits/stl_iterator.h: (__detail::__iter_key_t):
Replace remove_const_t with __remove_cvref_t.
(__detail::__iter_val_t): Apply __remove_cvref_t.
* testsuite/23_containers/flat_map/1.cc: New tests.
* testsuite/23_containers/flat_multimap/1.cc: New tests.
* testsuite/23_containers/map/cons/deduction.cc: New tests.
* testsuite/23_containers/map/cons/from_range.cc: New tests.
* testsuite/23_containers/multimap/cons/deduction.cc: New tests.
* testsuite/23_containers/multimap/cons/from_range.cc: New tests.
* testsuite/23_containers/unordered_map/cons/deduction.cc: New 
tests.
* testsuite/23_containers/unordered_map/cons/from_range.cc: New 
tests.
* testsuite/23_containers/unordered_multimap/cons/deduction.cc:
New tests.
* testsuite/23_containers/unordered_multimap/cons/from_range.cc:
New tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h|  4 +-
 libstdc++-v3/include/bits/stl_iterator.h   | 11 ++--
 libstdc++-v3/testsuite/23_containers/flat_map/1.cc | 21 +++
 .../testsuite/23_containers/flat_multimap/1.cc | 21 +++
 .../testsuite/23_containers/map/cons/deduction.cc  | 46 +++
 .../testsuite/23_containers/map/cons/from_range.cc |  8 +--
 .../23_containers/multimap/cons/deduction.cc   | 46 +++
 .../23_containers/multimap/cons/from_range.cc  |  8 +--
 .../23_containers/unordered_map/cons/deduction.cc  | 69 ++
 .../23_containers/unordered_map/cons/from_range.cc | 10 ++--
 .../unordered_multimap/cons/deduction.cc   | 69 ++
 .../unordered_multimap/cons/from_range.cc  | 10 ++--
 12 files changed, 279 insertions(+), 44 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index 488907da4466..dde164988569 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -1103,11 +1103,11 @@ namespace __detail
   // 4223. Deduction guides for maps are mishandling tuples and references
   template
 using __range_key_type
-  = remove_const_t>>;
+  = remove_cvref_t>>;
 
   template
 using __range_mapped_type
-  = tuple_element_t<1, ranges::range_value_t<_Range>>;
+  = remove_cvref_t>>;
 
   // The allocator's value_type for map-like containers.
   template
diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index 9203a66b2ff0..bed72955d0c4 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -3086,8 +3086,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cpp_deduction_guides >= 201606
   // These helper traits are used for deduction guides
   // of associative containers.
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 4223. Deduction guides for maps are mishandling tuples and references
   template
-using __iter_key_t = remove_const_t<
+using __iter_key_t = __remove_cvref_t<
 #ifdef __glibcxx_tuple_like // >= C++23
   tuple_element_t<0, typename 
iterator_traits<_InputIterator>::value_type>>;
 #else
@@ -3095,11 +3098,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   template
-using __iter_val_t
+using __iter_val_t = __remove_cvref_t<
 #ifdef __glibcxx_tuple_like // >= C++23
-  = tuple_element_t<1, typename 
iterator_traits<_InputIterator>::value_type>;
+  tuple_element_t<1, typename 
iterator_traits<_InputIterator>::value_type>>;
 #else
-  = typename iterator_traits<_InputIterator>::value_type::second_type;
+  typename iterator_traits<_InputIterator>::value_type::second_type>;
 #endif
 
   template
diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
index 4fd33f616f78..a4e0d867c936 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
+++ b/libstdc++

[gcc r15-9423] libstdc++: Use UTF-32BE as wide encoding for big-endian machines [PR119725]

2025-04-14 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:c2f1dda34defe739db6016dda97a6516243372e6

commit r15-9423-gc2f1dda34defe739db6016dda97a6516243372e6
Author: Tomasz Kamiński 
Date:   Mon Apr 14 08:43:58 2025 +0200

libstdc++: Use UTF-32BE as wide encoding for big-endian machines [PR119725]

This changes the `dg-options` line so UTF-32 with byte order native to the
machine is used as wide encoding.

We still do not handle mismatch in the byte order of the Unicode encodings
(UTF32-BE on little-endian machines). This would require larger changes,
as for example `unicode-data.h` tables are encoded with native byte order.

PR libstdc++/119725

libstdc++-v3/ChangeLog:

* testsuite/std/format/debug.cc: Updated dg-options.
* testsuite/std/format/debug_nonunicode.cc: Updated dg-options.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/testsuite/std/format/debug.cc| 3 ++-
 libstdc++-v3/testsuite/std/format/debug_nonunicode.cc | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/testsuite/std/format/debug.cc 
b/libstdc++-v3/testsuite/std/format/debug.cc
index 07cd1e0e349e..71bb7f4a0fe8 100644
--- a/libstdc++-v3/testsuite/std/format/debug.cc
+++ b/libstdc++-v3/testsuite/std/format/debug.cc
@@ -1,4 +1,5 @@
-// { dg-options "-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32LE 
-DUNICODE_ENC" }
+// { 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 }
 
diff --git a/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc 
b/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc
index 5c03171d71a1..2ac7e757ea8d 100644
--- a/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc
+++ b/libstdc++-v3/testsuite/std/format/debug_nonunicode.cc
@@ -1,4 +1,4 @@
-// { dg-options "-fexec-charset=ISO8859-1 -fwide-exec-charset=UTF-32LE" }
+// { dg-options "-fexec-charset=ISO8859-1" }
 // { dg-do run { target c++23 } }
 // { dg-add-options no_pch }


[gcc r15-9517] libstdc++: Implement formatters for pair and tuple [PR109162]

2025-04-16 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:473dde525248a694c0f4e62b31a7fc24b238c5b0

commit r15-9517-g473dde525248a694c0f4e62b31a7fc24b238c5b0
Author: Tomasz Kamiński 
Date:   Mon Apr 14 16:00:57 2025 +0200

libstdc++: Implement formatters for pair and tuple [PR109162]

This patch implements formatter specializations for pair and tuple form
P2286R8. In addition using 'm` and range_format::map (from P2585R1) for
ranges are now supported.

The formatters for pairs and tuples whose corresponding elements are the 
same
(after applying remove_cvref_t) derive from the same __tuple_formatter 
class.
This reduce the code duplication, as most of the parsing and formatting is 
the
same in such cases. We use a custom reduced implementation of the tuple
(__formatters_storage) to store the elements formatters.

Handling of the padding (width and fill) options, is extracted to
__format::__format_padded function, that is used both by __tuple_formatter 
and
range_formatter. To reduce number of instantations range_formatter::format
triggers, we cast incoming range to __format::__maybe_const_range<_Rg, 
_CharT>&,
before formatting it.

As in the case of previous commits, the signatures of the user-facing parse
and format methods of the provided formatters deviate from the standard by
constraining types of parameters:
* _CharT is constrained __formatter::__char
* basic_format_parse_context<_CharT> for parse argument
* basic_format_context<_Out, _CharT> for format second argument
The standard specifies last three of above as unconstrained types.

Finally, test for tuple-like std::array and std::ranges::subrange,
that illustrate that they remain formatted as ranges.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/std/format (__formatter_int::_M_format_character_escaped)
(__formatter_str::format): Use __sink.out() to produce _Sink_iter.
(__format::__const_formattable_range): Moved closer to 
range_formatter.
(__format::__maybe_const_range): Use `__conditional_t` and moved 
closer
to range_formatter.
(__format::__format_padded, __format::maybe_const)
(__format::__indexed_formatter_storage, __format::__tuple_formatter)
(std::formatter, _CharT>>)
(std::formatter, _CharT): Define.
(std::formatter<_Rg, _CharT>::format): Cast incoming range to
__format::__maybe_const_range<_Rg, _CharT>&.
(std::formatter<_Rg, _CharT>::_M_format): Extracted from format,
and use __format_padded.
(std::formatter<_Rg, _CharT>::_M_format_no_padding): Rename...
(std::formatter<_Rg, _CharT>::_M_format_elems): ...to this.
(std::formatter<_Rg, _CharT>::_M_format_with_padding): Extracted as
__format_padded.
* testsuite/util/testsuite_iterators.h (test_input_range_nocopy):
Define.
* testsuite/std/format/ranges/formatter.cc: Tests for `m` specifier.
* testsuite/std/format/ranges/sequence.cc: Tests for array and 
subrange.
* testsuite/std/format/ranges/map.cc: New test.
* testsuite/std/format/tuple.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/format| 377 +
 .../testsuite/std/format/ranges/formatter.cc   |   6 +-
 libstdc++-v3/testsuite/std/format/ranges/map.cc| 209 
 .../testsuite/std/format/ranges/sequence.cc|  52 ++-
 libstdc++-v3/testsuite/std/format/tuple.cc | 259 ++
 libstdc++-v3/testsuite/util/testsuite_iterators.h  |   3 +
 6 files changed, 813 insertions(+), 93 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 096dda4f989c..b1455977c65f 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1350,8 +1350,7 @@ namespace __format
__fc, _M_spec);
 
  __format::_Str_sink<_CharT> __sink;
- __format::_Sink_iter<_CharT> __out(__sink);
- __format::__write_escaped(__out, __s, __term);
+ __format::__write_escaped(__sink.out(), __s, __term);
  basic_string_view<_CharT> __escaped(__sink.view().data(),
  __sink.view().size());
  const size_t __escaped_width = _S_trunc(__escaped, __prec);
@@ -1387,13 +1386,13 @@ namespace __format
{
  ranges::iterator_t<_Rg> __first = ranges::begin(__rg);
  ranges::subrange __sub(__first, __first + __n);
- return format(_String(from_range, __sub), __fc);
+ return format(_String(from_range, __sub), __fc);
}
  else
{
  

[gcc r14-11649] libstdc++: Correct preprocessing checks for floatX_t and bfloat_16 formatting

2025-04-17 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:a295863e953c772a0ae91a11f652d1f641d3a3dc

commit r14-11649-ga295863e953c772a0ae91a11f652d1f641d3a3dc
Author: Tomasz Kamiński 
Date:   Tue Mar 11 11:59:36 2025 +0100

libstdc++: Correct preprocessing checks for floatX_t and bfloat_16 
formatting

Floating points types _Float16, _Float32, _Float64, and bfloat16,
can be formatted only if std::to_chars overloads for such types
were provided. Currently this is only the case for architectures
where float and double are 32-bits and 64-bits IEEE floating points types.

This patch updates the preprocessing checks for formatters
for above types to check _GLIBCXX_FLOAT_IS_IEEE_BINARY32
and _GLIBCXX_DOUBLE_IS_IEEE_BINARY64. Making them non-formattable
on non-IEEE architectures.

Remove a potential UB, where we could produce basic_format_arg
with _M_type set to _Arg_fp32 or _Arg_fp64, that was later not
handled by `_M_visit`.

libstdc++-v3/ChangeLog:

* include/std/format (formatter<_Float16, _CharT>): Define only if
_GLIBCXX_FLOAT_IS_IEEE_BINARY32 macro is defined.
(formatter<_Float16, _CharT>): As above.
(formatter<__gnu_cxx::__bfloat16_t, _CharT>): As above.
(formatter<_Float64, _CharT>): Define only if
_GLIBCXX_DOUBLE_IS_IEEE_BINARY64 is defined.
(basic_format_arg::_S_to_arg_type): Normalize _Float32 and _Float64
only to float and double respectivelly.
(basic_format_arg::_S_to_enum): Remove handling of _Float32 and 
_Float64.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 
(cherry picked from commit 445128c12cf22081223f7385196ee3889ef4c4b2)

Diff:
---
 libstdc++-v3/include/std/format | 32 
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index b8830766f40f..604f4cde3c47 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -2208,7 +2208,7 @@ namespace __format
 };
 #endif
 
-#ifdef __STDCPP_FLOAT16_T__
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   // Reuse __formatter_fp::format for _Float16.
   template<__format::__char _CharT>
 struct formatter<_Float16, _CharT>
@@ -2230,7 +2230,7 @@ namespace __format
 };
 #endif
 
-#if defined(__FLT32_DIG__)
+#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   // Reuse __formatter_fp::format for _Float32.
   template<__format::__char _CharT>
 struct formatter<_Float32, _CharT>
@@ -2252,7 +2252,7 @@ namespace __format
 };
 #endif
 
-#if defined(__FLT64_DIG__)
+#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
   // Reuse __formatter_fp::format for _Float64.
   template<__format::__char _CharT>
 struct formatter<_Float64, _CharT>
@@ -2296,7 +2296,7 @@ namespace __format
 };
 #endif
 
-#ifdef __STDCPP_BFLOAT16_T__
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   // Reuse __formatter_fp::format for bfloat16_t.
   template<__format::__char _CharT>
 struct formatter<__gnu_cxx::__bfloat16_t, _CharT>
@@ -3367,22 +3367,16 @@ namespace __format
return type_identity();
 #endif
 
-#ifdef __FLT32_DIG__
+#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
  else if constexpr (is_same_v<_Td, _Float32>)
-# ifdef _GLIBCXX_FLOAT_IS_IEEE_BINARY32
return type_identity();
-# else
-   return type_identity<_Float32>();
-# endif
 #endif
-#ifdef __FLT64_DIG__
+
+#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
  else if constexpr (is_same_v<_Td, _Float64>)
-# ifdef _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
return type_identity();
-# else
-   return type_identity<_Float64>();
-# endif
 #endif
+
 #if _GLIBCXX_FORMAT_F128
 # if __FLT128_DIG__
  else if constexpr (is_same_v<_Td, _Float128>)
@@ -3462,16 +3456,6 @@ namespace __format
return _Arg_u128;
 #endif
 
- // N.B. some of these types will never actually be used here,
- // because they get normalized to a standard floating-point type.
-#if defined __FLT32_DIG__ && ! _GLIBCXX_FLOAT_IS_IEEE_BINARY32
- else if constexpr (is_same_v<_Tp, _Float32>)
-   return _Arg_f32;
-#endif
-#if defined __FLT64_DIG__ && ! _GLIBCXX_DOUBLE_IS_IEEE_BINARY64
- else if constexpr (is_same_v<_Tp, _Float64>)
-   return _Arg_f64;
-#endif
 #if _GLIBCXX_FORMAT_F128 == 2
  else if constexpr (is_same_v<_Tp, __format::__float128_t>)
return _Arg_f128;


[gcc r15-9551] libstdc++: Fixed signed comparision in _M_parse_fill_and_align [PR119840]

2025-04-17 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:930b504b598864ba1774eb209a748ed76b6fc7c1

commit r15-9551-g930b504b598864ba1774eb209a748ed76b6fc7c1
Author: Tomasz Kamiński 
Date:   Thu Apr 17 10:33:10 2025 +0200

libstdc++: Fixed signed comparision in _M_parse_fill_and_align [PR119840]

Explicitly cast elements of __not_fill to _CharT. Only '{' and ':'
are used as `__not_fill`, so they are never negative.

PR libstdc++/119840

libstdc++-v3/ChangeLog:

* include/std/format (_M_parse_fill_and_align): Cast elements of
__not_fill to _CharT.

Diff:
---
 libstdc++-v3/include/std/format | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index f3fd837897bd..e557e104d74d 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -555,8 +555,8 @@ namespace __format
   constexpr iterator
   _M_parse_fill_and_align(iterator __first, iterator __last, string_view 
__not_fill) noexcept
   {
-   for (char c : __not_fill)
- if (*__first == c)
+   for (char __c : __not_fill)
+ if (*__first == static_cast<_CharT>(__c))
return __first;
 
using namespace __unicode;


[gcc r16-136] libstdc++: Define __cpp_lib_format_ranges in format header [PR109162]

2025-04-25 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:8b6cc2064306ba506b61f3e224829219033a9373

commit r16-136-g8b6cc2064306ba506b61f3e224829219033a9373
Author: Tomasz Kamiński 
Date:   Tue Apr 22 09:56:42 2025 +0200

libstdc++: Define __cpp_lib_format_ranges in format header [PR109162]

As P2286R8 and P2585R1 as now fully implemented, we now define
__cpp_lib_format_ranges feature test macro with __cpp_lib_format_ranges.
This macro is provided only in .

Uses of internal __glibcxx_format_ranges are also updated.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/bits/version.def (format_ranges): Remove no_stdname and
update value.
* include/bits/version.h: Regenerate.
* src/c++23/std.cc.in: Replace __glibcxx_format_ranges with
__cpp_lib_format_ranges.
* testsuite/std/format/formatter/lwg3944.cc: Likewise.
* testsuite/std/format/parse_ctx.cc: Likewise.
* testsuite/std/format/string.cc: Likewise.
* testsuite/std/format/ranges/feature_test.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/version.def| 3 +--
 libstdc++-v3/include/bits/version.h  | 3 ++-
 libstdc++-v3/src/c++23/std.cc.in | 6 ++
 libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc   | 2 +-
 libstdc++-v3/testsuite/std/format/parse_ctx.cc   | 2 +-
 libstdc++-v3/testsuite/std/format/ranges/feature_test.cc | 9 +
 libstdc++-v3/testsuite/std/format/string.cc  | 2 +-
 7 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 0afaf0dec244..737b3f421bf7 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1416,9 +1416,8 @@ ftms = {
   // 202207 P2286R8 Formatting Ranges
   // 202207 P2585R1 Improving default container formatting
   // LWG3750 Too many papers bump __cpp_lib_format
-  no_stdname = true; // TODO remove
   values = {
-v = 1; // TODO 202207
+v = 202207;
 cxxmin = 23;
 hosted = yes;
   };
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 980fee641e9d..59ff0cee0436 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1562,8 +1562,9 @@
 
 #if !defined(__cpp_lib_format_ranges)
 # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
-#  define __glibcxx_format_ranges 1L
+#  define __glibcxx_format_ranges 202207L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_ranges)
+#   define __cpp_lib_format_ranges 202207L
 #  endif
 # endif
 #endif /* !defined(__cpp_lib_format_ranges) && 
defined(__glibcxx_want_format_ranges) */
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index ea50496b057c..930a489ff44b 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1319,8 +1319,7 @@ export namespace std
   using std::format_to_n;
   using std::format_to_n_result;
   using std::formatted_size;
-// FIXME __cpp_lib_format_ranges
-#if __cplusplus > 202002L
+#if __cpp_lib_format_ranges
   using std::formattable;
 #endif
   using std::formatter;
@@ -1336,8 +1335,7 @@ export namespace std
   using std::wformat_context;
   using std::wformat_parse_context;
   using std::wformat_string;
-// FIXME __cpp_lib_format_ranges
-#ifdef __glibcxx_format_ranges
+#ifdef __cpp_lib_format_ranges
   using std::format_kind;
   using std::range_format;
   using std::range_formatter;
diff --git a/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc 
b/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
index 1f3edc9cb030..07e63af56529 100644
--- a/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
+++ b/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
@@ -18,7 +18,7 @@ void test_lwg3944()
   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" }
-#ifdef __glibcxx_format_ranges
+#ifdef __cpp_lib_format_ranges
   // LWG 3944 does not change this, it's still valid.
   std::format(L"{}", std::vector{'h', 'e', 'l', 'l', 'o'});
 #endif
diff --git a/libstdc++-v3/testsuite/std/format/parse_ctx.cc 
b/libstdc++-v3/testsuite/std/format/parse_ctx.cc
index b338ac7b762d..b5dd7cdba782 100644
--- a/libstdc++-v3/testsuite/std/format/parse_ctx.cc
+++ b/libstdc++-v3/testsuite/std/format/parse_ctx.cc
@@ -108,7 +108,7 @@ is_std_format_spec_for(std::string_view spec)
   }
 }
 
-#if __glibcxx_format_ranges
+#if __cpp_lib_format_ranges
 constexpr bool escaped_strings_supported = true;
 #else
 constexpr bool escaped_strings_supported = false;
diff --git a/libstdc++-v3/testsuite/std/format/ranges/feature_test.cc 
b/libstdc++-v3/testsuite/st

[gcc r16-135] libstdc++: Implement formatters for queue, priority_queue and stack [PR109162]

2025-04-25 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:bacf741a92a9a84becd23542b73186da4e4acbf6

commit r16-135-gbacf741a92a9a84becd23542b73186da4e4acbf6
Author: Tomasz Kamiński 
Date:   Fri Apr 18 14:56:39 2025 +0200

libstdc++: Implement formatters for queue, priority_queue and stack 
[PR109162]

This patch implements formatter specializations for standard container 
adaptors
(queue, priority_queue and stack) from P2286R8.

To be able to access the protected `c` member, the adaptors befriend
corresponding formatter specializations. Note that such specialization
may be disable if the container is formattable, in such case
specializations are unharmful.

As in the case of previous commits, the signatures of the user-facing parse
and format methods of the provided formatters deviate from the standard by
constraining types of parameters:
 * _CharT is constrained __formatter::__char
 * basic_format_parse_context<_CharT> for parse argument
 * basic_format_context<_Out, _CharT> for format second argument
The standard specifies all above as unconstrained types. In particular
_CharT constrain, allow us to befriend all allowed specializations.

Furthermore the standard specifies these formatters as delegating to
formatter, charT>, which in turn
delegates to range_formatter. This patch avoids one level of indirection,
and dependency of ranges::ref_view.  This is technically observable if
user specializes formatter> where PD is program defined
container, but I do not think this is the case worth extra indirection.

This patch also moves the formattable and it's dependencies to the 
formatfwd.h,
so it can be used in adapters formatters, without including format header.
The definition of _Iter_for is changed from alias to denoting
back_insert_iterator>, to struct with type nested 
typedef
that points to same type, that is forward declared.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/bits/formatfwd.h (__format::__parsable_with)
(__format::__formattable_with, __format::__formattable_impl)
(__format::__has_debug_format, __format::__const_formattable_range)
(__format::__maybe_const_range, __format::__maybe_const)
(std::formattable): Moved from std/format.
(__format::Iter_for, std::range_formatter): Forward declare.
* include/bits/stl_queue.h (std::formatter): Forward declare.
(std::queue, std::priority_queue): Befriend formatter 
specializations.
* include/bits/stl_stack.h (std::formatter): Forward declare.
(std::stack): Befriend formatter specializations.
* include/std/format (__format::_Iter_for): Define as struct with
(__format::__parsable_with, __format::__formattable_with)
(__format::__formattable_impl, __format::__has_debug_format)
(_format::__const_formattable_range, __format::__maybe_const_range)
(__format::__maybe_const, std::formattable): Moved to 
bits/formatfwd.h.
(std::range_formatter): Remove default argument specified in 
declaration
in bits/formatfwd.h.
* include/std/queue: Include bits/version.h before bits/stl_queue.h.
(formatter, _CharT>)
(formatter, _CharT>): 
Define.
* include/std/stack: Include bits/version.h before bits/stl_stack.h
(formatter, _CharT>): Define.
* testsuite/std/format/ranges/adaptors.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/formatfwd.h  |  78 +++
 libstdc++-v3/include/bits/stl_queue.h  |  14 ++
 libstdc++-v3/include/bits/stl_stack.h  |   9 ++
 libstdc++-v3/include/std/format|  76 ++
 libstdc++-v3/include/std/queue |  80 ++-
 libstdc++-v3/include/std/stack |  48 ++-
 .../testsuite/std/format/ranges/adaptors.cc| 156 +
 7 files changed, 387 insertions(+), 74 deletions(-)

diff --git a/libstdc++-v3/include/bits/formatfwd.h 
b/libstdc++-v3/include/bits/formatfwd.h
index a6b5ac8c8ce1..9ba658b078a5 100644
--- a/libstdc++-v3/include/bits/formatfwd.h
+++ b/libstdc++-v3/include/bits/formatfwd.h
@@ -37,6 +37,12 @@
 //  must have been included before this header:
 #ifdef __glibcxx_format // C++ >= 20 && HOSTED
 
+#include 
+#include 
+#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
+#  include   // input_range, range_reference_t
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -50,6 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // [format.formatter], formatter
   template struct formatter;
 
+/// @cond undocumented
 namespace __format
 {
 #ifdef _GLIBCXX_USE_WCHAR_T
@@ -60,9 +67,80 @@ namespace __format
 concept

[gcc r16-142] libstdc++: Minimalize temporary allocations when width is specified [PR109162]

2025-04-25 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:01e5ef3e8b91288f5d387a27708f9f8979a50edf

commit r16-142-g01e5ef3e8b91288f5d387a27708f9f8979a50edf
Author: Tomasz Kamiński 
Date:   Wed Apr 23 13:17:09 2025 +0200

libstdc++: Minimalize temporary allocations when width is specified 
[PR109162]

When width parameter is specified for formatting range, tuple or escaped
presentation of string, we used to format characters to temporary string,
and write produce sequence padded according to the spec. However, once the
estimated width of formatted representation of input is larger than the 
value
of spec width, it can be written directly to the output. This limits size of
required allocation, especially for large ranges.

Similarly, if precision (maximum) width is provided for string presentation,
only a prefix of sequence with estimated width not greater than precision, 
needs
to be buffered.

To realize above, this commit implements a new _Padding_sink specialization.
This sink holds an output iterator, a value of padding width, (optionally)
maximum width and a string buffer inherited from _Str_sink.
Then any incoming characters are treated in one of following ways, 
depending of
estimated width W of written sequence:
* written to string if W is smaller than padding width and maximum width 
(if present)
* ignored, if W is greater than maximum width
* written to output iterator, if W is greater than padding width

The padding sink is used instead of _Str_sink in __format::__format_padded,
__formatter_str::_M_format_escaped functions.

Furthermore __formatter_str::_M_format implementation was reworked, to:
* reduce number of instantiations by delegating to _Rg& and const _Rg& 
overloads,
* non-debug presentation is written to _Out directly or via _Padding_sink
* if maximum width is specified for debug format with non-unicode encoding,
  string size is limited to that number.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/bits/formatfwd.h (__simply_formattable_range): Moved from
std/format.
* include/std/format (__formatter_str::_format): Extracted escaped
string handling to separate method...
(__formatter_str::_M_format_escaped): Use __Padding_sink.
(__formatter_str::_M_format): Adjusted implementation.
(__formatter_str::_S_trunc): Extracted as namespace function...
(__format::_truncate): Extracted from __formatter_str::_S_trunc.
(__format::_Seq_sink): Removed forward declarations, made members
protected and non-final.
(_Seq_sink::_M_trim): Define.
(_Seq_sink::_M_span): Renamed from view.
(_Seq_sink::view): Returns string_view instead of span.
(__format::_Str_sink): Moved after _Seq_sink.
(__format::__format_padded): Use _Padding_sink.
* testsuite/std/format/debug.cc: Add timeout and new tests.
* testsuite/std/format/ranges/sequence.cc: Specify unicode as
encoding and new tests.
* testsuite/std/format/ranges/string.cc: Likewise.
* testsuite/std/format/tuple.cc: Likewise.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/formatfwd.h  |   8 +
 libstdc++-v3/include/std/format| 399 +++--
 libstdc++-v3/testsuite/std/format/debug.cc | 388 +++-
 .../testsuite/std/format/ranges/sequence.cc| 116 ++
 libstdc++-v3/testsuite/std/format/ranges/string.cc |  63 
 libstdc++-v3/testsuite/std/format/tuple.cc |  93 +
 6 files changed, 961 insertions(+), 106 deletions(-)

diff --git a/libstdc++-v3/include/bits/formatfwd.h 
b/libstdc++-v3/include/bits/formatfwd.h
index 12ae2ad2ac08..3fa01ad1eab7 100644
--- a/libstdc++-v3/include/bits/formatfwd.h
+++ b/libstdc++-v3/include/bits/formatfwd.h
@@ -145,6 +145,14 @@ namespace __format
   = ranges::input_range
  && formattable, _CharT>;
 
+  // _Rg& and const _Rg& are both formattable and use same formatter
+  // specialization for their references.
+  template
+concept __simply_formattable_range
+  = __const_formattable_range<_Rg, _CharT>
+ && same_as>,
+remove_cvref_t>>;
+
   template
 using __maybe_const_range
   = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, 
_Rg>;
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 86c93f0e6ebd..69d8d189db62 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -56,7 +56,7 @@
 #include   // input_range, range_reference_t
 #include   // subrange
 #include  // ranges::copy
-#include  // back_insert_iterator
+#include  // back_insert_iterator, counted_iterator
 #include  // __is_pair
 #incl

[gcc r15-9589] libstdc++: Define __cpp_lib_format_ranges in format header [PR109162]

2025-04-25 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:17e0decc1dbf827747aebfa0573cc8e50969ae3f

commit r15-9589-g17e0decc1dbf827747aebfa0573cc8e50969ae3f
Author: Tomasz Kamiński 
Date:   Tue Apr 22 09:56:42 2025 +0200

libstdc++: Define __cpp_lib_format_ranges in format header [PR109162]

As P2286R8 and P2585R1 as now fully implemented, we now define
__cpp_lib_format_ranges feature test macro with __cpp_lib_format_ranges.
This macro is provided only in .

Uses of internal __glibcxx_format_ranges are also updated.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/bits/version.def (format_ranges): Remove no_stdname and
update value.
* include/bits/version.h: Regenerate.
* src/c++23/std.cc.in: Replace __glibcxx_format_ranges with
__cpp_lib_format_ranges.
* testsuite/std/format/formatter/lwg3944.cc: Likewise.
* testsuite/std/format/parse_ctx.cc: Likewise.
* testsuite/std/format/string.cc: Likewise.
* testsuite/std/format/ranges/feature_test.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 
(cherry picked from commit 049fefd7e1501ac9dcc66a5ef6c34cea0331dc43)

Diff:
---
 libstdc++-v3/include/bits/version.def| 3 +--
 libstdc++-v3/include/bits/version.h  | 3 ++-
 libstdc++-v3/src/c++23/std.cc.in | 6 ++
 libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc   | 2 +-
 libstdc++-v3/testsuite/std/format/parse_ctx.cc   | 2 +-
 libstdc++-v3/testsuite/std/format/ranges/feature_test.cc | 9 +
 libstdc++-v3/testsuite/std/format/string.cc  | 2 +-
 7 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 0afaf0dec244..737b3f421bf7 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1416,9 +1416,8 @@ ftms = {
   // 202207 P2286R8 Formatting Ranges
   // 202207 P2585R1 Improving default container formatting
   // LWG3750 Too many papers bump __cpp_lib_format
-  no_stdname = true; // TODO remove
   values = {
-v = 1; // TODO 202207
+v = 202207;
 cxxmin = 23;
 hosted = yes;
   };
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 980fee641e9d..59ff0cee0436 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1562,8 +1562,9 @@
 
 #if !defined(__cpp_lib_format_ranges)
 # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED
-#  define __glibcxx_format_ranges 1L
+#  define __glibcxx_format_ranges 202207L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_ranges)
+#   define __cpp_lib_format_ranges 202207L
 #  endif
 # endif
 #endif /* !defined(__cpp_lib_format_ranges) && 
defined(__glibcxx_want_format_ranges) */
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 5e18ad739083..6da6d3829149 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1315,8 +1315,7 @@ export namespace std
   using std::format_to_n;
   using std::format_to_n_result;
   using std::formatted_size;
-// FIXME __cpp_lib_format_ranges
-#if __cplusplus > 202002L
+#if __cpp_lib_format_ranges
   using std::formattable;
 #endif
   using std::formatter;
@@ -1332,8 +1331,7 @@ export namespace std
   using std::wformat_context;
   using std::wformat_parse_context;
   using std::wformat_string;
-// FIXME __cpp_lib_format_ranges
-#ifdef __glibcxx_format_ranges
+#ifdef __cpp_lib_format_ranges
   using std::format_kind;
   using std::range_format;
   using std::range_formatter;
diff --git a/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc 
b/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
index 1f3edc9cb030..07e63af56529 100644
--- a/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
+++ b/libstdc++-v3/testsuite/std/format/formatter/lwg3944.cc
@@ -18,7 +18,7 @@ void test_lwg3944()
   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" }
-#ifdef __glibcxx_format_ranges
+#ifdef __cpp_lib_format_ranges
   // LWG 3944 does not change this, it's still valid.
   std::format(L"{}", std::vector{'h', 'e', 'l', 'l', 'o'});
 #endif
diff --git a/libstdc++-v3/testsuite/std/format/parse_ctx.cc 
b/libstdc++-v3/testsuite/std/format/parse_ctx.cc
index b338ac7b762d..b5dd7cdba782 100644
--- a/libstdc++-v3/testsuite/std/format/parse_ctx.cc
+++ b/libstdc++-v3/testsuite/std/format/parse_ctx.cc
@@ -108,7 +108,7 @@ is_std_format_spec_for(std::string_view spec)
   }
 }
 
-#if __glibcxx_format_ranges
+#if __cpp_lib_format_ranges
 constexpr bool escaped_strings_supported = true;
 #else
 constexpr bool escaped_strings_supported = false;
diff --git a/libstdc++-v

[gcc r15-9490] libstdc++: Implement formatter for ranges and range_formatter [PR109162]

2025-04-15 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:f62e5d720de829cf346b799f3463fee53728ba6c

commit r15-9490-gf62e5d720de829cf346b799f3463fee53728ba6c
Author: Tomasz Kamiński 
Date:   Fri Mar 28 09:30:22 2025 +0100

libstdc++: Implement formatter for ranges and range_formatter [PR109162]

This patch implements formatter specialization for input_ranges and
range_formatter class from P2286R8, as adjusted by P2585R1. The formatter
for pair/tuple is not yet provided, making maps not formattable.

This introduces an new _M_format_range member to internal __formatter_str,
that formats range as _CharT as string, according to the format spec.
This function transform any contiguous range into basic_string_view 
directly,
by computing size if necessary. Otherwise, for ranges for which size can be
computed (forward_range or sized_range) we use a stack buffer, if they are
sufficiently small. Finally, we create a basic_string<_CharT> from the 
range,
and format its content.

In case when padding is specified, this is handled by firstly formatting
the content of the range to the temporary string object. However, this can 
be
only implemented if the iterator of the basic_format_context is internal
type-erased iterator used by implementation. Otherwise a new 
basic_format_context
would need to be created, which would require rebinding of handles stored in
the arguments: note that format spec for element type could retrieve any 
format
argument from format context, visit and use handle to format it.
As basic_format_context provide no user-facing constructor, the user are 
not able
to construct object of that type with arbitrary iterators.

The signatures of the user-facing parse and format methods of the provided
formatters deviate from the standard by constraining types of params:
* _CharT is constrained __formatter::__char
* basic_format_parse_context<_CharT> for parse argument
* basic_format_context<_Out, _CharT> for format second argument
The standard specifies last three of above as unconstrained types. These 
types
are later passed to possibly user-provided formatter specializations, that 
are
required via formattable concept to only accept above types.

Finally, the formatter specialization is implemented
without using specialization of range-default-formatter exposition only
template as base class, while providing same functionality.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/std/format (__format::__has_debug_format, 
_Pres_type::_Pres_seq)
(_Pres_type::_Pres_str, __format::__Stackbuf_size): Define.
(_Separators::_S_squares, _Separators::_S_parens, 
_Separators::_S_comma)
(_Separators::_S_colon): Define additional constants.
(_Spec::_M_parse_fill_and_align): Define overload accepting
list of excluded characters for fill, and forward existing overload.
(__formatter_str::_M_format_range): Define.
(__format::_Buf_sink) Use __Stackbuf_size for size of array.
(__format::__is_map_formattable, std::range_formatter)
(std::formatter<_Rg, _CharT>): Define.
* src/c++23/std.cc.in (std::format_kind, std::range_format)
(std::range_formatter): Export.
* testsuite/std/format/formatter/lwg3944.cc: Guarded tests with
__glibcxx_format_ranges.
* testsuite/std/format/formatter/requirements.cc: Adjusted for 
standard
behavior.
* testsuite/23_containers/vector/bool/format.cc: Test vector 
formatting.
* testsuite/std/format/ranges/format_kind.cc: New test.
* testsuite/std/format/ranges/formatter.cc: New test.
* testsuite/std/format/ranges/sequence.cc: New test.
* testsuite/std/format/ranges/string.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/format| 505 ++---
 libstdc++-v3/src/c++23/std.cc.in   |   6 +
 .../testsuite/23_containers/vector/bool/format.cc  |   6 +
 .../testsuite/std/format/formatter/lwg3944.cc  |   4 +-
 .../testsuite/std/format/formatter/requirements.cc |  14 +-
 .../testsuite/std/format/ranges/format_kind.cc |  94 
 .../testsuite/std/format/ranges/formatter.cc   | 145 ++
 .../testsuite/std/format/ranges/sequence.cc| 190 
 libstdc++-v3/testsuite/std/format/ranges/string.cc | 226 +
 9 files changed, 1125 insertions(+), 65 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 23f00970840f..096dda4f989c 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -97,6 +97,10 @@ namespace __format
 #define _GLIBCXX_WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
 #define _GLIBCXX_WIDEN

[gcc r14-11384] libstdc++: Fix subrange conversion to pair-like [PR119121]

2025-03-05 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:750d691077d96879068312dd4b25a51c1d6958c5

commit r14-11384-g750d691077d96879068312dd4b25a51c1d6958c5
Author: Tomasz Kamiński 
Date:   Wed Mar 5 11:11:55 2025 +0100

libstdc++: Fix subrange conversion to pair-like [PR119121]

Fix regression introduced by r14-8710-g65b4cba9d6a9ff

PR libstdc++/119121

libstdc++-v3/ChangeLog:

* include/bits/ranges_util.h 
(__detail::__pair_like_convertible_from):
Use `_Tp` in `is_reference_v` check
* testsuite/std/ranges/subrange/tuple_like.cc: New tests for
pair-like conversion

Reviewed-by: Jonathan Wakely 
(cherry picked from commit 95b2f8d8fb3131165b1b38645dacf10a5dd2bc15)

Diff:
---
 libstdc++-v3/include/bits/ranges_util.h|  2 +-
 .../testsuite/std/ranges/subrange/tuple_like.cc| 29 ++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/ranges_util.h 
b/libstdc++-v3/include/bits/ranges_util.h
index aba5b6a88c0c..c2a87a233415 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -243,7 +243,7 @@ namespace ranges
 
 template
   concept __pair_like_convertible_from
-   = !range<_Tp> && !is_reference_v<_Vp> && __pair_like<_Tp>
+   = !range<_Tp> && !is_reference_v<_Tp> && __pair_like<_Tp>
&& constructible_from<_Tp, _Up, _Vp>
&& __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
&& convertible_to<_Vp, tuple_element_t<1, _Tp>>;
diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/tuple_like.cc 
b/libstdc++-v3/testsuite/std/ranges/subrange/tuple_like.cc
index a02475b1157e..71f9535106d7 100644
--- a/libstdc++-v3/testsuite/std/ranges/subrange/tuple_like.cc
+++ b/libstdc++-v3/testsuite/std/ranges/subrange/tuple_like.cc
@@ -18,6 +18,8 @@
 // { dg-do compile { target c++20 } }
 
 #include 
+#include 
+#include 
 
 using S1 = std::ranges::subrange;
 using S2 = std::ranges::subrange;
@@ -49,3 +51,30 @@ static_assert( std::same_as(s2)), 
void*> );
 const S2 c2;
 static_assert( std::same_as(c2)), long*> );
 static_assert( std::same_as(c2)), void*> );
+
+std::pair p1 = s1;
+std::pair p2 = s2;
+std::tuple t1 = s1;
+std::tuple t2 = s2;
+
+std::pair const& p3 = s1;
+std::tuple&& t3 = s1;
+
+std::pair p4 = s1;
+std::tuple t4 = s1;
+
+static_assert( !std::convertible_to, 
std::pair> );
+static_assert( !std::convertible_to, 
std::tuple> );
+
+static_assert( !std::convertible_to, 
std::pair> );
+static_assert( !std::convertible_to, 
std::tuple> );
+
+struct B {};
+struct D : B {};
+
+std::ranges::subrange sd;
+std::pair p5 = sd;
+std::tuple t5 = sd;
+
+static_assert( !std::convertible_to, std::pair> );
+static_assert( !std::convertible_to, std::tuple> );


[gcc r15-9198] libstdc++: Provide formatter for vector::reference [PR109162]

2025-04-04 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:84d668b0ca67c5d3fe6430f101d61e60aa796a81

commit r15-9198-g84d668b0ca67c5d3fe6430f101d61e60aa796a81
Author: Tomasz Kamiński 
Date:   Thu Apr 3 17:22:39 2025 +0200

libstdc++: Provide formatter for vector::reference [PR109162]

This patch implement formatter for vector::reference which
is part of P2286R8.

To indicate partial support we define __glibcxx_format_ranges macro
value 1, without defining __cpp_lib_format_ranges.

To avoid including the whole content of the  header, we
introduce new bits/formatfwd.h forward declares classes required
for newly introduce formatter.

The signatures of the user-facing parse and format method of the provided
formatters deviate from the standard by constraining types of params:
* _Bit_reference instead T satisfying is-vector-bool-reference
* _CharT is constrained __formatter::__char
* basic_format_parse_context<_CharT> for parse argument
* basic_format_context<_Out, _CharT> for format second argument
The standard specifies last three of above as unconstrained types, which 
leads
to formattable::reference, char32_t> (and any other type as 
char)
being true.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/Makefile.am: Add bits/formatfwd.h.
* include/Makefile.in: Add bits/formatfwd.h.
* include/bits/version.def: Define __glibcxx_format_ranges without
corresponding std name.
* include/bits/version.h: Regenerate.
* include/std/format (basic_format_context, __format::__char):
Move declartions to bits/formatfwd.h.
(formatter<_Tp, _CharT>): Remove default argument for _CharT
parameter, now specified in forward declaration in bits/formatfwd.h.
* include/std/vector (formatter<_Bit_reference, _CharT>): Define.
* include/bits/formatfwd.h: New file with forward declarations
for bits of std/format.
* testsuite/23_containers/vector/bool/format.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/Makefile.am   |  1 +
 libstdc++-v3/include/Makefile.in   |  1 +
 libstdc++-v3/include/bits/formatfwd.h  | 71 ++
 libstdc++-v3/include/bits/version.def  | 18 +++---
 libstdc++-v3/include/bits/version.h|  9 +++
 libstdc++-v3/include/std/format| 14 +
 libstdc++-v3/include/std/vector| 32 ++
 .../testsuite/23_containers/vector/bool/format.cc  | 67 
 8 files changed, 192 insertions(+), 21 deletions(-)

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 4dc771a540c4..537774c26689 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -195,6 +195,7 @@ bits_headers = \
${bits_srcdir}/cow_string.h \
${bits_srcdir}/deque.tcc \
${bits_srcdir}/erase_if.h \
+   ${bits_srcdir}/formatfwd.h \
${bits_srcdir}/forward_list.h \
${bits_srcdir}/forward_list.tcc \
${bits_srcdir}/fs_dir.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 0e3d09b3a750..7b96b2207f84 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -548,6 +548,7 @@ bits_freestanding = \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/cow_string.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/deque.tcc \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/erase_if.h \
+@GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/formatfwd.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/forward_list.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/forward_list.tcc \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/fs_dir.h \
diff --git a/libstdc++-v3/include/bits/formatfwd.h 
b/libstdc++-v3/include/bits/formatfwd.h
new file mode 100644
index ..44922cb83fc7
--- /dev/null
+++ b/libstdc++-v3/include/bits/formatfwd.h
@@ -0,0 +1,71 @@
+//  Formatting -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License

[gcc r15-8293] libstdc++-v3: Implement allocator-aware from_range_t constructors for unordered containers.

2025-03-19 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:64f5c854597759fd11648b7d9e3884b8c69f218f

commit r15-8293-g64f5c854597759fd11648b7d9e3884b8c69f218f
Author: Tomasz Kamiński 
Date:   Tue Mar 18 16:10:48 2025 +0100

libstdc++-v3: Implement allocator-aware from_range_t constructors for 
unordered containers.

This patch implements part of LWG2713 covering the from_range
constructors, which makes std::ranges::to(alloc)
well-formed. Likewise for rest of unordered containers.

As this consturctors were added to v15, this has no impact
on code that compiled with previous versions.

libstdc++-v3/ChangeLog:

* include/bits/unordered_map.h
(unordered_map(from_range_t, _Rg&&, const allocator_type&))
(unordered_multimap(from_range_t, _Rg&&, const allocator_type&)):
Define.
* include/bits/unordered_set.h
(unordered_set(from_range_t, _Rg&&, const allocator_type&))
(unordered_multiset(from_range_t, _Rg&&, const allocator_type&)):
Define.
* testsuite/23_containers/unordered_map/cons/from_range.cc: New 
tests.
New tests.
* testsuite/23_containers/unordered_multimap/cons/from_range.cc:
New tests.
* testsuite/23_containers/unordered_multiset/cons/from_range.cc:
New tests.
* testsuite/23_containers/unordered_set/cons/from_range.cc: New 
tests.
* testsuite/std/ranges/conv/1.cc: New tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/unordered_map.h  | 14 +
 libstdc++-v3/include/bits/unordered_set.h  | 15 ++
 .../23_containers/unordered_map/cons/from_range.cc | 24 ++
 .../unordered_multimap/cons/from_range.cc  | 24 ++
 .../unordered_multiset/cons/from_range.cc  | 22 +---
 .../23_containers/unordered_set/cons/from_range.cc | 22 +---
 libstdc++-v3/testsuite/std/ranges/conv/1.cc| 22 
 7 files changed, 93 insertions(+), 50 deletions(-)

diff --git a/libstdc++-v3/include/bits/unordered_map.h 
b/libstdc++-v3/include/bits/unordered_map.h
index 4a0527c6025e..49e97e2dfca9 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -300,6 +300,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  : _M_h(__n, __hf, __eql, __a)
  { insert_range(std::forward<_Rg>(__rg)); }
 
+   // _GLIBCXX_RESOLVE_LIB_DEFECTS
+   // 2713. More missing allocator-extended constructors for unordered 
containers
+   template<__detail::__container_compatible_range _Rg>
+unordered_map(from_range_t, _Rg&& __rg, const allocator_type& __a)
+ : _M_h(0, hasher(), key_equal(), __a)
+ { insert_range(std::forward<_Rg>(__rg)); }
+
template<__detail::__container_compatible_range _Rg>
 unordered_map(from_range_t, _Rg&& __rg, size_type __n,
   const allocator_type& __a)
@@ -1546,6 +1553,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  : _M_h(__n, __hf, __eql, __a)
  { insert_range(std::forward<_Rg>(__rg)); }
 
+   // _GLIBCXX_RESOLVE_LIB_DEFECTS
+   // 2713. More missing allocator-extended constructors for unordered 
containers
+   template<__detail::__container_compatible_range _Rg>
+unordered_multimap(from_range_t, _Rg&& __rg, const allocator_type& __a)
+ : _M_h(0, hasher(), key_equal(), __a)
+ { insert_range(std::forward<_Rg>(__rg)); }
+
template<__detail::__container_compatible_range _Rg>
 unordered_multimap(from_range_t, _Rg&& __rg, size_type __n,
const allocator_type& __a)
diff --git a/libstdc++-v3/include/bits/unordered_set.h 
b/libstdc++-v3/include/bits/unordered_set.h
index cfa8ee297f4e..4bc256c17c1e 100644
--- a/libstdc++-v3/include/bits/unordered_set.h
+++ b/libstdc++-v3/include/bits/unordered_set.h
@@ -294,6 +294,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  : _M_h(__n, __hf, __eql, __a)
  { insert_range(std::forward<_Rg>(__rg)); }
 
+   // _GLIBCXX_RESOLVE_LIB_DEFECTS
+   // 2713. More missing allocator-extended constructors for unordered 
container
+   template<__detail::__container_compatible_range<_Value> _Rg>
+unordered_set(from_range_t, _Rg&& __rg, const allocator_type& __a)
+ : _M_h(0, hasher(), key_equal(), __a)
+ { insert_range(std::forward<_Rg>(__rg)); }
+
template<__detail::__container_compatible_range<_Value> _Rg>
 unordered_set(from_range_t, _Rg&& __rg, size_type __n,
   const allocator_type& __a)
@@ -1265,6 +1272,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  : _M_h(__n, __hf, __eql, __a)
  { insert_range(std::forward<_Rg>(__rg)); }
 
+
+   // _GLIBCXX_RESOLVE_LIB_DEFECTS
+   // 2713. More missing allocator-exte

[gcc r15-8879] libstdc++: Fix handling of common cpp20-only ranges for flat sets [PR119415]

2025-03-25 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:4d1b19695669e6c67b9c3df07673bc22cae3a662

commit r15-8879-g4d1b19695669e6c67b9c3df07673bc22cae3a662
Author: Tomasz Kamiński 
Date:   Mon Mar 24 18:04:28 2025 +0100

libstdc++: Fix handling of common cpp20-only ranges for flat sets [PR119415]

These patch add check to verify if common range iterators satisfies
Cpp17LegacyIterator requirements (__detail::__cpp17_input_iterator),
before invoking overloads of insert that accepts two iterators.
As such overloads existed before c++20 iterators were introduced,
they commonly assume existence of iterator_traits<..>::iterator_category,
and passing a cpp20-only iterators, leads to hard errors.

In case if user-defined container wants to support more efficient
insertion in such cases, it should provided insert_range method,
as in the case of standard containers.

PR libstdc++/119415

libstdc++-v3/ChangeLog:

* include/std/flat_set (_Flat_set_impl:insert_range):
Add __detail::__cpp17_input_iterator check.
* testsuite/23_containers/flat_multiset/1.cc: New tests
* testsuite/23_containers/flat_set/1.cc: New tests

Reviewed-by: Patrick Palka , Jonathan Wakely 

Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/flat_set  |  3 ++-
 .../testsuite/23_containers/flat_multiset/1.cc | 27 ++
 libstdc++-v3/testsuite/23_containers/flat_set/1.cc | 27 ++
 3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/flat_set 
b/libstdc++-v3/include/std/flat_set
index 9240f2b9a2eb..bab56742ddd6 100644
--- a/libstdc++-v3/include/std/flat_set
+++ b/libstdc++-v3/include/std/flat_set
@@ -480,7 +480,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  typename container_type::iterator __it;
  if constexpr (requires { _M_cont.insert_range(_M_cont.end(), __rg); })
__it = _M_cont.insert_range(_M_cont.end(), __rg);
- else if constexpr (ranges::common_range<_Rg>)
+ else if constexpr (ranges::common_range<_Rg>
+&& 
__detail::__cpp17_input_iterator>)
__it = _M_cont.insert(_M_cont.end(), ranges::begin(__rg), 
ranges::end(__rg));
  else
{
diff --git a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc
index 910f5dca5be4..cc31164315ae 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc
@@ -143,6 +143,32 @@ test06()
   VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) );
 }
 
+template
+struct NoInsertRange : std::vector
+{
+  using std::vector::vector;
+
+  template
+  void insert_range(typename std::vector::const_iterator, R&&) = delete;
+};
+
+void test07()
+{
+#ifdef __SIZEOF_INT128__
+  // PR libstdc++/119415 - flat_foo::insert_range cannot handle common ranges
+  // on c++20 only iterators
+  auto r = std::views::iota(__int128(1), __int128(6));
+
+  std::flat_multiset s;
+  s.insert_range(r);
+  VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) );
+
+  std::flat_multiset, NoInsertRange> s2;
+  s2.insert_range(r);
+  VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) );
+#endif
+}
+
 int
 main()
 {
@@ -153,4 +179,5 @@ main()
   test04();
   test05();
   test06();
+  test07();
 }
diff --git a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc
index f0eaac936bf6..16881d788fcd 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc
@@ -158,6 +158,32 @@ test06()
   VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) );
 }
 
+template
+struct NoInsertRange : std::vector
+{
+  using std::vector::vector;
+
+  template
+  void insert_range(typename std::vector::const_iterator, R&&) = delete;
+};
+
+void test07()
+{
+#ifdef __SIZEOF_INT128__
+  // PR libstdc++/119415 - flat_foo::insert_range cannot handle common ranges
+  // on c++20 only iterators
+  auto r = std::views::iota(__int128(1), __int128(6));
+
+  std::flat_set s;
+  s.insert_range(r);
+  VERIFY( std::ranges::equal(s, (int[]){1, 2, 3, 4, 5}) );
+
+  std::flat_set, NoInsertRange> s2;
+  s2.insert_range(r);
+  VERIFY( std::ranges::equal(s2, (int[]){1, 2, 3, 4, 5}) );
+#endif
+}
+
 int
 main()
 {
@@ -168,4 +194,5 @@ main()
   test04();
   test05();
   test06();
+  test07();
 }


[gcc r15-9179] libstdc++: Restored accidentally removed test case.

2025-04-03 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:81c990aa84b22562157ce2926577b392b4a129d3

commit r15-9179-g81c990aa84b22562157ce2926577b392b4a129d3
Author: Tomasz Kamiński 
Date:   Thu Apr 3 14:56:49 2025 +0200

libstdc++: Restored accidentally removed test case.

It was removed by accident r15-9178-g5c7f6272f43f42.

libstdc++-v3/ChangeLog:

* testsuite/std/format/functions/format.cc: Restored line.

Diff:
---
 libstdc++-v3/testsuite/std/format/functions/format.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc 
b/libstdc++-v3/testsuite/std/format/functions/format.cc
index d8dbf4634133..000f2671816d 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -522,6 +522,7 @@ test_unicode()
   std::string sP = std::format("{:1.1} {:*<1.1}", "£", "🤡");
   VERIFY( sP == "£ *" );
   sP = std::format("{:*<2.1} {:*<2.1}", "£", "🤡");
+  VERIFY( sP == "£* **" );
 
   // Verify field width handling for extended grapheme clusters,
   // and that a cluster gets output as a single item, not truncated.


[gcc r14-11524] libstdc++: Restored accidentally removed test case.

2025-04-03 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:83cd4bda12f1218fea878acfc964949649ca9fc7

commit r14-11524-g83cd4bda12f1218fea878acfc964949649ca9fc7
Author: Tomasz Kamiński 
Date:   Thu Apr 3 14:56:49 2025 +0200

libstdc++: Restored accidentally removed test case.

It was removed by accident r14-11523-gad1b71fc2882c1.

libstdc++-v3/ChangeLog:

* testsuite/std/format/functions/format.cc: Restored line.

(cherry picked from commit 81c990aa84b22562157ce2926577b392b4a129d3)

Diff:
---
 libstdc++-v3/testsuite/std/format/functions/format.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc 
b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 97eb0957e5e1..78010e159d36 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -518,6 +518,7 @@ test_unicode()
   std::string sP = std::format("{:1.1} {:*<1.1}", "£", "🤡");
   VERIFY( sP == "£ *" );
   sP = std::format("{:*<2.1} {:*<2.1}", "£", "🤡");
+  VERIFY( sP == "£* **" );
 
   // Verify field width handling for extended grapheme clusters,
   // and that a cluster gets output as a single item, not truncated.


[gcc r15-9631] libstdc++: Fix width computation for the chrono formatting [PR120114]

2025-05-07 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:e52f71b6dd888f0d5548d9f5bd139601dbafb3be

commit r15-9631-ge52f71b6dd888f0d5548d9f5bd139601dbafb3be
Author: Tomasz Kamiński 
Date:   Mon May 5 16:32:58 2025 +0200

libstdc++: Fix width computation for the chrono formatting [PR120114]

Use `__unicode::_field_width` to compute the field width of the output when 
writting
the formatted output for std::chrono::types. This applies both to 
characters copied
from format string, and one produced by localized formatting.

We also use _Str_sink::view() instead of get(), which avoids copying the 
content of
the buffer to std::string in case of small output.

PR libstdc++/120114

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (__formatter_chrono::_M_format): Use 
__field_width.
* testsuite/std/time/format/pr120114.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 
(cherry picked from commit 52f6ab55051ff43fd1b40ff06d9501043f8ba844)

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h  |  10 +-
 libstdc++-v3/testsuite/std/time/format/pr120114.cc | 125 +
 2 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h 
b/libstdc++-v3/include/bits/chrono_io.h
index b7f6f5f49e5e..f5aa8a3e18af 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -705,8 +705,14 @@ namespace __format
if (__write_direct)
  return __out;
 
- auto __str = std::move(__sink).get();
- return __format::__write_padded_as_spec(__str, __str.size(),
+ auto __span = __sink.view();
+ __string_view __str(__span.data(), __span.size());
+ size_t __width;
+ if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+   __width = __unicode::__field_width(__str);
+ else
+   __width = __str.size();
+ return __format::__write_padded_as_spec(__str, __width,
  __fc, _M_spec);
}
 
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120114.cc 
b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
new file mode 100644
index ..c630bb35a9d0
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
@@ -0,0 +1,125 @@
+// { dg-do run { target c++23 } }
+// { dg-options "-fexec-charset=UTF-8" }
+// { dg-timeout-factor 2 }
+
+#include 
+#include 
+#include 
+
+#define WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template
+void
+test_from_format_string()
+{
+  std::basic_string<_CharT> res;
+  using namespace std::chrono_literals;
+  auto date = 2025y/std::chrono::May/05d;
+
+  res = std::format(WIDEN("{:+<13%F\U0001f921}"), date);
+  VERIFY( res == WIDEN("2025-05-05\U0001f921+") );
+
+  res = std::format(WIDEN("{:->15%F\U0001f921}"), date);
+  VERIFY( res == WIDEN("---2025-05-05\U0001f921") );
+
+  res = std::format(WIDEN("{:=^20%F\U0001f921}"), date);
+  VERIFY( res == WIDEN("2025-05-05\U0001f921") );
+}
+
+template
+void
+test_formatted_value()
+{
+  // Custom time_put facet which returns Ideographic Telegraph Symbol
+  // for given month for Om.
+  struct TimePut : std::time_put<_CharT>
+  {
+using iter_type = std::time_put<_CharT>::iter_type;
+using char_type = std::time_put<_CharT>::char_type;
+
+iter_type
+do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t,
+  char format, char modifier) const override
+{
+  if (format != 'm' && modifier != 'm')
+   return std::time_put<_CharT>::do_put(out, io, fill, t, format, 
modifier);
+  std::basic_string_view<_CharT> str;
+  switch (t->tm_mon)
+   {
+case 0:
+  str = WIDEN("\u32C0");
+  break;
+case 1:
+  str = WIDEN("\u32C1");
+  break;
+case 2:
+  str = WIDEN("\u32C2");
+  break;
+case 3:
+  str = WIDEN("\u32C3");
+  break;
+case 4:
+  str = WIDEN("\u32C4");
+  break;
+case 5:
+  str = WIDEN("\u32C5");
+  break;
+case 6:
+  str = WIDEN("\u32C6");
+  break;
+case 7:
+  str = WIDEN("\u32C7");
+  break;
+case 8:
+  str = WIDEN("\u32C8");
+  break;
+case 9:
+  str = WIDEN("\u32C9");
+  break;
+case 10:
+  str = WIDEN("\u32CA");
+  break;
+case 11:
+  str = WIDEN("\u32CB");
+  break;
+   };
+   return std::copy(str.begin(), str.end(), out);
+}
+  };
+  const std::locale loc(std::locale::classic(), new TimePut);
+
+  std::basic_string<_CharT> res;
+
+  res = std::format(loc, WIDEN("{:<1L%Om}"), std::chrono::January);
+  VERIFY( res == WIDEN("\u32C0") );
+
+  res = std::format(loc, WIDEN("{:>2L%Om}"), std::chrono::February);
+

[gcc r16-617] libstdc++: Avoid double indirection in move_only_function when possible [PR119125]

2025-05-14 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:708d40ff109c6e49d02b684a368571722a160af8

commit r16-617-g708d40ff109c6e49d02b684a368571722a160af8
Author: Tomasz Kamiński 
Date:   Thu May 8 08:08:43 2025 +0200

libstdc++: Avoid double indirection in move_only_function when possible 
[PR119125]

Based on the provision in C++26 [func.wrap.general] p2 this patch adjust 
the generic
move_only_function(_Fn&&) constructor, such that when _Fn refers to selected
move_only_function instantiations, the ownership of the target object is 
directly
transfered to constructor object. This avoid cost of double indirection in 
this situation.
We apply this also in C++23 mode.

We also fix handling of self assignments, to match behavior required by 
standard,
due use of copy and swap idiom.

An instantiations MF1 of move_only_function can transfer target of another
instantiation MF2, if it can be constructed via usual rules 
(__is_callable_from<_MF2>),
and their invoker are convertible (__is_invoker_convertible()), 
i.e.:
* MF1 is less noexcept than MF2,
* return types are the same after stripping cv-quals,
* adujsted parameters type are the same (__poly::_param_t), i.e. param of 
types T and T&&
  are compatible for non-trivially copyable objects.
Compatiblity of cv ref qualification is checked via 
__is_callable_from<_MF2>.

To achieve above the generation of _M_invoke functions is moved to _Invoker 
class
templates, that only depends on noexcept, return type and adjusted 
parameter of the
signature. To make the invoker signature compatible between const and 
mutable
qualified signatures, we always accept _Storage as const& and perform a 
const_cast
for locally stored object. This approach guarantees that we never strip 
const from
const object.

Another benefit of this approach is that 
move_only_function
and move_only_function use same funciton pointer, 
which should
reduce binary size.

The _Storage and _Manager functionality was also extracted and adjusted from
_Mofunc_base, in preparation for implementation for copyable_function and
function_ref. The _Storage was adjusted to store functions pointers as 
void(*)().
The manage function, now accepts _Op enum parameter, and supports additional
operations:
 * _Op::_Address stores address of target object in destination
 * _Op::_Copy, when enabled, copies from source to destination
Furthermore, we provide a type-independent mamange functions for handling 
all:
 * function pointer types
 * trivially copyable object stored locally.
Similary as in case of invoker, we always pass source as const (for copy),
and cast away constness in case of move operations, where we know that 
source
is mutable.

Finally, the new helpers are defined in __polyfunc internal namespace.

PR libstdc++/119125

libstdc++-v3/ChangeLog:

* include/bits/mofunc_impl.h: (std::move_only_function): Adjusted 
for
changes in bits/move_only_function.h
(move_only_function::move_only_function(_Fn&&)): Special case
move_only_functions with same invoker.
(move_only_function::operator=(move_only_function&&)): Handle self
assigment.
* include/bits/move_only_function.h (__polyfunc::_Ptrs)
(__polyfunc::_Storage): Refactored from _Mo_func::_Storage.
(__polyfunc::__param_t): Moved from move_only_function::__param_t.
(__polyfunc::_Base_invoker, __polyfunc::_Invoke): Refactored from
move_only_function::_S_invoke.
(__polyfunc::_Manager): Refactored from _Mo_func::_S_manager.
(std::_Mofunc_base): Moved into __polyfunc::_Mo_base with parts
extracted to __polyfunc::_Storage and __polyfunc::_Manager.
(__polyfunc::__deref_as, __polyfunc::__invoker_of)
(__polyfunc::__base_of, __polyfunc::__is_invoker_convertible): 
Define.
(std::__is_move_only_function_v): Renamed to
__is_polymorphic_function_v.
(std::__is_polymorphic_function_v): Renamed from
__is_move_only_function_v.
* testsuite/20_util/move_only_function/call.cc: Test for
functions pointers.
* testsuite/20_util/move_only_function/conv.cc: New test.
* testsuite/20_util/move_only_function/move.cc: Tests for
self assigment.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/mofunc_impl.h|  74 ++--
 libstdc++-v3/include/bits/move_only_function.h | 455 +++--
 .../testsuite/20_util/move_only_function/call.cc   |  14 +
 .../testsuite/20_util/move_only_function/conv.cc   | 188 +
 .../testsuite/20_util/move_only_function/move.cc   |  11 +
 5 files changed, 588 insertions(+), 154 deletions(-)

diff --git a/

[gcc r16-618] libstdc++: Implement C++26 copyable_function [PR119125]

2025-05-14 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:0e93f7cd4ed0cf6bcfda90ed4dcad51a1f65b4b6

commit r16-618-g0e93f7cd4ed0cf6bcfda90ed4dcad51a1f65b4b6
Author: Tomasz Kamiński 
Date:   Mon May 12 10:01:22 2025 +0200

libstdc++: Implement C++26 copyable_function [PR119125]

This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.

For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.

As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage 
invocations
in noexcept member functions (_M_move, _M_destroy, swap).

PR libstdc++/119125

libstdc++-v3/ChangeLog:

* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v>)

(__variant::_Never_valueless_alt>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v>)

(__variant::_Never_valueless_alt>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/doc/doxygen/stdheader.cc  |   1 +
 libstdc++-v3/include/Makefile.am   |   1 +
 libstdc++-v3/include/Makefile.in   |   1 +
 libstdc++-v3/include/bits/cpyfunc_impl.h   | 269 +
 libstdc++-v3/include/bits/mofunc_impl.h|   4 +
 libstdc++-v3/include/bits/move_only_function.h |  92 ++-
 libstdc++-v3/include/bits/version.def  |   9 +
 libstdc++-v3/include/bits/version.h|  10 +
 libstdc++-v3/include/std/functional|   1 +
 libstdc++-v3/src/c++23/std.cc.in   |   3 +
 .../testsuite/20_util/copyable_function/call.cc| 224 +
 .../testsuite/20_util/copyable_function/cons.cc| 126 ++
 .../testsuite/20_util/copyable_function/conv.cc| 251 +++
 .../testsuite/20_util/copyable_function/copy.cc| 154 
 .../testsuite/20_util/copyable_function/move.cc| 120 +
 15 files changed, 1262 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/doc/doxygen/stdheader.cc 
b/libstdc++-v3/doc/doxygen/stdheader.cc
index 3ee825feb668..8a2013344100 100644
--- a/libstdc++-v3/doc/doxygen/stdheader.cc
+++ b/libstdc++-v3/doc/doxygen/stdheader.cc
@@ -54,6 +54,7 @@ void init_map()
 headers["function.h"]   = "functional";
 headers["functional_hash.h"]= "functional";
 headers["mofunc_impl.h"]= "functional";
+headers["cpyfunc_impl.h"]   = "functional";
 headers["move_only_function.h"] = "functional";
 headers["invoke.h"] = "functional";
 headers["ranges_cmp.h"] = "functional";
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 1140fa0dff

[gcc r16-620] libstdc++: Renamed bits/move_only_function.h to bits/funcwrap.h [PR119125]

2025-05-14 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:d9055d010475fa1c624d6036881eee9c37034b21

commit r16-620-gd9055d010475fa1c624d6036881eee9c37034b21
Author: Tomasz Kamiński 
Date:   Mon May 12 11:06:34 2025 +0200

libstdc++: Renamed bits/move_only_function.h to bits/funcwrap.h [PR119125]

The file now includes copyable_function in addition to
move_only_function.

PR libstdc++/119125

libstdc++-v3/ChangeLog:
* include/bits/move_only_function.h: Move to...
* include/bits/funcwrap.h: ...here.
* doc/doxygen/stdheader.cc (init_map): Replaced move_only_function.h
with funcwrap.h, and changed include guard to use feature test 
macro.
Move bits/version.h include before others.
* include/Makefile.am: Likewise.
* include/Makefile.in: Likewise.
* include/std/functional: Likewise.

Reviewed-by: Patrick Palka 
Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/doc/doxygen/stdheader.cc  |  2 +-
 libstdc++-v3/include/Makefile.am   |  2 +-
 libstdc++-v3/include/Makefile.in   |  2 +-
 .../bits/{move_only_function.h => funcwrap.h}  |  8 +++---
 libstdc++-v3/include/std/functional| 32 +++---
 5 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/libstdc++-v3/doc/doxygen/stdheader.cc 
b/libstdc++-v3/doc/doxygen/stdheader.cc
index 8a2013344100..839bfc81bc02 100644
--- a/libstdc++-v3/doc/doxygen/stdheader.cc
+++ b/libstdc++-v3/doc/doxygen/stdheader.cc
@@ -55,7 +55,7 @@ void init_map()
 headers["functional_hash.h"]= "functional";
 headers["mofunc_impl.h"]= "functional";
 headers["cpyfunc_impl.h"]   = "functional";
-headers["move_only_function.h"] = "functional";
+headers["funcwrap.h"]   = "functional";
 headers["invoke.h"] = "functional";
 headers["ranges_cmp.h"] = "functional";
 headers["refwrap.h"]= "functional";
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 5cc13381b025..3e5b6c4142ed 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -205,6 +205,7 @@ bits_headers = \
${bits_srcdir}/fs_ops.h \
${bits_srcdir}/fs_path.h \
${bits_srcdir}/fstream.tcc \
+   ${bits_srcdir}/funcwrap.h \
${bits_srcdir}/gslice.h \
${bits_srcdir}/gslice_array.h \
${bits_srcdir}/hashtable.h \
@@ -224,7 +225,6 @@ bits_headers = \
${bits_srcdir}/mask_array.h \
${bits_srcdir}/memory_resource.h \
${bits_srcdir}/mofunc_impl.h \
-   ${bits_srcdir}/move_only_function.h \
${bits_srcdir}/new_allocator.h \
${bits_srcdir}/node_handle.h \
${bits_srcdir}/ostream.tcc \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 6e5e97aa2362..3531162b5f75 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -558,6 +558,7 @@ bits_freestanding = \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/fs_ops.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/fs_path.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/fstream.tcc \
+@GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/funcwrap.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/gslice.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/gslice_array.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/hashtable.h \
@@ -577,7 +578,6 @@ bits_freestanding = \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/mask_array.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/memory_resource.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/mofunc_impl.h \
-@GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/move_only_function.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/new_allocator.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/node_handle.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/ostream.tcc \
diff --git a/libstdc++-v3/include/bits/move_only_function.h 
b/libstdc++-v3/include/bits/funcwrap.h
similarity index 98%
rename from libstdc++-v3/include/bits/move_only_function.h
rename to libstdc++-v3/include/bits/funcwrap.h
index b7328dbf4d89..4e053534cf57 100644
--- a/libstdc++-v3/include/bits/move_only_function.h
+++ b/libstdc++-v3/include/bits/funcwrap.h
@@ -22,13 +22,13 @@
 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 // .
 
-/** @file include/bits/move_only_function.h
+/** @file include/bits/funcwrap.h
  *  This is an internal header file, included by other library headers.
  *  Do not attempt to use it directly. @headername{functional}
  */
 
-#ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H
-#define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1
+#ifndef _GLIBCXX_FUNCWRAP_H
+#define _GLIBCXX_FUNCWRAP_H 1
 
 #ifdef _GLIBCXX_SYSHDR
 #pragma GCC system_header
@@ -504,4 +504,4 @@ _GLIBCXX_END_NAMESPACE_VERSION
 #endif // __glibcxx_copyable_function
 
 #endif // __glibcxx_copyable_function || __glibcx

[gcc r16-616] libstdc++: Preserve the argument type in basic_format_args [PR119246]

2025-05-14 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:9c9a7316adb99693e237164908893a78b86ba000

commit r16-616-g9c9a7316adb99693e237164908893a78b86ba000
Author: Tomasz Kamiński 
Date:   Wed Apr 30 10:37:48 2025 +0200

libstdc++: Preserve the argument type in basic_format_args [PR119246]

This commits adjust the way how the arguments are stored in the _Arg_value
(and thus basic_format_args), by preserving the types of fixed width
floating-point types, that were previously converted to float, double,
long double.

The _Arg_value union now contains alternatives with std::bfloat16_t,
std::float16_t, std::float32_t, std::float64_t that use pre-existing
_Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f32 argument types.

This does not affect formatting, as specialization of formatters for fixed
width floating-point types formats them by casting to the corresponding
standard floating point type.

For the 128bit floating we need to handle the ppc64 architecture,
(_GLIBCXX_LONG_DOUBLE_ALT128_COMPAT) for which the long double may (per TU
basis) designate either __ibm128 and __ieee128 type, we need to store both
types in the _Arg_value and have two _Arg_types (_Arg_ibm128, _Arg_ieee128).
On other architectures we use extra enumerator value to store __float128,
that is different from long double and _Float128. This is consistent with 
ppc64,
for which __float128, if present, is same type as __ieee128. We use 
_Arg_float128
_M_float128 names that deviate from _Arg_fN naming scheme, to emphasize that
this flag is not used for std::float128_t (_Float128) type, that is 
consistenly
formatted via handle.

The __format::__float128_t type is renamed to __format::__flt128_t, to 
mitigate
visual confusion between this type and __float128. We also introduce 
__bflt16_t
typedef instead of using of decltype.

We add new alternative for the _Arg_value and allow them to be accessed via 
_S_get,
when the types are available. However, we produce and handle corresponding 
_Arg_type,
only when we can format them. See also r14-3329-g27d0cfcb2b33de.

The formatter<_Float128, _CharT> that formats via __format::__flt128_t is 
always
provided, when type is available. It is still correct when 
__format::__flt128_t
is _Float128.

We also provide formatter<__float128, _CharT> that formats via __flt128_t.
As this type may be disabled (-mno-float128), extra care needs to be taken,
for situation when __float128 is same as long double. If the formatter 
would be
defined in such case, the formatter would be generated
from different specializations, and have different mangling:
  * formatter<__float128, _CharT> if __float128 is present,
  * formatter<__format::__formattable_float, _CharT> otherwise.
To best of my knowledge this happens only on ppc64 for __ieee128 and 
__float128,
so the formatter is not defined in this case. static_assert is added to 
detect
other configurations like that. In such case we should replace it with 
constraint.

PR libstdc++/119246

libstdc++-v3/ChangeLog:

* include/std/format (__format::__bflt16_t): Define.
(_GLIBCXX_FORMAT_F128): Separate value for cases where _Float128
is used.
(__format::__float128_t): Renamed to __format::__flt128_t.
(std::formatter<_Float128, _CharT>): Define always if there is
formattable 128bit float.
(std::formatter<__float128, _CharT>): Define.
(_Arg_type::_Arg_f128): Rename to _Arg_float128 and adjust value.
(_Arg_type::_Arg_ibm128): Change value to _Arg_ldbl.
(_Arg_type::_Arg_ieee128): Define as alias to _Arg_float128.
(_Arg_value::_M_f128): Replaced with _M_ieee128 and _M_float128.
(_Arg_value::_M_ieee128, _Arg_value::_M_float128)
(_Arg_value::_M_bf16, _Arg_value::_M_f16, _Arg_value::_M_f32)
(_Arg_value::_M_f64): Define.
(_Arg_value::_S_get, basic_format_arg::_S_to_enum): Handle __bflt16,
_Float16, _Float32, _Float64, and __float128 types.
(basic_format_arg::_S_to_arg_type): Preserve _bflt16, _Float16,
_Float32, _Float64 and __float128 types.
(basic_format_arg::_M_visit): Handle _Arg_float128, _Arg_ieee128,
_Arg_b16, _Arg_f16, _Arg_f32, _Arg_f64.
* testsuite/std/format/arguments/args.cc: Updated to illustrate
that extended floating point types use handles now. Added test
for __float128.
* testsuite/std/format/parse_ctx.cc: Extended test to cover class
to check_dynamic_spec with floating point types and handles.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/format| 217 ++---
 .../testsuite/std/format/arguments/args.cc  

[gcc r16-878] libstdc++: Implement C++26 std::indirect [PR119152]

2025-05-26 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:caf804b1795575d7714c62dd45b649831598055e

commit r16-878-gcaf804b1795575d7714c62dd45b649831598055e
Author: Jonathan Wakely 
Date:   Thu Mar 21 23:07:56 2024 +

libstdc++: Implement C++26 std::indirect [PR119152]

This patch implements C++26 std::indirect as specified
in P3019 with amendment to move assignment from LWG 4251.

PR libstdc++/119152

libstdc++-v3/ChangeLog:

* doc/doxygen/stdheader.cc: Added indirect.h file.
* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* include/bits/indirect.h: New file.
* include/bits/version.def (indirect): Define.
* include/bits/version.h: Regenerate.
* include/std/memory: Include new header.
* testsuite/std/memory/indirect/copy.cc
* testsuite/std/memory/indirect/copy_alloc.cc
* testsuite/std/memory/indirect/ctor.cc
* testsuite/std/memory/indirect/incomplete.cc
* testsuite/std/memory/indirect/invalid_neg.cc
* testsuite/std/memory/indirect/move.cc
* testsuite/std/memory/indirect/move_alloc.cc
* testsuite/std/memory/indirect/relops.cc

Co-authored-by: Tomasz Kamiński 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/doc/doxygen/stdheader.cc  |   1 +
 libstdc++-v3/include/Makefile.am   |   1 +
 libstdc++-v3/include/Makefile.in   |   1 +
 libstdc++-v3/include/bits/indirect.h   | 459 +
 libstdc++-v3/include/bits/version.def  |   9 +
 libstdc++-v3/include/bits/version.h|  10 +
 libstdc++-v3/include/std/memory|   5 +
 libstdc++-v3/testsuite/std/memory/indirect/copy.cc | 121 ++
 .../testsuite/std/memory/indirect/copy_alloc.cc| 228 ++
 libstdc++-v3/testsuite/std/memory/indirect/ctor.cc | 203 +
 .../testsuite/std/memory/indirect/incomplete.cc|  38 ++
 .../testsuite/std/memory/indirect/invalid_neg.cc   |  28 ++
 libstdc++-v3/testsuite/std/memory/indirect/move.cc | 144 +++
 .../testsuite/std/memory/indirect/move_alloc.cc| 296 +
 .../testsuite/std/memory/indirect/relops.cc|  82 
 15 files changed, 1626 insertions(+)

diff --git a/libstdc++-v3/doc/doxygen/stdheader.cc 
b/libstdc++-v3/doc/doxygen/stdheader.cc
index 938b2b04a262..cb5d17a4f1f7 100644
--- a/libstdc++-v3/doc/doxygen/stdheader.cc
+++ b/libstdc++-v3/doc/doxygen/stdheader.cc
@@ -106,6 +106,7 @@ void init_map()
 headers["uses_allocator.h"] = "memory";
 headers["uses_allocator_args.h"]= "memory";
 headers["out_ptr.h"]= "memory";
+headers["indirect.h"]   = "memory";
 headers["memory_resource.h"]= "memory_resource";
 headers["unique_lock.h"]= "mutex";
 headers["sat_arith.h"]  = "numeric";
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index baf0290d6559..cc402f0648f4 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -211,6 +211,7 @@ bits_headers = \
${bits_srcdir}/gslice_array.h \
${bits_srcdir}/hashtable.h \
${bits_srcdir}/hashtable_policy.h \
+   ${bits_srcdir}/indirect.h \
${bits_srcdir}/indirect_array.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index e4e1079d8bdb..a6e602327b6e 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -564,6 +564,7 @@ bits_freestanding = \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/gslice_array.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/hashtable.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/hashtable_policy.h \
+@GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/indirect.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/indirect_array.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/ios_base.h \
 @GLIBCXX_HOSTED_TRUE@  ${bits_srcdir}/istream.tcc \
diff --git a/libstdc++-v3/include/bits/indirect.h 
b/libstdc++-v3/include/bits/indirect.h
new file mode 100644
index ..85908e219b77
--- /dev/null
+++ b/libstdc++-v3/include/bits/indirect.h
@@ -0,0 +1,459 @@
+// Vocabulary Types for Composite Class Design -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Un

[gcc r16-647] libstdc++: Fix preprocessor check for __float128 formatter [PR119246]

2025-05-15 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:d010a39b9e788a1b3c58e0954c1b2c6afad8210a

commit r16-647-gd010a39b9e788a1b3c58e0954c1b2c6afad8210a
Author: Tomasz Kamiński 
Date:   Thu May 15 08:58:09 2025 +0200

libstdc++: Fix preprocessor check for __float128 formatter [PR119246]

The previous check `_GLIBCXX_FORMAT_F128 != 1` was passing if
_GLIBCXX_FORMAT_F128 was not defined, i.e. evaluted to zero.

This broke sparc-sun-solaris2.11 and x86_64-darwin.

PR libstdc++/119246

libstdc++-v3/ChangeLog:

* include/std/format: Updated check for _GLIBCXX_FORMAT_F128.

Diff:
---
 libstdc++-v3/include/std/format | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index f0b0252255d3..bfda5895e0c0 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -2973,7 +2973,7 @@ namespace __format
 };
 #endif
 
-#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 != 1
+#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 > 1
   // Reuse __formatter_fp::format<__format::__flt128_t, Out> for __float128.
   // This formatter is not declared if _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT is 
true,
   // as __float128 when present is same type as __ieee128, which may be same as


[gcc r16-821] libstdc++: Define _Scoped_allocation RAII helper

2025-05-22 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:0faa31da113768a626daa294e840ff1b17499ebf

commit r16-821-g0faa31da113768a626daa294e840ff1b17499ebf
Author: Jonathan Wakely 
Date:   Thu May 22 10:58:31 2025 +0200

libstdc++: Define _Scoped_allocation RAII helper

libstdc++-v3/ChangeLog:

* include/bits/allocated_ptr.h (_Scoped_allocation): New class
template.

Co-authored-by: Tomasz Kamiński 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/allocated_ptr.h | 96 +++
 1 file changed, 96 insertions(+)

diff --git a/libstdc++-v3/include/bits/allocated_ptr.h 
b/libstdc++-v3/include/bits/allocated_ptr.h
index 0b2b6fe5820e..aa5355f0e2fc 100644
--- a/libstdc++-v3/include/bits/allocated_ptr.h
+++ b/libstdc++-v3/include/bits/allocated_ptr.h
@@ -36,6 +36,7 @@
 # include 
 # include 
 # include 
+# include 
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -136,6 +137,101 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   return { std::__allocate_guarded(__a) };
 }
 
+  // An RAII type that acquires memory from an allocator.
+  // N.B.  'scoped' here in in the RAII sense, not the scoped allocator model,
+  // so this has nothing to do with `std::scoped_allocator_adaptor`.
+  // This class can be used to simplify the common pattern:
+  //
+  // auto ptr = alloc.allocate(1);
+  // try {
+  //   std::construct_at(std::to_address(ptr), args);
+  //   m_ptr = ptr;
+  // } catch (...) {
+  //   alloc.deallocate(ptr, 1);
+  //   throw;
+  // }
+  //
+  // Instead you can do:
+  //
+  // _Scoped_allocation sa(alloc);
+  // m_ptr = std::construct_at(sa.get(), args);
+  // (void) sa.release();
+  //
+  // Or even simpler:
+  //
+  // _Scoped_allocation sa(alloc, std::in_place, args);
+  // m_ptr = sa.release();
+  //
+  template
+struct _Scoped_allocation
+{
+  using value_type = typename allocator_traits<_Alloc>::value_type;
+  using pointer = typename allocator_traits<_Alloc>::pointer;
+
+  // Use `a` to allocate memory for `n` objects.
+  constexpr explicit
+  _Scoped_allocation(const _Alloc& __a, size_t __n = 1)
+  : _M_a(__a), _M_n(__n), _M_p(_M_a.allocate(__n))
+  { }
+
+#if __glibcxx_optional >= 201606L
+  // Allocate memory for a single object and if that succeeds,
+  // construct an object using args.
+  //
+  // Does not do uses-allocator construction; don't use if you need that.
+  //
+  // CAUTION: the destructor will *not* destroy this object, it will only
+  // free the memory. That means the following pattern is unsafe:
+  //
+  // _Scoped_allocation  sa(alloc, in_place, args);
+  // potentially_throwing_operations();
+  // return sa.release();
+  //
+  // If the middle operation throws, the object will not be destroyed.
+  template
+   constexpr explicit
+   _Scoped_allocation(const _Alloc& __a, in_place_t, _Args&&... __args)
+   : _Scoped_allocation(__a, 1)
+   {
+ // The target constructor has completed, so if the next line throws,
+ // the destructor will deallocate the memory.
+ allocator_traits<_Alloc>::construct(_M_a, get(),
+ std::forward<_Args>(__args)...);
+   }
+#endif
+
+  _GLIBCXX20_CONSTEXPR
+  ~_Scoped_allocation()
+  {
+   if (_M_p) [[__unlikely__]]
+ _M_a.deallocate(_M_p, _M_n);
+  }
+
+  _Scoped_allocation(_Scoped_allocation&&) = delete;
+
+  constexpr _Alloc
+  get_allocator() const noexcept { return _M_a; }
+
+  constexpr value_type*
+  get() const noexcept
+  { return std::__to_address(_M_p); }
+
+  [[__nodiscard__]]
+  constexpr pointer
+  release() noexcept { return std::__exchange(_M_p, nullptr); }
+
+private:
+  [[__no_unique_address__]] _Alloc _M_a;
+  size_t _M_n;
+  pointer _M_p;
+};
+
+#if __glibcxx_optional >= 201606L && __cpp_deduction_guides >= 201606L
+  template
+_Scoped_allocation(_Alloc, in_place_t, _Args...)
+  -> _Scoped_allocation<_Alloc>;
+#endif
+
 /// @endcond
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std


[gcc r16-1107] libstdc++: Test for formatting with empty spec for time points.

2025-06-04 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:3cfa53aa95a19c3b5fc711ad4d9f39ec9b8e7c3f

commit r16-1107-g3cfa53aa95a19c3b5fc711ad4d9f39ec9b8e7c3f
Author: Tomasz Kamiński 
Date:   Tue Jun 3 11:40:17 2025 +0200

libstdc++: Test for formatting with empty spec for time points.

Adding a tests for behavior of the ostream operator and the formatting
with empty chrono-spec for the chrono types. Current coverage is:
 * time point, zoned_time and local_time_format in this commit,
 * duration and hh_mm_ss in r16-1099-gac0a04b7a254fb,
 * calendar types in r16-1016-g28a17985dd34b7.

libstdc++-v3/ChangeLog:

* testsuite/std/time/format/empty_spec.cc: New tests.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 .../testsuite/std/time/format/empty_spec.cc| 208 +++--
 1 file changed, 194 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc 
b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index 46942dc30fc6..ec57a6f0d209 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -12,6 +12,46 @@ using namespace std::chrono;
 #define WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
 #define WIDEN(S) WIDEN_(_CharT, S)
 
+template
+void
+test_no_empty_spec()
+{
+  try
+  {
+T t{};
+
+if constexpr (std::is_same_v)
+  (void)std::vformat("{}", std::make_format_args(t));
+#ifdef _GLIBCXX_USE_WCHAR_T
+else
+  (void)std::vformat(L"{}", std::make_wformat_args(t));
+#endif // _GLIBCXX_USE_WCHAR_T
+VERIFY(false);
+  }
+  catch (const std::format_error&)
+  {
+VERIFY(true);
+  }
+}
+
+template
+void verify(const T& t, std::basic_string_view<_CharT> str)
+{
+  std::basic_string<_CharT> res;
+
+  res = std::format(WIDEN("{}"), t);
+  VERIFY( res == str );
+
+  std::basic_stringstream<_CharT> os;
+  os << t;
+  res = std::move(os).str();
+  VERIFY( res == str );
+}
+
+template
+void verify(const T& t, const CharT* str)
+{ verify(t, std::basic_string_view(str)); }
+
 template
 void
 test_padding()
@@ -37,20 +77,6 @@ test_padding()
   VERIFY( res == WIDEN("==16 is not a valid month==") );
 }
 
-template
-void verify(const T& t, const _CharT* str)
-{
-  std::basic_string<_CharT> res;
-
-  res = std::format(WIDEN("{}"), t);
-  VERIFY( res == str );
-
-  std::basic_stringstream<_CharT> os;
-  os << t;
-  res = std::move(os).str();
-  VERIFY( res == str );
-}
-
 template
 struct Rep
 {
@@ -553,6 +579,159 @@ test_calendar()
   test_year_month_weekday_last();
 }
 
+template
+constexpr auto
+wall_cast(const local_time& tp)
+{
+  using TP = time_point>;
+  if constexpr (std::is_same_v || std::is_same_v)
+return clock_cast(wall_cast(tp));
+  else if constexpr (std::is_same_v)
+return TP(floor(tp.time_since_epoch()) + days(4383));
+  else if constexpr (std::is_same_v)
+return TP(floor(tp.time_since_epoch()) - days(3657));
+  else // system_clock, local_t
+return time_point(floor(tp.time_since_epoch()));
+}
+
+using decadays = duration>;
+using kilodays = duration>;
+
+template
+void
+test_time_point(bool daysAsTime)
+{
+  std::basic_string<_CharT> res;
+
+  const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
+  auto strip_time = [daysAsTime](std::basic_string_view<_CharT> sv)
+  { return daysAsTime ? sv : sv.substr(0, 10); };
+
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54.111222333") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54.111222") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54.111") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:54") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:24:00") );
+  verify( wall_cast(lt),
+ WIDEN("2024-03-22 13:00:00") );
+  verify( wall_cast(lt),
+ strip_time(WIDEN("2024-03-22 00:00:00")) );
+  verify( wall_cast(lt),
+ strip_time(WIDEN("2024-03-18 00:00:00")) );
+  verify( wall_cast(lt),
+ strip_time(WIDEN("2022-01-08 00:00:00")) );
+}
+
+template
+void
+test_leap_second()
+{
+  std::basic_string<_CharT> res;
+
+  const auto st = sys_days(2012y/June/30) + 23h + 59min + 59s + 111222333ns;
+  auto tp = clock_cast(st);
+  tp += 1s;
+
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60.111222333") );
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60.111222") );
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60.111") );
+  verify( floor(tp),
+ WIDEN("2012-06-30 23:59:60") );
+}
+
+template
+auto
+make_zoned(const sys_time& st, const time_zone* tz)
+{ return zoned_time(tz, floor(st)); }
+
+template
+void
+test_zoned_time()
+{
+  const auto st = sys_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
+  const time_zone* tz = locate_zone("Europe/Sofia");
+  VERIFY( tz != nullptr );
+
+  verify( make_zoned(st, tz),
+ WIDEN("2024-03-22 15:24:54.111222333 EET") );
+  verify( make_zoned(st, tz),

[gcc r16-1423] libstdc++: Test for precision and floting point durations.

2025-06-11 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:2f2e51b6596c3796b907c6289d3e631508d8774e

commit r16-1423-g2f2e51b6596c3796b907c6289d3e631508d8774e
Author: Tomasz Kamiński 
Date:   Wed Jun 11 15:56:25 2025 +0200

libstdc++: Test for precision and floting point durations.

libstdc++-v3/ChangeLog:

* testsuite/std/time/format/empty_spec.cc: New tests.
* testsuite/std/time/format/precision.cc: New test.

Diff:
---
 .../testsuite/std/time/format/empty_spec.cc|  51 ++
 .../testsuite/std/time/format/precision.cc | 107 +
 2 files changed, 158 insertions(+)

diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc 
b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index 99cbd740d5f5..a94eee19f577 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -170,6 +170,13 @@ test_duration()
   verify( -di, WIDEN("-40ms") );
   res = std::format(WIDEN("{:>6}"), -di);
   VERIFY( res == WIDEN(" -40ms") );
+}
+
+template
+void
+test_duration_fp()
+{
+  std::basic_string<_CharT> res;
 
   const duration df(11.22);
   verify( df, WIDEN("11.22s") );
@@ -179,6 +186,10 @@ test_duration()
   verify( -df, WIDEN("-11.22s") );
   res = std::format(WIDEN("{:=^12}"), -df);
   VERIFY( res == WIDEN("==-11.22s===") );
+
+  // precision accepted but ignored
+  res = std::format(WIDEN("{:.6}"), df);
+  VERIFY( res == WIDEN("11.22s") );
 }
 
 template
@@ -292,6 +303,44 @@ test_hh_mm_ss()
  WIDEN("-14322:24:54.111222333") );
 }
 
+template
+void
+test_hh_mm_ss_fp()
+{
+  duration dt = 22h + 24min + 54s + 111222333ns;
+  // period controls number of subseconds
+  verify( hms(dt),
+ WIDEN("22:24:54.111222333") );
+  verify( hms(dt),
+ WIDEN("22:24:54.111222") );
+  verify( hms(dt),
+ WIDEN("22:24:54.111") );
+  verify( hms(dt),
+ WIDEN("22:24:54.1") );
+  verify( hms(dt),
+ WIDEN("22:24:54") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54.111222333") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54.111222") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54.111") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54.1") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54") );
+
+  // but hour and minutes are preserved
+  verify( hms(dt),
+ WIDEN("22:24:54") );
+  verify( hms(dt),
+ WIDEN("22:24:54") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54") );
+  verify( hms(-dt),
+ WIDEN("-22:24:54") );
+}
+
 template
 void
 test_hh_mm_ss_cust()
@@ -339,9 +388,11 @@ void
 test_durations()
 {
   test_duration();
+  test_duration_fp();
   test_duration_cust();
 
   test_hh_mm_ss();
+  test_hh_mm_ss_fp();
   test_hh_mm_ss_cust();
 }
 
diff --git a/libstdc++-v3/testsuite/std/time/format/precision.cc 
b/libstdc++-v3/testsuite/std/time/format/precision.cc
new file mode 100644
index ..5a9acbfe1e08
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/precision.cc
@@ -0,0 +1,107 @@
+// { dg-do run { target c++20 } }
+
+#include 
+#include 
+#include 
+
+using namespace std::chrono;
+
+#define WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template
+void
+test_empty()
+{
+  std::basic_string<_CharT> res;
+
+  const duration d(33.111222);
+  res = std::format(WIDEN("{:.3}"), d);
+  VERIFY( res == WIDEN("33.1112s") );
+  res = std::format(WIDEN("{:.6}"), d);
+  VERIFY( res == WIDEN("33.1112s") );
+  res = std::format(WIDEN("{:.9}"), d);
+  VERIFY( res == WIDEN("33.1112s") );
+
+  // Uses ostream operator<<
+  const duration nd = d;
+  res = std::format(WIDEN("{:.3}"), nd);
+  VERIFY( res == WIDEN("3.31112e+10ns") );
+  res = std::format(WIDEN("{:.6}"), nd);
+  VERIFY( res == WIDEN("3.31112e+10ns") );
+  res = std::format(WIDEN("{:.9}"), nd);
+  VERIFY( res == WIDEN("3.31112e+10ns") );
+}
+
+template
+void
+test_Q()
+{
+  std::basic_string<_CharT> res;
+
+  const duration d(7.111222);
+  res = std::format(WIDEN("{:.3%Q}"), d);
+  VERIFY( res == WIDEN("7.111222") );
+  res = std::format(WIDEN("{:.6%Q}"), d);
+  VERIFY( res == WIDEN("7.111222") );
+  res = std::format(WIDEN("{:.9%Q}"), d);
+  VERIFY( res == WIDEN("7.111222") );
+
+  const duration nd = d;
+  res = std::format(WIDEN("{:.3%Q}"), nd);
+  VERIFY( res == WIDEN("7111222000") );
+  res = std::format(WIDEN("{:.6%Q}"), nd);
+  VERIFY( res == WIDEN("7111222000") );
+  res = std::format(WIDEN("{:.9%Q}"), nd);
+  VERIFY( res == WIDEN("7111222000") );
+}
+
+template
+void
+test_S()
+{
+  std::basic_string<_CharT> res;
+
+  // Precision is ignored, but period affects output
+  const duration d(5.111222);
+  res = std::format(WIDEN("{:.3%S}"), d);
+  VERIFY( res == WIDEN("05") );
+  res = std::format(WIDEN("{:.6%S}"), d);
+  VERIFY( res == WIDEN("05") );
+  res = std::format(WIDEN("{:.9%S}"), d);
+  VERIFY( res == WIDEN("05") );
+
+  const duration md = d;
+  res = std::format(WIDEN("{:.3%S}"), md);
+  VERIFY( res == WIDEN("05.111") );
+  res 

[gcc r16-1474] libstdc++: Uglify __mapping_alike template parameter and fix test and typo in comment.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:90f7bbfe2219770ac8b25d0f99320ed3a4fd7736

commit r16-1474-g90f7bbfe2219770ac8b25d0f99320ed3a4fd7736
Author: Tomasz Kamiński 
Date:   Thu Jun 5 10:40:10 2025 +0200

libstdc++: Uglify __mapping_alike template parameter and fix test and typo 
in comment.

When the static assert was generated from instantiations of default member
initializer of class B, the error was not generated for B<1, 
std::layout_left,
std::layout_left> case, only when -D_GLIBCXX_DEBUG was set. Changing B 
calls to
functions fixes that.

We also replace class with typename in template head of 
layout_right::mapping
constructors.

libstdc++-v3/ChangeLog:

* include/std/mdspan (__mdspan::__mapping_alike): Rename template
parameter from M to _M_p.
(layout_right::mapping): Replace class with typename in template
head.
(layout_stride::mapping): Fix typo in comment.
* testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc:
Changed B to function.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/mdspan| 22 +++---
 .../mdspan/layouts/class_mandate_neg.cc| 18 ++
 2 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 4a3e863bed5f..6dc2441f80bd 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -691,7 +691,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: mapping(__other.extents(), __mdspan::__internal_ctor{})
{ }
 
-  template
+  template
requires (extents_type::rank() <= 1)
&& is_constructible_v
constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
@@ -699,7 +699,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: mapping(__other.extents(), __mdspan::__internal_ctor{})
{ }
 
-  template
+  template
requires is_constructible_v
constexpr explicit(extents_type::rank() > 0)
mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
@@ -780,16 +780,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   namespace __mdspan
   {
-template
+template
   concept __mapping_alike = requires
   {
-   requires __is_extents;
-   { M::is_always_strided() } -> same_as;
-   { M::is_always_exhaustive() } -> same_as;
-   { M::is_always_unique() } -> same_as;
-   bool_constant::value;
-   bool_constant::value;
-   bool_constant::value;
+   requires __is_extents;
+   { _Mp::is_always_strided() } -> same_as;
+   { _Mp::is_always_exhaustive() } -> same_as;
+   { _Mp::is_always_unique() } -> same_as;
+   bool_constant<_Mp::is_always_strided()>::value;
+   bool_constant<_Mp::is_always_exhaustive()>::value;
+   bool_constant<_Mp::is_always_unique()>::value;
   };
 
 template
@@ -847,7 +847,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   mapping() noexcept
   {
// The precondition is either statically asserted, or automatically
-   // satisfied because dynamic extents are zero-initialzied.
+   // satisfied because dynamic extents are zero-initialized.
size_t __stride = 1;
for (size_t __i = extents_type::rank(); __i > 0; --__i)
  {
diff --git 
a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc 
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
index 70a25707cb2a..7091153daba8 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
@@ -18,7 +18,8 @@ template
   };
 
 template
-  struct B
+  bool
+  B()
   {
 using Extents = std::extents;
 using OExtents = std::extents;
@@ -27,20 +28,21 @@ template
 using OMapping = typename OLayout::mapping;
 
 Mapping m{OMapping{}};
+return true;
   };
 
 A a_left;  // { dg-error "required from" 
}
 A a_right;// { dg-error "required from" 
}
 A a_stride;  // { dg-error "required from" 
}
 
-B<1, std::layout_left, std::layout_left> b0; // { dg-error "required here" 
}
-B<2, std::layout_left, std::layout_stride> b1;   // { dg-error "required here" 
}
+auto b1 = B<1, std::layout_left, std::layout_left>(); // { dg-error 
"required from" }
+auto b2 = B<2, std::layout_left, std::layout_stride>();   // { dg-error 
"required from" }
 
-B<3, std::layout_right, std::layout_right> b2;   // { dg-error "required here" 
}
-B<4, std::layout_right, std::layout_stride> b3;  // { dg-error "required here" 
}
+auto b3 = B<3, std::layout_right, std::layout_right>();   // { dg-error 
"required from" }
+auto b4 = B<4, std::layout_right, std::layout_stride>();  // { dg-error 
"required from" }
 
-B<5, std::layout_stride, std::layout

[gcc r16-1484] libstdc++: Format empty chrono-spec for the calendar types directly.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:83a878c31b4f20d00638e44d689b04669247b0ed

commit r16-1484-g83a878c31b4f20d00638e44d689b04669247b0ed
Author: Tomasz Kamiński 
Date:   Fri Jun 6 10:45:21 2025 +0200

libstdc++: Format empty chrono-spec for the calendar types directly.

This patch change implementation of the formatters for the calendar types,
so they no longer delegate to operator<< for ostream in case of empty 
chrono-spec.
Instead of that, we define the behavior in terms of format specifiers
supplied by each formatter as an argument to _M_parse. Similarly each 
formatter
constructs its __formatter_chrono from a relevant default spec, preserving 
the
functionality of calling format on default constructed formatters.

Expressing  the existing functionality of the operator ostream, requires
providing two additional features:
 * printing "is not a valid sth" for !ok objects,
 * printing a weekday index in the month.

The formatter functionality is enabled by setting spec _M_debug 
(corresponding
to '?') that is currently unused. This is currently supported only for
subset of format specifiers used by the ostream operators. In future, we 
could
make this user configurable (by adding '?' after 'L') and cover all flags.

For the handling of the weekday index (for weekday_indexed, month_weekday,
year_month_weekday), we need to introduce a new format specifier. To not
conflict with future extension we use '%\0' (embedded null) as this 
character
cannot be placed in valid format spec.

Finally, the format strings for calendar types subsets each other, e.g.
year_month_weekday_last ("%Y/%b/%a[last])" contains month_weekday_last,
weekday_last, weekday, e.t.c.. We introduce a _ChronoFormats class that 
provide
consteval accessors to format specs, internally sharing they 
representations.

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (__format::_ChronoFormats): Define.
(__formatter_chrono::__formatter_chrono())
(__formatter_chrono::__formatter_chrono(_ChronoSpec<_CharT>)): 
Define.
(__formatter_chrono::_M_parse): Add parameter with default spec,
and merge it with new values. Handle '%\0' as weekday index
specifier.
(__formatter_chrono::_M_a_A, __formatter_chrono::_M_b_B)
(__formatter_chrono::_M_C_y_Y, __formatter_chrono::_M_d_e)
(__formatter_chrono::_M_F): Support _M_debug flag.
(__formatter_chrono::_M_wi, __formatter_chrono::_S_weekday_index):
Define.
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter)
(std::formatter):
Define __defSpec, and pass it as argument to _M_parse and
constructor of __formatter_chrono.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h | 398 ++
 1 file changed, 361 insertions(+), 37 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h 
b/libstdc++-v3/include/bits/chrono_io.h
index c5c5e4bae53d..69cf2a6aa2b9 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -238,6 +238,93 @@ namespace __format
   operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
   { return __x = __x | __y; }
 
+  template
+  struct _ChronoFormats
+  {
+using _String_view = basic_string_view<_CharT>;
+
+static consteval
+_String_view
+_S_f() noexcept
+{ return _GLIBCXX_WIDEN("%F"); }
+
+static consteval
+_String_view
+_S_ymd() noexcept
+{ return _GLIBCXX_WIDEN("%Y/%b/%d"); }
+
+static consteval
+_String_view
+_S_ym() noexcept
+{ return _S_ymd().substr(0, 5); }
+
+static consteval
+_String_view
+_S_md() noexcept
+{ return _S_ymd().substr(3); }
+
+static consteval
+_String_view
+_S_y() noexcept
+{ return _S_ymd().substr(0, 2); }
+
+static consteval
+_String_view
+_S_m() noexcept
+{ return _S_ymd().substr(3, 2); }
+
+static consteval
+_String_view
+_S_d() noexcept
+{ return _S_ymd().substr(6, 2); }
+
+static consteval
+_String_view
+_S_ymwi() noexcept
+// %\0 is extension for handling weekday index
+{ return _String_view(_GLIBCXX_WIDEN("%Y/%b/%a[%\0]"), 12); }
+
+static consteval
+_String_view
+_S_mwi() noexcept
+{ return _S_ymwi().substr(3); }
+
+static consteval
+_String_view
+_S_wi() noexcept
+{ return _S_ymwi().substr(6); }
+
+static consteval
+_String_view

[gcc r16-1472] libstdc++: Add tests for layout_stride.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:4e3dbecb90dec76714474df867bfcc2073ad6a9b

commit r16-1472-g4e3dbecb90dec76714474df867bfcc2073ad6a9b
Author: Luc Grosheintz 
Date:   Wed Jun 4 16:58:52 2025 +0200

libstdc++: Add tests for layout_stride.

Implements the tests for layout_stride and for the features of the other
two layouts that depend on layout_stride.

libstdc++-v3/ChangeLog:

* testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: Add
tests for layout_stride.
* testsuite/23_containers/mdspan/layouts/ctors.cc: Add test for
layout_stride and the interaction with other layouts.
* testsuite/23_containers/mdspan/layouts/empty.cc: Ditto.
* testsuite/23_containers/mdspan/layouts/mapping.cc: Ditto.
* testsuite/23_containers/mdspan/layouts/stride.cc: New test.

Signed-off-by: Luc Grosheintz 
Reviewed-by: Tomasz Kamiński 

Diff:
---
 .../mdspan/layouts/class_mandate_neg.cc|   7 +
 .../23_containers/mdspan/layouts/ctors.cc  |  99 
 .../23_containers/mdspan/layouts/empty.cc  |  20 +-
 .../23_containers/mdspan/layouts/mapping.cc|  75 ++-
 .../23_containers/mdspan/layouts/stride.cc | 526 +
 5 files changed, 725 insertions(+), 2 deletions(-)

diff --git 
a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc 
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
index ce721277435a..70a25707cb2a 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
@@ -31,9 +31,16 @@ template
 
 A a_left;  // { dg-error "required from" 
}
 A a_right;// { dg-error "required from" 
}
+A a_stride;  // { dg-error "required from" 
}
 
 B<1, std::layout_left, std::layout_left> b0; // { dg-error "required here" 
}
+B<2, std::layout_left, std::layout_stride> b1;   // { dg-error "required here" 
}
 
 B<3, std::layout_right, std::layout_right> b2;   // { dg-error "required here" 
}
+B<4, std::layout_right, std::layout_stride> b3;  // { dg-error "required here" 
}
+
+B<5, std::layout_stride, std::layout_right> b4;  // { dg-error "required here" 
}
+B<6, std::layout_stride, std::layout_left> b5;   // { dg-error "required here" 
}
+B<7, std::layout_stride, std::layout_stride> b6; // { dg-error "required here" 
}
 
 // { dg-prune-output "must be representable as index_type" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc 
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
index 6c428c4b111c..92507a8e769d 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
@@ -321,6 +321,104 @@ namespace from_left_or_right
 }
 }
 
+// ctor: mapping(layout_stride::mapping)
+namespace from_stride
+{
+  template
+constexpr auto
+strides(Mapping m)
+{
+  constexpr auto rank = Mapping::extents_type::rank();
+  std::array s;
+
+  if constexpr (rank > 0)
+   for(size_t i = 0; i < rank; ++i)
+ s[i] = m.stride(i);
+  return s;
+}
+
+  template
+constexpr void
+verify_convertible(OExtents oexts)
+{
+  using Mapping = typename Layout::mapping;
+  using OMapping = std::layout_stride::mapping;
+
+  constexpr auto other = OMapping(oexts, strides(Mapping(Extents(oexts;
+  if constexpr (std::is_same_v)
+   ::verify_nothrow_convertible(other);
+  else
+   ::verify_convertible(other);
+}
+
+  template
+constexpr void
+verify_constructible(OExtents oexts)
+{
+  using Mapping = typename Layout::mapping;
+  using OMapping = std::layout_stride::mapping;
+
+  constexpr auto other = OMapping(oexts, strides(Mapping(Extents(oexts;
+  if constexpr (std::is_same_v)
+   ::verify_nothrow_constructible(other);
+  else
+   ::verify_constructible(other);
+}
+
+  template
+constexpr bool
+test_ctor()
+{
+  assert_not_constructible<
+   typename Layout::mapping>,
+   std::layout_stride::mapping>>();
+
+  assert_not_constructible<
+   typename Layout::mapping>,
+   std::layout_stride::mapping>>();
+
+  assert_not_constructible<
+   typename Layout::mapping>,
+   std::layout_stride::mapping>>();
+
+  verify_convertible>(std::extents{});
+
+  verify_convertible>(
+   std::extents{});
+
+  // Rank ==  0 doesn't check IndexType for convertibility.
+  verify_convertible>(
+   std::extents{});
+
+  verify_constructible>(
+   std::extents{});
+
+  verify_constructible>(
+   std::extents{});
+
+  verify_constructible>(
+   std::extents{});
+
+  verify_constructible>(
+   std::extents{});
+
+  verify_constructible>(
+   std::extents{});
+
+ 

[gcc r16-1485] libstdc++: Format empty chrono-spec for the time points and hh_mm_ss directly.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:8fa1e98493def5eb327397a587aa846f2145d634

commit r16-1485-g8fa1e98493def5eb327397a587aa846f2145d634
Author: Tomasz Kamiński 
Date:   Fri Jun 6 11:32:27 2025 +0200

libstdc++: Format empty chrono-spec for the time points and hh_mm_ss 
directly.

This patch change implementation of the formatters for time points and 
hh_mm_ss,
so they no longer delegate to operator<< for ostream in case of empty 
chrono-spec.
As in case of calendar types, the formatters for specific type now provide
__formatter_chrono with default _ChronoSpec that are used in case if empty
chrono-spec.

The configuration of __defSpec is straight forward, except for the sys_time,
and local_time that print time, if the duration is convertible to days,
which is equivalent to setting _M_chrono_specs "%F" instead of "%F %T".
Furthermore, certain sys_time do not support ostream operator, and
should not be formattable with empty spec - in such case default
_M_chrono_spec, allowing the issue to still be detected in _M_parse.

Finally, _ChronoFormats are extended to cover required format strings.

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (_ChronoFormats::_S_ftz)
(_ChronoFormats::_S_ft, _ChronoFormats::_S_t): Define.
(__formatter_chrono::_M_format_to_ostream): Remove handling for
time_points.
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>)
(std::formatter, _CharT>):
Define __defSpec, and pass it as argument to _M_prase and
constructor of __formatter_chrono.

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h | 220 +-
 1 file changed, 135 insertions(+), 85 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h 
b/libstdc++-v3/include/bits/chrono_io.h
index 69cf2a6aa2b9..247d40c82d76 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -243,10 +243,25 @@ namespace __format
   {
 using _String_view = basic_string_view<_CharT>;
 
+static consteval
+_String_view
+_S_ftz() noexcept
+{ return _GLIBCXX_WIDEN("%F %T %Z"); }
+
+static consteval
+_String_view
+_S_ft() noexcept
+{ return _S_ftz().substr(0, 5); }
+
 static consteval
 _String_view
 _S_f() noexcept
-{ return _GLIBCXX_WIDEN("%F"); }
+{ return _S_ftz().substr(0, 2); }
+
+static consteval
+_String_view
+_S_t() noexcept
+{ return _S_ftz().substr(3, 2); }
 
 static consteval
 _String_view
@@ -828,58 +843,17 @@ namespace __format
  __os.imbue(_M_locale(__fc));
 
  if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
-   {
- // Format as "{:L%F %T}"
- auto __days = chrono::floor(__t._M_time);
- __os << chrono::year_month_day(__days) << ' '
-  << chrono::hh_mm_ss(__t._M_time - __days);
-
- // For __local_time_fmt the __is_neg flags says whether to
- // append " %Z" to the result.
- if (__is_neg)
-   {
- if (!__t._M_abbrev) [[unlikely]]
-   __format::__no_timezone_available();
- else if constexpr (is_same_v<_CharT, char>)
-   __os << ' ' << *__t._M_abbrev;
- else
-   {
- __os << L' ';
- for (char __c : *__t._M_abbrev)
-   __os << __c;
-   }
-   }
-   }
+   __builtin_trap();
+ else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
+   __builtin_trap();
+ else if constexpr (chrono::__is_time_point_v<_Tp>)
+__builtin_trap();
  else
{
- if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
-   __os << __t._M_date << ' ' << __t._M_time;
- else if constexpr (chrono::__is_time_point_v<_Tp>)
-   {
- // Need to be careful here because not all specializations
- // of chrono::sys_time can be written to an ostream.
- // For the specializations of time_point that can be
- // formatted with an empty chrono-specs, either it's a
- // sys_time with period greater or equal to days:
- if constexpr (is_convertible_v<_Tp, chrono::sys_days>)
-   __os << _S_date(__t);
- // Or a local_time with period greater or equal to days:
- else if constexpr (is_convertible_v<_Tp, chrono::local_days>)
-   __os << _S_date(__t);
- 

[gcc r16-1467] libstdc++: Implement layout_left from mdspan.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:71493a473145566190caff10a378852cc9ce

commit r16-1467-g71493a473145566190caff10a378852cc9ce
Author: Luc Grosheintz 
Date:   Wed Jun 4 16:58:47 2025 +0200

libstdc++: Implement layout_left from mdspan.

Implements the parts of layout_left that don't depend on any of the
other layouts.

libstdc++-v3/ChangeLog:

* include/std/mdspan (layout_left): New class.
* src/c++23/std.cc.in: Add layout_left.

Signed-off-by: Luc Grosheintz 
Reviewed-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/mdspan  | 303 ++-
 libstdc++-v3/src/c++23/std.cc.in |   1 +
 2 files changed, 303 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 0f49b0e09a03..4c80438dbd62 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -144,6 +144,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  { return __exts[__i]; });
  }
 
+   static constexpr span
+   _S_static_extents(size_t __begin, size_t __end) noexcept
+   {
+ return {_Extents.data() + __begin, _Extents.data() + __end};
+   }
+
+   constexpr span
+   _M_dynamic_extents(size_t __begin, size_t __end) const noexcept
+   requires (_Extents.size() > 0)
+   {
+ return {_M_dyn_exts + _S_dynamic_index[__begin],
+ _M_dyn_exts + _S_dynamic_index[__end]};
+   }
+
   private:
using _S_storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
[[no_unique_address]] _S_storage _M_dyn_exts{};
@@ -160,6 +174,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| _Extent <= numeric_limits<_IndexType>::max();
   }
 
+  namespace __mdspan
+  {
+template
+  constexpr span
+  __static_extents(size_t __begin = 0, size_t __end = _Extents::rank())
+  noexcept
+  { return _Extents::_S_storage::_S_static_extents(__begin, __end); }
+
+template
+  constexpr span
+  __dynamic_extents(const _Extents& __exts, size_t __begin = 0,
+   size_t __end = _Extents::rank()) noexcept
+  {
+   return __exts._M_exts._M_dynamic_extents(__begin, __end);
+  }
+  }
+
   template
 class extents
 {
@@ -251,7 +282,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_exts(span(__exts))
{ }
 
-
   template<__mdspan::__valid_index_type _OIndexType, size_t 
_Nm>
requires (_Nm == rank() || _Nm == rank_dynamic())
constexpr explicit(_Nm != rank_dynamic())
@@ -276,6 +306,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
 
 private:
+  friend span
+  __mdspan::__static_extents(size_t, size_t);
+
+  friend span
+  __mdspan::__dynamic_extents(const extents&, size_t, size_t);
+
   using _S_storage = __mdspan::_ExtentsStorage<
_IndexType, array{_Extents...}>;
   [[no_unique_address]] _S_storage _M_exts;
@@ -286,6 +322,69 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   namespace __mdspan
   {
+template
+  constexpr bool
+  __contains_zero(span<_Tp, _Nm> __exts) noexcept
+  {
+   for (size_t __i = 0; __i < __exts.size(); ++__i)
+ if (__exts[__i] == 0)
+   return true;
+   return false;
+  }
+
+template
+  constexpr bool
+  __empty(const _Extents& __exts) noexcept
+  {
+   if constexpr (__contains_zero(__static_extents<_Extents>()))
+ return true;
+   else if constexpr (_Extents::rank_dynamic() > 0)
+ return __contains_zero(__dynamic_extents(__exts));
+   else
+ return false;
+  }
+
+constexpr size_t
+__static_extents_prod(const auto& __sta_exts) noexcept
+{
+  size_t __ret = 1;
+  for (auto __factor : __sta_exts)
+   if (__factor != dynamic_extent)
+ __ret *= __factor;
+  return __ret;
+}
+
+template
+  constexpr typename _Extents::index_type
+  __exts_prod(const _Extents& __exts, size_t __begin, size_t __end) 
noexcept
+  {
+   using _IndexType = typename _Extents::index_type;
+
+   size_t __ret = 1;
+   if constexpr (_Extents::rank_dynamic() != _Extents::rank())
+ {
+   auto __sta_exts = __static_extents<_Extents>(__begin, __end);
+   __ret = __static_extents_prod(__sta_exts);
+   if (__ret == 0)
+ return 0;
+ }
+
+   if constexpr (_Extents::rank_dynamic() > 0)
+ for (auto __factor : __dynamic_extents(__exts, __begin, __end))
+   __ret *= size_t(__factor);
+   return _IndexType(__ret);
+  }
+
+template
+  constexpr typename _Extents::index_type
+  __fwd_prod(const _Extents& __exts, size_t __r) noexcept
+  { return __exts_prod(__exts, 0, __r); }
+
+template
+  constexpr typename _Extents::index_type
+  __rev_prod(const _Extents& __exts, size_t __r) noexcept
+  { return __exts_prod(__exts, __r + 1, __exts.rank()); }
+
 templ

[gcc r16-1468] libstdc++: Add tests for layout_left.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:8a8672c957edf2a826a8aab048c8680cf266090b

commit r16-1468-g8a8672c957edf2a826a8aab048c8680cf266090b
Author: Luc Grosheintz 
Date:   Wed Jun 4 16:58:48 2025 +0200

libstdc++: Add tests for layout_left.

Implements a suite of tests for the currently implemented parts of
layout_left. The individual tests are templated over the layout type, to
allow reuse as more layouts are added.

libstdc++-v3/ChangeLog:

* testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: New 
test.
* testsuite/23_containers/mdspan/layouts/ctors.cc: New test.
* testsuite/23_containers/mdspan/layouts/empty.cc: New test.
* testsuite/23_containers/mdspan/layouts/mapping.cc: New test.

Signed-off-by: Luc Grosheintz 
Reviewed-by: Tomasz Kamiński 

Diff:
---
 .../mdspan/layouts/class_mandate_neg.cc|  36 ++
 .../23_containers/mdspan/layouts/ctors.cc  | 278 +
 .../23_containers/mdspan/layouts/empty.cc  | 112 ++
 .../23_containers/mdspan/layouts/mapping.cc| 437 +
 4 files changed, 863 insertions(+)

diff --git 
a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc 
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
new file mode 100644
index ..c6c55bdd4bc5
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
@@ -0,0 +1,36 @@
+// { dg-do compile { target c++23 } }
+#include
+
+#include 
+
+constexpr size_t dyn = std::dynamic_extent;
+static constexpr size_t n = std::numeric_limits::max() / 2;
+
+template
+  struct A
+  {
+typename Layout::mapping> m0;
+typename Layout::mapping> m1;
+typename Layout::mapping> m2;
+
+using extents_type = std::extents;
+typename Layout::mapping m3; // { dg-error "required from" }
+  };
+
+template
+  struct B
+  {
+using Extents = std::extents;
+using OExtents = std::extents;
+
+using Mapping = typename Layout::mapping;
+using OMapping = typename OLayout::mapping;
+
+Mapping m{OMapping{}};
+  };
+
+A a_left;  // { dg-error "required from" 
}
+
+B<1, std::layout_left, std::layout_left> b0; // { dg-error "required here" 
}
+
+// { dg-prune-output "must be representable as index_type" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc 
b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
new file mode 100644
index ..d634fa867cc1
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
@@ -0,0 +1,278 @@
+// { dg-do run { target c++23 } }
+#include 
+
+#include 
+#include 
+
+constexpr size_t dyn = std::dynamic_extent;
+
+template
+  constexpr void
+  verify(std::extents oexts)
+  {
+auto m = Mapping(oexts);
+VERIFY(m.extents() == oexts);
+  }
+
+template
+  requires (requires { typename OMapping::layout_type; })
+  constexpr void
+  verify(OMapping other)
+  {
+constexpr auto rank = Mapping::extents_type::rank();
+auto m = Mapping(other);
+VERIFY(m.extents() == other.extents());
+if constexpr (rank > 0)
+  for(size_t i = 0; i < rank; ++i)
+   VERIFY(std::cmp_equal(m.stride(i), other.stride(i)));
+  }
+
+
+template
+  constexpr void
+  verify_convertible(From from)
+  {
+static_assert(std::is_convertible_v);
+verify(from);
+  }
+
+template
+  constexpr void
+  verify_nothrow_convertible(From from)
+  {
+static_assert(std::is_nothrow_constructible_v);
+verify_convertible(from);
+  }
+
+template
+  constexpr void
+  verify_constructible(From from)
+  {
+static_assert(!std::is_convertible_v);
+static_assert(std::is_constructible_v);
+verify(from);
+  }
+
+template
+  constexpr void
+  verify_nothrow_constructible(From from)
+  {
+static_assert(std::is_nothrow_constructible_v);
+verify_constructible(from);
+  }
+
+template
+  constexpr void
+  assert_not_constructible()
+  {
+static_assert(!std::is_constructible_v);
+  }
+
+// ctor: mapping()
+namespace default_ctor
+{
+  template
+constexpr void
+test_default_ctor()
+{
+  using Mapping = typename Layout::mapping;
+
+  Mapping m;
+  for(size_t i = 0; i < Extents::rank(); ++i)
+   if (Extents::static_extent(i) == std::dynamic_extent)
+ VERIFY(m.extents().extent(i) == 0);
+   else
+ VERIFY(m.extents().static_extent(i) == Extents::static_extent(i));
+}
+
+  template
+constexpr bool
+test_default_ctor_all()
+{
+  test_default_ctor>();
+  test_default_ctor>();
+  test_default_ctor>();
+  test_default_ctor>();
+  test_default_ctor>();
+  test_default_ctor>();
+  return true;
+}
+
+  template
+  constexpr void
+  test_all()
+  {
+test_default_ctor_all();
+static_assert(test_default_ctor_all());
+  }
+}
+
+// ctor: mapping(const extents&)
+namespace from_extents
+{
+  template
+constexpr v

[gcc r16-1469] libstdc++: Implement layout_right from mdspan.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:f40f96bcf251dcb4b13b87e1569bb144dd53ebe0

commit r16-1469-gf40f96bcf251dcb4b13b87e1569bb144dd53ebe0
Author: Luc Grosheintz 
Date:   Wed Jun 4 16:58:49 2025 +0200

libstdc++: Implement layout_right from mdspan.

Implement the parts of layout_left that depend on layout_right; and the
parts of layout_right that don't depend on layout_stride.

libstdc++-v3/ChangeLog:

* include/std/mdspan (layout_right): New class.
* src/c++23/std.cc.in: Add layout_right.

Signed-off-by: Luc Grosheintz 
Reviewed-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/std/mdspan  | 153 ++-
 libstdc++-v3/src/c++23/std.cc.in |   1 +
 2 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 4c80438dbd62..8ab7a1a52fbe 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -409,6 +409,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   class mapping;
   };
 
+  struct layout_right
+  {
+template
+  class mapping;
+  };
+
   namespace __mdspan
   {
 template
@@ -501,7 +507,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  _Mapping>;
 
 template
-  concept __standardized_mapping = __mapping_of;
+  concept __standardized_mapping = __mapping_of
+  || __mapping_of;
 
 // A tag type to create internal ctors.
 class __internal_ctor
@@ -539,6 +546,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: mapping(__other.extents(), __mdspan::__internal_ctor{})
{ }
 
+  template
+   requires (extents_type::rank() <= 1)
+ && is_constructible_v
+   constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+   mapping(const layout_right::mapping<_OExtents>& __other) noexcept
+   : mapping(__other.extents(), __mdspan::__internal_ctor{})
+   { }
+
   constexpr mapping&
   operator=(const mapping&) noexcept = default;
 
@@ -605,6 +620,142 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[no_unique_address]] extents_type _M_extents{};
 };
 
+  namespace __mdspan
+  {
+template
+  constexpr typename _Extents::index_type
+  __linear_index_right(const _Extents& __exts, _Indices... __indices)
+  noexcept
+  {
+   using _IndexType = typename _Extents::index_type;
+   array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
+   _IndexType __res = 0;
+   if constexpr (sizeof...(__indices) > 0)
+ {
+   _IndexType __mult = 1;
+   auto __update = [&, __pos = __exts.rank()](_IndexType) mutable
+ {
+   --__pos;
+   __res += __ind_arr[__pos] * __mult;
+   __mult *= __exts.extent(__pos);
+ };
+   (__update(__indices), ...);
+ }
+   return __res;
+  }
+  }
+
+  template
+class layout_right::mapping
+{
+public:
+  using extents_type = _Extents;
+  using index_type = typename extents_type::index_type;
+  using size_type = typename extents_type::size_type;
+  using rank_type = typename extents_type::rank_type;
+  using layout_type = layout_right;
+
+  static_assert(__mdspan::__representable_size,
+   "The size of extents_type must be representable as index_type");
+
+  constexpr
+  mapping() noexcept = default;
+
+  constexpr
+  mapping(const mapping&) noexcept = default;
+
+  constexpr
+  mapping(const extents_type& __extents) noexcept
+  : _M_extents(__extents)
+  { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
+
+  template
+   requires is_constructible_v
+   constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+   mapping(const mapping<_OExtents>& __other) noexcept
+   : mapping(__other.extents(), __mdspan::__internal_ctor{})
+   { }
+
+  template
+   requires (extents_type::rank() <= 1)
+   && is_constructible_v
+   constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+   mapping(const layout_left::mapping<_OExtents>& __other) noexcept
+   : mapping(__other.extents(), __mdspan::__internal_ctor{})
+   { }
+
+  constexpr mapping&
+  operator=(const mapping&) noexcept = default;
+
+  constexpr const extents_type&
+  extents() const noexcept { return _M_extents; }
+
+  constexpr index_type
+  required_span_size() const noexcept
+  { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+
+  template<__mdspan::__valid_index_type... _Indices>
+   requires (sizeof...(_Indices) == extents_type::rank())
+   constexpr index_type
+   operator()(_Indices... __indices) const noexcept
+   {
+ return __mdspan::__linear_index_right(
+   _M_extents, static_cast(__indices)...);
+   }
+
+  static constexpr bool
+  is_always_unique() n

[gcc r16-1051] libstdc++: Implement C++26 std::polymorphic [PR119152]

2025-06-02 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:a2e1c97205063d7550d9b9c32319715961abd73f

commit r16-1051-ga2e1c97205063d7550d9b9c32319715961abd73f
Author: Jonathan Wakely 
Date:   Tue May 27 11:38:41 2025 +0200

libstdc++: Implement C++26 std::polymorphic [PR119152]

This patch implements C++26 std::polymorphic as specified in P3019 with
amendment to move assignment from LWG 4251.

The implementation always allocate stored object on the heap. The manager
function (_M_manager) is similary keep with the object (polymorphic::_Obj),
which reduces the size of the polymorphic to size of the single pointer plus
allocator (that is declared with [[no_unique_address]]).

The implementation does not not use small-object optimization (SSO). We may
consider adding this in the future, as SSO is allowed by the standard. 
However,
storing any polimorphic object will require providing space for two pointers
(manager function and vtable pointer) and user-declared data members.

PR libstdc++/119152

libstdc++-v3/ChangeLog:

* include/bits/indirect.h (std::polymorphic, pmr::polymorphic)
[__glibcxx_polymorphic]: Define.
* include/bits/version.def (polymorphic): Define.
* include/bits/version.h: Regenerate.
* include/std/memory: Define __cpp_lib_polymorphic.
* testsuite/std/memory/polymorphic/copy.cc: New test.
* testsuite/std/memory/polymorphic/copy_alloc.cc: New test.
* testsuite/std/memory/polymorphic/ctor.cc: New test.
* testsuite/std/memory/polymorphic/ctor_poly.cc: New test.
* testsuite/std/memory/polymorphic/incomplete.cc: New test.
* testsuite/std/memory/polymorphic/invalid_neg.cc: New test.
* testsuite/std/memory/polymorphic/move.cc: New test.
* testsuite/std/memory/polymorphic/move_alloc.cc: New test.

Co-authored-by: Tomasz Kamiński 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 libstdc++-v3/include/bits/indirect.h   | 376 -
 libstdc++-v3/include/bits/version.def  |   9 +
 libstdc++-v3/include/bits/version.h|  10 +
 libstdc++-v3/include/std/memory|   1 +
 .../testsuite/std/memory/polymorphic/copy.cc   | 157 +
 .../testsuite/std/memory/polymorphic/copy_alloc.cc | 270 +++
 .../testsuite/std/memory/polymorphic/ctor.cc   | 190 +++
 .../testsuite/std/memory/polymorphic/ctor_poly.cc  | 220 
 .../testsuite/std/memory/polymorphic/incomplete.cc |  13 +
 .../std/memory/polymorphic/invalid_neg.cc  |  28 ++
 .../testsuite/std/memory/polymorphic/move.cc   | 177 ++
 .../testsuite/std/memory/polymorphic/move_alloc.cc | 339 +++
 12 files changed, 1789 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/indirect.h 
b/libstdc++-v3/include/bits/indirect.h
index 85908e219b77..e8000d7c0243 100644
--- a/libstdc++-v3/include/bits/indirect.h
+++ b/libstdc++-v3/include/bits/indirect.h
@@ -452,7 +452,381 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 #endif // __glibcxx_indirect
 
- _GLIBCXX_END_NAMESPACE_VERSION
+#if __glibcxx_polymorphic // C++26 && HOSTED
+  template>
+class polymorphic;
+
+  namespace pmr
+  {
+template
+  using polymorphic = polymorphic<_Tp, polymorphic_allocator<_Tp>>;
+  }
+
+  // [polymorphic], class template polymorphic
+  template
+class polymorphic
+{
+  static_assert(is_object_v<_Tp>);
+  static_assert(!is_array_v<_Tp>);
+  static_assert(!is_same_v<_Tp, in_place_t>);
+  static_assert(!__is_in_place_type_v<_Tp>);
+  static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>);
+
+  using _ATraits = allocator_traits<_Alloc>;
+  static_assert(is_same_v<_Tp, typename _ATraits::value_type>);
+
+  // The owned object is embedded within a control block which knows the
+  // dynamic type and manages cloning and destroying the owned object.
+  struct _Obj
+  {
+   typename _ATraits::pointer _M_objp{}; // pointer to the owned object.
+
+   // A pointer to this type, e.g. _Obj*
+   using pointer
+ = typename _ATraits::template rebind_traits<_Obj>::pointer;
+
+   enum class _Op { _Dispose = 1, _Copy = 2, _Move = 3 };
+
+   constexpr virtual pointer
+   _M_manage(const _Alloc&, _Op, void* = nullptr) = 0;
+  };
+
+  template
+   struct _Obj_impl : _Obj
+   {
+ using _MyTraits
+   = typename _ATraits::template rebind_traits<_Obj_impl>;
+
+ using _Op = _Obj::_Op;
+
+ union _Uninitialized {
+   constexpr _Uninitialized() { }
+   constexpr ~_Uninitialized() { }
+   _Up _M_objp;
+ };
+ _Uninitialized _M_u;
+
+ template
+   constexpr
+   _Obj_impl(typename _MyTraits::allocator_type& __a,
+ _Args&&... __args)
+

[gcc r15-9788] libstdc++: Fix format call in formatting with empty specs for durations.

2025-06-06 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:b2338ebf3e698589c69a521b4b4a7908dd959751

commit r15-9788-gb2338ebf3e698589c69a521b4b4a7908dd959751
Author: Tomasz Kamiński 
Date:   Wed Jun 4 11:05:11 2025 +0200

libstdc++: Fix format call in formatting with empty specs for durations.

This patches fixes an obvious error, where the output iterator argument was
missing for call to format_to, when duration with custom representation 
types
are used.

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (__formatter_chrono:_M_s): Add missing
__out argument to format_to call.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 
(cherry picked from commit ac0a04b7a254fb8e1d8d7088336bcb4375807b1e)

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h 
b/libstdc++-v3/include/bits/chrono_io.h
index 7ab989f59a1c..32ef3533c720 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -1318,7 +1318,8 @@ namespace __format
  else
{
  auto __str = std::format(_S_empty_spec, __ss.count());
- __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"),
+ __out = std::format_to(std::move(__out),
+_GLIBCXX_WIDEN("{:0>{}s}"),
 __str,
 __hms.fractional_width);
}


[gcc r16-1495] libstdc++: Test chrono-spec containing only whitespaces.

2025-06-12 Thread Tomasz Kaminski via Libstdc++-cvs
https://gcc.gnu.org/g:cec7355d9fe2e24ccb1d82913034eebcc6c0e974

commit r16-1495-gcec7355d9fe2e24ccb1d82913034eebcc6c0e974
Author: Tomasz Kamiński 
Date:   Thu Jun 12 16:36:15 2025 +0200

libstdc++: Test chrono-spec containing only whitespaces.

libstdc++-v3/ChangeLog:

* testsuite/std/time/format/whitespace.cc: New test.

Reviewed-by: Jonathan Wakely 
Signed-off-by: Tomasz Kamiński 

Diff:
---
 .../testsuite/std/time/format/whitespace.cc| 56 ++
 1 file changed, 56 insertions(+)

diff --git a/libstdc++-v3/testsuite/std/time/format/whitespace.cc 
b/libstdc++-v3/testsuite/std/time/format/whitespace.cc
new file mode 100644
index ..debda08995cf
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/whitespace.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++20 } }
+
+#include 
+#include 
+
+using namespace std::chrono;
+
+#define WIDEN_(C, S) ::std::__format::_Widen(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template
+void
+test(const ChronoType& ct)
+{
+  std::basic_string<_CharT> res;
+  
+  res = std::format(WIDEN("{:%% %t %n  more text}"), ct);
+  VERIFY( res == WIDEN("% \t \n  more text") );
+
+  res = std::format(WIDEN("{:7%% %t %n}"), ct);
+  VERIFY( res == WIDEN("% \t \n  ") );
+
+  res = std::format(WIDEN("{:>6%% %t %n}"), ct);
+  VERIFY( res == WIDEN(" % \t \n") );
+
+  res = std::format(WIDEN("{:+>7%% %t %n}"), ct);
+  VERIFY( res == WIDEN("++% \t \n") );
+
+  res = std::format(WIDEN("{:=^7%% %t %n}"), ct);
+  VERIFY( res == WIDEN("=% \t \n=") );
+}
+
+template
+void
+test_all()
+{
+  test(20s);
+  test(10d);
+  test(Monday);
+  test(2020y/January/8);
+  test(local_days(2020y/January/8));
+  test(sys_days(2020y/January/8) + 13h + 10min + 5s);
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+  test(sys_info());
+  test(local_info());
+#endif
+}
+
+int main()
+{
+  test_all();
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  test_all();
+#endif // _GLIBCXX_USE_WCHAR_T
+}