GCC: why cannot compile clean printf("%f\n", f16) under -std=c11 -Wall?

c, gcc, half-precision-float, language-lawyer, printf

Solution

From the clang manual:

Because default argument promotion only applies to the standard floating-point types, `_Float16` values are not promoted to `double` when passed as variadic or untyped arguments. As a consequence, some caution must be taken when using certain library facilities with `_Float16`; for example, there is no `printf` format specifier for `_Float16`, and (unlike `float`) it will not be implicitly promoted to `double` when passed to `printf`, so the programmer must explicitly cast it to double before using it with an `%f` or similar specifier.

Problem

Sample code: ``` #include <stdio.h> #define __STDC_WANT_IEC_60559_TYPES_EXT__ #include <float.h> #ifdef FLT16_MAX _Float16 f16; int main(void) { printf("%f\n", f16); return 0; } #endif ``` Invocation: ``` # gcc trunk on linux on x86_64 $ gcc t0.c -std=c11 -Wall ``` Expected diagnostics: ``` <nothing> ``` Actual diagnostics: ``` t0.c:9:14: warning: format '%f' expects argument of type 'double', but argument 2 has type '_Float16' [-Wformat=] 9 | printf("%f\n", f16); | ~^ ~~~ | | | | | _Float16 | double ``` Does it mean that under `__STDC_WANT_IEC_60559_TYPES_EXT__` AND if `FLT16_MAX` defined the gcc is unaware that `printf` may be used with `_Float16`? Should it be aware? Also: `printf("%f\n", f);` when `f` is a `float` leads to no warning above despite the fact that `format '%f' expects argument of type 'double', but argument 2 has type 'float'`. Confused.

Original source