diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -334,6 +334,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(__APPLE__) || defined(__sun__) || defined(__linux__) || defined(__FreeBSD__) || \ + defined(__NetBSD__) || defined(__OpenBSD__) +# 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,11 @@ { 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,9 +792,15 @@ _CharT basic_ios<_CharT, _Traits>::fill() const { - if (traits_type::eq_int_type(traits_type::eof(), __fill_)) - __fill_ = widen(' '); - return __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_; } template @@ -790,11 +808,9 @@ _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_; - __fill_ = __ch; - return __r; + char_type __r = fill(); + __fill_ = __ch; + return __r; } template @@ -807,6 +823,9 @@ 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 +841,9 @@ __tie_ = __rhs.__tie_; __rhs.__tie_ = nullptr; __fill_ = __rhs.__fill_; + if (__has_fill_set) { + __fill_set_[0] = __rhs.__fill_set_[0]; + } } template @@ -832,6 +854,9 @@ 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,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Test that weof as a wchar_t value can be set as the fill character. + +// UNSUPPORTED: no-wide-characters +// REQUIRES: target=powerpc{{(64)?}}-ibm-aix || target=s390x-ibm-zos + +// + +// 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; +}