icecream-cpp
icecream-cpp copied to clipboard
Clang dump struct float members limitation
Due to a Clang bug, is not possible correctly print float and double struct members declared using aliased type names.
When calling variadic functions, float arguments are promoted to doubles before being passed. However, the Clang float promotion before the calling of some_printf_func
, given as argument of __builtin_dump_struct
, is buggy. It seems like instead of converting it to a double with the same numeric value, the float 32 bits are just copied to the first 32 bits of a double.
As a consequence of that behavior, inside of some_printf_func
, if you know that your next %f
specified variadic argument is a double
, you can just do va_arg(args, double)
as usual. On other hand, if you know that your next argument is a float
, you can do double d = va_arg(args, double)
and reinterpret the first 32 bits with *((float*)&d)
. However, if you don't know if your argument is either a double
or a float
, it won't be possible decide between interpret the whole 64 bits as a double
or the first 32 bits as a float
.
When using the __builtin_dump_struct
function, a %f
specifier will be used to both float
and double
arguments indistinctly. Luckily, preceding each call to some_printf_func
with a %
specifier, a call to that same function will be done having as argument a string with the variable signature (type and name). So, inspecting that string would be possible deduce the variable type before its promotions to a double
. The %f
argument with a "const float foo" string must be a float
, and with a "double bar" must be a double
.
However, if the %f
argument has been declared with an aliased type name, its inference as float
or double
is not possible. With the code:
using MyNumber = float;
struct S
{
MyNumber num;
};
, when dumping the struct S
, the information of num
variable being either float
or double
is lost. The IceCream-cpp approach is presume num
as a double
, but print its value alongside a warning.
Summarizing, float
and double
struct members declared with canonical names will work just fine. If a name alias is used, on IceCream-cpp side is not possible distinguish between them, and a double
type is presumed. If num
is a double
the printed value is correct, if it is a float
the printed value is wrong.