fmt icon indicating copy to clipboard operation
fmt copied to clipboard

Missing named arguments do not cause compilation error when using FMT_COMPILE

Open schaerfo opened this issue 1 year ago • 3 comments

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

schaerfo avatar Aug 17 '24 12:08 schaerfo

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);
}

Lounarok avatar Dec 02 '24 02:12 Lounarok

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.

dinomight avatar Mar 01 '25 15:03 dinomight

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

quadrisufiyan avatar Sep 11 '25 07:09 quadrisufiyan