[committed] libstdc++: Make std::basic_format_context non-copyable [PR114387]

Message ID 20240710211437.918580-1-jwakely@redhat.com
State New
Headers
Series [committed] libstdc++: Make std::basic_format_context non-copyable [PR114387] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch is already merged
linaro-tcwg-bot/tcwg_gcc_check--master-arm warning Patch is already merged

Commit Message

Jonathan Wakely July 10, 2024, 9:11 p.m. UTC
  Tested x86_64-linux. Pushed to trunk. Probably a good idea to backport
it to 13 and 14, for consistency.

-- >8 --

Users are not supposed to create objects of this type, and there's no
reason it needs to be copyable. LWG 4061 makes it non-copyable and
non-default constructible.

libstdc++-v3/ChangeLog:

	PR libstdc++/114387
	* include/std/format (basic_format_context): Define copy
	operations as deleted, as per LWG 4061.
	* testsuite/std/format/context.cc: New test.
---
 libstdc++-v3/include/std/format              |  7 +++-
 libstdc++-v3/testsuite/std/format/context.cc | 36 ++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/testsuite/std/format/context.cc
  

Patch

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 48deba2bcb2..16cee0d3c74 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -3851,6 +3851,12 @@  namespace __format
       : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
       { }
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 4061. Should std::basic_format_context be
+      //       default-constructible/copyable/movable?
+      basic_format_context(const basic_format_context&) = delete;
+      basic_format_context& operator=(const basic_format_context&) = delete;
+
       template<typename _Out2, typename _CharT2, typename _Context2>
 	friend _Out2
 	__format::__do_vformat_to(_Out2, basic_string_view<_CharT2>,
@@ -3858,7 +3864,6 @@  namespace __format
 				  const locale*);
 
     public:
-      basic_format_context() = default;
       ~basic_format_context() = default;
 
       using iterator = _Out;
diff --git a/libstdc++-v3/testsuite/std/format/context.cc b/libstdc++-v3/testsuite/std/format/context.cc
new file mode 100644
index 00000000000..5cc5e9c9ba2
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/context.cc
@@ -0,0 +1,36 @@ 
+// { dg-do compile { target c++20 } }
+
+#include <format>
+
+template<typename Context>
+concept format_context_reqs = std::is_destructible_v<Context>
+  && (!std::is_default_constructible_v<Context>)
+  && (!std::is_copy_constructible_v<Context>)
+  && (!std::is_move_constructible_v<Context>)
+  && (!std::is_copy_assignable_v<Context>)
+  && (!std::is_move_assignable_v<Context>)
+  && requires (Context& ctx, const Context& cctx) {
+    typename Context::iterator;
+    typename Context::char_type;
+    requires std::same_as<typename Context::template formatter_type<int>,
+			  std::formatter<int, typename Context::char_type>>;
+    { ctx.locale() } -> std::same_as<std::locale>;
+    { ctx.out() } -> std::same_as<typename Context::iterator>;
+    { ctx.advance_to(ctx.out()) } -> std::same_as<void>;
+    { cctx.arg(1) } -> std::same_as<std::basic_format_arg<Context>>;
+  };
+
+template<typename Out, typename charT>
+constexpr bool
+check(std::basic_format_context<Out, charT>*)
+{
+  using context = std::basic_format_context<Out, charT>;
+  static_assert( format_context_reqs<context> );
+  static_assert( std::is_same_v<typename context::iterator, Out> );
+  static_assert( std::is_same_v<typename context::char_type, charT> );
+  return true;
+}
+
+static_assert( check( (std::format_context*)nullptr) );
+static_assert( check( (std::wformat_context*)nullptr) );
+static_assert( check( (std::basic_format_context<char*, char>*)nullptr) );