Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chrono locale format code has some bug when using RHEL gcc on CentOS 7.6 to compile #3858

Closed
g199209 opened this issue Feb 20, 2024 · 0 comments · Fixed by #3859
Closed

chrono locale format code has some bug when using RHEL gcc on CentOS 7.6 to compile #3858

g199209 opened this issue Feb 20, 2024 · 0 comments · Fixed by #3859

Comments

@g199209
Copy link
Contributor

g199209 commented Feb 20, 2024

Test version : 10.2.1

Test code snippet:

std::locale::global(loc);
auto sat = fmt::weekday(6);
fmt::format(loc, "{:L}", sat);

The code above will throw std::bad_cast when using specifed compiler and OS.

Compiler: g++ (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4)
OS: CentOS 7.6

This gcc is from RHEL Dev tool set 12: https://access.redhat.com/documentation/en-us/red_hat_developer_toolset/12


Root cause: This compile has predefined #define _GLIBCXX_USE_DUAL_ABI 0, the old CentOS 7.6 do not support dual ABI, but the _GLIBCXX_USE_DUAL_ABI IS defined to 0, not undefined.

And related code in include/fmt/chrono.h:

template <typename OutputIt>
auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)
    -> OutputIt {
  if (detail::is_utf8() && loc != get_classic_locale()) {
    // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
    // gcc-4.
#if FMT_MSC_VERSION != 0 || \
    (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
    // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
    // and newer.
    using code_unit = wchar_t;
#else
    using code_unit = char32_t;
#endif

    using unit_t = codecvt_result<code_unit>;
    unit_t unit;
    write_codecvt(unit, in, loc);
    // ......
}

If _GLIBCXX_USE_DUAL_ABI IS defined, std::use_facet<std::codecvt<char32_t, char, std::mbstate_t>>(loc) will be called in write_codecvt(), which throw std::bad_cast. If I only keep using code_unit = wchar_t; here, the code above can work well.

I think we should not only check whether _GLIBCXX_USE_DUAL_ABI is defined, but also check it's value here:

#if FMT_MSC_VERSION != 0 || \
    (defined(__GLIBCXX__) && (!defined(_GLIBCXX_USE_DUAL_ABI) || _GLIBCXX_USE_DUAL_ABI == 0 ))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant