It's been reported that when using attribute((format)) on non-variadic functions, certain values that normally get promoted when passed as variadic arguments now unconditionally emit a diagnostic:
c void foo(const char *fmt, float f) __attribute__((format(printf, 1, 2))); void bar(void) { foo("%g", 123.f); // ^ format specifies type 'double' but the argument has type 'float' }
This is normally not an issue because float values get promoted to doubles when passed as variadic arguments, but needless to say, variadic argument promotion does not apply to non-variadic arguments.
While this can be fixed by adjusting the prototype of foo, this is sometimes undesirable in C (for instance, if foo is ABI). In C++, using variadic templates, this might instead require call-site fixing, which is tedious and arguably needless work:
c++ template<typename... Args> void foo(const char *fmt, Args &&...args) __attribute__((format(printf, 1, 2))); void bar(void) { foo("%g", 123.f); // ^ format specifies type 'double' but the argument has type 'float' }
To address this issue, we teach FormatString about a few promotions that have always been around but that have never been exercised in the direction that FormatString checks for:
- char, unsigned char -> int, unsigned
- half, float16, float -> double
This addresses issue https://github.com/llvm/llvm-project/issues/59824.
bool types?