Studying note of GCC-3.4.6 source (14)

2.2.3.1.5.2.2.5.        Layout of UNION

Above line 854, rli->t is tree node of the type to be laid out., amd comes at here, field must be a FIELD_DECL. If rli->t is not a RECORD_TYPE, in C++, it must a node for a union. It has different layout policy than class and struct.

 

778  static void

779  place_union_field (record_layout_info rli, tree field)                              in stor-layout.c

780  {

781    update_alignment_for_field (rli, field, /*known_align=*/0);

782 

783    DECL_FIELD_OFFSET (field) = size_zero_node;

784    DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;

785    SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);

786 

787    /* We assume the union's size will be a multiple of a byte so we don't

788      bother with BITPOS.  */

789    if (TREE_CODE (rli->t) == UNION_TYPE)

790      rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));

791    else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)

792      rli->offset = fold (build (COND_EXPR, sizetype,

793                              DECL_QUALIFIER (field),

794                              DECL_SIZE_UNIT (field), rli->offset));

795  }

 

Below update_alignment_for_field updates the variable alignment fields in rli, and return the alignment to give the field. Note that above at line 785, BIGGEST_ALIGNMENT, for x86 is 128.

 

686  static unsigned int

687  update_alignment_for_field (record_layout_info rli, tree field,                in stor-layout.c

688                           unsigned int known_align)

689  {

690    /* The alignment required for FIELD.  */

691    unsigned int desired_align;

692    /* The type of this field.  */

693    tree type = TREE_TYPE (field);

694    /* True if the field was explicitly aligned by the user.  */

695    bool user_align;

696    bool is_bitfield;

697 

698    /* Lay out the field so we know what alignment it needs.  */

699    layout_decl (field, known_align);

2.2.3.1.5.2.2.5.1.  Layout FIELD_DECL

We have seen layout_decl is invoked when creating node for declaration of variable, parameter and function return type. The function will set the size, mode and alignment of the node. However in build_decl, no FIELD_DECL will be laid out directly, it is delayed till now. Notice that known_align here is zero which means "as much alignment as you like".

 

352  void

353  layout_decl (tree decl, unsigned int known_align)                                  in stor-layout.c

354  {

355    tree type = TREE_TYPE (decl);

356    enum tree_code code = TREE_CODE (decl);

357    rtx rtl = NULL_RTX;

358 

359    if (code == CONST_DECL)

360      return;

361    else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL

362            && code != TYPE_DECL && code != FIELD_DECL)

363      abort ();

364 

365    rtl = DECL_RTL_IF_SET (decl);

366 

367    if (type == error_mark_node)

368      type = void_type_node;

369 

370    /* Usually the size and mode come from the data type without change,

371      however, the front-end may set the explicit width of the field, so its

372      size may not be the same as the size of its type. This happens with

373      bitfields, of course (an `int' bitfield may be only 2 bits, say), but it

374      also happens with other fields. For example, the C++ front-end creates

375      zero-sized fields corresponding to empty base classes, and depends on

376      layout_type setting DECL_FIELD_BITPOS correctly for the field. Set the

377      size in bytes from the size in bits. If we have already set the mode,

378      don't set it again since we can be called twice for FIELD_DECLs.  */

379 

380    TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);

381    if (DECL_MODE (decl) == VOIDmode)

382      DECL_MODE (decl) = TYPE_MODE (type);

383 

384    if (DECL_SIZE (decl) == 0)

385    {

386      DECL_SIZE (decl) = TYPE_SIZE (type);

387      DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);

388    }

389    else if (DECL_SIZE_UNIT (decl) == 0)

390      DECL_SIZE_UNIT (decl)

391        = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),

392                                     bitsize_unit_node));

 

The first part of the function just initializes certain fields of DECL node with associated TYPE node appropriately.

2.2.3.1.5.2.2.5.2.  Treatment for Bit Field Decl

Below at line 402, DECL_BIT_FIELD returns nonzero, if the FIELD_DECL is for bit field.

 

layout_decl (continue)

 

394    if (code != FIELD_DECL)

395      /* For non-fields, update the alignment from the type.  */

396      do_type_align (type, decl);

397    else

398      /* For fields, it's a bit more complicated...  */

399    {

400      bool old_user_align = DECL_USER_ALIGN (decl);

401 

402      if (DECL_BIT_FIELD (decl))

403      {

404        DECL_BIT_FIELD_TYPE (decl) = type;

405 

406        /* A zero-length bit-field affects the alignment of the next

407          field.  */

408        if (integer_zerop (DECL_SIZE (decl))

409            && ! DECL_PACKED (decl)

410            && ! (*targetm.ms_bitfield_layout_p) (DECL_FIELD_CONTEXT (decl)))

411        {

412  #ifdef PCC_BITFIELD_TYPE_MATTERS

413          if (PCC_BITFIELD_TYPE_MATTERS)

414            do_type_align (type, decl);

415          else

416  #endif

417          {

418  #ifdef EMPTY_FIELD_BOUNDARY

419            if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))

420            {

421              DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;

422              DECL_USER_ALIGN (decl) = 0;

423            }

424  #endif

425          }

426        }

 

Among bit field declarations, there is special case of declaring size 0 (line 408). If fields are not required to be packed at bit boundary, it needs to further check the attribution of the aggregate type. Note that at line 410, DECL_FIELD_CONTEXT retrieves the node of UNION_TYPE or RECORD_TYPE containing the FIELD_DECL. Object targetm is target platform specified, for x86 system, the function pointer ms_bitfield_layout_p points to ix86_ms_bitfield_layout_p.

The explaination given in [2] is shown below:

This target hook returns true if bit-fields in the given RECORD_TYPE are to be laid out following the rules of Microsoft Visual C/C++, namely: (i) a bit-field won't share the same storage unit with the previous bit-field if their underlying types have different sizes, and the bit-field will be aligned to the highest alignment of the underlying types of itself and of the previous bit-field; (ii) a zero-sized bit-field will affect the alignment of the whole enclosing structure, even if it is unnamed; except that (iii) a zero-sized bit-field will be disregarded unless it follows another bit-field of nonzero size. If this hook returns true, other macros that control bit-field layout are ignored.

When a bit-field is inserted into a packed record, the whole size of the underlying type is used by one or more same-size adjacent bit-fields (that is, if its long:3, 32 bits is used in the record, and any additional adjacent long bit-fields are packed into the same chunk of 32 bits. However, if the size changes, a new field of that size is allocated). In an unpacked record, this is the same as using alignment, but not equivalent when packing.

If both MS bit-fields and `__attribute__((packed))' are used, the latter will take precedence. If `__attribute__((packed))' is used on a single field when MS bit-fields are in use, it will take precedence for that field, but the alignment of the rest of the structure may affect its placement.[2]

 

15481 static bool

15482 ix86_ms_bitfield_layout_p (tree record_type)                                                   in i386.c

15483 {

15484   return (TARGET_USE_MS_BITFIELD_LAYOUT &&

15485       !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))

15486     || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));

15487 }

 

Above, TYPE_ATTRIBUTES fetches a TREE_LIST of IDENTIFIER nodes of the attributes that apply to the type. lookup_attribute iterates the TREE_LIST to find out the IDENTIFIER node of attr_name.

 

2733 tree

2734 lookup_attribute (const char *attr_name, tree list)                                               in tree.c

2735 {

2736   tree l;

2737

2738   for (l = list; l; l = TREE_CHAIN (l))

2739   {

2740     if (TREE_CODE (TREE_PURPOSE (l)) != IDENTIFIER_NODE)

2741       abort ();

2742     if (is_attribute_p (attr_name, TREE_PURPOSE (l)))

2743       return l;

2744   }

2745

2746   return NULL_TREE;

2747 }

 

In GCC, the attribute name can be prefixed and postfixed with “__”, it is regarded as same as that without prefix and postfix. is_attribute_p recognizes attributes (attributes are defined by GNU C++, and supported by the compiler. Refer to [6] for the attributes available and the details).

 

2688 int

2689 is_attribute_p (const char *attr, tree ident)                                                          in tree.c

2690 {

2691   int ident_len, attr_len;

2692   const char *p;

2693

2694   if (TREE_CODE (ident) != IDENTIFIER_NODE)

2695     return 0;

2696

2697   if (strcmp (attr, IDENTIFIER_POINTER (ident)) == 0)

2698     return 1;

2699

2700   p = IDENTIFIER_POINTER (ident);

2701   ident_len = strlen (p);

2702   attr_len = strlen (attr);

2703

2704   /* If ATTR is `__text__', IDENT must be `text'; and vice versa.  */

2705   if (attr[0] == '_')

2706   {

2707     if (attr[1] != '_'

2708        || attr[attr_len - 2] != '_'

2709        || attr[attr_len - 1] != '_')

2710       abort ();

2711     if (ident_len == attr_len - 4

2712        && strncmp (attr + 2, p, attr_len - 4) == 0)

2713       return 1;

2714   }

2715   else

2716   {

2717     if (ident_len == attr_len + 4

2718        && p[0] == '_' && p[1] == '_'

2719        && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'

2720        && strncmp (attr, p + 2, attr_len) == 0)

2721       return 1;

2722   }

2723

2724   return 0;

2725 }

 

Back to ix86_ms_bitfield_layout_p, GCC supports two kinds layout of struct, one is adopted by MicroSoft (native), and the other used by GCC. TARGET_USE_MS_BITFIELD_LAYOUT is nonzero if using switch ms-bitfields (Table 7: target_switches for i386 system) which means using MS layout. ix86_ms_bitfield_layout_p returns nonzero if MS layout in used.

If GCC layout is required (not MS layout), PCC_BITFIELD_TYPE_MATTERS, at line 412, is 1 for x86 system. So alignment of bit-field unpacked and of zero size will be set with that of the type. For example, short i: 0, for GCC layout, the alignment will be 16 bits (same as short).

For PCC_BITFIELD_TYPE_MATTERS, the detail can be found in [2] as below.

[ Define this if you wish to imitate the way many other C compilers handle alignment of bit-fields and the structures that contain them.

The behavior is that the type written for a named bit-field (int, short, or other integer type) imposes an alignment for the entire structure, as if the structure really did contain an ordinary field of that type. In addition, the bit-field is placed within the structure so that it would fit within such a field, not crossing a boundary for it.

Thus, on most machines, a named bit-field whose type is written as int would not cross a four-byte boundary, and would force four-byte alignment for the whole structure. (The alignment used may not be four bytes; it is controlled by the other alignment parameters.) [Note: in below, we will see that the compiler will find the fittest integer type as the final type of the bit-filed]

An unnamed bit-field will not affect the alignment of the containing structure.

If the macro is defined, its definition should be a C expression; a nonzero value for the expression enables this behavior.

Note that if this macro is not defined, or its value is zero, some bit-fields may cross more than one alignment boundary. The compiler can support such references if there are `insv', `extv', and `extzv' insns that can directly reference memory.

The other known way of making bit-fields work is to define STRUCTURE_SIZE_BOUNDARY as large as BIGGEST_ALIGNMENT. Then every structure can be accessed with fullwords.

Unless the machine has bit-field instructions or you define STRUCTURE_SIZE_BOUNDARY that way, you must define PCC_BITFIELD_TYPE_MATTERS to have a nonzero value.

If your aim is to make GCC use the same conventions for laying out bit-fields as are used by another compiler, here is how to investigate what the other compiler does. Compile and run this program:

          struct foo1 {

            char x;

            char :0;

            char y;

          };

         

          struct foo2 {

            char x;

            int :0;

            char y;

          };

         

          main () {

            printf ("Size of foo1 is %d/n", sizeof (struct foo1));

            printf ("Size of foo2 is %d/n", sizeof (struct foo2));

            exit (0);

          }

If this prints 2 and 5, then the compiler's behavior is what you would get from PCC_BITFIELD_TYPE_MATTERS.]

Following, for bit-field of nonzero size, the function tries to find out if certain integer mode can replace the bit field, for example, int j: 8; may be replaced by char j;. And note that only bit-filed of nonzero size will get handled.

 

layout_decl (continue)

 

428        /* See if we can use an ordinary integer mode for a bit-field.

429          Conditions are: a fixed size that is correct for another mode

430          and occupying a complete byte or bytes on proper boundary.  */

431        if (TYPE_SIZE (type) != 0

432            && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST

433            && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)

434        {

435          enum machine_mode xmode

436               = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);

437 

438          if (xmode != BLKmode

439               && (known_align == 0

440               || known_align >= GET_MODE_ALIGNMENT (xmode)))

441          {

442            DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),

443                                     DECL_ALIGN (decl));

444            DECL_MODE (decl) = xmode;

445            DECL_BIT_FIELD (decl) = 0;

446          }

447        }

448 

449             /* Turn off DECL_BIT_FIELD if we won't need it set.  */

450             if (TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode

451            && known_align >= TYPE_ALIGN (type)

452            && DECL_ALIGN (decl) >= TYPE_ALIGN (type))

453           DECL_BIT_FIELD (decl) = 0;

454      }

 

At line 436, we have seen that mode_for_size_tree finds out the integer mode larger but most close to size of the declaration. Then GET_MODE_ALIGNMENT at line 440 just invokes get_mode_alignment.

 

299  unsigned int

300  get_mode_alignment (enum machine_mode mode)                                 in stor-layout.c

301  {

302    return MIN (BIGGEST_ALIGNMENT, MAX (1, mode_base_align[mode]*BITS_PER_UNIT));

303  }

 

mode_base_align is the data generated by genmode according to machmode.def and i386-mode.def, it records the alignment of modes. Notice that VOID and BLK modes have alignment of 0.

BIGGEST_ALIGNMENT defines minimum size in bits of the largest boundary to which any and all fundamental data types supported by the hardware might need to be aligned. No data type wants to be aligned rounder than this. For x86 system, Pentium+ prefers DFmode values to be aligned to 64 bit boundary and Pentium Pro XFmode values at 128 bit boundaries.

However, this hides an important fact. It is that if the bit field is not of zero size, neither it can be replaced by certain integer mode, the DECL_ALIGN is unset here (0 as initialized in make_node). For RECORD_TYPE, this fact is crucial for bit field layout.

2.2.3.1.5.2.2.5.3.  Treatment for Other Field Decl

Fields other than bit-field then are handled by following code snippet.

 

layout_decl (continue)

 

455      else if (DECL_PACKED (decl) && DECL_USER_ALIGN (decl))

456        /* Don't touch DECL_ALIGN. For other packed fields, go ahead and

457          round up; we'll reduce it again below. We want packing to

458          supersede USER_ALIGN inherited from the type, but defer to

459        alignment explicitly specified on the field decl.  */;

460      else

461        do_type_align (type, decl);

 

Take declaration like below as example:

  struct sdla_cmd {

   char  opp_flag         __attribute__((packed));

   char  cmd               __attribute__((packed));

   short length                     __attribute__((packed));

   char  retval             __attribute__((packed));

   short dlci                  __attribute__((packed));

   char  flags               __attribute__((packed));

   short rxlost_int         __attribute__((packed));

   long  rxlost_app      __attribute__((packed));

   char  reserve[2]              __attribute__((packed));

   char  data[SDLA_MAX_DATA]     __attribute__((packed)); /* transfer data buffer */

} __attribute__((aligned (2)));

 

For above declared fields, DECL_PACKED will be set, and DECL_USER_ALIGN is also set because the struct containing them is declared as aligned at boundary 2. For such case, we leave DECL_ALIGN to be handled below.

For other declarations, do_type_align updates the alignment attributions for declarations according to associated types, which also comes from mode_base_align

2.2.3.1.5.2.2.5.4.  Further Adjustment

Next, further adjustment according to the target platform is expected.

 

layout_decl (continue)

 

463      /* If the field is of variable size, we can't misalign it since we

464        have no way to make a temporary to align the result. But this

465        isn't an issue if the decl is not addressable. Likewise if it

466        is of unknown size.

467 

468        Note that do_type_align may set DECL_USER_ALIGN, so we need to

469        check old_user_align instead.  */

470      if (DECL_PACKED (decl)

471         && !old_user_align

472         && (DECL_NONADDRESSABLE_P (decl)

473             || DECL_SIZE_UNIT (decl) == 0

474             || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))

475        DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);

476 

477      /* Should this be controlled by DECL_USER_ALIGN, too?  */

478      if (maximum_field_alignment != 0)

479        DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);

480      if (!DECL_USER_ALIGN (decl))

481      {

482        /* Some targets (i.e. i386, VMS) limit struct field alignment

483          to a lower boundary than alignment of variables unless

484          it was overridden by attribute aligned.  */

485  #ifdef BIGGEST_FIELD_ALIGNMENT

486        DECL_ALIGN (decl)

487          = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT);

488  #endif

489  #ifdef ADJUST_FIELD_ALIGN

490        DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl));

491  #endif

492      }

493    }

 

For condition at line 470 & 471, indicates that if the field is packed but the alignment is not specified by “packed” attribute. And condition from line 472 to 474 indicates that, at the same time, if the field is either nonaddressable (for instance, bit-field), or its DECL_SIZE_UNIT is 0 (ECL_SIZE_UNIT is unset, seems impossible), or its DECL_SIZE_UNIT is integer constant; then it must ensure that its alignment is at least 1 byte (consider empty base class within this packed derived).

Above, at line 478, maximum_field_alignment is set by #pragma pack(N). See that this directive works at last for user.

At line 485 following, BIGGEST_FIELD_ALIGNMENT is used by libobjc. It is not defined here for C++ language.

Then at line 489, for x86 system, ADJUST_FIELD_ALIGN is defined as following. It and  BIGGEST_FIELD_ALIGNMENT are exclusive.

 

843  #define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) /                                   in i386.h

844     x86_field_alignment (FIELD, COMPUTED)

845  #endif

 

x86_field_alignment does platform special adjustment. When coming here, the declaration of unpacked type has been set after the type, which in turn comes from machmode.def. The file is constructed for all platforms. For certain types, upon certain platform, finer adjustment is expected. For example, double type, machmode.def says the alignment is 8 bytes. But on 32 bits x86 system, unless special specified, only 4 bytes is enough.

 

15705 int

15706 x86_field_alignment (tree field, int computed)                                                         in i386.c

15707 {

15708   enum machine_mode mode;

15709   tree type = TREE_TYPE (field);

15710

15711   if (TARGET_64BIT || TARGET_ALIGN_DOUBLE)

15712     return computed;

15713   mode = TYPE_MODE (TREE_CODE (type) == ARRAY_TYPE

15714                ? get_inner_array_type (type) : type);

15715   if (mode == DFmode || mode == DCmode

15716       || GET_MODE_CLASS (mode) == MODE_INT

15717       || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)

15718     return MIN (32, computed);

15719   return computed;

15720 }

 

At line 15711, TARGET_64BIT holds for 64 bits chip. And if TARGET_ALIGN_DOUBLE holds, it indicates target switch “-malign-double” is in used (by default is closed), which makes double, long double and long long be placed at boundary of double, i.e. 8 bytes. Of course, for these cases, no further adjustment is required.

And at line 15714, get_inner_array_type is used fetch the type of element of the array.

 

3827 tree

3828 get_inner_array_type (tree array)                                                                      in tree.c

3829 {

3830   tree type = TREE_TYPE (array);

3831

3832   while (TREE_CODE (type) == ARRAY_TYPE)

3833     type = TREE_TYPE (type);

3834

3835   return type;

3836 }

 

Rest code of layout_decl handles variable size declaration. For example, GNU C++ supports local variable size array, for instance: int j = 5; char arrC[i]; however this extension is inapplicable to fields of class.

2.2.3.1.5.2.2.5.5.  Update record_layout_info

Following, we need update the layout data into record_layout_info. In below, field holds data from layout_decl.

 

update_alignment_for_field (continue)

 

700    desired_align = DECL_ALIGN (field);

701    user_align = DECL_USER_ALIGN (field);

702 

703    is_bitfield = (type != error_mark_node

704                && DECL_BIT_FIELD_TYPE (field)

705                && ! integer_zerop (TYPE_SIZE (type)));

706 

707    /* Record must have at least as much alignment as any field.

708      Otherwise, the alignment of the field within the record is

709      meaningless.  */

710    if (is_bitfield && (* targetm.ms_bitfield_layout_p) (rli->t))

711    {

712      /* Here, the alignment of the underlying type of a bitfield can

713        affect the alignment of a record; even a zero-sized field

714        can do this. The alignment should be to the alignment of

715        the type, except that for zero-size bitfields this only

716        applies if there was an immediately prior, nonzero-size

717        bitfield. (That's the way it is, experimentally.) */

718      if (!integer_zerop (DECL_SIZE (field))

719          ? ! DECL_PACKED (field)

720           : (rli->prev_field

721             && DECL_BIT_FIELD_TYPE (rli->prev_field)

722             && ! integer_zerop (DECL_SIZE (rli->prev_field))))

723      {

724        unsigned int type_align = TYPE_ALIGN (type);

725        type_align = MAX (type_align, desired_align);

726        if (maximum_field_alignment != 0)

727          type_align = MIN (type_align, maximum_field_alignment);

728        rli->record_align = MAX (rli->record_align, type_align);

729        rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));

730      }

731    }

732  #ifdef PCC_BITFIELD_TYPE_MATTERS

733    else if (is_bitfield && PCC_BITFIELD_TYPE_MATTERS)

734    {

735      /* Named bit-fields cause the entire structure to have the

736        alignment implied by their type.  */

737      if (DECL_NAME (field) != 0)

738      {

739        unsigned int type_align = TYPE_ALIGN (type);

740 

741  #ifdef ADJUST_FIELD_ALIGN

742        if (!TYPE_USER_ALIGN (type))

743          type_align = ADJUST_FIELD_ALIGN (field, type_align);

744  #endif

745 

746        if (maximum_field_alignment != 0)

747          type_align = MIN (type_align, maximum_field_alignment);

748        else if (DECL_PACKED (field))

749          type_align = MIN (type_align, BITS_PER_UNIT);

750 

751        /* The alignment of the record is increased to the maximum

752          of the current alignment, the alignment indicated on the

753          field (i.e., the alignment specified by an __aligned__

754          attribute), and the alignment indicated by the type of

755          the field.  */

756        rli->record_align = MAX (rli->record_align, desired_align);

757        rli->record_align = MAX (rli->record_align, type_align);

758 

759        if (warn_packed)

760          rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));

761        user_align |= TYPE_USER_ALIGN (type);

762      }

763    }

764  #endif

765    else

766    {

767      rli->record_align = MAX (rli->record_align, desired_align);

768      rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));

769    }

770 

771    TYPE_USER_ALIGN (rli->t) |= user_align;

772 

773    return desired_align;

774  }

 

At line 710 above, the condition tells that if it is MS struct layout and it is the bit-field declaration, then to enter block at line 724, it must be packed; or if it has zero size, and previous field is bit field of nonzero size. Notice that for GCC default bit field layout, only naming declaration should have impact upon the structure.

As we expect, the size of the union is determined by it biggest field. In place_union_field, rli->offset is set in this way.

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (14))