https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/76632
>From 1165b11477ab59122a4db35221fcefe3c9505387 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sat, 30 Dec 2023 17:34:56 +0200 Subject: [PATCH 1/8] [libc++][streams] P1759R6: Native handles and file streams Implements: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1759r6.html - https://eel.is/c++draft/filebuf - https://eel.is/c++draft/ifstream - https://eel.is/c++draft/ofstream - https://eel.is/c++draft/fstream --- libcxx/docs/FeatureTestMacroTable.rst | 2 +- libcxx/docs/ReleaseNotes/18.rst | 1 + libcxx/docs/Status/Cxx2cPapers.csv | 2 +- libcxx/include/fstream | 59 +++++++++++++++++++ libcxx/include/version | 2 +- libcxx/src/CMakeLists.txt | 1 + libcxx/src/fstream.cpp | 33 +++++++++++ .../fstream.version.compile.pass.cpp | 16 ++--- .../version.version.compile.pass.cpp | 16 ++--- .../generate_feature_test_macro_components.py | 1 - 10 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 libcxx/src/fstream.cpp diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index ad12b109023154..0427615a9636fd 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -418,7 +418,7 @@ Status --------------------------------------------------- ----------------- ``__cpp_lib_freestanding_variant`` *unimplemented* --------------------------------------------------- ----------------- - ``__cpp_lib_fstream_native_handle`` *unimplemented* + ``__cpp_lib_fstream_native_handle`` ``202306L`` --------------------------------------------------- ----------------- ``__cpp_lib_function_ref`` *unimplemented* --------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst index fa60a581652d6a..e6f1adf4d5529b 100644 --- a/libcxx/docs/ReleaseNotes/18.rst +++ b/libcxx/docs/ReleaseNotes/18.rst @@ -58,6 +58,7 @@ Implemented Papers - P2870R3 - Remove basic_string::reserve() - P2909R4 - Fix formatting of code units as integers (Dude, where’s my ``char``?) - P0521R0 - Proposed Resolution for CA 14 (shared_ptr use_count/unique) +- P1759R6 - Native handles and file streams Improvements and New Features diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index ff83648aa76830..1d7807a4291a99 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -19,7 +19,7 @@ "`P2757R3 <https://wg21.link/P2757R3>`__","LWG","Type-checking format args","Varna June 2023","","","|format|" "`P2637R3 <https://wg21.link/P2637R3>`__","LWG","Member ``visit``","Varna June 2023","","","|format|" "`P2641R4 <https://wg21.link/P2641R4>`__","CWG, LWG","Checking if a ``union`` alternative is active","Varna June 2023","","","" -"`P1759R6 <https://wg21.link/P1759R6>`__","LWG","Native handles and file streams","Varna June 2023","","","" +"`P1759R6 <https://wg21.link/P1759R6>`__","LWG","Native handles and file streams","Varna June 2023","|Complete|","18.0","" "`P2697R1 <https://wg21.link/P2697R1>`__","LWG","Interfacing ``bitset`` with ``string_view``","Varna June 2023","|Complete|","18.0","" "`P1383R2 <https://wg21.link/P1383R2>`__","LWG","More ``constexpr`` for ``<cmath>`` and ``<complex>``","Varna June 2023","","","" "`P2734R0 <https://wg21.link/P2734R0>`__","LWG","Adding the new SI prefixes","Varna June 2023","|Complete|","17.0","" diff --git a/libcxx/include/fstream b/libcxx/include/fstream index 7a4e15b55d56fe..9609ff420220fa 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -73,6 +73,7 @@ public: typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; + using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // Since C++26 basic_ifstream(); explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in); @@ -85,6 +86,7 @@ public: void swap(basic_ifstream& rhs); basic_filebuf<char_type, traits_type>* rdbuf() const; + native_handle_type native_handle() const noexcept; // Since C++26 bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::in); void open(const string& s, ios_base::openmode mode = ios_base::in); @@ -110,6 +112,7 @@ public: typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; + using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // Since C++26 basic_ofstream(); explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out); @@ -122,6 +125,8 @@ public: void swap(basic_ofstream& rhs); basic_filebuf<char_type, traits_type>* rdbuf() const; + native_handle_type native_handle() const noexcept; // Since C++26 + bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::out); void open(const string& s, ios_base::openmode mode = ios_base::out); @@ -148,6 +153,7 @@ public: typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; + using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // Since C++26 basic_fstream(); explicit basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out); @@ -160,6 +166,7 @@ public: void swap(basic_fstream& rhs); basic_filebuf<char_type, traits_type>* rdbuf() const; + native_handle_type native_handle() const noexcept; // Since C++26 bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out); void open(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out); @@ -219,6 +226,13 @@ public: typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; typedef typename traits_type::state_type state_type; +# if _LIBCPP_STD_VER >= 26 +# if defined(_LIBCPP_WIN32API) + using native_handle_type = void*; // HANDLE +# else + using native_handle_type = int; // POSIX file descriptor +# endif +# endif // 27.9.1.2 Constructors/destructor: basic_filebuf(); @@ -245,6 +259,9 @@ public: # endif _LIBCPP_HIDE_FROM_ABI basic_filebuf* __open(int __fd, ios_base::openmode __mode); basic_filebuf* close(); +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle(); +# endif _LIBCPP_HIDE_FROM_ABI inline static const char* __make_mdstring(ios_base::openmode __mode) _NOEXCEPT; @@ -1024,6 +1041,9 @@ public: typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; +# if _LIBCPP_STD_VER >= 26 + using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; +# endif _LIBCPP_HIDE_FROM_ABI basic_ifstream(); _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in); @@ -1041,6 +1061,9 @@ public: _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream& __rhs); _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const; +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { return rdbuf()->native_handle(); } +# endif _LIBCPP_HIDE_FROM_ABI bool is_open() const; void open(const char* __s, ios_base::openmode __mode = ios_base::in); # ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR @@ -1116,6 +1139,14 @@ inline basic_filebuf<_CharT, _Traits>* basic_ifstream<_CharT, _Traits>::rdbuf() return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_); } +// # if _LIBCPP_STD_VER >= 26 +// template <class _CharT, class _Traits> +// inline basic_filebuf<_CharT, _Traits>::native_handle_type +// basic_ifstream<_CharT, _Traits>::native_handle() const noexcept { +// return rdbuf()->native_handle(); +// } +// # endif + template <class _CharT, class _Traits> inline bool basic_ifstream<_CharT, _Traits>::is_open() const { return __sb_.is_open(); @@ -1171,6 +1202,9 @@ public: typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; +# if _LIBCPP_STD_VER >= 26 + using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; +# endif _LIBCPP_HIDE_FROM_ABI basic_ofstream(); _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const char* __s, ios_base::openmode __mode = ios_base::out); @@ -1190,6 +1224,9 @@ public: _LIBCPP_HIDE_FROM_ABI void swap(basic_ofstream& __rhs); _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const; +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { return rdbuf()->native_handle(); } +# endif _LIBCPP_HIDE_FROM_ABI bool is_open() const; void open(const char* __s, ios_base::openmode __mode = ios_base::out); # ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR @@ -1266,6 +1303,14 @@ inline basic_filebuf<_CharT, _Traits>* basic_ofstream<_CharT, _Traits>::rdbuf() return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_); } +// # if _LIBCPP_STD_VER >= 26 +// template <class _CharT, class _Traits> +// inline basic_filebuf<_CharT, _Traits>::native_handle_type +// basic_ofstream<_CharT, _Traits>::native_handle() const noexcept { +// return rdbuf()->native_handle(); +// } +// # endif + template <class _CharT, class _Traits> inline bool basic_ofstream<_CharT, _Traits>::is_open() const { return __sb_.is_open(); @@ -1321,6 +1366,9 @@ public: typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; +# if _LIBCPP_STD_VER >= 26 + using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; +# endif _LIBCPP_HIDE_FROM_ABI basic_fstream(); _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const char* __s, @@ -1345,6 +1393,9 @@ public: _LIBCPP_HIDE_FROM_ABI void swap(basic_fstream& __rhs); _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const; +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { return rdbuf()->native_handle(); } +# endif _LIBCPP_HIDE_FROM_ABI bool is_open() const; _LIBCPP_HIDE_FROM_ABI void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); # ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR @@ -1420,6 +1471,14 @@ inline basic_filebuf<_CharT, _Traits>* basic_fstream<_CharT, _Traits>::rdbuf() c return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_); } +// # if _LIBCPP_STD_VER >= 26 +// template <class _CharT, class _Traits> +// inline basic_filebuf<_CharT, _Traits>::native_handle_type +// basic_fstream<_CharT, _Traits>::native_handle() const noexcept { +// return rdbuf()->native_handle(); +// } +// # endif + template <class _CharT, class _Traits> inline bool basic_fstream<_CharT, _Traits>::is_open() const { return __sb_.is_open(); diff --git a/libcxx/include/version b/libcxx/include/version index 768710ef5c84aa..a2bb11b62a44d3 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -495,7 +495,7 @@ __cpp_lib_within_lifetime 202306L <type_traits> // # define __cpp_lib_freestanding_optional 202311L // # define __cpp_lib_freestanding_string_view 202311L // # define __cpp_lib_freestanding_variant 202311L -// # define __cpp_lib_fstream_native_handle 202306L +# define __cpp_lib_fstream_native_handle 202306L // # define __cpp_lib_function_ref 202306L // # define __cpp_lib_hazard_pointer 202306L // # define __cpp_lib_linalg 202311L diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 329964a001363b..b931460ec76297 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -14,6 +14,7 @@ set(LIBCXX_SOURCES filesystem/filesystem_error.cpp filesystem/path_parser.h filesystem/path.cpp + fstream.cpp functional.cpp hash.cpp include/apple_availability.h diff --git a/libcxx/src/fstream.cpp b/libcxx/src/fstream.cpp new file mode 100644 index 00000000000000..c680ff638fe7e5 --- /dev/null +++ b/libcxx/src/fstream.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <cassert> +#include <cstdio> +#include <fstream> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 +template <class _CharT, class _Traits> +basic_filebuf<_CharT, _Traits>::native_handle_type basic_filebuf<_CharT, _Traits>::native_handle() { + assert(is_open()); + // __file_ is a FILE* +# if defined(_LIBCPP_WIN32API) + // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 + intptr_t __handle = _get_osfhandle(::fileno(__file_)); + if (__handle == -1) + return nullptr; + return reinterpret_cast<void*>(__handle); +# else + return ::fileno(__file_); +# endif +} +#endif + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/fstream.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/fstream.version.compile.pass.cpp index 981f5420ff7e0f..eab0313b2c1ef7 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/fstream.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/fstream.version.compile.pass.cpp @@ -56,17 +56,11 @@ #elif TEST_STD_VER > 23 -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_fstream_native_handle -# error "__cpp_lib_fstream_native_handle should be defined in c++26" -# endif -# if __cpp_lib_fstream_native_handle != 202306L -# error "__cpp_lib_fstream_native_handle should have the value 202306L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_fstream_native_handle -# error "__cpp_lib_fstream_native_handle should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_fstream_native_handle +# error "__cpp_lib_fstream_native_handle should be defined in c++26" +# endif +# if __cpp_lib_fstream_native_handle != 202306L +# error "__cpp_lib_fstream_native_handle should have the value 202306L in c++26" # endif #endif // TEST_STD_VER > 23 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 index 650a14b019ed87..af7037a1392fbf 100644 --- 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 @@ -6490,17 +6490,11 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_fstream_native_handle -# error "__cpp_lib_fstream_native_handle should be defined in c++26" -# endif -# if __cpp_lib_fstream_native_handle != 202306L -# error "__cpp_lib_fstream_native_handle should have the value 202306L in c++26" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_fstream_native_handle -# error "__cpp_lib_fstream_native_handle should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_fstream_native_handle +# error "__cpp_lib_fstream_native_handle should be defined in c++26" +# endif +# if __cpp_lib_fstream_native_handle != 202306L +# error "__cpp_lib_fstream_native_handle should have the value 202306L in c++26" # endif # if !defined(_LIBCPP_VERSION) diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 2f506f32f565cb..cb7c532c05251f 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -570,7 +570,6 @@ def add_version_header(tc): "name": "__cpp_lib_fstream_native_handle", "values": {"c++26": 202306}, # P1759R6 Native handles and file streams "headers": ["fstream"], - "unimplemented": True, }, { "name": "__cpp_lib_function_ref", >From 9d4b10e4739c44e867ae40dc942fc6577212d94e Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sat, 30 Dec 2023 22:28:46 +0200 Subject: [PATCH 2/8] Added tests --- libcxx/include/fstream | 70 ++++++++++--------- libcxx/src/fstream.cpp | 17 +++-- .../filebuf.members/native_handle.pass.cpp | 52 ++++++++++++++ .../fstream.members/native_handle.pass.cpp | 57 +++++++++++++++ .../ifstream.members/native_handle.pass.cpp | 57 +++++++++++++++ .../ofstream.members/native_handle.pass.cpp | 59 ++++++++++++++++ .../file.streams/fstreams/test_helpers.h | 33 +++++++++ 7 files changed, 305 insertions(+), 40 deletions(-) create mode 100644 libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp create mode 100644 libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp create mode 100644 libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp create mode 100644 libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp create mode 100644 libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h diff --git a/libcxx/include/fstream b/libcxx/include/fstream index 9609ff420220fa..f0cb5bb50fc9b6 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -215,8 +215,37 @@ _LIBCPP_PUSH_MACROS #if !defined(_LIBCPP_HAS_NO_FILESYSTEM) +# if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +# endif + +#include <fcntl.h> + _LIBCPP_BEGIN_NAMESPACE_STD +# if _LIBCPP_STD_VER >= 26 +# if defined(_LIBCPP_WIN32API) +using __filebuf_native_handle_type = void*; // HANDLE +# else +using __filebuf_native_handle_type = int; // POSIX file descriptor +# endif +_LIBCPP_HIDE_FROM_ABI __filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept; +__filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept { +# if defined(_LIBCPP_WIN32API) + // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 + intptr_t __handle = _get_osfhandle(::fileno(__file)); + if (__handle == -1) + return nullptr; + return reinterpret_cast<void*>(__handle); +# else + return ::fileno(__file); +# endif +} +# endif + template <class _CharT, class _Traits> class _LIBCPP_TEMPLATE_VIS basic_filebuf : public basic_streambuf<_CharT, _Traits> { public: @@ -227,11 +256,7 @@ public: typedef typename traits_type::off_type off_type; typedef typename traits_type::state_type state_type; # if _LIBCPP_STD_VER >= 26 -# if defined(_LIBCPP_WIN32API) - using native_handle_type = void*; // HANDLE -# else - using native_handle_type = int; // POSIX file descriptor -# endif + using native_handle_type = __filebuf_native_handle_type; # endif // 27.9.1.2 Constructors/destructor: @@ -260,7 +285,10 @@ public: _LIBCPP_HIDE_FROM_ABI basic_filebuf* __open(int __fd, ios_base::openmode __mode); basic_filebuf* close(); # if _LIBCPP_STD_VER >= 26 - _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle(); + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { + assert(is_open()); + return std::__filebuf_native_handle(__file_); + } # endif _LIBCPP_HIDE_FROM_ABI inline static const char* __make_mdstring(ios_base::openmode __mode) _NOEXCEPT; @@ -1042,7 +1070,7 @@ public: typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; # if _LIBCPP_STD_VER >= 26 - using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; + using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type; # endif _LIBCPP_HIDE_FROM_ABI basic_ifstream(); @@ -1139,14 +1167,6 @@ inline basic_filebuf<_CharT, _Traits>* basic_ifstream<_CharT, _Traits>::rdbuf() return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_); } -// # if _LIBCPP_STD_VER >= 26 -// template <class _CharT, class _Traits> -// inline basic_filebuf<_CharT, _Traits>::native_handle_type -// basic_ifstream<_CharT, _Traits>::native_handle() const noexcept { -// return rdbuf()->native_handle(); -// } -// # endif - template <class _CharT, class _Traits> inline bool basic_ifstream<_CharT, _Traits>::is_open() const { return __sb_.is_open(); @@ -1203,7 +1223,7 @@ public: typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; # if _LIBCPP_STD_VER >= 26 - using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; + using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type; # endif _LIBCPP_HIDE_FROM_ABI basic_ofstream(); @@ -1303,14 +1323,6 @@ inline basic_filebuf<_CharT, _Traits>* basic_ofstream<_CharT, _Traits>::rdbuf() return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_); } -// # if _LIBCPP_STD_VER >= 26 -// template <class _CharT, class _Traits> -// inline basic_filebuf<_CharT, _Traits>::native_handle_type -// basic_ofstream<_CharT, _Traits>::native_handle() const noexcept { -// return rdbuf()->native_handle(); -// } -// # endif - template <class _CharT, class _Traits> inline bool basic_ofstream<_CharT, _Traits>::is_open() const { return __sb_.is_open(); @@ -1367,7 +1379,7 @@ public: typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; # if _LIBCPP_STD_VER >= 26 - using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; + using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type; # endif _LIBCPP_HIDE_FROM_ABI basic_fstream(); @@ -1471,14 +1483,6 @@ inline basic_filebuf<_CharT, _Traits>* basic_fstream<_CharT, _Traits>::rdbuf() c return const_cast<basic_filebuf<char_type, traits_type>*>(&__sb_); } -// # if _LIBCPP_STD_VER >= 26 -// template <class _CharT, class _Traits> -// inline basic_filebuf<_CharT, _Traits>::native_handle_type -// basic_fstream<_CharT, _Traits>::native_handle() const noexcept { -// return rdbuf()->native_handle(); -// } -// # endif - template <class _CharT, class _Traits> inline bool basic_fstream<_CharT, _Traits>::is_open() const { return __sb_.is_open(); diff --git a/libcxx/src/fstream.cpp b/libcxx/src/fstream.cpp index c680ff638fe7e5..e5611e2d48b0a6 100644 --- a/libcxx/src/fstream.cpp +++ b/libcxx/src/fstream.cpp @@ -7,25 +7,28 @@ //===----------------------------------------------------------------------===// #include <__config> -#include <cassert> #include <cstdio> #include <fstream> +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +#endif + _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 26 -template <class _CharT, class _Traits> -basic_filebuf<_CharT, _Traits>::native_handle_type basic_filebuf<_CharT, _Traits>::native_handle() { - assert(is_open()); - // __file_ is a FILE* +_LIBCPP_EXPORTED_FROM_ABI __filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept { # if defined(_LIBCPP_WIN32API) // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 - intptr_t __handle = _get_osfhandle(::fileno(__file_)); + intptr_t __handle = _get_osfhandle(::fileno(__file)); if (__handle == -1) return nullptr; return reinterpret_cast<void*>(__handle); # else - return ::fileno(__file_); + return ::fileno(__file); # endif } #endif diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp new file mode 100644 index 00000000000000..4104aa061e1546 --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++23 + +// <fstream> + +// class basic_filebuf; + +// native_handle_type native_handle() const noexcept; + +#include <cassert> +#include <fstream> +#include <filesystem> +#include <utility> + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +#endif + +#include "platform_support.h" +#include "test_macros.h" +#include "../test_helpers.h" + +template <typename CharT> +void test() { + std::basic_filebuf<CharT> f; + assert(!f.is_open()); + std::filesystem::path p = get_temp_file_name(); + f.open(p, std::ios_base::in); + assert(f.is_open()); + assert(is_handle_valid(f.native_handle())); + assert(is_handle_valid(std::as_const(f).native_handle())); + static_assert(noexcept(f.native_handle())); +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp new file mode 100644 index 00000000000000..44da8bd3e18bad --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++23 + +// <fstream> + +// class basic_fstream; + +// native_handle_type native_handle() const noexcept; + +#include <cassert> +#include <fstream> +#include <filesystem> +#include <utility> + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +#endif + +#include "platform_support.h" +#include "test_macros.h" +#include "../test_helpers.h" + +template <typename CharT> +void test() { + static_assert(std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, + typename std::basic_fstream<CharT>::native_handle_type>); + + std::basic_fstream<CharT> f; + static_assert(noexcept(f.native_handle())); + assert(!f.is_open()); + std::filesystem::path p = get_temp_file_name(); + f.open(p); + assert(f.is_open()); + assert(f.native_handle() == f.rdbuf()->native_handle()); + assert(is_handle_valid(f.native_handle())); + assert(is_handle_valid(std::as_const(f).native_handle())); + static_assert(noexcept(f.native_handle())); +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp new file mode 100644 index 00000000000000..1345b72b158e28 --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++23 + +// <fstream> + +// class basic_ifstream; + +// native_handle_type native_handle() const noexcept; + +#include <cassert> +#include <fstream> +#include <filesystem> +#include <utility> + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +#endif + +#include "platform_support.h" +#include "test_macros.h" +#include "../test_helpers.h" + +template <typename CharT> +void test() { + static_assert(std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, + typename std::basic_ifstream<CharT>::native_handle_type>); + + std::basic_ifstream<CharT> f; + static_assert(noexcept(f.native_handle())); + assert(!f.is_open()); + std::filesystem::path p = get_temp_file_name(); + f.open(p); + assert(f.is_open()); + assert(f.native_handle() == f.rdbuf()->native_handle()); + assert(is_handle_valid(f.native_handle())); + assert(is_handle_valid(std::as_const(f).native_handle())); + static_assert(noexcept(f.native_handle())); +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp new file mode 100644 index 00000000000000..cd69c8087608df --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++23 + +// <fstream> + +// class basic_ofstream; + +// native_handle_type native_handle() const noexcept; + +#include <cassert> +#include <fstream> +#include <filesystem> +#include <utility> + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +#endif + +#include "platform_support.h" +#include "test_macros.h" +#include "../test_helpers.h" + +template <typename CharT> +void test() { + static_assert(std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, + typename std::basic_ofstream<CharT>::native_handle_type>); + + std::basic_ofstream<CharT> f; + static_assert(noexcept(f.native_handle())); + assert(!f.is_open()); + std::filesystem::path p = get_temp_file_name(); + f.open(p); + assert(f.is_open()); + assert(f.native_handle() == f.rdbuf()->native_handle()); + assert(f.native_handle()); + assert(std::as_const(f).native_handle()); + assert(is_handle_valid(f.native_handle())); + assert(is_handle_valid(std::as_const(f).native_handle())); + static_assert(noexcept(f.native_handle())); +} + +int main(int, char**) { + test<char>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h new file mode 100644 index 00000000000000..06ddbf8287f039 --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H +#define TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H + +#include <cstdio> + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +#else +# include <fcntl.h> +#endif + +#if defined(_LIBCPP_WIN32API) +auto is_handle_valid([[maybe_unused]] HANDLE handle) { + // TODO: GetFileInformationByHandle + return true; +}; +#else +// POSIX +auto is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; +#endif + +#endif // TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H \ No newline at end of file >From 37a871ace443c45dae2c048a91de712a1c369fe4 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 31 Dec 2023 11:25:48 +0200 Subject: [PATCH 3/8] Added missing include --- libcxx/include/fstream | 1 + 1 file changed, 1 insertion(+) diff --git a/libcxx/include/fstream b/libcxx/include/fstream index f0cb5bb50fc9b6..5598943268276d 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -195,6 +195,7 @@ typedef basic_fstream<wchar_t> wfstream; #include <__utility/move.h> #include <__utility/swap.h> #include <__utility/unreachable.h> +#include <cassert> #include <cstdio> #include <filesystem> #include <istream> >From 5aeb33918bd80840469cec803ba054f1f4aeec8e Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 31 Dec 2023 14:38:06 +0200 Subject: [PATCH 4/8] WIP: Addressed some comments and simplified/generalized the tests --- libcxx/include/fstream | 22 +++----- libcxx/src/fstream.cpp | 9 +-- .../fstream.members/native_handle.pass.cpp | 34 +----------- .../ifstream.members/native_handle.pass.cpp | 35 +----------- .../ofstream.members/native_handle.pass.cpp | 36 +----------- .../file.streams/fstreams/test_helpers.h | 55 ++++++++++++++----- 6 files changed, 60 insertions(+), 131 deletions(-) diff --git a/libcxx/include/fstream b/libcxx/include/fstream index 5598943268276d..ab854cf534e7fb 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -195,7 +195,6 @@ typedef basic_fstream<wchar_t> wfstream; #include <__utility/move.h> #include <__utility/swap.h> #include <__utility/unreachable.h> -#include <cassert> #include <cstdio> #include <filesystem> #include <istream> @@ -223,24 +222,21 @@ _LIBCPP_PUSH_MACROS # include <windows.h> # endif -#include <fcntl.h> +// # include <fcntl.h> _LIBCPP_BEGIN_NAMESPACE_STD # if _LIBCPP_STD_VER >= 26 # if defined(_LIBCPP_WIN32API) -using __filebuf_native_handle_type = void*; // HANDLE -# else -using __filebuf_native_handle_type = int; // POSIX file descriptor +using __filebuf_native_handle_type = HANDLE; +_LIBCPP_EXPORTED_FROM_ABI __filebuf_native_handle_type __filebuf_windows_native_handle(FILE* __file); +# else // POSIX +using __filebuf_native_handle_type = int; // File descriptor # endif -_LIBCPP_HIDE_FROM_ABI __filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept; -__filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept { + +_LIBCPP_HIDE_FROM_ABI inline __filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept { # if defined(_LIBCPP_WIN32API) - // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 - intptr_t __handle = _get_osfhandle(::fileno(__file)); - if (__handle == -1) - return nullptr; - return reinterpret_cast<void*>(__handle); + return __filebuf_windows_native_handle(__file); # else return ::fileno(__file); # endif @@ -287,7 +283,7 @@ public: basic_filebuf* close(); # if _LIBCPP_STD_VER >= 26 _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { - assert(is_open()); + _LIBCPP_ASSERT_UNCATEGORIZED(this->is_open(), "File must be opened"); return std::__filebuf_native_handle(__file_); } # endif diff --git a/libcxx/src/fstream.cpp b/libcxx/src/fstream.cpp index e5611e2d48b0a6..814d912e7d22b3 100644 --- a/libcxx/src/fstream.cpp +++ b/libcxx/src/fstream.cpp @@ -20,17 +20,14 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 26 -_LIBCPP_EXPORTED_FROM_ABI __filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept { # if defined(_LIBCPP_WIN32API) +_LIBCPP_EXPORTED_FROM_ABI __filebuf_native_handle_type __filebuf_windows_native_handle(FILE* __file) noexcept { // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 intptr_t __handle = _get_osfhandle(::fileno(__file)); if (__handle == -1) return nullptr; - return reinterpret_cast<void*>(__handle); -# else - return ::fileno(__file); + return reinterpret_cast<__filebuf_native_handle_type>(__handle); # endif -} #endif -_LIBCPP_END_NAMESPACE_STD + _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp index 44da8bd3e18bad..900475069a1c9b 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp @@ -14,43 +14,13 @@ // native_handle_type native_handle() const noexcept; -#include <cassert> -#include <fstream> -#include <filesystem> -#include <utility> - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <io.h> -# include <windows.h> -#endif - -#include "platform_support.h" #include "test_macros.h" #include "../test_helpers.h" -template <typename CharT> -void test() { - static_assert(std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, - typename std::basic_fstream<CharT>::native_handle_type>); - - std::basic_fstream<CharT> f; - static_assert(noexcept(f.native_handle())); - assert(!f.is_open()); - std::filesystem::path p = get_temp_file_name(); - f.open(p); - assert(f.is_open()); - assert(f.native_handle() == f.rdbuf()->native_handle()); - assert(is_handle_valid(f.native_handle())); - assert(is_handle_valid(std::as_const(f).native_handle())); - static_assert(noexcept(f.native_handle())); -} - int main(int, char**) { - test<char>(); + test_native_handle<char, std::basic_fstream<char>>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS - test<wchar_t>(); + test_native_handle<wchar_t, std::basic_fstream<wchar_t>>(); #endif return 0; diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp index 1345b72b158e28..ffe5e922225da8 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp @@ -14,44 +14,15 @@ // native_handle_type native_handle() const noexcept; -#include <cassert> -#include <fstream> -#include <filesystem> -#include <utility> - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <io.h> -# include <windows.h> -#endif - -#include "platform_support.h" #include "test_macros.h" #include "../test_helpers.h" -template <typename CharT> -void test() { - static_assert(std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, - typename std::basic_ifstream<CharT>::native_handle_type>); - - std::basic_ifstream<CharT> f; - static_assert(noexcept(f.native_handle())); - assert(!f.is_open()); - std::filesystem::path p = get_temp_file_name(); - f.open(p); - assert(f.is_open()); - assert(f.native_handle() == f.rdbuf()->native_handle()); - assert(is_handle_valid(f.native_handle())); - assert(is_handle_valid(std::as_const(f).native_handle())); - static_assert(noexcept(f.native_handle())); -} - int main(int, char**) { - test<char>(); + test_native_handle<char, std::basic_ifstream<char>>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS - test<wchar_t>(); + test_native_handle<wchar_t, std::basic_ifstream<wchar_t>>(); #endif return 0; } + diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp index cd69c8087608df..45f0841dad18cb 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp @@ -14,45 +14,13 @@ // native_handle_type native_handle() const noexcept; -#include <cassert> -#include <fstream> -#include <filesystem> -#include <utility> - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <io.h> -# include <windows.h> -#endif - -#include "platform_support.h" #include "test_macros.h" #include "../test_helpers.h" -template <typename CharT> -void test() { - static_assert(std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, - typename std::basic_ofstream<CharT>::native_handle_type>); - - std::basic_ofstream<CharT> f; - static_assert(noexcept(f.native_handle())); - assert(!f.is_open()); - std::filesystem::path p = get_temp_file_name(); - f.open(p); - assert(f.is_open()); - assert(f.native_handle() == f.rdbuf()->native_handle()); - assert(f.native_handle()); - assert(std::as_const(f).native_handle()); - assert(is_handle_valid(f.native_handle())); - assert(is_handle_valid(std::as_const(f).native_handle())); - static_assert(noexcept(f.native_handle())); -} - int main(int, char**) { - test<char>(); + test_native_handle<char, std::basic_ofstream<char>>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS - test<wchar_t>(); + test_native_handle<wchar_t, std::basic_ofstream<wchar_t>>(); #endif return 0; diff --git a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h index 06ddbf8287f039..7691c04c750448 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h +++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h @@ -9,25 +9,52 @@ #ifndef TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H #define TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H -#include <cstdio> - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <io.h> -# include <windows.h> -#else -# include <fcntl.h> -#endif - -#if defined(_LIBCPP_WIN32API) +#if _LIBCPP_STD_VER >= 26 + +# include <cassert> +# include <cstdio> +# include <fstream> +# include <filesystem> +# include <utility> + +# if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <io.h> +# include <windows.h> +# else +# include <fcntl.h> +# endif + +# include "platform_support.h" + +# if defined(_LIBCPP_WIN32API) auto is_handle_valid([[maybe_unused]] HANDLE handle) { // TODO: GetFileInformationByHandle return true; }; -#else +# else // POSIX auto is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; -#endif +# endif + +template <typename CharT, typename StreamT> +void test_native_handle() { + static_assert( + std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, typename StreamT::native_handle_type>); + + StreamT f; + static_assert(noexcept(f.native_handle())); + assert(!f.is_open()); + std::filesystem::path p = get_temp_file_name(); + f.open(p); + assert(f.is_open()); + assert(f.native_handle() == f.rdbuf()->native_handle()); + assert(is_handle_valid(f.native_handle())); + assert(is_handle_valid(std::as_const(f).native_handle())); + static_assert(noexcept(f.native_handle())); +} + +#endif // _LIBCPP_STD_VER >= 26 #endif // TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H \ No newline at end of file >From 822633dd56bf65b25a265aafb3c16b7e1f071bb4 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 31 Dec 2023 14:48:56 +0200 Subject: [PATCH 5/8] WIP: Fixed formatting error --- .../fstreams/filebuf.members/native_handle.pass.cpp | 7 ------- .../fstreams/ifstream.members/native_handle.pass.cpp | 1 - .../std/input.output/file.streams/fstreams/test_helpers.h | 4 ++-- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp index 4104aa061e1546..790cc91effc822 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp @@ -19,13 +19,6 @@ #include <filesystem> #include <utility> -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <io.h> -# include <windows.h> -#endif - #include "platform_support.h" #include "test_macros.h" #include "../test_helpers.h" diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp index ffe5e922225da8..95a95cb69560b7 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp @@ -25,4 +25,3 @@ int main(int, char**) { return 0; } - diff --git a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h index 7691c04c750448..a3069549315611 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h +++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h @@ -30,7 +30,7 @@ # if defined(_LIBCPP_WIN32API) auto is_handle_valid([[maybe_unused]] HANDLE handle) { - // TODO: GetFileInformationByHandle + // TODO: Maybe test HANDLE with GetFileInformationByHandle?? return true; }; # else @@ -57,4 +57,4 @@ void test_native_handle() { #endif // _LIBCPP_STD_VER >= 26 -#endif // TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H \ No newline at end of file +#endif // TEST_STD_INPUT_OUTPUT_FILE_STREAMS_FSTREAMS_TEST_HELPERS_H >From ecaf77e4da4fa56db9a07b738bcc0b75fa2b7b5a Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 31 Dec 2023 15:18:13 +0200 Subject: [PATCH 6/8] WIP: Refactored `fstream->native_handle()` implementation --- libcxx/include/fstream | 38 ++++++++----------- libcxx/src/fstream.cpp | 4 +- .../file.streams/fstreams/test_helpers.h | 7 ++-- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/libcxx/include/fstream b/libcxx/include/fstream index ab854cf534e7fb..6f6e36f259f381 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -215,32 +215,12 @@ _LIBCPP_PUSH_MACROS #if !defined(_LIBCPP_HAS_NO_FILESYSTEM) -# if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <io.h> -# include <windows.h> -# endif - -// # include <fcntl.h> - _LIBCPP_BEGIN_NAMESPACE_STD # if _LIBCPP_STD_VER >= 26 # if defined(_LIBCPP_WIN32API) -using __filebuf_native_handle_type = HANDLE; -_LIBCPP_EXPORTED_FROM_ABI __filebuf_native_handle_type __filebuf_windows_native_handle(FILE* __file); -# else // POSIX -using __filebuf_native_handle_type = int; // File descriptor -# endif - -_LIBCPP_HIDE_FROM_ABI inline __filebuf_native_handle_type __filebuf_native_handle(FILE* __file) noexcept { -# if defined(_LIBCPP_WIN32API) - return __filebuf_windows_native_handle(__file); -# else - return ::fileno(__file); +_LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file); # endif -} # endif template <class _CharT, class _Traits> @@ -253,7 +233,13 @@ public: typedef typename traits_type::off_type off_type; typedef typename traits_type::state_type state_type; # if _LIBCPP_STD_VER >= 26 - using native_handle_type = __filebuf_native_handle_type; +# if defined(_LIBCPP_WIN32API) + using native_handle_type = void*; // HANDLE +# elif __has_include(<unistd.h>) + using native_handle_type = int; // POSIX file descriptor +# else +# error "Provide a file native handle!" +# endif # endif // 27.9.1.2 Constructors/destructor: @@ -284,7 +270,13 @@ public: # if _LIBCPP_STD_VER >= 26 _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { _LIBCPP_ASSERT_UNCATEGORIZED(this->is_open(), "File must be opened"); - return std::__filebuf_native_handle(__file_); +# if defined(_LIBCPP_WIN32API) + return __filebuf_windows_native_handle(__file_); +# elif __has_include(<unistd.h>) + return ::fileno(__file_); +# else +# error "Provide a way to determine the file native handle! +# endif } # endif diff --git a/libcxx/src/fstream.cpp b/libcxx/src/fstream.cpp index 814d912e7d22b3..27150389627594 100644 --- a/libcxx/src/fstream.cpp +++ b/libcxx/src/fstream.cpp @@ -21,12 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 26 # if defined(_LIBCPP_WIN32API) -_LIBCPP_EXPORTED_FROM_ABI __filebuf_native_handle_type __filebuf_windows_native_handle(FILE* __file) noexcept { +_LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) noexcept { // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 intptr_t __handle = _get_osfhandle(::fileno(__file)); if (__handle == -1) return nullptr; - return reinterpret_cast<__filebuf_native_handle_type>(__handle); + return reinterpret_cast<void*>(__handle); # endif #endif diff --git a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h index a3069549315611..fd6d732638ad32 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h +++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h @@ -29,13 +29,12 @@ # include "platform_support.h" # if defined(_LIBCPP_WIN32API) -auto is_handle_valid([[maybe_unused]] HANDLE handle) { +bool is_handle_valid([[maybe_unused]] HANDLE handle) { // TODO: Maybe test HANDLE with GetFileInformationByHandle?? return true; }; -# else -// POSIX -auto is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; +# else // POSIX +bool is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; # endif template <typename CharT, typename StreamT> >From a066b7957ee85e6c208e531c12b6adf96a8ef3f8 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Mon, 1 Jan 2024 09:17:09 +0200 Subject: [PATCH 7/8] Addressed comments --- libcxx/include/fstream | 2 +- libcxx/src/fstream.cpp | 9 ++++--- .../filebuf.members/native_handle.pass.cpp | 14 ++++++++-- .../file.streams/fstreams/test_helpers.h | 27 ++++++++++++++----- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/libcxx/include/fstream b/libcxx/include/fstream index 6f6e36f259f381..287c4280f18e99 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -238,7 +238,7 @@ public: # elif __has_include(<unistd.h>) using native_handle_type = int; // POSIX file descriptor # else -# error "Provide a file native handle!" +# error "Provide a native file handle!" # endif # endif diff --git a/libcxx/src/fstream.cpp b/libcxx/src/fstream.cpp index 27150389627594..f063b7020cb373 100644 --- a/libcxx/src/fstream.cpp +++ b/libcxx/src/fstream.cpp @@ -19,15 +19,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 26 -# if defined(_LIBCPP_WIN32API) +#if defined(_LIBCPP_WIN32API) + +// Confirm that `HANDLE` is `void*` +static_assert(std::same_as<HANDLE, void*>); + _LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) noexcept { // https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 intptr_t __handle = _get_osfhandle(::fileno(__file)); if (__handle == -1) return nullptr; return reinterpret_cast<void*>(__handle); -# endif + #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp index 790cc91effc822..c87bda5382c85e 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp @@ -30,9 +30,19 @@ void test() { std::filesystem::path p = get_temp_file_name(); f.open(p, std::ios_base::in); assert(f.is_open()); - assert(is_handle_valid(f.native_handle())); - assert(is_handle_valid(std::as_const(f).native_handle())); +#if defined(_LIBCPP_WIN32API) + using HandleT = void*; +#elif __has_include(<unistd.h>) // POSIX + using HandleT = int; +#else +# error "Provide a native file handle!" +#endif + std::same_as<HandleT> decltype(auto) handle = f.native_handle(); + assert(is_handle_valid(handle)); + std::same_as<HandleT> decltype(auto) const_handle = std::as_const(f).native_handle(); + assert(is_handle_valid(const_handle)); static_assert(noexcept(f.native_handle())); + static_assert(noexcept(std::as_const(f).native_handle())); } int main(int, char**) { diff --git a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h index fd6d732638ad32..e32c8fb5fc9de3 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h +++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h @@ -12,9 +12,11 @@ #if _LIBCPP_STD_VER >= 26 # include <cassert> +# include <concepts> # include <cstdio> # include <fstream> # include <filesystem> +# include <type_traits> # include <utility> # if defined(_LIBCPP_WIN32API) @@ -29,12 +31,15 @@ # include "platform_support.h" # if defined(_LIBCPP_WIN32API) -bool is_handle_valid([[maybe_unused]] HANDLE handle) { - // TODO: Maybe test HANDLE with GetFileInformationByHandle?? +bool is_handle_valid([[void* handle) { + if (LPBY_HANDLE_FILE_INFORMATION & pFileInformation; !GetFileInformationByHandle(handle, &lpFileInformation)) + return false; return true; }; -# else // POSIX +# elif __has_include(<unistd.h>) // POSIX bool is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; +# else +# error "Provide a native file handle!" # endif template <typename CharT, typename StreamT> @@ -43,15 +48,25 @@ void test_native_handle() { std::is_same_v<typename std::basic_filebuf<CharT>::native_handle_type, typename StreamT::native_handle_type>); StreamT f; - static_assert(noexcept(f.native_handle())); + assert(!f.is_open()); std::filesystem::path p = get_temp_file_name(); f.open(p); assert(f.is_open()); assert(f.native_handle() == f.rdbuf()->native_handle()); - assert(is_handle_valid(f.native_handle())); - assert(is_handle_valid(std::as_const(f).native_handle())); +# if defined(_LIBCPP_WIN32API) + using HandleT = void*; +# elif __has_include(<unistd.h>) // POSIX + using HandleT = int; +# else +# error "Provide a native file handle!" +# endif + std::same_as<HandleT> decltype(auto) handle = f.native_handle(); + assert(is_handle_valid(handle)); + std::same_as<HandleT> decltype(auto) const_handle = std::as_const(f).native_handle(); + assert(is_handle_valid(const_handle)); static_assert(noexcept(f.native_handle())); + static_assert(noexcept(std::as_const(f).native_handle())); } #endif // _LIBCPP_STD_VER >= 26 >From f730cf84c1faa9ab05848776351813a3f4000d85 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Mon, 1 Jan 2024 09:56:05 +0200 Subject: [PATCH 8/8] Minor tweak --- .../filebuf.members/native_handle.pass.cpp | 7 ------- .../file.streams/fstreams/test_helpers.h | 15 ++++++--------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp index c87bda5382c85e..abcaf489e68019 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp +++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp @@ -30,13 +30,6 @@ void test() { std::filesystem::path p = get_temp_file_name(); f.open(p, std::ios_base::in); assert(f.is_open()); -#if defined(_LIBCPP_WIN32API) - using HandleT = void*; -#elif __has_include(<unistd.h>) // POSIX - using HandleT = int; -#else -# error "Provide a native file handle!" -#endif std::same_as<HandleT> decltype(auto) handle = f.native_handle(); assert(is_handle_valid(handle)); std::same_as<HandleT> decltype(auto) const_handle = std::as_const(f).native_handle(); diff --git a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h index e32c8fb5fc9de3..65ec8bded2d7e5 100644 --- a/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h +++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h @@ -31,13 +31,17 @@ # include "platform_support.h" # if defined(_LIBCPP_WIN32API) -bool is_handle_valid([[void* handle) { +using HandleT = void*; + +bool is_handle_valid([[HandleT handle) { if (LPBY_HANDLE_FILE_INFORMATION & pFileInformation; !GetFileInformationByHandle(handle, &lpFileInformation)) return false; return true; }; # elif __has_include(<unistd.h>) // POSIX -bool is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; +using HandleT = int; + +bool is_handle_valid(HandleT fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; }; # else # error "Provide a native file handle!" # endif @@ -54,13 +58,6 @@ void test_native_handle() { f.open(p); assert(f.is_open()); assert(f.native_handle() == f.rdbuf()->native_handle()); -# if defined(_LIBCPP_WIN32API) - using HandleT = void*; -# elif __has_include(<unistd.h>) // POSIX - using HandleT = int; -# else -# error "Provide a native file handle!" -# endif std::same_as<HandleT> decltype(auto) handle = f.native_handle(); assert(is_handle_valid(handle)); std::same_as<HandleT> decltype(auto) const_handle = std::as_const(f).native_handle(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits