https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63495
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2014-10-09 CC| |jakub at gcc dot gnu.org, | |jsm28 at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- This started with r205685. The problem is in the x86 32-bit ABI, which decreases alignment of fields to 32 bits if the field has integral mode, or DFmode/DCmode or complex integral mode. int x86_field_alignment (tree field, int computed) { enum machine_mode mode; tree type = TREE_TYPE (field); if (TARGET_64BIT || TARGET_ALIGN_DOUBLE) return computed; mode = TYPE_MODE (strip_array_types (type)); if (mode == DFmode || mode == DCmode || GET_MODE_CLASS (mode) == MODE_INT || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT) return MIN (32, computed); return computed; } When the struct has only a single field, it is QImode, therefore despite the user forced alignment the alignment is lowered to 32 bits. Now, when actually laying out struct s fields, such as: struct T { char a; struct s s; } t = { 1, { 2 } }; it actually is given 64-bit alignment, because ADJUST_FIELD_ALIGN is not used in that case: if (! packed_p && ! DECL_USER_ALIGN (decl)) { /* Some targets (i.e. i386, VMS) limit struct field alignment to a lower boundary than alignment of variables unless it was overridden by attribute aligned. */ #ifdef BIGGEST_FIELD_ALIGNMENT DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT); #endif #ifdef ADJUST_FIELD_ALIGN DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl)); #endif } As do_type_align for FIELD_DECLs sets DECL_USER_ALIGN: static inline void do_type_align (tree type, tree decl) { if (TYPE_ALIGN (type) > DECL_ALIGN (decl)) { DECL_ALIGN (decl) = TYPE_ALIGN (type); if (TREE_CODE (decl) == FIELD_DECL) DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type); } } if TYPE_USER_ALIGN is set, IMHO ADJUST_FIELD_ALIGN and corresponding BIGGEST_FIELD_ALIGNMENT will never be used.