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

Richard Smith richard at metafoo.co.uk
Mon Sep 16 13:37:40 PDT 2013


On Mon, Sep 16, 2013 at 12:20 PM, Gao, Yunzhong <
yunzhong_gao at playstation.sony.com> wrote:

>  Hi Richard,****
>
> ** **
>
> According to c11 6.7.9p19, “The initialization shall occur in initializer
> list order, each initializer provided for a****
>
> particular subobject overriding any previously listed initializer for the
> same subobject; all sub-objects that are****
>
> not initialized explicitly shall be initialized implicitly the same as
> objects that have static storage duration.”****
>
> ** **
>
> In Matthew’s example, ** **
>
>   my_agg_t agg_instance =
>   {
>     .b[0] = 0,
>     .a.one = 1,
>     .b[2] = 2,
>     .a.three = 3,
>   };****
>
> ** **
>
> If you think that “.a.three = 3” overrides “.b[2] = 2”, “.a.one = 1” and
> “.b[0] = 0”, then .b[0] and .b[2] should take the value****
>
> zero as if they were initialized as static objects, giving the end result
> {0, 0, 0, 3}.****
>
> ** **
>
> If you think that “.a.three = 3” does not override “.b[2] = 2” and “.b[0]
> = 0”, then .b[0] and .b[2] will be****
>
> initialized to 0 and 2 respectively, giving the end result {0, 1, 2, 3}.
>

How can it give that result? agg_instance.a.zero and agg_instance.a.two
were never initialized.


> **
>
> I do not think {unspecified, unspecified, unspecified, 3} is a viable
> interpretation.****
>
> ** **
>
> - Gao.****
>
> ** **
>
> ** **
>
> ** **
>
> *From:* cfe-dev-bounces at cs.uiuc.edu [mailto:cfe-dev-bounces at cs.uiuc.edu] *On
> Behalf Of *Richard Smith
> *Sent:* Monday, September 16, 2013 11:05 AM
> *To:* Matthew Curtis
> *Cc:* cfe-dev at cs.uiuc.edu Developers
>
> *Subject:* Re: [cfe-dev] question about initializing multiple members of
> unions****
>
>  ** **
>
> 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
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> 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/ea9d4097/attachment.html>


More information about the cfe-dev mailing list