This is a regression present on all active branches which comes from an 
oversight in self_referential_size: the code sets DECL_ARG_TYPE of the 
parameters it builds as the C/C++/Ada compilers but it doesn't generate the 
associated conversions in the GENERIC code, which later fools the combiner.

The original idea was to mimic the C/C++/Ada compilers here, but the actual 
conversions have never been generated and the size functions are meant to be 
inlined anyway, so the attached patch simply removes the problematic code.

Tested on x86_64-suse-linux, applied on all active branches (this only affects 
the Ada compiler).


2014-10-15  Eric Botcazou  <ebotca...@adacore.com>

        * stor-layout.c (self_referential_size): Do not promote arguments.


2014-10-15  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt41.adb: New test.
        * gnat.dg/opt41_pkg.ad[sb]: New helper.


-- 
Eric Botcazou
Index: stor-layout.c
===================================================================
--- stor-layout.c	(revision 216144)
+++ stor-layout.c	(working copy)
@@ -211,12 +211,7 @@ self_referential_size (tree size)
       param_type = TREE_TYPE (ref);
       param_decl
 	= build_decl (input_location, PARM_DECL, param_name, param_type);
-      if (targetm.calls.promote_prototypes (NULL_TREE)
-	  && INTEGRAL_TYPE_P (param_type)
-	  && TYPE_PRECISION (param_type) < TYPE_PRECISION (integer_type_node))
-	DECL_ARG_TYPE (param_decl) = integer_type_node;
-      else
-	DECL_ARG_TYPE (param_decl) = param_type;
+      DECL_ARG_TYPE (param_decl) = param_type;
       DECL_ARTIFICIAL (param_decl) = 1;
       TREE_READONLY (param_decl) = 1;
 
-- { dg-do run }
-- { dg-options "-Os" }

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Opt41_Pkg;             use Opt41_Pkg;

procedure Opt41 is
   R  : Rec := (Five, To_Unbounded_String ("CONFIG"));
   SP : String_Access := new String'(To_String (Rec_Write (R)));
   RP : Rec_Ptr := new Rec'(Rec_Read (SP));
begin
   if RP.D /= R.D then
      raise Program_Error;
   end if;
end;
with Ada.Streams; use Ada.Streams;

package body Opt41_Pkg is

   type Wstream is new Root_Stream_Type with record
      S : Unbounded_String;
   end record;

   procedure Read (Stream : in out Wstream;
                   Item   : out Stream_Element_Array;
                   Last   : out Stream_Element_Offset) is null;

   procedure Write (Stream : in out Wstream; Item : Stream_Element_Array) is
   begin
      for J in Item'Range loop
         Append (Stream.S, Character'Val (Item (J)));
      end loop;
   end Write;

   function Rec_Write (R : Rec) return Unbounded_String is
      S : aliased Wstream;
   begin
      Rec'Output (S'Access, R);
      return S.S;
   end Rec_Write;

   type Rstream is new Root_Stream_Type with record
      S   : String_Access;
      Idx : Integer := 1;
   end record;

   procedure Write (Stream : in out Rstream; Item : Stream_Element_Array) is null;

   procedure Read (Stream : in out Rstream;
                   Item   : out Stream_Element_Array;
                   Last   : out Stream_Element_Offset) is
   begin
      Last := Stream_Element_Offset'Min
         (Item'Last, Item'First + Stream_Element_Offset (Stream.S'Last - Stream.Idx));
      for I in Item'First .. Last loop
         Item (I) := Stream_Element (Character'Pos (Stream.S (Stream.Idx)));
         Stream.Idx := Stream.Idx + 1;
      end loop;
   end Read;

   function Rec_Read (Str : String_Access) return Rec is
      S : aliased Rstream;
   begin
      S.S := Str;
      return Rec'Input (S'Access);
   end Rec_Read;

end Opt41_Pkg;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

package Opt41_Pkg is

   type Enum is (One, Two, Three, Four, Five, Six);

   type Rec (D : Enum) is record
      case D is
         when One => 
            I : Integer;
         when Two | Five | Six =>
            S : Unbounded_String;
            case D is
               when Two => B : Boolean;
               when others => null;
            end case;
         when others =>
            null;
      end case;
   end record;

   type Rec_Ptr is access all Rec;

   function Rec_Write (R : Rec) return Unbounded_String;

   function Rec_Read (Str : String_Access) return Rec;

end Opt41_Pkg;

Reply via email to