diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -321,6 +321,15 @@ # define _LIBCPP_SHORT_WCHAR 1 # endif +# if _LIBCPP_ABI_VERSION < 2 +# if defined(_AIX) || (defined(__MVS__) && defined(__64BIT__)) +# define _LIBCPP_BASIC_IOS_HAS_FILL_SET 1 +# elif defined(_WIN32) || defined(__sun__) || || defined(__APPLE__) || defined(__linux__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) +# define _LIBCPP_BASIC_IOS_HAS_FILL_SET 0 +# endif +# endif + // Libc++ supports various implementations of std::random_device. // // _LIBCPP_USING_DEV_RANDOM diff --git a/libcxx/include/ios b/libcxx/include/ios --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -686,7 +686,15 @@ void set_rdbuf(basic_streambuf* __sb); private: basic_ostream* __tie_; + +#if defined(_LIBCPP_BASIC_IOS_HAS_FILL_SET) + static const bool __has_fill_set = _LIBCPP_BASIC_IOS_HAS_FILL_SET; +#else + static const bool __has_fill_set = sizeof(char_type) >= sizeof(int_type); +#endif + mutable int_type __fill_; + mutable bool __fill_set_[__has_fill_set]; }; template @@ -708,7 +716,14 @@ { ios_base::init(__sb); __tie_ = nullptr; - __fill_ = traits_type::eof(); + if (__has_fill_set) + { + __fill_set_[0] = false; + } + else + { + __fill_ = traits_type::eof(); + } } template @@ -780,8 +795,18 @@ _CharT basic_ios<_CharT, _Traits>::fill() const { - if (traits_type::eq_int_type(traits_type::eof(), __fill_)) + if (__has_fill_set) + { + if (!__fill_set_[0]) + { + __fill_ = widen(' '); + __fill_set_[0] = true; + } + } + else if (traits_type::eq_int_type(traits_type::eof(), __fill_)) + { __fill_ = widen(' '); + } return __fill_; } @@ -790,9 +815,7 @@ _CharT basic_ios<_CharT, _Traits>::fill(char_type __ch) { - if (traits_type::eq_int_type(traits_type::eof(), __fill_)) - __fill_ = widen(' '); - char_type __r = __fill_; + char_type __r = fill(); __fill_ = __ch; return __r; } @@ -807,6 +830,10 @@ ios_base::copyfmt(__rhs); __tie_ = __rhs.__tie_; __fill_ = __rhs.__fill_; + if (__has_fill_set) + { + __fill_set_[0] = __rhs.__fill_set_[0]; + } __call_callbacks(copyfmt_event); exceptions(__rhs.exceptions()); } @@ -822,6 +849,10 @@ __tie_ = __rhs.__tie_; __rhs.__tie_ = nullptr; __fill_ = __rhs.__fill_; + if (__has_fill_set) + { + __fill_set_[0] = __rhs.__fill_set_[0]; + } } template @@ -832,6 +863,10 @@ ios_base::swap(__rhs); _VSTD::swap(__tie_, __rhs.__tie_); _VSTD::swap(__fill_, __rhs.__fill_); + if (__has_fill_set) + { + _VSTD::swap(__fill_set_[0], __rhs.__fill_set_[0]); + } } template diff --git a/libcxx/test/std/input.output/iostream.format/std.manip/setfill_eof.pass.cpp b/libcxx/test/std/input.output/iostream.format/std.manip/setfill_eof.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/std.manip/setfill_eof.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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: no-wide-characters + +// XFAIL: stdlib=libc++ && target=aarch64-linux-gnu +// XFAIL: stdlib=libc++ && target=armv7l-linux-gnueabihf +// XFAIL: stdlib=libc++ && target=armv8l-linux-gnueabihf +// XFAIL: stdlib=libc++ && target=x86_64-pc-windows-msvc +// XFAIL: stdlib=libc++ && target=x86_64-w64-windows-gnu + +// + +// template unspecified setfill(charT c); + +#include +#include +#include +#include + +#include "test_macros.h" + +template +struct testbuf : public std::basic_streambuf { + testbuf() {} +}; + +int main(int, char**) { + testbuf sb; + std::wostream os(&sb); + os << std::setfill((wchar_t)std::char_traits::eof()); + assert(os.fill() == (wchar_t)std::char_traits::eof()); + + return 0; +}