fmtlib / fmt

A modern formatting library
https://fmt.dev
Other
19.83k stars 2.42k forks source link

Fix compilation errors due to `make_format_args` in gcc 14.1.1 with c++20 #4042

Closed toge closed 1 day ago

toge commented 3 days ago

In gcc 14.1.1 with c++20, there are compilation errors following code:

// g++ --std=c++20 test.cpp -lfmt
#include <fmt/printf.h>
#include <fmt/ostream.h>

int main() {
    const std::string thing("World");
    fmt::printf("PRINTF: Hello, %s!\n", thing);
    return 0;
}

The error messages are like this:

In file included from test_package.cpp:10:
include/fmt/printf.h: In instantiation of 'int fmt::v10::printf(string_view, const T& ...) [with T = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}; string_view = basic_string_view<char>]':
test_package.cpp:16:16:   required from here
   16 |     fmt::printf("PRINTF: Hello, %s!\n", thing);
      |     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/fmt/printf.h:645:48: error: no matching function for call to 'make_printf_args(const std::__cxx11::basic_string<char>&)'
  645 |   return vfprintf(stdout, fmt, make_printf_args(args...));
      |                                ~~~~~~~~~~~~~~~~^~~~~~~~~
include/fmt/printf.h:571:13: note: candidate: 'template<class Char, class ... T> decltype (make_format_args<fmt::v10::basic_printf_context<Char> >(fmt::v10::make_printf_args::args ...)) fmt::v10::make_printf_args(T& ...)'
  571 | inline auto make_printf_args(T&... args)
      |             ^~~~~~~~~~~~~~~~
include/fmt/printf.h:571:13: note:   template argument deduction/substitution failed:
include/fmt/printf.h: In substitution of 'template<class Char, class ... T> decltype (make_format_args<fmt::v10::basic_printf_context<Char> >(fmt::v10::make_printf_args::args ...)) fmt::v10::make_printf_args(T& ...) [with Char = char; T = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]':
include/fmt/printf.h:645:48:   required from 'int fmt::v10::printf(string_view, const T& ...) [with T = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}; string_view = basic_string_view<char>]'
  645 |   return vfprintf(stdout, fmt, make_printf_args(args...));
      |                                ~~~~~~~~~~~~~~~~^~~~~~~~~
test_package.cpp:16:16:   required from here
   16 |     fmt::printf("PRINTF: Hello, %s!\n", thing);
      |     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/fmt/printf.h:572:61: error: call of overloaded 'make_format_args<fmt::v10::basic_printf_context<char> >(const std::__cxx11::basic_string<char>&)' is ambiguous
  572 |     -> decltype(make_format_args<basic_printf_context<Char>>(args...)) {
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
In file included from include/fmt/format.h:41,
                 from include/fmt/printf.h:16:
include/fmt/base.h:2000:34: note: candidate: 'constexpr fmt::v10::detail::format_arg_store<Context, NUM_ARGS, 0, DESC> fmt::v10::make_format_args(T& ...) [with Context = basic_printf_context<char>; T = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}; long unsigned int NUM_ARGS = 1; long unsigned int NUM_NAMED_ARGS = 0; long long unsigned int DESC = 13; typename std::enable_if<(NUM_NAMED_ARGS == 0), int>::type <anonymous> = 0]'
 2000 | constexpr FMT_ALWAYS_INLINE auto make_format_args(T&... args)
      |                                  ^~~~~~~~~~~~~~~~
In file included from /usr/include/c++/14/bits/chrono_io.h:39,
                 from /usr/include/c++/14/chrono:3360,
                 from include/fmt/chrono.h:13,
                 from include/fmt/ostream.h:23,
                 from test_package.cpp:11:
/usr/include/c++/14/format:3799:5: note: candidate: 'auto std::make_format_args(_Args& ...) [with _Context = fmt::v10::basic_printf_context<char>; _Args = {const __cxx11::basic_string<char, char_traits<char>, allocator<char> >}]'
 3799 |     make_format_args(_Args&... __fmt_args) noexcept
      |     ^~~~~~~~~~~~~~~~

It seems to be caused by recursive make_printf_args calls without namespace. This PR tries to solve it.

I think this is an adhoc approach, so if there is a more elegant way, I will gladly close this PR.

vitaut commented 3 days ago

Repro: https://www.godbolt.org/z/dWfWcrKb5

toge commented 2 days ago

@vitaut I update printf-test.cc and CMakeLists.txt for checking this situation. Please review it again.

vitaut commented 1 day ago

Thank you!