[Bug c/63645] Incorrect code generation
trippels at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Mon Oct 27 14:59:00 GMT 2014
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645
--- Comment #16 from Markus Trippelsdorf <trippels at gcc dot gnu.org> ---
(In reply to M Welinder from comment #14)
> > 2) In the if statement, where you probe the different members, you
> > also invoke undefined behavior.
>
> Absolutely not! I went other that in painful detail in comment 8.
> Bottom line: only one member is accessed.
Let's take this example:
markus@x4 tmp % cat union.c
#include <stdlib.h>
typedef union _GnmExpr GnmExpr;
typedef char GnmFunc;
typedef unsigned char guint8;
typedef enum
{
GNM_EXPR_OP_LT,
GNM_EXPR_OP_FUNCALL
} GnmExprOp;
typedef struct
{
guint8 oper;
int argc;
GnmFunc *func;
} GnmExprFunction;
typedef struct
{
guint8 oper;
} GnmExprBinary;
union _GnmExpr
{
GnmExprFunction func;
GnmExprBinary binary;
};
int
main (void)
{
GnmExprBinary res;
res.oper = GNM_EXPR_OP_LT;
GnmExpr const *expr = (GnmExpr *)&res;
if (expr->binary.oper == GNM_EXPR_OP_FUNCALL
&& expr->func.argc == 1
&& expr->func.func == getenv ("NOT"))
abort ();
return 0;
}
Here the compiler even warns:
markus@x4 tmp % gcc -Wall -Wextra -g -O2 union.c
union.c: In function ‘main’:
union.c:40:7: warning: ‘res.func.func’ may be used uninitialized in this
function [-Wmaybe-uninitialized]
&& expr->func.func == getenv ("NOT"))
^
And that is because the compiler assumes that no undefined behavior
happens and optimizes accordingly.
The gcc documentation even mentions this case explicitly (under
-fstrict-aliasing):
»Similarly, access by taking the address, casting the resulting pointer and
dereferencing the result has undefined behavior, even if the cast uses a union
type.«
More information about the Gcc-bugs
mailing list