I'm investigating an assert in clang compiling the following code:
typedef union {
struct {
int zero;
int one;
int two;
int three;
} a;
int b[4];
} my_agg_t;
my_agg_t agg_instance =
{
.b[0] = 0,
.a.one = 1,
.b[2] = 2,
.a.three = 3,
};
I'm a little uncertain as to what this *should* do.
GCC (4.4.3) produces this assembly:
agg_instance:
.zero 12
.long 3
I had thought that maybe it should produce
agg_instance:
.long 0
.long 1
.long 2
.long 3
Which is the effect that most implementations would have if you
were to execute the analogous assignments:
agg_instance.b[0] = 0,
agg_instance.a.one = 1,
agg_instance.b[2] = 2,
agg_instance.a.three = 3,
Experimenting with various orderings of the designated initializers
leads me to believe that whenever the member of the union being
initialized changes, GCC discards any previous member initializations.
For clang, this ordering
my_agg_t agg_instance =
{
.a.one = 1,
.b[0] = 0,
.a.three = 3,
.b[2] = 2,
};
does not assert and produces
agg_instance:
.long 0
.long 1
.long 2
.long 3
Though after stepping through some of the code I think this may be
accidental.
Reading sections 6.7.2.1 and 6.7.8 of the spec, it's not clear to me
exactly what the behavior should be, though I could see how GCC's
behavior would be considered compliant.
Thoughts?
Matthew Curtis