[libcxx-commits] [PATCH] D124555: [libcxx][AIX][z/OS] basic_ios<wchar_t> cannot store fill character WCHAR_MAX

Louis Dionne via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jun 8 07:41:45 PDT 2022


ldionne requested changes to this revision.
ldionne added a comment.
This revision now requires changes to proceed.

In its current state, this patch would cause any new target where ` wint_t` can't represent all values of `CharType` to have the same bug. IIUC, the same is true on existing targets like x86_64 Darwin with a custom `CharType` that has the same size as `int_type` -- is that correct? If so, I think we should instead fix the problem by default, but provide an escape hatch for existing targets where this would break the ABI to opt out. For example:

  template <class _Traits>
  struct _OptionalFill {
    _OptionalFill() : __set_(false) { }
    _OptionalFill& operator=(typename _Traits::int_type __x) { __set_ = true; __fill_ = __x; return *this; }
    bool __is_set() const { return __set_; }
    typename _Traits::int_type __fill() const { return __fill_; }
  
  private:
    typename _Traits::int_type __fill_;
    bool __set_;
  };
  
  template <class _Traits>
  struct _SentinelValueFill {
    _SentinelValueFill() : __fill_(_Traits::eof()) { }
    _SentinelValueFill& operator=(typename _Traits::int_type __x) { __fill_ = __x; return *this; }
    bool __is_set() const { return __fill_ == _Traits::eof(); }
    typename _Traits::int_type __fill() const { return __fill_; }
  
  private:
    typename _Traits::int_type __fill_;
  };
  
  template <class _CharT, class _Traits>
  class basic_ios {
    // ...
  
  private:
    basic_ostream<char_type, traits_type>* __tie_;
  
  #if defined(_WIN32) || defined(whatever)
    static constexpr bool _OptOutForABICompat = true;
  #else
    static constexpr bool _OptOutForABICompat = false;
  #endif
  
    // Here, basically always use an appropriate representation for the fill, except on
    // platforms where we'd rather keep the bug in place than break the ABI.
    using _FillType = _If<sizeof(char_type) >= sizeof(typename traits_type::int_type) && !_OptOutForABICompat, _OptionalFill<_Traits>, _SentinelValueFill<_Traits> >;
    _FillType __fill_;
  };

Thoughts?

Also, please make sure to follow https://www.llvm.org/docs/Phabricator.html#requesting-a-review-via-the-command-line when uploading patches, it ensures that there's context in Phabricator, which is useful for reviewing :-)



================
Comment at: libcxx/include/ios:707
     __tie_ = nullptr;
     __fill_ = traits_type::eof();
+#if defined(_LIBCPP_BASIC_IOS_HAS_FILL_SET)
----------------
Do we need to set the `__fill_` when we use `__fill_set_`?


================
Comment at: libcxx/include/ios:782
 {
     if (traits_type::eq_int_type(traits_type::eof(), __fill_))
+    {
----------------
When we use `__fill_set_`, isn't this condition redundant?


================
Comment at: libcxx/test/std/input.output/iostream.format/std.manip/setfill_wcharmax.pass.cpp:9-12
+// 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
----------------
Do I understand correctly that all of those targets currently have a bug that one can't set a fill char to `WCHAR_MAX`, however fixing that requires breaking the ABI?


================
Comment at: libcxx/test/std/input.output/iostream.format/std.manip/setfill_wcharmax.pass.cpp:17
+
+// template<charT> T4 setfill(charT c);
+
----------------



================
Comment at: libcxx/test/std/input.output/iostream.format/std.manip/setfill_wcharmax.pass.cpp:35
+{
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+    {
----------------
Let's use `// UNSUPPORTED: no-wide-characters` instead.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124555/new/

https://reviews.llvm.org/D124555



More information about the libcxx-commits mailing list