Skip to content

std::wcout fails to output wide Unicode strings even when a suitable C locale is setΒ #158430

@ckwastra

Description

@ckwastra

Test code (CE):

#include <cstdio>
#include <iostream>

namespace my {
template <class CharT>
std::basic_ios<CharT> &check_ios(std::basic_ios<CharT> &ios) {
  if (ios) {
    return ios;
  }
  auto state = ios.rdstate();
  using std::ios_base;
  std::cerr << "eofbit: " << ((state & ios_base::eofbit) != 0) << '\n';
  std::cerr << "failbit: " << ((state & ios_base::failbit) != 0) << '\n';
  std::cerr << "badbit: " << ((state & ios_base::badbit) != 0) << '\n';
  std::terminate();
}
template <auto Error> auto check(auto result) {
  if (result != Error) {
    return result;
  }
  std::terminate();
}
} // namespace my

int main() {
  constexpr auto wide_test = L"Ο€|πŸ˜€|€";
#if TEST == 1 // Test C++ locale
  std::ios_base::sync_with_stdio(false);
  std::wcout.imbue(std::locale{"en_US.UTF-8"});
  std::wcout << wide_test << '\n' << my::check_ios;
  // - βœ… libc++:
  //   - returned: 0
  //   - stdout:
  //     - Ο€|πŸ˜€|€
  // - βœ… libstdc++:
  //   - returned: 0
  //   - stdout:
  //     - Ο€|πŸ˜€|€
#elif TEST == 2 // Test C locale
  my::check<nullptr>(std::setlocale(LC_ALL, "en_US.UTF-8"));
  my::check<EOF>(std::fputws(wide_test, stdout));
  my::check<WEOF>(std::putwchar(L'\n'));
  std::wcout << wide_test << '\n' << my::check_ios;
  // - ❌ libc++:
  //   - returned: 139
  //   - stdout:
  //     - Ο€|πŸ˜€|€
  //   - stderr:
  //     - eofbit: 0
  //     - failbit: 1
  //     - badbit: 1
  //     - libc++abi: terminating
  //     - Program terminated with signal: SIGSEGV
  // - βœ… libstdc++:
  //   - returned: 0
  //   - stdout:
  //     - Ο€|πŸ˜€|€
  //     - Ο€|πŸ˜€|€
#endif
}

In Test 2 above, since sync_with_stdio(false) is not called, std::wcout should remain synchronized with stdout. In other words, it should behave similarly to the C-style I/O functions (e.g., std::fputws). After setting the C locale, std::fputws can correctly output wide Unicode strings, so there seems to be little reason why std::wcout cannot follow suit in this case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.localeissues related to localization

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions