The front-end cannot inline subprograms that contain certain declarations,
such as nested subprograms.  If the the subprogram to inline includes a
subtype declaration with predicates, it cannot be inlined because the
analysis of the predicate will generate (nested) predicate functions.

Source:

---
package body Foo
with SPARK_Mode
is

   pragma Warnings (Off, "analyzing unreferenced procedure *");

   G_V  : Natural          := 123;
   G_VC : constant Natural := G_V;
   G_SC : constant Natural := 500;

   procedure Test_05 (A, B : Natural;
                      O    : out Boolean)
   is
      --  ok
      subtype T is Natural range 0 .. A  with Predicate => (3 <= T);
      subtype U is Natural range 0 .. 10 with Predicate => (B <= U);
      subtype V is Natural range 0 .. 10 with Predicate => (V in G_VC .. G_SC);

      X : Natural := 10;
   begin
      O := X in T | U | V;
   end Test_05;

end Foo;
--
package Foo
with SPARK_Mode
is
   pragma Elaborate_Body;
end Foo;
--
Command:

   gcc -c -gnatd.F foo.adb

Output:

foo.adb:15:07: info:
   no contextual analysis of "Test_05"(subtype declaration with predicate)

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

2015-10-26  Ed Schonberg  <schonb...@adacore.com>

        * inline.adb (Has_Excluded_Declaration): A subtype declaration
        with a predicate aspect generates a subprogram, and therefore
        prevents the inlining of the enclosing subprogram.

Index: inline.adb
===================================================================
--- inline.adb  (revision 229313)
+++ inline.adb  (working copy)
@@ -3513,6 +3513,37 @@
               ("cannot inline & (nested procedure instantiation)?",
                D, Subp);
             return True;
+
+         --  Subtype declarations with predicates will generate predicate
+         --  functions, i.e. nested subprogram bodies, so inlining is not
+         --  possible.
+
+         elsif Nkind (D) = N_Subtype_Declaration
+           and then Present (Aspect_Specifications (D))
+         then
+            declare
+               A    : Node_Id;
+               A_Id : Aspect_Id;
+
+            begin
+               A := First (Aspect_Specifications (D));
+               while Present (A) loop
+                  A_Id := Get_Aspect_Id (Chars (Identifier (A)));
+
+                  if A_Id = Aspect_Predicate
+                    or else A_Id = Aspect_Static_Predicate
+                    or else A_Id = Aspect_Dynamic_Predicate
+                  then
+                     Cannot_Inline
+                       ("cannot inline & "
+                        & "(subtype declaration with predicate)?",
+                        D, Subp);
+                     return True;
+                  end if;
+
+                  Next (A);
+               end loop;
+            end;
          end if;
 
          Next (D);

Reply via email to