This change lifts the arbitrary limitation on the number of iterations that
can be executed between loading of the inlined bodies and instantiation of
the generic bodies of external units when inter-unit inlining is activated.
It was previously limited to 1 but this may be not sufficient in some cases,
which can result in pragma Inline_Always not being honored.

The following code must compile quietly with -O -gnatn:

with Q; use Q;

package P is

   function F (Cal : Calendar) return Boolean;

end P;
package body P is

   function F (Cal : Calendar) return Boolean is
   begin
      return Pred (Cal);
   end;

end P;

with R; use R;

package Q is

   type Calendar is new Object_Ref;

   type Root_Calendar is new Root_Object with record
      B : Boolean;
   end record;

   type Root_Calendar_Ptr is access all Root_Calendar'Class;

   function Pred (Cal : Calendar) return Boolean;
   pragma Inline (Pred);

end Q;
package body Q is

   function Get_Calendar is new Get_Object (Root_Calendar, Root_Calendar_Ptr);
   pragma Inline (Get_Calendar);

   function Pred (Cal : Calendar) return Boolean is
      Cal_Object : constant Root_Calendar_Ptr
         := Get_Calendar (Object_Ref (Cal));
   begin
      return Cal_Object.B;
   end;
end Q;

with Ada.Finalization;

package R is

   type Root_Object is new Ada.Finalization.Controlled with record
      Reference_Count : Natural;
   end record;

   type Object_Ref is private;

   type Root_Object_Ptr is access all Root_Object'Class;

   generic
      type Object (<>) is abstract new Root_Object with private;
      type Object_Ptr is access all Object'Class;
   function Get_Object (Ref : in Object_Ref) return Object_Ptr;

private

   type Object_Ref is new Ada.Finalization.Controlled with record
      Ptr : Root_Object_Ptr;
   end record;

end R;
package body R is

   function Get_Object (Ref : in Object_Ref) return Object_Ptr is
   begin
      return Object_Ptr (Ref.Ptr);
   end Get_Object;

end R;

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-11-20  Eric Botcazou  <ebotca...@adacore.com>

        * inline.adb (Analyze_Inlined_Bodies): Iterate between loading
        of the inlined bodies and instantiation of the generic bodies
        until no more bodies need to be loaded.

Index: inline.adb
===================================================================
--- inline.adb  (revision 217828)
+++ inline.adb  (working copy)
@@ -774,16 +774,21 @@
             end if;
 
             J := J + 1;
-         end loop;
 
-         --  The analysis of required bodies may have produced additional
-         --  generic instantiations. To obtain further inlining, we perform
-         --  another round of generic body instantiations. Establishing a
-         --  fully recursive loop between inlining and generic instantiations
-         --  is unlikely to yield more than this one additional pass.
+            if J > Inlined_Bodies.Last then
 
-         Instantiate_Bodies;
+               --  The analysis of required bodies may have produced additional
+               --  generic instantiations. To obtain further inlining, we need
+               --  to perform another round of generic body instantiations.
 
+               Instantiate_Bodies;
+
+               --  Symmetrically, the instantiation of required generic bodies
+               --  may have caused additional bodies to be inlined. To obtain
+               --  further inlining, we keep looping over the inlined bodies.
+            end if;
+         end loop;
+
          --  The list of inlined subprograms is an overestimate, because it
          --  includes inlined functions called from functions that are compiled
          --  as part of an inlined package, but are not themselves called. An

Reply via email to