This is the mail archive of the gcc-patches@gcc.gnu.org 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 wrong code with subtype of discriminated packed record


When processing a record-with-discriminant subtype, gigi first assigns
the GCC type/size of each component by getting the GCC equivalent of
the component Ada type, and fallsback on the the parent versions in
specific circumstances:

     << case E_Record_Subtype:

        /* When the type has discriminants, and these discriminants
           affect the shape of what it built, factor them in.

        for (gnat_field = First_Entity (gnat_entity);
             Present (gnat_field); gnat_field = Next_Entity (gnat_field))
        ...
        tree gnu_field_type
            = gnat_to_gnu_type (Etype (gnat_field));
        tree gnu_size = TYPE_SIZE (gnu_field_type);
        ...
        /* If there was a component clause, the field types must be
           the same for the type and subtype, so copy the data from
           the old field to avoid recomputation here. ... */

        /* If this was a bitfield, get the size from the old field.
           Also ensure the type can be placed into a bitfield.  */
     >>

This was missing important cases. For example with ...

   subtype Ubyte is Integer range 0 .. 255;
   type Packet (Id : Ubyte) is record
      A, B : Ubyte;
   end record;
   pragma Pack (Packet);

   subtype My_Packet is Packet (Id => 1);

... we fall into none of the special cases for any of the fields on
x86-linux, and their Etype node reads

      N_Defining_Identifier "packed_subtype__ubyte" (Entity_Id=1661)
      Ekind = E_Signed_Integer_Subtype
      Etype = N_Defining_Identifier "integer" (Entity_Id=715s)
  =>  Esize = 32 (Uint = 600032800)
      RM_Size = 8 (Uint = 600032776)

The positions are inherited properly, so we end up with the very nasty
combination below (-gnatR3):

      for My_Packet'Size use 24;
      for My_Packet'Alignment use 1;
      for My_Packet use record
         Id at 0 range  0 .. 31;
         A  at 1 range  0 .. 31;
         B  at 2 range  0 .. 31;
      end record;

Assignments to fields of My_Packet then store 32bits instead of 8,
with miscellaneous possible outcome. The testcase below

   procedure Packed_Subtype is

      subtype Ubyte is Integer range 0 .. 255;
      type Packet (Id : Ubyte) is record
	 A, B : Ubyte;
      end record;
      pragma Pack (Packet);

      subtype My_Packet is Packet (Id => 1);

      MP : My_Packet;
   begin
      MP.A := 1;
      MP.B := 2;

      if MP.A /= 1 or else MP.B /= 2 then
	 raise Program_Error;
      end if;
   end;

typically raises Program_Error or SEGVs on x86-linux depending on the
compilation options.

The change attached fixes this by generalizing the processing we
were doing for bitfields to packed fields of constant size, and also
propagates the DECL_PACKED indication to the subtype components.

Bootstrapped/regtested on i686-pc-linux-gnu. Applying to mainline.

2007-09-12  Olivier Hainque  <hainque@adacore.com>

	ada/
	* decl.c (gnat_to_gnu_entity) <E_Record_Subtype>: For a	subtype
	with discriminant constraints, generalize the code for BIT_FIELDs
	to PACKED fields of constant size and propagate DECL_PACKED.

	testsuite/
	* gnat.dg/packed_subtype.adb: New test.

Attachment: packed-subtype.dif
Description: Text document


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