icecream-cpp icon indicating copy to clipboard operation
icecream-cpp copied to clipboard

Clang dump struct float members limitation

Open renatoGarcia opened this issue 4 years ago • 0 comments

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.

renatoGarcia avatar Apr 16 '20 01:04 renatoGarcia