[Ada] Crash with Inline_Always on a function with an extended return
authorEd Schonberg <schonberg@adacore.com>
Mon, 11 Jun 2018 09:17:04 +0000 (09:17 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Mon, 11 Jun 2018 09:17:04 +0000 (09:17 +0000)
This patch fixes a crash on a unit with a function with the GNAT-specific
Inline_Always pragma whose body is an extended return statement, when compiling
with no optimization level specified.

2018-06-11  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

* inline.adb (Expand_Inlined_Call): If no optimization level is
specified, the expansion of a call to an Inline_Always function is
fully performed in the front-end even on a target that support back-end
inlining.

gcc/testsuite/

* gnat.dg/inline_always1.adb: New testcase.

From-SVN: r261402

gcc/ada/ChangeLog
gcc/ada/inline.adb
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/inline_always1.adb [new file with mode: 0644]

index a2624b895348834c14cf7cb572f7dc7385643961..25e133e0d718e3a2fb432eff27cd42d787bb36b5 100644 (file)
@@ -1,3 +1,10 @@
+2018-06-11  Ed Schonberg  <schonberg@adacore.com>
+
+       * inline.adb (Expand_Inlined_Call): If no optimization level is
+       specified, the expansion of a call to an Inline_Always function is
+       fully performed in the front-end even on a target that support back-end
+       inlining.
+
 2018-06-11  Arnaud Charlet  <charlet@adacore.com>
 
        * bindgen.adb (Gen_Adainit): Protect reference to System.Parameters
index 336b336365af134d0db176effc333e3efcc279dd..f7e6b28ed0762c0d41d7acda5e3f438ca8f848c1 100644 (file)
@@ -2269,11 +2269,16 @@ package body Inline is
      Subp      : Entity_Id;
      Orig_Subp : Entity_Id)
    is
-      Loc       : constant Source_Ptr := Sloc (N);
-      Is_Predef : constant Boolean :=
-                    Is_Predefined_Unit (Get_Source_Unit (Subp));
-      Orig_Bod  : constant Node_Id :=
+      Loc           : constant Source_Ptr := Sloc (N);
+      Is_Predef     : constant Boolean :=
+                        Is_Predefined_Unit (Get_Source_Unit (Subp));
+      Orig_Bod      : constant Node_Id :=
                     Body_To_Inline (Unit_Declaration_Node (Subp));
+      Uses_Back_End : constant Boolean :=
+                         Back_End_Inlining and then Optimization_Level > 0;
+      --  The back-end expansion is used if the target supports back-end
+      --  inlining and some level of optimixation is required; otherwise
+      --  the inlining takes place fully as a tree expansion.
 
       Blk      : Node_Id;
       Decl     : Node_Id;
@@ -2840,7 +2845,7 @@ package body Inline is
    begin
       --  Initializations for old/new semantics
 
-      if not Back_End_Inlining then
+      if not Uses_Back_End then
          Is_Unc      := Is_Array_Type (Etype (Subp))
                           and then not Is_Constrained (Etype (Subp));
          Is_Unc_Decl := False;
@@ -2914,7 +2919,7 @@ package body Inline is
 
       --  Old semantics
 
-      if not Back_End_Inlining then
+      if not Uses_Back_End then
          declare
             Bod : Node_Id;
 
@@ -2958,8 +2963,20 @@ package body Inline is
                begin
                   First_Decl := First (Declarations (Blk));
 
+                  --  If the body is a single extended return statement,
+                  --  the resulting block is a nested block.
+
+                  if No (First_Decl) then
+                        First_Decl := First
+                          (Statements (Handled_Statement_Sequence (Blk)));
+
+                     if Nkind (First_Decl) = N_Block_Statement then
+                        First_Decl := First (Declarations (First_Decl));
+                     end if;
+                  end if;
+
                   if Nkind (First_Decl) /= N_Object_Declaration then
-                     return;
+                     return;  --  No front-end inlining possible,
                   end if;
 
                   if Nkind (Parent (N)) /= N_Assignment_Statement then
@@ -3288,7 +3305,7 @@ package body Inline is
          --  of the result of a call to an inlined function that returns
          --  an unconstrained type
 
-         elsif Back_End_Inlining
+         elsif Uses_Back_End
            and then Nkind (Parent (N)) = N_Object_Declaration
            and then Is_Unc
          then
index 579cc617c4d89ca2c2d516b969bc7c982a14e4c0..6d5e9644f99cfc26eb7dfab17b1c99560a7ef63d 100644 (file)
@@ -1,3 +1,7 @@
+2018-06-11  Ed Schonberg  <schonberg@adacore.com>
+
+       * gnat.dg/inline_always1.adb: New testcase.
+
 2018-06-11  Ed Schonberg  <schonberg@adacore.com>
 
        * gnat.dg/nested_generic2.adb, gnat.dg/nested_generic2.ads,
diff --git a/gcc/testsuite/gnat.dg/inline_always1.adb b/gcc/testsuite/gnat.dg/inline_always1.adb
new file mode 100644 (file)
index 0000000..59f161c
--- /dev/null
@@ -0,0 +1,57 @@
+--  { dg-do compile }
+
+with Ada.Text_IO;
+
+procedure Inline_Always1 is
+
+   function S(N : Integer ) return String is
+   begin
+      return "hello world";
+   end S;
+
+   type String_Access is access all String;
+   type R  is record
+      SA : String_Access;
+   end record;
+
+   Data : aliased String := "hello world";
+   My_SA : constant String_Access :=  Data'Access;
+   function Make_R( S : String ) return R is
+      My_R : R;
+   begin
+      My_R.SA := My_SA;
+      return My_R;
+   end Make_R;
+
+   function Get_String( My_R : R ) return String
+   is
+   begin
+      return S : String(My_R.SA.all'Range) do
+         S := My_R.SA.all;
+      end return;
+   end Get_String;
+   pragma Inline_Always( Get_String);
+
+   My_R : constant R := Make_R( "hello world");
+begin
+   for I in 1..10000 loop
+      declare
+         Res : constant String := S( 4 );
+      begin
+         Ada.Text_IO.Put_Line(Res);
+      end;
+      declare
+         Res : constant String := S( 4 );
+      begin
+         Ada.Text_IO.Put_Line(Res);
+      end;
+
+      declare
+         S : constant String := Get_String( My_R );
+      begin
+         Ada.Text_IO.Put_Line(S);
+         Ada.Text_IO.Put_Line(My_R.SA.all);
+      end;
+   end loop;
+
+end Inline_Always1;