[libcxx-commits] [libcxx] af8c49d - [libc++] Introduce a setting to remove fstream from the library

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Sun Nov 20 07:51:46 PST 2022


Author: Louis Dionne
Date: 2022-11-20T10:51:32-05:00
New Revision: af8c49dc1ec44339d915d988ffe0f38da68ca0e7

URL: https://github.com/llvm/llvm-project/commit/af8c49dc1ec44339d915d988ffe0f38da68ca0e7
DIFF: https://github.com/llvm/llvm-project/commit/af8c49dc1ec44339d915d988ffe0f38da68ca0e7.diff

LOG: [libc++] Introduce a setting to remove fstream from the library

This allows porting the library to platforms that are able to support
<iostream> but that do not have a notion of a filesystem, and where it
hence doesn't make sense to support std::fstream (and never will).

Also, remove reliance on <fstream> in various tests that didn't
actually need it.

Differential Revision: https://reviews.llvm.org/D138327

Added: 
    libcxx/cmake/caches/Generic-no-fstream.cmake

Modified: 
    libcxx/CMakeLists.txt
    libcxx/include/CMakeLists.txt
    libcxx/include/__config_site.in
    libcxx/include/fstream
    libcxx/include/module.modulemap.in
    libcxx/src/ios.instantiations.cpp
    libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
    libcxx/test/libcxx/clang_tidy.sh.cpp
    libcxx/test/libcxx/double_include.sh.cpp
    libcxx/test/libcxx/min_max_macros.compile.pass.cpp
    libcxx/test/libcxx/modules_include.sh.cpp
    libcxx/test/libcxx/nasty_macros.compile.pass.cpp
    libcxx/test/libcxx/no_assert_include.compile.pass.cpp
    libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/seekoff.pass.cpp
    libcxx/test/std/input.output/file.streams/lit.local.cfg
    libcxx/test/std/input.output/stream.buffers/streambuf/streambuf.virtuals/streambuf.virt.put/xsputn.PR14074.pass.cpp
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp
    libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp
    libcxx/test/support/test_macros.h
    libcxx/utils/ci/buildkite-pipeline.yml
    libcxx/utils/ci/run-buildbot
    libcxx/utils/generate_header_tests.py
    libcxx/utils/libcxx/test/features.py

Removed: 
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat
    libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat


################################################################################
diff  --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index f08ca950735f3..ba1651265ccf7 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -84,6 +84,8 @@ option(LIBCXX_ENABLE_LOCALIZATION
    the C locale API (e.g. embedded). When localization is not supported,
    several parts of the library will be disabled: <iostream>, <regex>, <locale>
    will be completely unusable, and other parts may be only partly available." ON)
+option(LIBCXX_ENABLE_FSTREAM
+   "Whether to include support for <fstream>." ON) # TODO: Consider rolling that into LIBCXX_ENABLE_FILESYSTEM
 option(LIBCXX_ENABLE_UNICODE
   "Whether to include support for Unicode in the library. Disabling Unicode can
    be useful when porting to platforms that don't support UTF-8 encoding (e.g.
@@ -860,6 +862,7 @@ config_define_if(LIBCXX_ENABLE_PARALLEL_ALGORITHMS _LIBCPP_HAS_PARALLEL_ALGORITH
 config_define_if_not(LIBCXX_ENABLE_FILESYSTEM _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
 config_define_if_not(LIBCXX_ENABLE_RANDOM_DEVICE _LIBCPP_HAS_NO_RANDOM_DEVICE)
 config_define_if_not(LIBCXX_ENABLE_LOCALIZATION _LIBCPP_HAS_NO_LOCALIZATION)
+config_define_if_not(LIBCXX_ENABLE_FSTREAM _LIBCPP_HAS_NO_FSTREAM)
 config_define_if_not(LIBCXX_ENABLE_UNICODE _LIBCPP_HAS_NO_UNICODE)
 config_define_if_not(LIBCXX_ENABLE_WIDE_CHARACTERS _LIBCPP_HAS_NO_WIDE_CHARACTERS)
 config_define_if_not(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS)

diff  --git a/libcxx/cmake/caches/Generic-no-fstream.cmake b/libcxx/cmake/caches/Generic-no-fstream.cmake
new file mode 100644
index 0000000000000..000d300fe763c
--- /dev/null
+++ b/libcxx/cmake/caches/Generic-no-fstream.cmake
@@ -0,0 +1 @@
+set(LIBCXX_ENABLE_FSTREAM OFF CACHE BOOL "")

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 4310cfdc50308..d7bf369d7da5c 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -838,7 +838,7 @@ set(files
   wctype.h
   )
 
-foreach(feature LIBCXX_ENABLE_FILESYSTEM LIBCXX_ENABLE_LOCALIZATION LIBCXX_ENABLE_THREADS LIBCXX_ENABLE_WIDE_CHARACTERS)
+foreach(feature LIBCXX_ENABLE_FILESYSTEM LIBCXX_ENABLE_LOCALIZATION LIBCXX_ENABLE_FSTREAM LIBCXX_ENABLE_THREADS LIBCXX_ENABLE_WIDE_CHARACTERS)
   if (NOT ${${feature}})
     set(requires_${feature} "requires LIBCXX_CONFIGURED_WITHOUT_SUPPORT_FOR_THIS_HEADER")
   endif()

diff  --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in
index 7c11fae986192..2ff67254c3445 100644
--- a/libcxx/include/__config_site.in
+++ b/libcxx/include/__config_site.in
@@ -28,6 +28,7 @@
 #cmakedefine _LIBCPP_HAS_PARALLEL_ALGORITHMS
 #cmakedefine _LIBCPP_HAS_NO_RANDOM_DEVICE
 #cmakedefine _LIBCPP_HAS_NO_LOCALIZATION
+#cmakedefine _LIBCPP_HAS_NO_FSTREAM
 #cmakedefine _LIBCPP_HAS_NO_WIDE_CHARACTERS
 #cmakedefine01 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT
 #cmakedefine _LIBCPP_ENABLE_DEBUG_MODE

diff  --git a/libcxx/include/fstream b/libcxx/include/fstream
index 6b6e5b603c2e7..b8417f3e6c02d 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -210,6 +210,8 @@ _LIBCPP_PUSH_MACROS
 #  define _LIBCPP_HAS_NO_OFF_T_FUNCTIONS
 #endif
 
+#if !defined(_LIBCPP_HAS_NO_FSTREAM)
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _CharT, class _Traits>
@@ -1742,6 +1744,8 @@ extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_filebuf<char>;
 
 _LIBCPP_END_NAMESPACE_STD
 
+#endif // _LIBCPP_HAS_NO_FSTREAM
+
 _LIBCPP_POP_MACROS
 
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20

diff  --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 120cf1916e8cd..5f07d9df0a59b 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -855,6 +855,7 @@ module std [system] {
   }
   module fstream {
     @requires_LIBCXX_ENABLE_LOCALIZATION@
+    @requires_LIBCXX_ENABLE_FSTREAM@
     header "fstream"
     export *
   }

diff  --git a/libcxx/src/ios.instantiations.cpp b/libcxx/src/ios.instantiations.cpp
index 2ff7057fa66a4..ca77ce11fd205 100644
--- a/libcxx/src/ios.instantiations.cpp
+++ b/libcxx/src/ios.instantiations.cpp
@@ -36,9 +36,12 @@ template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringbuf<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostringstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istringstream<char>;
+
+#ifndef _LIBCPP_HAS_NO_FSTREAM
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ifstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ofstream<char>;
 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_filebuf<char>;
+#endif
 
 // Add more here if needed...
 

diff  --git a/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
index 481b7ac8262a3..c3179c26e50db 100644
--- a/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
+++ b/libcxx/test/libcxx/assertions/headers_declare_verbose_abort.sh.cpp
@@ -325,7 +325,7 @@ int main(int, char**) { return 0; }
 #endif
 
 // RUN: %{build} -DTEST_51
-#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #   include <fstream>
     using HandlerType = decltype(std::__libcpp_verbose_abort);
 #endif

diff  --git a/libcxx/test/libcxx/clang_tidy.sh.cpp b/libcxx/test/libcxx/clang_tidy.sh.cpp
index 9c2ad8a4f47d1..a3dcc57567b06 100644
--- a/libcxx/test/libcxx/clang_tidy.sh.cpp
+++ b/libcxx/test/libcxx/clang_tidy.sh.cpp
@@ -98,7 +98,7 @@ END-SCRIPT
 #include <float.h>
 #include <format>
 #include <forward_list>
-#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #   include <fstream>
 #endif
 #include <functional>

diff  --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp
index bcc808100a2e1..4a55dcaeb777a 100644
--- a/libcxx/test/libcxx/double_include.sh.cpp
+++ b/libcxx/test/libcxx/double_include.sh.cpp
@@ -100,7 +100,7 @@ END-SCRIPT
 #include <float.h>
 #include <format>
 #include <forward_list>
-#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #   include <fstream>
 #endif
 #include <functional>

diff  --git a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp
index 90bda8634d2d3..a21524bb133a2 100644
--- a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp
+++ b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp
@@ -151,7 +151,7 @@ TEST_MACROS();
 TEST_MACROS();
 #include <forward_list>
 TEST_MACROS();
-#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #   include <fstream>
 TEST_MACROS();
 #endif

diff  --git a/libcxx/test/libcxx/modules_include.sh.cpp b/libcxx/test/libcxx/modules_include.sh.cpp
index 569d582513f7d..91e99d617369e 100644
--- a/libcxx/test/libcxx/modules_include.sh.cpp
+++ b/libcxx/test/libcxx/modules_include.sh.cpp
@@ -251,7 +251,7 @@ END-SCRIPT
 #include <forward_list>
 #endif
 // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_51
-#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #include <fstream>
 #endif
 // RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_52

diff  --git a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp
index 9843b87ad2906..43845ea042b43 100644
--- a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp
+++ b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp
@@ -219,7 +219,7 @@ END-SCRIPT
 #include <float.h>
 #include <format>
 #include <forward_list>
-#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #   include <fstream>
 #endif
 #include <functional>

diff  --git a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp
index 5e37fa2488341..68e303bfbaa08 100644
--- a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp
+++ b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp
@@ -97,7 +97,7 @@ END-SCRIPT
 #include <float.h>
 #include <format>
 #include <forward_list>
-#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
 #   include <fstream>
 #endif
 #include <functional>

diff  --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/seekoff.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/seekoff.pass.cpp
index 475974e3acd39..8008901802e91 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/seekoff.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/seekoff.pass.cpp
@@ -13,8 +13,6 @@
 // pos_type seekpos(pos_type sp,
 //                  ios_base::openmode which = ios_base::in | ios_base::out);
 
-// FILE_DEPENDENCIES: underflow.dat
-
 #include <fstream>
 #include <cassert>
 

diff  --git a/libcxx/test/std/input.output/file.streams/lit.local.cfg b/libcxx/test/std/input.output/file.streams/lit.local.cfg
index 781b508d3e6e8..c62247c9a0e45 100644
--- a/libcxx/test/std/input.output/file.streams/lit.local.cfg
+++ b/libcxx/test/std/input.output/file.streams/lit.local.cfg
@@ -1,3 +1,6 @@
 # All non-trivial uses of iostreams require localization support
 if 'no-localization' in config.available_features:
   config.unsupported = True
+
+if 'no-fstream' in config.available_features:
+  config.unsupported = True

diff  --git a/libcxx/test/std/input.output/stream.buffers/streambuf/streambuf.virtuals/streambuf.virt.put/xsputn.PR14074.pass.cpp b/libcxx/test/std/input.output/stream.buffers/streambuf/streambuf.virtuals/streambuf.virt.put/xsputn.PR14074.pass.cpp
index 86f9c15bb6ba7..84c7263b7b412 100644
--- a/libcxx/test/std/input.output/stream.buffers/streambuf/streambuf.virtuals/streambuf.virt.put/xsputn.PR14074.pass.cpp
+++ b/libcxx/test/std/input.output/stream.buffers/streambuf/streambuf.virtuals/streambuf.virt.put/xsputn.PR14074.pass.cpp
@@ -17,6 +17,8 @@
 // basic_streambuf, but I can't seem to reproduce without going through one
 // of its derived classes.
 
+// UNSUPPORTED: no-fstream
+
 #include <cassert>
 #include <cstddef>
 #include <cstdio>

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp
index a971f0f752719..e0333042e8497 100644
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/overflow.pass.cpp
@@ -19,9 +19,10 @@
 // XFAIL: no-wide-characters
 
 #include <locale>
+#include <cassert>
 #include <codecvt>
 #include <fstream>
-#include <cassert>
+#include <sstream>
 
 #include "test_macros.h"
 
@@ -46,62 +47,73 @@ struct test_buf
 int main(int, char**)
 {
     {
-        std::ofstream bs("overflow.dat");
-        test_buf f(bs.rdbuf());
-        assert(f.pbase() == 0);
-        assert(f.pptr() == 0);
-        assert(f.epptr() == 0);
-        assert(f.overflow(L'a') == L'a');
-        assert(f.pbase() != 0);
-        assert(f.pptr() == f.pbase());
-        assert(f.epptr() - f.pbase() == 4095);
-    }
-    {
-        std::ifstream bs("overflow.dat");
-        test_buf f(bs.rdbuf());
-        assert(f.sgetc() == L'a');
-    }
-    std::remove("overflow.dat");
-    {
-        std::ofstream bs("overflow.dat");
-        test_buf f(bs.rdbuf());
-        f.pubsetbuf(0, 0);
-        assert(f.pbase() == 0);
-        assert(f.pptr() == 0);
-        assert(f.epptr() == 0);
-        assert(f.overflow('a') == 'a');
-        assert(f.pbase() == 0);
-        assert(f.pptr() == 0);
-        assert(f.epptr() == 0);
-    }
-    {
-        std::ifstream bs("overflow.dat");
-        test_buf f(bs.rdbuf());
-        assert(f.sgetc() == L'a');
+        std::string s;
+        {
+            std::ostringstream out;
+            test_buf f(out.rdbuf());
+            assert(f.pbase() == 0);
+            assert(f.pptr() == 0);
+            assert(f.epptr() == 0);
+            assert(f.overflow(L'a') == L'a');
+            assert(f.pbase() != 0);
+            assert(f.pptr() == f.pbase());
+            assert(f.epptr() - f.pbase() == 4095);
+            s = out.str();
+        }
+        {
+            std::istringstream in(s);
+            test_buf f(in.rdbuf());
+            assert(f.sgetc() == L'a');
+        }
     }
-    std::remove("overflow.dat");
     {
-        std::ofstream bs("overflow.dat");
-        test_buf f(bs.rdbuf());
-        assert(f.sputc(0x4E51) == 0x4E51);
-        assert(f.sputc(0x4E52) == 0x4E52);
-        assert(f.sputc(0x4E53) == 0x4E53);
+        std::string s;
+        {
+            std::ostringstream out;
+            test_buf f(out.rdbuf());
+            f.pubsetbuf(0, 0);
+            assert(f.pbase() == 0);
+            assert(f.pptr() == 0);
+            assert(f.epptr() == 0);
+            assert(f.overflow('a') == 'a');
+            assert(f.pbase() == 0);
+            assert(f.pptr() == 0);
+            assert(f.epptr() == 0);
+            s = out.str();
+        }
+        {
+            std::istringstream in(s);
+            test_buf f(in.rdbuf());
+            assert(f.sgetc() == L'a');
+        }
     }
+    // TODO: Move this to std::stringstream once https://llvm.org/PR59083 has been resolved
+#ifndef TEST_HAS_NO_FSTREAM
     {
-        std::ifstream f("overflow.dat");
-        assert(f.is_open());
-        assert(f.get() == 0xE4);
-        assert(f.get() == 0xB9);
-        assert(f.get() == 0x91);
-        assert(f.get() == 0xE4);
-        assert(f.get() == 0xB9);
-        assert(f.get() == 0x92);
-        assert(f.get() == 0xE4);
-        assert(f.get() == 0xB9);
-        assert(f.get() == 0x93);
-        assert(f.get() == -1);
+        {
+            std::ofstream bs("overflow.dat");
+            test_buf f(bs.rdbuf());
+            assert(f.sputc(0x4E51) == 0x4E51);
+            assert(f.sputc(0x4E52) == 0x4E52);
+            assert(f.sputc(0x4E53) == 0x4E53);
+        }
+        {
+            std::ifstream f("overflow.dat");
+            assert(f.is_open());
+            assert(f.get() == 0xE4);
+            assert(f.get() == 0xB9);
+            assert(f.get() == 0x91);
+            assert(f.get() == 0xE4);
+            assert(f.get() == 0xB9);
+            assert(f.get() == 0x92);
+            assert(f.get() == 0xE4);
+            assert(f.get() == 0xB9);
+            assert(f.get() == 0x93);
+            assert(f.get() == -1);
+        }
+        std::remove("overflow.dat");
     }
-    std::remove("overflow.dat");
+#endif // TEST_HAS_NO_FSTREAM
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp
index 94191a098246b..e8e4953426741 100644
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/pbackfail.pass.cpp
@@ -6,8 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// FILE_DEPENDENCIES: underflow.dat
-
 // <locale>
 
 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
@@ -21,11 +19,9 @@
 // XFAIL: no-wide-characters
 
 #include <locale>
-#include <codecvt>
-#include <fstream>
 #include <cassert>
-
-#include "test_macros.h"
+#include <codecvt>
+#include <sstream>
 
 struct test_buf
     : public std::wbuffer_convert<std::codecvt_utf8<wchar_t> >
@@ -47,16 +43,17 @@ struct test_buf
 
 int main(int, char**)
 {
+    std::string const s = "123456789";
     {
-        std::ifstream bs("underflow.dat");
-        test_buf f(bs.rdbuf());
+        std::istringstream in(s);
+        test_buf f(in.rdbuf());
         assert(f.sbumpc() == L'1');
         assert(f.sgetc() == L'2');
         assert(f.pbackfail(L'a') == test_buf::traits_type::eof());
     }
     {
-        std::fstream bs("underflow.dat");
-        test_buf f(bs.rdbuf());
+        std::istringstream in(s);
+        test_buf f(in.rdbuf());
         assert(f.sbumpc() == L'1');
         assert(f.sgetc() == L'2');
         assert(f.pbackfail(L'a') == test_buf::traits_type::eof());

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp
index 2d800b57e7b75..a6f58e996f025 100644
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/seekoff.pass.cpp
@@ -21,13 +21,14 @@
 
 // XFAIL: no-wide-characters
 
+// TODO: Avoid using <fstream> in this test.
+// XFAIL: no-fstream
+
 #include <locale>
 #include <codecvt>
 #include <fstream>
 #include <cassert>
 
-#include "test_macros.h"
-
 class test_codecvt
     : public std::codecvt<wchar_t, char, std::mbstate_t>
 {

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp
index 244670d488aa5..b37424bb5595e 100644
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/test.pass.cpp
@@ -14,30 +14,28 @@
 
 // XFAIL: no-wide-characters
 
-#include <fstream>
-#include <locale>
-#include <codecvt>
 #include <cassert>
+#include <codecvt>
+#include <locale>
+#include <sstream>
 
-#include "test_macros.h"
-
-int main(int, char**)
-{
+int main(int, char**) {
+    std::string storage;
     {
-        std::ofstream bytestream("myfile.txt");
+        std::ostringstream bytestream;
         std::wbuffer_convert<std::codecvt_utf8<wchar_t> > mybuf(bytestream.rdbuf());
         std::wostream mystr(&mybuf);
         mystr << L"Hello" << std::endl;
+        storage = bytestream.str();
     }
     {
-        std::ifstream bytestream("myfile.txt");
+        std::istringstream bytestream(storage);
         std::wbuffer_convert<std::codecvt_utf8<wchar_t> > mybuf(bytestream.rdbuf());
         std::wistream mystr(&mybuf);
         std::wstring ws;
         mystr >> ws;
         assert(ws == L"Hello");
     }
-    std::remove("myfile.txt");
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat
deleted file mode 100644
index e2e107ac61ac2..0000000000000
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.dat
+++ /dev/null
@@ -1 +0,0 @@
-123456789
\ No newline at end of file

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp
index 409a1b4639afc..32a3b18dda030 100644
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow.pass.cpp
@@ -6,8 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// FILE_DEPENDENCIES: underflow.dat, underflow_utf8.dat
-
 // <locale>
 
 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
@@ -21,9 +19,9 @@
 // XFAIL: no-wide-characters
 
 #include <locale>
-#include <codecvt>
-#include <fstream>
 #include <cassert>
+#include <codecvt>
+#include <sstream>
 
 #include "test_macros.h"
 
@@ -48,7 +46,8 @@ struct test_buf
 int main(int, char**)
 {
     {
-        std::ifstream bs("underflow.dat");
+        std::string s = "123456789";
+        std::istringstream bs(s);
         test_buf f(bs.rdbuf());
         assert(f.eback() == 0);
         assert(f.gptr() == 0);
@@ -60,7 +59,8 @@ int main(int, char**)
         assert(f.egptr() - f.eback() == 9);
     }
     {
-        std::ifstream bs("underflow.dat");
+        std::string s = "123456789";
+        std::istringstream bs(s);
         test_buf f(bs.rdbuf());
         assert(f.eback() == 0);
         assert(f.gptr() == 0);
@@ -81,7 +81,8 @@ int main(int, char**)
         assert(f.egptr() - f.gptr() == 1);
     }
     {
-        std::ifstream bs("underflow_utf8.dat");
+        std::string s = "乑乒乓";
+        std::istringstream bs(s);
         test_buf f(bs.rdbuf());
         assert(f.sbumpc() == 0x4E51);
         assert(f.sbumpc() == 0x4E52);
@@ -89,5 +90,5 @@ int main(int, char**)
         assert(f.sbumpc() == test_buf::traits_type::eof());
     }
 
-  return 0;
+    return 0;
 }

diff  --git a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat b/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat
deleted file mode 100644
index ee7063e1207c0..0000000000000
--- a/libcxx/test/std/localization/locales/locale.convenience/conversions/conversions.buffer/underflow_utf8.dat
+++ /dev/null
@@ -1 +0,0 @@
-乑乒乓
\ No newline at end of file

diff  --git a/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp b/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp
index 8652a2d10fcb8..69e11a6e60475 100644
--- a/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.msvc/test.cpp
@@ -9,7 +9,6 @@
 #include <charconv>
 #include <chrono>
 #include <cmath>
-#include <fstream>
 #include <functional>
 #include <iterator>
 #include <limits>
@@ -49,7 +48,7 @@
 
 using namespace std;
 
-void initialize_randomness(mt19937_64& mt64, const int argc, char** const argv) {
+void initialize_randomness(mt19937_64& mt64, const int argc, char** const /*argv*/) {
     constexpr size_t n = mt19937_64::state_size;
     constexpr size_t w = mt19937_64::word_size;
     static_assert(w % 32 == 0);
@@ -59,32 +58,11 @@ void initialize_randomness(mt19937_64& mt64, const int argc, char** const argv)
 
     puts("USAGE:");
     puts("test.exe              : generates seed data from random_device.");
-    puts("test.exe filename.txt : loads seed data from a given text file.");
 
     if (argc == 1) {
         random_device rd;
         generate(vec.begin(), vec.end(), ref(rd));
         puts("Generated seed data.");
-    } else if (argc == 2) {
-        const char* const filename = argv[1];
-
-        ifstream file(filename);
-
-        if (!file) {
-            printf("ERROR: Can't open %s.\n", filename);
-            abort();
-        }
-
-        for (auto& elem : vec) {
-            file >> elem;
-
-            if (!file) {
-                printf("ERROR: Can't read seed data from %s.\n", filename);
-                abort();
-            }
-        }
-
-        printf("Loaded seed data from %s.\n", filename);
     } else {
         puts("ERROR: Too many command-line arguments.");
         abort();

diff  --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 22af2592781d0..573c8d839fe5b 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -387,6 +387,10 @@ inline void DoNotOptimize(Tp const& value) {
 #  define TEST_HAS_NO_FILESYSTEM_LIBRARY
 #endif
 
+#if defined(_LIBCPP_HAS_NO_FSTREAM)
+#  define TEST_HAS_NO_FSTREAM
+#endif
+
 #if defined(_LIBCPP_HAS_NO_FGETPOS_FSETPOS)
 #  define TEST_HAS_NO_FGETPOS_FSETPOS
 #endif

diff  --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index 2c8f74f3e9b7f..6a51cddc80609 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -520,6 +520,23 @@ steps:
             limit: 2
       timeout_in_minutes: 120
 
+    - label: "No fstream"
+      command: "libcxx/utils/ci/run-buildbot generic-no-fstream"
+      artifact_paths:
+        - "**/test-results.xml"
+        - "**/*.abilist"
+      env:
+          CC: "clang-${LLVM_HEAD_VERSION}"
+          CXX: "clang++-${LLVM_HEAD_VERSION}"
+      agents:
+        queue: "libcxx-builders"
+        os: "linux"
+      retry:
+        automatic:
+          - exit_status: -1  # Agent was lost
+            limit: 2
+      timeout_in_minutes: 120
+
     - label: "No locale"
       command: "libcxx/utils/ci/run-buildbot generic-no-localization"
       artifact_paths:

diff  --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 08ab52316611c..d6a2a55c26dfe 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -196,6 +196,7 @@ check-generated-output)
            --exclude 'locale-specific_form.pass.cpp' \
            --exclude 'ostream.pass.cpp' \
            --exclude 'std_format_spec_string_unicode.bench.cpp' \
+           --exclude 'underflow.pass.cpp' \
            || false
 
     # Reject code with trailing whitespace
@@ -334,6 +335,11 @@ generic-no-random_device)
     generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-random_device.cmake"
     check-runtimes
 ;;
+generic-no-fstream)
+    clean
+    generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-fstream.cmake"
+    check-runtimes
+;;
 generic-no-localization)
     clean
     generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-localization.cmake"

diff  --git a/libcxx/utils/generate_header_tests.py b/libcxx/utils/generate_header_tests.py
index 897e0228d0673..eb602909eea9a 100755
--- a/libcxx/utils/generate_header_tests.py
+++ b/libcxx/utils/generate_header_tests.py
@@ -21,7 +21,7 @@
 
     "clocale": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
     "codecvt": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
-    "fstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
+    "fstream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)",
     "iomanip": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
     "ios": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",
     "iostream": "!defined(_LIBCPP_HAS_NO_LOCALIZATION)",

diff  --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 582d9d5ef948b..7843e5dc8a9f8 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -206,6 +206,7 @@ def _hasSuitableClangQuery(cfg):
   '_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY': 'no-filesystem',
   '_LIBCPP_HAS_NO_RANDOM_DEVICE': 'no-random-device',
   '_LIBCPP_HAS_NO_LOCALIZATION': 'no-localization',
+  '_LIBCPP_HAS_NO_FSTREAM': 'no-fstream',
   '_LIBCPP_HAS_NO_WIDE_CHARACTERS': 'no-wide-characters',
   '_LIBCPP_HAS_NO_UNICODE': 'libcpp-has-no-unicode',
   '_LIBCPP_ENABLE_DEBUG_MODE': 'libcpp-has-debug-mode',


        


More information about the libcxx-commits mailing list