From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id F1653385800E for ; Thu, 9 Dec 2021 23:30:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F1653385800E Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-349-00HclcoiPSeZMAPNjQlWPw-1; Thu, 09 Dec 2021 18:30:25 -0500 X-MC-Unique: 00HclcoiPSeZMAPNjQlWPw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7B9038042E0; Thu, 9 Dec 2021 23:30:24 +0000 (UTC) Received: from localhost (unknown [10.33.36.71]) by smtp.corp.redhat.com (Postfix) with ESMTP id 002F660BD8; Thu, 9 Dec 2021 23:30:23 +0000 (UTC) From: Jonathan Wakely 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 Message-Id: <20211209233022.1569388-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII" X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, UNWANTED_LANGUAGE_BODY autolearn=unavailable autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Dec 2021 23:30:31 -0000 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 + +#if __cplusplus >= 202200L +#ifndef __cpp_lib_ios_noreplace +# error "Feature-test macro for ios::noreplace missing in " +#elif __cpp_lib_ios_noreplace < 202200L +# error "Feature-test macro for ios::noreplace has wrong value in " +#endif +#endif + +#include +#include + +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 + +#if __cplusplus >= 202200L +#ifndef __cpp_lib_ios_noreplace +# error "Feature-test macro for ios::noreplace missing in " +#elif __cpp_lib_ios_noreplace < 202200L +# error "Feature-test macro for ios::noreplace has wrong value in " +#endif +#endif + +#include +#include + +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