https://gcc.gnu.org/g:08782a5d92bacc3af947caf79d19bf25eae02e7b

commit r15-2448-g08782a5d92bacc3af947caf79d19bf25eae02e7b
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Tue Jul 16 10:14:45 2024 +0100

    libstdc++: Define C++26 member visit for std::basic_format_arg [PR110356]
    
    Implement the std::format changes from P2637R3. This adds visit member
    functions to std::basic_format_arg and deprecates the non-member
    function std::visit_format_arg.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/110356
            * include/bits/c++config (_GLIBCXX26_DEPRECATED): Define.
            (_GLIBCXX26_DEPRECATED_SUGGEST): Define.
            * include/bits/version.def (format): Update for C++26.
            * include/bits/version.h: Regenerate.
            * include/std/format (basic_format_arg::visit): New member
            functions.
            (visit_format_arg): Add deprecated attribute.
            * testsuite/std/format/arguments/args.cc: Expect deprecated
            warnings. Check member visit.
            * testsuite/std/format/functions/format.cc: Update expected
            value for __cpp_lib_format macro.
            * testsuite/std/format/parse_ctx.cc: Add dg-warning for
            deprecation.

Diff:
---
 libstdc++-v3/include/bits/c++config                | 10 +++++
 libstdc++-v3/include/bits/version.def              |  2 +-
 libstdc++-v3/include/bits/version.h                |  4 +-
 libstdc++-v3/include/std/format                    | 16 ++++++++
 .../testsuite/std/format/arguments/args.cc         | 43 ++++++++++++++++++++++
 .../testsuite/std/format/functions/format.cc       |  4 +-
 libstdc++-v3/testsuite/std/format/parse_ctx.cc     |  2 +-
 7 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index 6dca2d9467aa..0f0cc7cd6599 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -90,6 +90,8 @@
 //   _GLIBCXX20_DEPRECATED_SUGGEST( string-literal )
 //   _GLIBCXX23_DEPRECATED
 //   _GLIBCXX23_DEPRECATED_SUGGEST( string-literal )
+//   _GLIBCXX26_DEPRECATED
+//   _GLIBCXX26_DEPRECATED_SUGGEST( string-literal )
 #ifndef _GLIBCXX_USE_DEPRECATED
 # define _GLIBCXX_USE_DEPRECATED 1
 #endif
@@ -143,6 +145,14 @@
 # define _GLIBCXX23_DEPRECATED_SUGGEST(ALT)
 #endif
 
+#if defined(__DEPRECATED) && (__cplusplus >= 202400L)
+# define _GLIBCXX26_DEPRECATED [[__deprecated__]]
+# define _GLIBCXX26_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT)
+#else
+# define _GLIBCXX26_DEPRECATED
+# define _GLIBCXX26_DEPRECATED_SUGGEST(ALT)
+#endif
+
 // Macros for ABI tag attributes.
 #ifndef _GLIBCXX_ABI_TAG_CXX11
 # define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11")))
diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 806f1e9549be..ec330911d665 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1171,7 +1171,7 @@ ftms = {
   // 202306 P2637R3 Member visit
   // 202311 P2918R2 Runtime format strings II
   values = {
-    v = 202305;
+    v = 202306;
     cxxmin = 26;
     hosted = yes;
   };
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index e8ca0faf5dcd..148ee87e087c 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1310,9 +1310,9 @@
 
 #if !defined(__cpp_lib_format)
 # if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
-#  define __glibcxx_format 202305L
+#  define __glibcxx_format 202306L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_format)
-#   define __cpp_lib_format 202305L
+#   define __cpp_lib_format 202306L
 #  endif
 # elif (__cplusplus >= 202002L) && _GLIBCXX_HOSTED
 #  define __glibcxx_format 202304L
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 6a88705ec7b9..715fdf934924 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -3346,6 +3346,18 @@ namespace __format
       explicit operator bool() const noexcept
       { return _M_type != __format::_Arg_none; }
 
+#if __cpp_lib_format >= 202306L // >= C++26
+      template<typename _Visitor>
+       decltype(auto)
+       visit(this basic_format_arg __arg, _Visitor&& __vis)
+       { return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type); }
+
+      template<typename _Res, typename _Visitor>
+       _Res
+       visit(this basic_format_arg __arg, _Visitor&& __vis)
+       { return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type); }
+#endif
+
     private:
       template<typename _Ctx>
        friend class basic_format_args;
@@ -3631,6 +3643,7 @@ namespace __format
     };
 
   template<typename _Visitor, typename _Context>
+    _GLIBCXX26_DEPRECATED_SUGGEST("std::basic_format_arg::visit")
     inline decltype(auto)
     visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
     {
@@ -3666,6 +3679,8 @@ namespace __format
       }
   };
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   template<typename _Context>
     inline size_t
     __int_from_arg(const basic_format_arg<_Context>& __arg)
@@ -4297,6 +4312,7 @@ namespace __format
       else
        return std::move(__sink)._M_finish().out;
     }
+#pragma GCC diagnostic pop
 
 } // namespace __format
 /// @endcond
diff --git a/libstdc++-v3/testsuite/std/format/arguments/args.cc 
b/libstdc++-v3/testsuite/std/format/arguments/args.cc
index 16ca71caecbe..2cea0a1b63f4 100644
--- a/libstdc++-v3/testsuite/std/format/arguments/args.cc
+++ b/libstdc++-v3/testsuite/std/format/arguments/args.cc
@@ -1,5 +1,7 @@
 // { dg-do run { target c++20 } }
 
+// { dg-warning "deprecated" "std::visit_format_arg" { target c++26 } 0 }
+
 #include <format>
 #include <testsuite_hooks.h>
 
@@ -55,6 +57,9 @@ test_args()
   char c = '2';
   double d = 3.4;
 
+  // We need an lvalue of type format-arg-store<Context, Args...> for the
+  // lvalue args to point to, otherwise it will have a dangling pointer.
+  // This is not how you're supposed to use format args, just for testing.
   auto store = std::make_format_args(b, i, c, d);
   std::format_args args = store;
   VERIFY(equals(args.get(0), false));
@@ -106,8 +111,46 @@ test_args()
   VERIFY(std::visit_format_arg(is_handle, args.get(1)));
 }
 
+void
+test_member_visit()
+{
+#if __cpp_lib_format >= 202306L // C++26 adds std::basic_format_arg::visit
+  int one = 1;
+  float two = 2.0;
+  std::string_view three = "three";
+  auto store = std::make_format_args(one, two, three); // See comment above.
+  std::format_args args = store;
+  auto a1 = args.get(0).visit([=](auto a) {
+    if constexpr (std::is_same_v<decltype(a), int>)
+      return a == one;
+    return false;
+  });
+  VERIFY( a1 );
+  auto a2 = args.get(1).visit([=](auto a) {
+    if constexpr (std::is_same_v<decltype(a), float>)
+      return a == two;
+    return false;
+  });
+  VERIFY( a2 );
+  auto a3 = args.get(2).visit([=](auto a) {
+    if constexpr (std::is_same_v<decltype(a), std::string_view>)
+      return a == three;
+    return false;
+  });
+  VERIFY( a3 );
+
+  auto a4 = args.get(0).visit<std::string_view>([](auto) { return "str"; });
+  static_assert( std::is_same_v<decltype(a4), std::string_view> );
+  VERIFY( a4 == "str" );
+  args.get(0).visit<void>([](auto){});
+  using V = decltype(args.get(0).visit<void>([](auto){}));
+  static_assert( std::is_same_v<V, void> );
+#endif
+}
+
 int main()
 {
   test_empty();
   test_args();
+  test_member_visit();
 }
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc 
b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 3c441d711b3e..0549d171e5a2 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -8,7 +8,7 @@
 # error "Feature test macro for std::format is missing in <format>"
 #elif __cpp_lib_format < 202110L
 # error "Feature test macro for std::format has wrong value in <format>"
-#elif __cplusplus > 202302L && __cpp_lib_format < 202305L
+#elif __cplusplus > 202302L && __cpp_lib_format < 202306L
 # error "Feature test macro for std::format has wrong value in <format>"
 #endif
 
@@ -24,7 +24,7 @@
 # error "Feature test macro for std::format is missing in <version>"
 #elif __cpp_lib_format < 202110L
 # error "Feature test macro for std::format has wrong value in <version>"
-#elif __cplusplus > 202302L && __cpp_lib_format < 202305L
+#elif __cplusplus > 202302L && __cpp_lib_format < 202306L
 # error "Feature test macro for std::format has wrong value in <version>"
 #endif
 
diff --git a/libstdc++-v3/testsuite/std/format/parse_ctx.cc 
b/libstdc++-v3/testsuite/std/format/parse_ctx.cc
index b0cef2da41bc..88ffd77debe0 100644
--- a/libstdc++-v3/testsuite/std/format/parse_ctx.cc
+++ b/libstdc++-v3/testsuite/std/format/parse_ctx.cc
@@ -473,7 +473,7 @@ struct std::formatter<X, char>
   std::format_context::iterator
   format(X, std::format_context& c) const
   {
-    std::visit_format_arg([this]<typename T>(T) {
+    std::visit_format_arg([this]<typename T>(T) { // { dg-warning "deprecated" 
"" { target c++26 } }
       if (is_integral_v<T> != this->integer)
        throw std::format_error("invalid argument type");
     }, c.arg(1));

Reply via email to