Phil Mayers wrote:
For those not following the Fedora bug, it (or rather, it's dependency) has been closed by Ulrich Drepper. He seems to be saying that the FreeRadius code is incorrect and specifically that an invalid typecast is triggering the compiler to generate bad code:
Interesting. So GCC doesn't complain, and it generates bad assembly for C code that it thinks is perfectly valid.
https://bugzilla.redhat.com/show_bug.cgi?id=448743#c6
Summary (as far as I can make out): Because the code looks like this: ... ...the compiler can't detect that the "i" value is "used", and optimises the code touching it away.
i.e. GCC doesn't properly analyze the code that it optimizes, so it generates the wrong optimizations. GCC has a history of doing this...
I'm not expert enough in the C99 standard to judge whether the comments at the above URL are correct or not; I suspect it's a matter of some controversy, and will back slowly away now... ;o)
I think your comments about the underlying cause are correct. Ulrich's comments about Posix are interesting:
The invalid casts are forbidden by ISO C. POSIX does not and cannot guarantee anything about this type of use of sockaddr_storage.
To quote the Opengroup page: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html ... The <sys/socket.h> header shall define the sockaddr_storage structure. This structure shall be: * Large enough to accommodate all supported protocol-specific address structures * Aligned at an appropriate boundary so that pointers to it can be cast as pointers to protocol-specific address structures and used to access the fields of those structures without alignment problems ... i.e. the code in FreeRADIUS is correct. It uses sockaddr_stoage as a generic container for protocol-specific address structures. It casts a pointer to sockaddr_storage to a pointer to protocol-specific address structures. The recommendation to use a union to hold both sockaddr_storage && sockaddr_in is... interesting. If you have to do that, WTF is the use of sockaddr_storage? Looking on the net, I also found a fair amount of code using sockaddr_storage in the recommended Posix way. It appears that FreeRADIUS is OK, and just got hit by a GCC bug. i.e. for ANY code like this: foo = (type_t *) bar; switch (x) { case 1: foo->a = 1; break; ... } function(&bar); GCC will "optimize away" the line doing "foo->a = 1;". Nice. Alan DeKok.