diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -322,6 +322,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_invoke_r`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_ios_noreplace`` ``202207L`` + ------------------------------------------------- ----------------- ``__cpp_lib_is_scoped_enum`` ``202011L`` ------------------------------------------------- ----------------- ``__cpp_lib_move_only_function`` *unimplemented* 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 _LIBCPP_STD_VER >= 23 + 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 _LIBCPP_STD_VER >= 23 + 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; @@ -276,8 +277,11 @@ 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; +#if _LIBCPP_STD_VER >= 23 + 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.string().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.string().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.string().c_str()); +#endif +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ios.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ios.version.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ios.version.compile.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// WARNING: This test was generated by generate_feature_test_macro_components.py +// and should not be edited manually. +// +// clang-format off + +// UNSUPPORTED: no-localization + +// + +// Test the feature test macros defined by + +/* Constant Value + __cpp_lib_ios_noreplace 202207L [C++2b] +*/ + +#include +#include "test_macros.h" + +#if TEST_STD_VER < 14 + +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 14 + +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 17 + +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 20 + +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + +#elif TEST_STD_VER > 20 + +# ifndef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should be defined in c++2b" +# endif +# if __cpp_lib_ios_noreplace != 202207L +# error "__cpp_lib_ios_noreplace should have the value 202207L in c++2b" +# endif + +#endif // TEST_STD_VER > 20 + diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -93,6 +93,7 @@ __cpp_lib_interpolate 201902L [C++20] __cpp_lib_invoke 201411L [C++17] __cpp_lib_invoke_r 202106L [C++2b] + __cpp_lib_ios_noreplace 202207L [C++2b] __cpp_lib_is_aggregate 201703L [C++17] __cpp_lib_is_constant_evaluated 201811L [C++20] __cpp_lib_is_final 201402L [C++14] @@ -484,6 +485,10 @@ # error "__cpp_lib_invoke_r should not be defined before c++2b" # endif +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + # ifdef __cpp_lib_is_aggregate # error "__cpp_lib_is_aggregate should not be defined before c++17" # endif @@ -1136,6 +1141,10 @@ # error "__cpp_lib_invoke_r should not be defined before c++2b" # endif +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + # ifdef __cpp_lib_is_aggregate # error "__cpp_lib_is_aggregate should not be defined before c++17" # endif @@ -1917,6 +1926,10 @@ # error "__cpp_lib_invoke_r should not be defined before c++2b" # endif +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + # ifndef __cpp_lib_is_aggregate # error "__cpp_lib_is_aggregate should be defined in c++17" # endif @@ -2977,6 +2990,10 @@ # error "__cpp_lib_invoke_r should not be defined before c++2b" # endif +# ifdef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should not be defined before c++2b" +# endif + # ifndef __cpp_lib_is_aggregate # error "__cpp_lib_is_aggregate should be defined in c++20" # endif @@ -4232,6 +4249,13 @@ # endif # endif +# ifndef __cpp_lib_ios_noreplace +# error "__cpp_lib_ios_noreplace should be defined in c++2b" +# endif +# if __cpp_lib_ios_noreplace != 202207L +# error "__cpp_lib_ios_noreplace should have the value 202207L in c++2b" +# endif + # ifndef __cpp_lib_is_aggregate # error "__cpp_lib_is_aggregate should be defined in c++2b" # 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 },