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?