Missing named arguments do not cause compilation error when using FMT_COMPILE
Specifying a named argument in the format string but not providing a value does not result in a compilation error on recent GCC and Clang versions when the format string is compiled using FMT_COMPILE.
This is the case both when the argument is missing altogether (1) and when it is present but no value is assigned (2).
When the FMT_COMPILE macro is removed, both fmt::format calls result in compilation errors.
#include <fmt/format.h>
#include <fmt/compile.h>
int main() {
using namespace fmt::literals;
fmt::format(FMT_COMPILE("{x}")); // 1
fmt::format(FMT_COMPILE("{x}"), "x"_a); // 2
return 0;
}
On Compiler Explorer: https://godbolt.org/z/4zGrofeoE
Did some investigation but don't have time to work on it yet. Feel free if anyone would like to help.
The problem seems to be inside how FMT_COMPILE() handles named arguments in compile_format_string().
When else if constexpr (arg_id_result.kind == arg_id_kind::name) is true, get_arg_index_by_name() should return a value non -1 to compile time named argument. I'm not quite sure if it's broken or I don't get the implementation in correct way. It seems like if constexpr (arg_index >= 0) { condition is never met.. then goes to below section all the time.
else if constexpr (c == '}') {
// static_assert(false, "foo");
return parse_tail<Args, arg_id_end_pos + 1, ID>(
runtime_named_field<char_type>{arg_id_result.arg_id.name}, fmt);
}
Duplicate named args are also not verified when using FMT_COMPILE strings for either static or dynamic named args.
fmt::print(FMT_COMPILE("{a}"), "a"_a = 42, "a"_a = 43); // compiles and prints 42.
fmt::print(FMT_COMPILE("{a}"), fmt::arg("a", 42), fmt::arg("a", 43)); // compiles and prints 42.
fmt::print(FMT_COMPILE("{a}"), "a"_a = 42, "a"_a = 43); // compiles and prints 42. fmt::print(FMT_COMPILE("{a}"), fmt::arg("a", 42), fmt::arg("a", 43)); // compiles and