[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