[cfe-dev] question about initializing multiple members of unions

Richard Smith richard at metafoo.co.uk
Mon Sep 16 11:05:20 PDT 2013


On Mon, Sep 16, 2013 at 7:11 AM, Matthew Curtis <mcurtis at codeaurora.org>wrote:

> Richard, Doug,
>
> Do either of you have an recommendation here?
>
> Eli recommends GCC's behavior, while Philip Reames and Gao would both
> prefer the alternate behavior below (same as a series of assignments).
>

Can you explain how treating the designated initializers as a sequence of
assignments could give the object the value {0, 1, 2, 3}?

Per C11 6.2.6.1/7, "When a value is stored in a member of an object of
union type, the bytes of the object representation that do not correspond
to that member but do correspond to other members take unspecified values."
This doesn't really say what happens if you store a value in a *subobject*
of a member of an object of union type, but the natural extension would
seem to be that the bytes of the object representation that do not
correspond to that subobject take unspecified values.

Footnote 95 allows reading the contents of an inactive member of a union
(by reinterpreting the value as the other type), but that only applies to
reads through an inactive union member, not to stores.

So under Eli's approach, we get {0, 0, 0, 3}, and under the other approach,
it can be argued that we get {unspecified, unspecified, unspecified, 3}.


I'm reasonably convinced that this is a hole in the C standard -- it
doesn't specify what to do in this case -- and Eli's approach seems
completely reasonable to me. Plus it has the benefit of being compatible
with at least two other major compilers (g++ and EDG), and doesn't require
us to invent a new representation for initializer lists.

Thanks,
> Matthew Curtis
>
>
>
> On 9/11/2013 8:10 AM, Matthew Curtis wrote:
>
>> 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
>>
>> ------------------------------**------------------------------**
>> ----------
>> BTW, Here are the portions of the C99 spec[0] that I thought were
>> relevant
>>
>> 6.7.2.1 Structure and union specifiers
>>
>> 14 [...] The value of at most one of the members can be stored in a
>> union object at any time. [...]
>>
>> 6.7.8 Initialization
>>
>> 17 [...] a designation causes the following initializer to begin
>> initialization of the subobject described by the designator.
>> Initialization then continues forward in order, beginning with the
>> next subobject after that described by the designator. 128)
>>
>> 19 The initialization shall occur in initializer list order, each
>> initializer provided for a particular subobject overriding any
>> previously listed initializer for the same subobject; 130) [...]
>>
>> 128) After a union member is initialized, the next object is not the
>> next member of the union; instead, it is the next subobject of an
>> object containing the union.
>>
>> 130) Any initializer for the subobject which is overridden and so not
>> used to initialize that subobject might not be evaluated at all.
>>
>> [0] http://www.open-std.org/jtc1/**sc22/WG14/www/docs/n1256.pdf<http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf>
>>
>> ______________________________**_________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/**mailman/listinfo/cfe-dev<http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev>
>>
>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted
> by The Linux Foundation
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130916/7854b207/attachment.html>


More information about the cfe-dev mailing list