In -gnatct mode, the compiler doesn't generate code and gigi is only invoked to lay out and back-annotate types. There were old issues when representation clauses are present: fields are shifted, sizes are wrong, component clauses are overridden.
Tested on i586-suse-linux, applied on the mainline. 2012-04-30 Eric Botcazou <ebotca...@adacore.com> * gcc-interface/decl.c (gnat_to_gnu_entity): In type annotation mode, do not adjust the size of a tagged type if there is a representation clause on it. Otherwise, round the adjustment up to the alignment of the first field and use the appropriate helper routine. (maybe_pad_type): Do not warn in type annotation mode on a tagged type. (gnat_to_gnu_field): Do not error out under the same circumstances. (annotate_rep): In type annotation mode, do not adjust the offset of components of a tagged type with representation clause. Otherwise, round the adjustment up to the alignment of the first field. -- Eric Botcazou
Index: gcc-interface/decl.c =================================================================== --- gcc-interface/decl.c (revision 186956) +++ gcc-interface/decl.c (working copy) @@ -5027,28 +5027,33 @@ gnat_to_gnu_entity (Entity_Id gnat_entit if (CONTAINS_PLACEHOLDER_P (gnu_size)) gnu_size = max_size (gnu_size, true); - if (type_annotate_only && Is_Tagged_Type (gnat_entity)) + /* If we are just annotating types and the type is tagged, the tag + and the parent components are not generated by the front-end so + sizes must be adjusted if there is no representation clause. */ + if (type_annotate_only + && Is_Tagged_Type (gnat_entity) + && !VOID_TYPE_P (gnu_type) + && (!TYPE_FIELDS (gnu_type) + || integer_zerop (bit_position (TYPE_FIELDS (gnu_type))))) { - /* In this mode, the tag and the parent components are not - generated by the front-end so the sizes must be adjusted. */ tree pointer_size = bitsize_int (POINTER_SIZE), offset; Uint uint_size; if (Is_Derived_Type (gnat_entity)) { - offset = UI_To_gnu (Esize (Etype (Base_Type (gnat_entity))), - bitsizetype); - Set_Alignment (gnat_entity, - Alignment (Etype (Base_Type (gnat_entity)))); + Entity_Id gnat_parent = Etype (Base_Type (gnat_entity)); + offset = UI_To_gnu (Esize (gnat_parent), bitsizetype); + Set_Alignment (gnat_entity, Alignment (gnat_parent)); } else offset = pointer_size; + if (TYPE_FIELDS (gnu_type)) + offset + = round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type))); + gnu_size = size_binop (PLUS_EXPR, gnu_size, offset); - gnu_size = size_binop (MULT_EXPR, pointer_size, - size_binop (CEIL_DIV_EXPR, - gnu_size, - pointer_size)); + gnu_size = round_up (gnu_size, POINTER_SIZE); uint_size = annotate_value (gnu_size); Set_Esize (gnat_entity, uint_size); Set_RM_Size (gnat_entity, uint_size); @@ -6619,7 +6624,9 @@ maybe_pad_type (tree type, tree size, un /* If the size was widened explicitly, maybe give a warning. Take the original size as the maximum size of the input if there was an unconstrained record involved and round it up to the specified alignment, - if one was specified. */ + if one was specified. But don't do it if we are just annotating types + and the type is tagged, since tagged types aren't fully laid out in this + mode. */ if (CONTAINS_PLACEHOLDER_P (orig_size)) orig_size = max_size (orig_size, true); @@ -6635,7 +6642,8 @@ maybe_pad_type (tree type, tree size, un && TREE_CODE (orig_size) == INTEGER_CST && (TREE_OVERFLOW (size) || TREE_OVERFLOW (orig_size) - || tree_int_cst_lt (size, orig_size)))) + || tree_int_cst_lt (size, orig_size))) + && !(type_annotate_only && Is_Tagged_Type (Etype (gnat_entity)))) { Node_Id gnat_error_node = Empty; @@ -6901,10 +6909,13 @@ gnat_to_gnu_field (Entity_Id gnat_field, } } - /* If this field needs strict alignment, ensure the record is - sufficiently aligned and that that position and size are - consistent with the alignment. */ - if (needs_strict_alignment) + /* If this field needs strict alignment, check that the record is + sufficiently aligned and that position and size are consistent + with the alignment. But don't do it if we are just annotating + types and the field's type is tagged, since tagged types aren't + fully laid out in this mode. */ + if (needs_strict_alignment + && !(type_annotate_only && Is_Tagged_Type (gnat_field_type))) { TYPE_ALIGN (gnu_record_type) = MAX (TYPE_ALIGN (gnu_record_type), TYPE_ALIGN (gnu_field_type)); @@ -7839,12 +7850,16 @@ annotate_rep (Entity_Id gnat_entity, tre { tree parent_offset; - if (type_annotate_only && Is_Tagged_Type (gnat_entity)) + /* If we are just annotating types and the type is tagged, the tag + and the parent components are not generated by the front-end so + we need to add the appropriate offset to each component without + representation clause. */ + if (type_annotate_only + && Is_Tagged_Type (gnat_entity) + && No (Component_Clause (gnat_field))) { - /* In this mode the tag and parent components are not - generated, so we add the appropriate offset to each - component. For a component appearing in the current - extension, the offset is the size of the parent. */ + /* For a component appearing in the current extension, the + offset is the size of the parent. */ if (Is_Derived_Type (gnat_entity) && Original_Record_Component (gnat_field) == gnat_field) parent_offset @@ -7852,6 +7867,11 @@ annotate_rep (Entity_Id gnat_entity, tre bitsizetype); else parent_offset = bitsize_int (POINTER_SIZE); + + if (TYPE_FIELDS (gnu_type)) + parent_offset + = round_up (parent_offset, + DECL_ALIGN (TYPE_FIELDS (gnu_type))); } else parent_offset = bitsize_zero_node;