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 ))
Test version : 10.2.1
Test code snippet:
The code above will throw
std::bad_castwhen 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_ABIIS defined to 0, not undefined.And related code in
include/fmt/chrono.h:If
_GLIBCXX_USE_DUAL_ABIIS defined,std::use_facet<std::codecvt<char32_t, char, std::mbstate_t>>(loc)will be called inwrite_codecvt(), which throwstd::bad_cast. If I only keepusing code_unit = wchar_t;here, the code above can work well.I think we should not only check whether
_GLIBCXX_USE_DUAL_ABIis defined, but also check it's value here: