Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][streams] P1759R6: Native handles and file streams #76632

Conversation

@H-G-Hristov
Copy link
Contributor Author

H-G-Hristov commented Dec 31, 2023

@mordante I decided to do this quickly and I post it to discuss and ask questions. Please excuse my incompetence!

  1. I implemented test but I am not sure these are enough but I don't have idea how to test the native handle better especially on non-POSIX (Windows).
  2. I added a native_handle implementation function to a file fstream.cpp similar to what's done in print.cpp. The macro # if _LIBCPP_STD_VER >= 26 doesn't seem to be defined in C++26 mode and in general I have trouble exporting the mangled symbol and getting the tests to link. Please advise.

NB: The submitted WIP version seems to work OK locally.

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/P1759R6-Native-handles-and-file-streams branch from 5c6bb71 to 37a871a Compare December 31, 2023 09:26
libcxx/include/fstream Outdated Show resolved Hide resolved
Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mainly looked at the issues for the CI. I have not closely looked at the test. I prefer to look at them when I do a review. (I have not looked at the paper either.)

libcxx/include/fstream Outdated Show resolved Hide resolved
libcxx/include/fstream Outdated Show resolved Hide resolved
libcxx/include/fstream Outdated Show resolved Hide resolved
libcxx/src/fstream.cpp Outdated Show resolved Hide resolved
@mordante mordante self-assigned this Dec 31, 2023
Copy link

github-actions bot commented Dec 31, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

libcxx/include/fstream Outdated Show resolved Hide resolved
Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates! Some more comments. I did a quick scan over the paper, but not a full review, still the patch seems to be getting close for a proper review.

When you feel it's ready for a final review, please remove the draft status.

libcxx/include/fstream Outdated Show resolved Hide resolved
libcxx/src/fstream.cpp Outdated Show resolved Hide resolved
@Zingam Zingam added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 31, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 31, 2023

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

Changes

Implements: P1759R6 https://wg21.link/P1759R6


Patch is 22.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/76632.diff

15 Files Affected:

  • (modified) libcxx/docs/FeatureTestMacroTable.rst (+1-1)
  • (modified) libcxx/docs/ReleaseNotes/18.rst (+1)
  • (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1)
  • (modified) libcxx/include/fstream (+60)
  • (modified) libcxx/include/version (+1-1)
  • (modified) libcxx/src/CMakeLists.txt (+1)
  • (added) libcxx/src/fstream.cpp (+33)
  • (added) libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp (+45)
  • (added) libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp (+27)
  • (added) libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp (+27)
  • (added) libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp (+27)
  • (added) libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h (+60)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/fstream.version.compile.pass.cpp (+5-11)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+5-11)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (-1)
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..ab854cf534e7fb 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);
@@ -208,8 +215,34 @@ _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);
+#    endif
+}
+#  endif
+
 template <class _CharT, class _Traits>
 class _LIBCPP_TEMPLATE_VIS basic_filebuf : public basic_streambuf<_CharT, _Traits> {
 public:
@@ -219,6 +252,9 @@ 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
+  using native_handle_type = __filebuf_native_handle_type;
+#  endif
 
   // 27.9.1.2 Constructors/destructor:
   basic_filebuf();
@@ -245,6 +281,12 @@ 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() const noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(this->is_open(), "File must be opened");
+    return std::__filebuf_native_handle(__file_);
+  }
+#  endif
 
   _LIBCPP_HIDE_FROM_ABI inline static const char* __make_mdstring(ios_base::openmode __mode) _NOEXCEPT;
 
@@ -1024,6 +1066,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 +1086,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
@@ -1171,6 +1219,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 +1241,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
@@ -1321,6 +1375,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 +1402,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
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..814d912e7d22b3
--- /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 <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
+#  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<__filebuf_native_handle_type>(__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
new file mode 100644
index 00000000000000..790cc91effc822
--- /dev/null
+++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+#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..900475069a1c9b
--- /dev/null
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "test_macros.h"
+#include "../test_helpers.h"
+
+int main(int, char**) {
+  test_native_handle<char, std::basic_fstream<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  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
new file mode 100644
index 00000000000000..95a95cb69560b7
--- /dev/null
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "test_macros.h"
+#include "../test_helpers.h"
+
+int main(int, char**) {
+  test_native_handle<char, std::basic_ifstream<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  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
new file mode 100644
index 00000000000000..45f0841dad18cb
--- /dev/null
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "test_macros.h"
+#include "../test_helpers.h"
+
+int main(int, char**) {
+  test_native_handle<char, std::basic_ofstream<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  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
new file mode 100644
index 00000000000000..a3069549315611
--- /dev/null
+++ b/libcxx/test/std/input.output/file.streams/fstreams/test_helpers.h
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+#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: Maybe test HANDLE with GetFileInformationByHandle??
+  return true;
+};
+#  else
+// POSIX
+auto is_handle_valid(int fd) { return fcntl(fd, F_GETFL) != -1 || errno != EBADF; };
+#  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
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 "...
[truncated]

@H-G-Hristov H-G-Hristov marked this pull request as ready for review January 1, 2024 15:49
@H-G-Hristov H-G-Hristov requested a review from a team as a code owner January 1, 2024 15:49
Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks LGTM!

@Zingam
Copy link
Contributor

Zingam commented Jan 4, 2024

Thanks LGTM!

Thank you very much for the review!

@Zingam Zingam merged commit 255f95a into llvm:main Jan 5, 2024
46 checks passed
@zeroomega
Copy link
Contributor

Hi, this change breaks libcxx test on Windows due to unable to find "unistd.h" file (which doesn't exist on msvc based environment).

Failed test message and failed commandline:

********************
Failed Tests (8):
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/filebuf/types.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/fstream/types.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ifstream/types.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ofstream/types.pass.cpp
Exit Code: 1

Command Output (stdout):
--
# COMPILED WITH
C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\native_handle.pass.cpp --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/llvm-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings  -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\std\input.output\file.streams\fstreams\filebuf.members\Output\native_handle.pass.cpp.dir\t.tmp.exe
# executed command: C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe 'C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\native_handle.pass.cpp' --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/llvm-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o 'C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\std\input.output\file.streams\fstreams\filebuf.members\Output\native_handle.pass.cpp.dir\t.tmp.exe'
# .---command stderr------------
# | In file included from C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\native_handle.pass.cpp:24:
# | In file included from C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\../native_handle_test_helpers.h:33:
# | C:/b/s/w/ir/x/w/llvm-llvm-project/libcxx/test/support\check_assertion.h:22:10: fatal error: 'unistd.h' file not found
# |    22 | #include <unistd.h>
# |       |          ^~~~~~~~~~
# | 1 error generated.
# `-----------------------------
# error: command failed with exit status: 1

--

Failed build task: https://ci.chromium.org/ui/p/fuchsia/builders/toolchain.ci/clang-windows-x64/b8759750519305630833/overview

Could you revert your change and reland it after fixing it please?
C.C. @petrhosek

zeroomega added a commit that referenced this pull request Jan 6, 2024
…76632)"

This reverts commit 255f95a, which
contains a breaking libcxx test on Windows when using C++26
@Zingam
Copy link
Contributor

Zingam commented Jan 6, 2024

Hi, this change breaks libcxx test on Windows due to unable to find "unistd.h" file (which doesn't exist on msvc based environment).

Failed test message and failed commandline:

********************
Failed Tests (8):
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/filebuf.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/filebuf/types.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/fstream.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/fstream/types.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ifstream.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ifstream/types.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ofstream.members/native_handle.pass.cpp
  llvm-libc++-static-clangcl.cfg.in :: std/input.output/file.streams/fstreams/ofstream/types.pass.cpp
Exit Code: 1

Command Output (stdout):
--
# COMPILED WITH
C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\native_handle.pass.cpp --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/llvm-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings  -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\std\input.output\file.streams\fstreams\filebuf.members\Output\native_handle.pass.cpp.dir\t.tmp.exe
# executed command: C:/b/s/w/ir/x/w/llvm_build/./bin/clang-cl.exe 'C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\native_handle.pass.cpp' --driver-mode=g++ --target=x86_64-pc-windows-msvc -fms-runtime-lib=static -nostdinc++ -I C:/b/s/w/ir/x/w/llvm_build/include/c++/v1 -I C:/b/s/w/ir/x/w/llvm_build/include/x86_64-pc-windows-msvc/c++/v1 -I C:/b/s/w/ir/x/w/llvm-llvm-project/libcxx/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -std=c++26 -Werror -Wall -Wctad-maybe-unsupported -Wextra -Wshadow -Wundef -Wunused-template -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move -Wno-noexcept-type -Wno-atomic-alignment -Wno-reserved-module-identifier -Wdeprecated-copy -Wdeprecated-copy-dtor -Wno-user-defined-literals -Wno-tautological-compare -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef -Wno-local-type-template-args -Wno-c++11-extensions -Wno-unknown-pragmas -Wno-pass-failed -Wno-mismatched-new-delete -Wno-redundant-move -Wno-self-move -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D_LIBCPP_ENABLE_EXPERIMENTAL -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE -Werror=thread-safety -Wuser-defined-warnings -llibc++experimental -nostdlib -L C:/b/s/w/ir/x/w/llvm_build/./lib/x86_64-pc-windows-msvc -llibc++ -llibcpmt -o 'C:\b\s\w\ir\x\w\llvm_build\runtimes\runtimes-x86_64-pc-windows-msvc-bins\test\std\input.output\file.streams\fstreams\filebuf.members\Output\native_handle.pass.cpp.dir\t.tmp.exe'
# .---command stderr------------
# | In file included from C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\native_handle.pass.cpp:24:
# | In file included from C:\b\s\w\ir\x\w\llvm-llvm-project\libcxx\test\std\input.output\file.streams\fstreams\filebuf.members\../native_handle_test_helpers.h:33:
# | C:/b/s/w/ir/x/w/llvm-llvm-project/libcxx/test/support\check_assertion.h:22:10: fatal error: 'unistd.h' file not found
# |    22 | #include <unistd.h>
# |       |          ^~~~~~~~~~
# | 1 error generated.
# `-----------------------------
# error: command failed with exit status: 1

--

Failed build task: https://ci.chromium.org/ui/p/fuchsia/builders/toolchain.ci/clang-windows-x64/b8759750519305630833/overview

Could you revert your change and reland it after fixing it please? C.C. @petrhosek

Thank you for reacting and providing that info! Sorry for the inconvenience!

Do yo use trunk build or the latest stable (e.g. 17)?
Are you running these tests automatically after landing a patch here? How can I verify on my own if there are any issues in chromium?

H-G-Hristov pushed a commit to H-G-Hristov/llvm-project that referenced this pull request Jan 6, 2024
Zingam added a commit that referenced this pull request Jan 7, 2024
…77190)

Fixes build on Windows in C++26 mode.

Reverted in:
40c07b5
Original PR: #76632

---------

Co-authored-by: Zingam <zingam@outlook.com>
@H-G-Hristov H-G-Hristov deleted the hgh/libcxx/P1759R6-Native-handles-and-file-streams branch January 9, 2024 07:56
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
…lvm#76632)"

This reverts commit 255f95a, which
contains a breaking libcxx test on Windows when using C++26
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
…lvm#77190)

Fixes build on Windows in C++26 mode.

Reverted in:
llvm@40c07b5
Original PR: llvm#76632

---------

Co-authored-by: Zingam <zingam@outlook.com>
blueboxd pushed a commit to blueboxd/libcxx that referenced this pull request Feb 1, 2024
…(#77190)

Fixes build on Windows in C++26 mode.

Reverted in:
llvm/llvm-project@40c07b5
Original PR: llvm/llvm-project#76632

---------

Co-authored-by: Zingam <zingam@outlook.com>
NOKEYCHECK=True
GitOrigin-RevId: 92e243173c09fc78c25814a7d7e392971034f5be
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants