diff --git a/libcxx/include/fstream b/libcxx/include/fstream --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -554,6 +554,18 @@ case ios_base::in | ios_base::out | ios_base::app | ios_base::binary: case ios_base::in | ios_base::app | ios_base::binary: return "a+b" _LIBCPP_FOPEN_CLOEXEC_MODE; +#if __cpp_lib_ios_noreplace >= 202207L + case ios_base::out | ios_base::noreplace: + case ios_base::out | ios_base::trunc | ios_base::noreplace: + return "wx" _LIBCPP_FOPEN_CLOEXEC_MODE; + case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace: + return "w+x" _LIBCPP_FOPEN_CLOEXEC_MODE; + case ios_base::out | ios_base::binary | ios_base::noreplace: + case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace: + return "wbx" _LIBCPP_FOPEN_CLOEXEC_MODE; + case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace: + return "w+bx" _LIBCPP_FOPEN_CLOEXEC_MODE; +#endif default: return nullptr; } @@ -667,6 +679,22 @@ case ios_base::in | ios_base::app | ios_base::binary: __mdstr = L"a+b"; break; +#if __cpp_lib_ios_noreplace >= 202207L + case ios_base::out | ios_base::noreplace: + case ios_base::out | ios_base::trunc | ios_base::noreplace: + __mdstr = L"wx"; + break; + case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace: + __mdstr = L"w+x"; + break; + case ios_base::out | ios_base::binary | ios_base::noreplace: + case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace: + __mdstr = L"wbx"; + break; + case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace: + __mdstr = L"w+bx"; + break; +#endif default: __rt = nullptr; break; diff --git a/libcxx/include/ios b/libcxx/include/ios --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -58,6 +58,7 @@ static constexpr openmode ate; static constexpr openmode binary; static constexpr openmode in; + static constexpr openmode noreplace; static constexpr openmode out; static constexpr openmode trunc; @@ -272,12 +273,15 @@ static const iostate goodbit = 0x0; typedef unsigned int openmode; - static const openmode app = 0x01; - static const openmode ate = 0x02; - static const openmode binary = 0x04; - static const openmode in = 0x08; - static const openmode out = 0x10; - static const openmode trunc = 0x20; + static const openmode app = 0x01; + static const openmode ate = 0x02; + static const openmode binary = 0x04; + static const openmode in = 0x08; +#if __cpp_lib_ios_noreplace >= 202207L + static const openmode noreplace = 0x40; +#endif + static const openmode out = 0x10; + static const openmode trunc = 0x20; enum seekdir {beg, cur, end}; diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -99,6 +99,7 @@ __cpp_lib_interpolate 201902L __cpp_lib_invoke 201411L __cpp_lib_invoke_r 202106L +__cpp_lib_ios_noreplace 202207L __cpp_lib_is_aggregate 201703L __cpp_lib_is_constant_evaluated 201811L __cpp_lib_is_final 201402L @@ -392,6 +393,7 @@ // # define __cpp_lib_constexpr_typeinfo 202106L # define __cpp_lib_forward_like 202207L // # define __cpp_lib_invoke_r 202106L +# define __cpp_lib_ios_noreplace 202207L # define __cpp_lib_is_scoped_enum 202011L // # define __cpp_lib_move_only_function 202110L # undef __cpp_lib_optional diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/noreplace.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/noreplace.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/noreplace.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: no-filesystem + +// Filesystem is supported on Apple platforms starting with macosx10.15. +// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}} + +// + +// plate > +// class basic_fstream + +// explicit basic_fstream(const filesystem::path& s, +// ios_base::openmode mode = ios_base::in|ios_base::out); + +#include +#include +#include +#include "test_macros.h" +#include "platform_support.h" + +namespace fs = std::filesystem; + +int main(int, char**) { + fs::path p = get_temp_file_name(); + { + std::fstream fs( + p.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::noreplace); + assert(fs.rdstate() == std::ios_base::failbit); + } + std::remove(p.c_str()); + + { + std::fstream fs( + p.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::noreplace); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + + fs.close(); + std::fstream fs2( + p.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::noreplace); + assert(fs2.rdstate() == std::ios_base::failbit); + } + std::remove(p.c_str()); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + { + std::wfstream fs( + p.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::noreplace); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + + fs.close(); + std::wfstream fs2( + p.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::noreplace); + assert(fs2.rdstate() == std::ios_base::failbit); + } + std::remove(p.c_str()); +#endif +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -391,6 +391,10 @@ "values": { "c++2b": 202106 }, "headers": ["functional"], "unimplemented": True, + }, { + "name": "__cpp_lib_ios_noreplace", + "values": { "c++2b": 202207 }, + "headers": ["ios"], }, { "name": "__cpp_lib_is_aggregate", "values": { "c++17": 201703 },