]> gcc.gnu.org Git - gcc.git/commitdiff
libstdc++: Implement std::ios_base::noreplace for C++23 [PR59769]
authorJonathan Wakely <jwakely@redhat.com>
Wed, 8 Dec 2021 20:58:11 +0000 (20:58 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 9 Dec 2021 22:59:48 +0000 (22:59 +0000)
This implements my P2467R0 proposal to support opening an fstream in
exclusive mode. The new constant is also supported pre-C++23 as
std::ios_base::__noreplace.

This proposal hasn't been approved for C++23 yet, but I am confident it
will be, as this is restoring a feture found in pre-ISO C++ iostreams
implementations (and still present in the MSVC library as _Noreplace).
If the proposal fails for C++23 we can remove the ios::noreplace
name and just keep ios::__noreplace as an extension.

libstdc++-v3/ChangeLog:

PR libstdc++/59769
* config/io/basic_file_stdio.cc (fopen_mode): Add support for
exclusive mode.
* include/bits/ios_base.h (_S_noreplace): Define new enumerator.
(ios_base::__noreplace): Define.
(ios_base::noreplace): Define for C++23.
* include/std/version (__cpp_lib_ios_noreplace): Define.
* testsuite/27_io/basic_ofstream/open/char/noreplace.cc: New test.
* testsuite/27_io/basic_ofstream/open/wchar_t/noreplace.cc: New test.

libstdc++-v3/config/io/basic_file_stdio.cc
libstdc++-v3/include/bits/ios_base.h
libstdc++-v3/include/std/version
libstdc++-v3/testsuite/27_io/basic_ofstream/open/char/noreplace.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_ofstream/open/wchar_t/noreplace.cc [new file with mode: 0644]

index ce4a6380ebb1a1d74cb5664df16e4e7fd2a03e5e..06ee016d016f6b5b8d05c036a6a624ddad2b5f2c 100644 (file)
@@ -78,32 +78,38 @@ namespace
        out    = std::ios_base::out,
        trunc  = std::ios_base::trunc,
        app    = std::ios_base::app,
-       binary = std::ios_base::binary
+       binary = std::ios_base::binary,
+       noreplace = std::_S_noreplace
       };
 
     // _GLIBCXX_RESOLVE_LIB_DEFECTS
     // 596. 27.8.1.3 Table 112 omits "a+" and "a+b" modes.
-    switch (mode & (in|out|trunc|app|binary))
+    switch (mode & (in|out|trunc|app|binary|noreplace))
       {
-      case (   out                 ): return "w";
-      case (   out      |app       ): return "a";
-      case (             app       ): return "a";
-      case (   out|trunc           ): return "w";
-      case (in                     ): return "r";
-      case (in|out                 ): return "r+";
-      case (in|out|trunc           ): return "w+";
-      case (in|out      |app       ): return "a+";
-      case (in          |app       ): return "a+";
-
-      case (   out          |binary): return "wb";
-      case (   out      |app|binary): return "ab";
-      case (             app|binary): return "ab";
-      case (   out|trunc    |binary): return "wb";
-      case (in              |binary): return "rb";
-      case (in|out          |binary): return "r+b";
-      case (in|out|trunc    |binary): return "w+b";
-      case (in|out      |app|binary): return "a+b";
-      case (in          |app|binary): return "a+b";
+      case (   out                           ): return "w";
+      case (   out                 |noreplace): return "wx";
+      case (   out|trunc                     ): return "w";
+      case (   out|trunc           |noreplace): return "wx";
+      case (   out      |app                 ): return "a";
+      case (             app                 ): return "a";
+      case (in                               ): return "r";
+      case (in|out                           ): return "r+";
+      case (in|out|trunc                     ): return "w+";
+      case (in|out|trunc           |noreplace): return "w+x";
+      case (in|out      |app                 ): return "a+";
+      case (in          |app                 ): return "a+";
+
+      case (   out          |binary          ): return "wb";
+      case (   out          |binary|noreplace): return "wbx";
+      case (   out      |app|binary          ): return "ab";
+      case (             app|binary          ): return "ab";
+      case (   out|trunc    |binary          ): return "wb";
+      case (in              |binary          ): return "rb";
+      case (in|out          |binary          ): return "r+b";
+      case (in|out|trunc    |binary          ): return "w+b";
+      case (in|out|trunc    |binary|noreplace): return "w+bx";
+      case (in|out      |app|binary          ): return "a+b";
+      case (in          |app|binary          ): return "a+b";
 
       default: return 0; // invalid
       }
index d6626d4d26bd75dc4d3c4c30401ef619d172ae74..5db05524e1c089b9e10d60ff216dad962c3c44f0 100644 (file)
@@ -116,6 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _S_in            = 1L << 3,
       _S_out           = 1L << 4,
       _S_trunc                 = 1L << 5,
+      _S_noreplace     = 1L << 6,
       _S_ios_openmode_end = 1L << 16,
       _S_ios_openmode_max = __INT_MAX__,
       _S_ios_openmode_min = ~__INT_MAX__
@@ -466,6 +467,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     /// Truncate an existing stream when opening.  Default for @c ofstream.
     static const openmode trunc =      _S_trunc;
 
+    static const openmode __noreplace =        _S_noreplace;
+
+#if __cplusplus >= 202100L
+#define __cpp_lib_ios_noreplace 202200L
+    /// Open a file in exclusive mode.
+    static const openmode noreplace =  _S_noreplace;
+#endif
+
     // 27.4.2.1.5  Type ios_base::seekdir
     /**
      *  @brief This is an enumerated type.
index eb612f57c73cbbb50804b48b4e7c6a5ccab4bd14..23890037b6b52973226ea36d8b0f0674a66c4cf0 100644 (file)
 #define __cpp_lib_adaptor_iterator_pair_constructor 202106L
 #define __cpp_lib_byteswap 202110L
 #define __cpp_lib_invoke_r 202106L
+#define __cpp_lib_ios_noreplace 202200L
 #define __cpp_lib_is_scoped_enum 202011L
 #if __cpp_lib_concepts
 # define __cpp_lib_monadic_optional 202110L
diff --git a/libstdc++-v3/testsuite/27_io/basic_ofstream/open/char/noreplace.cc b/libstdc++-v3/testsuite/27_io/basic_ofstream/open/char/noreplace.cc
new file mode 100644 (file)
index 0000000..e39f592
--- /dev/null
@@ -0,0 +1,29 @@
+// { dg-do run }
+
+#include <ios>
+
+#if __cplusplus >= 202200L
+#ifndef __cpp_lib_ios_noreplace
+# error "Feature-test macro for ios::noreplace missing in <ios>"
+#elif __cpp_lib_ios_noreplace < 202200L
+# error "Feature-test macro for ios::noreplace has wrong value in <ios>"
+#endif
+#endif
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+int main()
+{
+#if __cpp_lib_ios_noreplace
+  std::ios::openmode noreplace = std::ios::noreplace;
+#else
+  std::ios::openmode noreplace = std::ios::__noreplace;
+#endif
+
+  std::ofstream of("noreplace");
+  VERIFY( of.is_open() );
+  of.close();
+  of.open("noreplace", noreplace);
+  VERIFY( ! of.is_open() );
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ofstream/open/wchar_t/noreplace.cc b/libstdc++-v3/testsuite/27_io/basic_ofstream/open/wchar_t/noreplace.cc
new file mode 100644 (file)
index 0000000..77f1186
--- /dev/null
@@ -0,0 +1,29 @@
+// { dg-do run }
+
+#include <version>
+
+#if __cplusplus >= 202200L
+#ifndef __cpp_lib_ios_noreplace
+# error "Feature-test macro for ios::noreplace missing in <version>"
+#elif __cpp_lib_ios_noreplace < 202200L
+# error "Feature-test macro for ios::noreplace has wrong value in <version>"
+#endif
+#endif
+
+#include <fstream>
+#include <testsuite_hooks.h>
+
+int main()
+{
+#if __cpp_lib_ios_noreplace
+  std::wios::openmode noreplace = std::wios::noreplace;
+#else
+  std::wios::openmode noreplace = std::wios::__noreplace;
+#endif
+
+  std::wofstream of("noreplace");
+  VERIFY( of.is_open() );
+  of.close();
+  of.open("noreplace", noreplace);
+  VERIFY( ! of.is_open() );
+}
This page took 0.071402 seconds and 5 git commands to generate.