This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] fix bug in Component_Alignment pragma + c330001 - PR ada/19386

Tested under i686-linux, commited on mainline.

The key is the global pragma Component_Alignment (Storage_Unit) at the
beginning of the procedure: every single record is handled as a packed
record by gigi and the back-end.  In particular, the inner_t1 field of
the t1 type goes through the make_packable_type machinery and is promoted
to HImode and 16-bit aligned.  So t1 ends up being 16-bit aligned too.
The problem is that t2 is not promoted to 16-bit alignment: although it
contains an array of elements of variable-sized type, the element type is
wrapped up in a padding type with fixed size, so there is no reason to
propagate the alignment.  So t2 ends up with 8-bit alignment.
Problems arise when the address of an element (of type t1) of this array
is to be taken: because of the alignment discrepancy, a temporary might
be needed.  Now the back-end does not know how to make temporaries of
variable-sized objects and thus aborts.
This would work if the records were explicitly marked as pragma (Pack):
the difference comes from the addressable_p predicate, which returns True
if the former case and False in the latter case.  This in turn comes from
the following discrepancy:

 Pragma Component_Alignment (Storage_Unit)  ->  DECL_PACKED

 Pragma (Pack)  ->  DECL_PACKED + DECL_BIT_FIELD

in create_field_decl.
The fix is to be more consistent in the Component_Alignment (Storage_Unit)
case: since we do not preventively set DECL_BIT_FIELD in create_field_decl,
we should not try to overalign fields by calling make_packable_type on them.
procedure p is
  pragma Component_Alignment (Storage_Unit);
  type hword is mod 2**16;
  type inner_t1 is record f1,f2 : Boolean; end record;
  type t1 (d : hword := 0) is record
    i : inner_t1;
    case d is
      when 1 => fn : hword;
      when others => null;
    end case;
  end record;
  type t1_array is array(1..16) of t1;
  type t2 is record arr: t1_array; end record;
  procedure write_t1 (t : t1) is begin null; end;
  procedure write_t2 (t : t2) is
     for i in 1..16 loop write_t1(t.arr(i)); end loop;
  my_t2 : t2;
begin write_t2(my_t2); end;

Fix for c330001 - PR ada/19386:
If we have a subtype with a _Parent field, that field will overlap that of
fields within the subtype that were derived from the parent.  GCC assumes
that a RECORD_TYPE does not have any overlapping fields.  So we need to make
such a record a UNION_TYPE.  However, Gigi assumes all UNION_TYPEs are
Unchecked_Unions, so we need to add a flag to indicate that case and change
all code that handles unchecked unions to check that flag and a lot of code
that handles RECORD_TYPE to also handle UNION_TYPE.

Note that we do not have this problem with subtypes of variant records.  In
that case, fields may indeed overlap, but it is not legal to reference the
same item using both overlapping fields, so for that case the assumption that
GCC makes for RECORD_TYPE is the desired one.

Also, coordinate front-end and back-end warnings by propagating the front-end
  pragma Warnings (Off, Variable);
to the back-end by means of the TREE_NO_WARNING flag set on tree nodes.

2005-02-09  Eric Botcazou  <>
	    Richard Kenner  <>

	Fix for c330001 - PR ada/19386

	* decl.c: 
	(gnat_to_gnu_field): Do not necessarily invoke make_packable_type
	on the field if Pragma Component_Alignment (Storage_Unit).
	(gnat_to_gnu_entity, case object): Do not treat a renaming that has
	side-effects as if it were a constant; also make SAVE_EXPR to protect
	(gnat_to_gnu_entity, case E_Record_Subtype): If have _Parent, make a
	(make_dummy_type): Set TYPE_UNCHECKED_UNION_P.
	(components_to_record): Test it.
	Fix improper usage of REFERENCE_CLASS_P.

	* utils2.c (build_binary_op, case MODIFY_EXPRP): Treat UNION_TYPE as

	* utils2.c: Minor reformatting.

	* utils.c (convert, case UNION_TYPE): Check TYPE_UNCHECKED_UNION;
	handle other cases like RECORD_TYPE.

	* utils.c (gnat_pushdecl): Set TREE_NO_WARNING.

Attachment: difs.7
Description: Text document

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]