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

Gao, Yunzhong yunzhong_gao at playstation.sony.com
Mon Sep 16 12:20:09 PDT 2013


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}.

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<mailto: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<http://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<mailto: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/9609e0f7/attachment.html>


More information about the cfe-dev mailing list