mirror of
https://github.com/fmtlib/fmt.git
synced 2025-04-16 05:42:19 +00:00
Fix #2818: diagnose unformattable arguments in unpacked case
This commit is contained in:
parent
17ba99c1d2
commit
4ad90578f7
@ -1260,7 +1260,7 @@ template <typename Context> class value {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename T>
|
template <typename Context, typename T>
|
||||||
FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>;
|
FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg<Context>;
|
||||||
|
|
||||||
// To minimize the number of types we need to deal with, long is translated
|
// To minimize the number of types we need to deal with, long is translated
|
||||||
// either to int or to long long depending on its size.
|
// either to int or to long long depending on its size.
|
||||||
@ -1513,7 +1513,7 @@ template <typename Context> class basic_format_arg {
|
|||||||
detail::type type_;
|
detail::type type_;
|
||||||
|
|
||||||
template <typename ContextType, typename T>
|
template <typename ContextType, typename T>
|
||||||
friend FMT_CONSTEXPR auto detail::make_arg(const T& value)
|
friend FMT_CONSTEXPR auto detail::make_arg(T&& value)
|
||||||
-> basic_format_arg<ContextType>;
|
-> basic_format_arg<ContextType>;
|
||||||
|
|
||||||
template <typename Visitor, typename Ctx>
|
template <typename Visitor, typename Ctx>
|
||||||
@ -1674,19 +1674,7 @@ constexpr auto encode_types() -> unsigned long long {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Context, typename T>
|
template <typename Context, typename T>
|
||||||
FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> {
|
FMT_CONSTEXPR FMT_INLINE auto make_value(T&& val) -> value<Context> {
|
||||||
basic_format_arg<Context> arg;
|
|
||||||
arg.type_ = mapped_type_constant<T, Context>::value;
|
|
||||||
arg.value_ = arg_mapper<Context>().map(value);
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The type template parameter is there to avoid an ODR violation when using
|
|
||||||
// a fallback formatter in one translation unit and an implicit conversion in
|
|
||||||
// another (not recommended).
|
|
||||||
template <bool IS_PACKED, typename Context, type, typename T,
|
|
||||||
FMT_ENABLE_IF(IS_PACKED)>
|
|
||||||
FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
|
||||||
const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));
|
const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));
|
||||||
|
|
||||||
constexpr bool formattable_char =
|
constexpr bool formattable_char =
|
||||||
@ -1715,9 +1703,26 @@ FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
|||||||
return {arg};
|
return {arg};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Context, typename T>
|
||||||
|
FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg<Context> {
|
||||||
|
basic_format_arg<Context> arg;
|
||||||
|
arg.type_ = mapped_type_constant<T, Context>::value;
|
||||||
|
arg.value_ = make_value<Context>(value);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The type template parameter is there to avoid an ODR violation when using
|
||||||
|
// a fallback formatter in one translation unit and an implicit conversion in
|
||||||
|
// another (not recommended).
|
||||||
|
template <bool IS_PACKED, typename Context, type, typename T,
|
||||||
|
FMT_ENABLE_IF(IS_PACKED)>
|
||||||
|
FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
||||||
|
return make_value<Context>(val);
|
||||||
|
}
|
||||||
|
|
||||||
template <bool IS_PACKED, typename Context, type, typename T,
|
template <bool IS_PACKED, typename Context, type, typename T,
|
||||||
FMT_ENABLE_IF(!IS_PACKED)>
|
FMT_ENABLE_IF(!IS_PACKED)>
|
||||||
inline auto make_arg(const T& value) -> basic_format_arg<Context> {
|
FMT_CONSTEXPR inline auto make_arg(T&& value) -> basic_format_arg<Context> {
|
||||||
return make_arg<Context>(value);
|
return make_arg<Context>(value);
|
||||||
}
|
}
|
||||||
FMT_END_DETAIL_NAMESPACE
|
FMT_END_DETAIL_NAMESPACE
|
||||||
|
@ -6,6 +6,8 @@ project(compile-error-test CXX)
|
|||||||
set(fmt_headers "
|
set(fmt_headers "
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/xchar.h>
|
#include <fmt/xchar.h>
|
||||||
|
#include <fmt/ostream.h>
|
||||||
|
#include <iostream>
|
||||||
")
|
")
|
||||||
|
|
||||||
set(error_test_names "")
|
set(error_test_names "")
|
||||||
@ -154,6 +156,16 @@ expect_compile(format-function-error "
|
|||||||
fmt::format(\"{}\", f);
|
fmt::format(\"{}\", f);
|
||||||
" ERROR)
|
" ERROR)
|
||||||
|
|
||||||
|
# Formatting an unformattable argument should always be a compile time error
|
||||||
|
expect_compile(format-lots-of-arguments-with-unformattable "
|
||||||
|
struct E {};
|
||||||
|
fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, E());
|
||||||
|
" ERROR)
|
||||||
|
expect_compile(format-lots-of-arguments-with-function "
|
||||||
|
void (*f)();
|
||||||
|
fmt::format(\"\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, f);
|
||||||
|
" ERROR)
|
||||||
|
|
||||||
# Make sure that compiler features detected in the header
|
# Make sure that compiler features detected in the header
|
||||||
# match the features detected in CMake.
|
# match the features detected in CMake.
|
||||||
if (SUPPORTS_USER_DEFINED_LITERALS)
|
if (SUPPORTS_USER_DEFINED_LITERALS)
|
||||||
@ -181,6 +193,20 @@ if (CMAKE_CXX_STANDARD GREATER_EQUAL 20)
|
|||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
" ERROR)
|
" ERROR)
|
||||||
|
expect_compile(print-string-number-spec-error "
|
||||||
|
#ifdef FMT_HAS_CONSTEVAL
|
||||||
|
fmt::print(\"{:d}\", \"I am not a number\");
|
||||||
|
#else
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
" ERROR)
|
||||||
|
expect_compile(print-stream-string-number-spec-error "
|
||||||
|
#ifdef FMT_HAS_CONSTEVAL
|
||||||
|
fmt::print(std::cout, \"{:d}\", \"I am not a number\");
|
||||||
|
#else
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
" ERROR)
|
||||||
|
|
||||||
# Compile-time argument name check
|
# Compile-time argument name check
|
||||||
expect_compile(format-string-name "
|
expect_compile(format-string-name "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user