4 Commits

Author SHA1 Message Date
Lu Haocong
442f67c870 [Sema][test] Split format attribute test cases for _Float16
Fixes https://github.com/llvm/llvm-project/pull/74439#issuecomment-1880528376
2024-01-08 17:24:51 +08:00
Haocong Lu
5034994134
[Sema] Warning for _Float16 passed to format specifier '%f' (#74439)
According to https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2844.pdf,
default argument promotions for _FloatN types has been removed.

A warning is needed to notice user to promote _Float16 to double
explicitly, and then pass it to format specifier '%f', which is
consistent with GCC.

Fixes: https://github.com/llvm/llvm-project/issues/68538
2024-01-08 09:50:36 +08:00
Podchishchaeva, Mariya
e4e56f91df [clang] Emit Wformat for bool value and char specifier confusion in scanf
Fixes https://github.com/llvm/llvm-project/issues/64987

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D159279
2023-09-01 01:38:07 -07:00
Félix Cloutier
04e6178ae9
[Sema] tolerate more promotion matches in format string checking
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.
2023-08-25 10:14:01 -07:00