diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -316,6 +316,13 @@ # define _LIBCPP_SHORT_WCHAR 1 # endif +#if defined(_AIX) +# define _LIBCPP_BASIC_IOS_HAS_FILL_SET 1 +#elif _WIN32 || \ + (defined(__linux__) && (defined(_M_ARM) || defined(__arm__) || defined(_M_ARM64) || defined(__aarch64__))) +# define _LIBCPP_BASIC_IOS_HAS_FILL_SET 0 +#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 @@ -15,6 +15,10 @@ #include +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include +#endif + namespace std { @@ -686,7 +690,29 @@ void set_rdbuf(basic_streambuf* __sb); private: basic_ostream* __tie_; + + template + struct _HasFillSet + { +#if _LIBCPP_BASIC_IOS_HAS_FILL_SET + static const bool value = true; +#else + static const bool value = false; +#endif + }; + +#if !defined(_LIBCPP_BASIC_IOS_HAS_FILL_SET) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) + template <> + struct _HasFillSet + { + static const bool value = + (WEOF >= (wint_t)WCHAR_MIN || WEOF <= (wint_t)WCHAR_MAX); + }; +#endif + + static const bool __has_fill_set = _HasFillSet::value; mutable int_type __fill_; + mutable bool __fill_set_[__has_fill_set]; }; template @@ -708,7 +734,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 +813,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 +833,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 +848,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 +867,10 @@ __tie_ = __rhs.__tie_; __rhs.__tie_ = nullptr; __fill_ = __rhs.__fill_; + if (__has_fill_set) + { + __fill_set_[0] = __rhs.__fill_set_[0]; + } } template @@ -832,6 +881,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_wcharmax.pass.cpp b/libcxx/test/std/input.output/iostream.format/std.manip/setfill_wcharmax.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/iostream.format/std.manip/setfill_wcharmax.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(std::numeric_limits::max()); + assert(os.fill() == std::numeric_limits::max()); + + return 0; +}