libstdc++: Implement std::ios_base::noreplace for C++23 [PR59769]
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.
This commit is contained in:
parent
9e18a25331
commit
a219139e98
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() );
|
||||
}
|
|
@ -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() );
|
||||
}
|
Loading…
Reference in New Issue