-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
In the fstring constructor from a type that is convertible to string view, the s argument is passed to two different functions, which both internally convert it to a string_view. This s argument is frequently created by the FMT_STRING macro which has a conversion to string_view that evaluates a string literal expression.
Each evaluation of a string literal expression can produce a different pointer. Therefore it is not correct to assume that the two conversions of s to a string_view produce related string_views, but the code does assume this. Historically, compilers have let you get away with this in compile-time evaluation, but clang recently gained a more strict implementation of this rule and now rejects.
I think the fix is probably to do the same thing in this constructor that is done a few lines below in the next constructor:
template <typename S,
FMT_ENABLE_IF(std::is_convertible<const S&, string_view>::value)>
FMT_CONSTEVAL FMT_ALWAYS_INLINE fstring(const S& s) : str(s) {
if (FMT_USE_CONSTEVAL)
+ FMT_CONSTEXPR auto sv = string_view(S());
- detail::parse_format_string<char>(s, checker(s, arg_pack()));
+ detail::parse_format_string<char>(sv, checker(sv, arg_pack()));
#ifdef FMT_ENFORCE_COMPILE_STRING
static_assert(
FMT_USE_CONSTEVAL && sizeof(s) != 0,
"FMT_ENFORCE_COMPILE_STRING requires format strings to use FMT_STRING");
#endif
}
template <typename S,
FMT_ENABLE_IF(std::is_base_of<detail::compile_string, S>::value&&
std::is_same<typename S::char_type, char>::value)>
FMT_ALWAYS_INLINE fstring(const S&) : str(S()) {
FMT_CONSTEXPR auto sv = string_view(S());
FMT_CONSTEXPR int ignore =
(parse_format_string(sv, checker(sv, arg_pack())), 0);
detail::ignore_unused(ignore);
}