The MS bitfields ABI and its stringent rules totally break packing in Ada, so we cannot use the C layout in this case. The i386.c hunk fixes an oversight which would result in gazillions of warnings for QUAL_UNION_TYPE.
Tested on i586-suse-linux and i686-pc-mingw32, applied on the mainline and the 4.7 branch (as obvious for the i386.c hunk). 2012-04-30 Eric Botcazou <ebotca...@adacore.com> * config/i386/i386.c (ix86_handle_struct_attribute): Use the proper predicate to discriminate types. 2012-04-30 Eric Botcazou <ebotca...@adacore.com> * gcc-interface/utils.c (finish_record_type): Force the traditional GCC layout for bitfields on the type if it is packed or has a representation clause and an alternate layout is available. -- Eric Botcazou
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 186907) +++ config/i386/i386.c (working copy) @@ -32465,8 +32465,7 @@ ix86_handle_struct_attribute (tree *node else type = node; - if (!(type && (TREE_CODE (*type) == RECORD_TYPE - || TREE_CODE (*type) == UNION_TYPE))) + if (!(type && RECORD_OR_UNION_TYPE_P (*type))) { warning (OPT_Wattributes, "%qE attribute ignored", name); Index: ada/gcc-interface/utils.c =================================================================== --- ada/gcc-interface/utils.c (revision 186956) +++ ada/gcc-interface/utils.c (working copy) @@ -721,6 +721,19 @@ finish_record_type (tree record_type, tr case where there is a rep clause but all fields have errors and no longer have a position. */ TYPE_SIZE (record_type) = 0; + + /* Ensure we use the traditional GCC layout for bitfields when we need + to pack the record type or have a representation clause. The other + possible layout (Microsoft C compiler), if available, would prevent + efficient packing in almost all cases. */ +#ifdef TARGET_MS_BITFIELD_LAYOUT + if (TARGET_MS_BITFIELD_LAYOUT && TYPE_PACKED (record_type)) + decl_attributes (&record_type, + tree_cons (get_identifier ("gcc_struct"), + NULL_TREE, NULL_TREE), + ATTR_FLAG_TYPE_IN_PLACE); +#endif + layout_type (record_type); }