From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: [committed] libstdc++: Implement std::ios_base::noreplace for C++23 [PR59769]
Date: Thu, 9 Dec 2021 23:30:22 +0000 [thread overview]
Message-ID: <20211209233022.1569388-1-jwakely@redhat.com> (raw)
Tested powerpc64le-linux, pushed to trunk.
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 | 46 +++++++++++--------
libstdc++-v3/include/bits/ios_base.h | 9 ++++
libstdc++-v3/include/std/version | 1 +
.../basic_ofstream/open/char/noreplace.cc | 29 ++++++++++++
.../basic_ofstream/open/wchar_t/noreplace.cc | 29 ++++++++++++
5 files changed, 94 insertions(+), 20 deletions(-)
create mode 100644 libstdc++-v3/testsuite/27_io/basic_ofstream/open/char/noreplace.cc
create mode 100644 libstdc++-v3/testsuite/27_io/basic_ofstream/open/wchar_t/noreplace.cc
diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc b/libstdc++-v3/config/io/basic_file_stdio.cc
index ce4a6380ebb..06ee016d016 100644
--- a/libstdc++-v3/config/io/basic_file_stdio.cc
+++ b/libstdc++-v3/config/io/basic_file_stdio.cc
@@ -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 ): 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 |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 |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
}
diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h
index d6626d4d26b..5db05524e1c 100644
--- a/libstdc++-v3/include/bits/ios_base.h
+++ b/libstdc++-v3/include/bits/ios_base.h
@@ -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.
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index eb612f57c73..23890037b6b 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -296,6 +296,7 @@
#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
index 00000000000..e39f5928a1f
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ofstream/open/char/noreplace.cc
@@ -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
index 00000000000..77f11865ac4
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ofstream/open/wchar_t/noreplace.cc
@@ -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() );
+}
--
2.31.1
reply other threads:[~2021-12-09 23:30 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211209233022.1569388-1-jwakely@redhat.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).