[Ada] Fix expansion of blocks in loops inside elaboration code
authorEd Schonberg <schonberg@adacore.com>
Mon, 16 Jul 2018 14:12:18 +0000 (14:12 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Mon, 16 Jul 2018 14:12:18 +0000 (14:12 +0000)
2018-07-16  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

* exp_ch7.adb (Check_Unnesting_Elaboration_Code): Handle loops that
contain blocks in the elaboration code for a package body. Create the
elaboration subprogram wrapper only if there is a subprogram
declaration in a block or loop.

From-SVN: r262728

gcc/ada/ChangeLog
gcc/ada/exp_ch7.adb

index 22fc57b87520e64d8428862e468d34c63e76606f..cea35021a1de368dcf5685d1f4e08c6cfea982be 100644 (file)
@@ -1,3 +1,10 @@
+2018-07-16  Ed Schonberg  <schonberg@adacore.com>
+
+       * exp_ch7.adb (Check_Unnesting_Elaboration_Code): Handle loops that
+       contain blocks in the elaboration code for a package body. Create the
+       elaboration subprogram wrapper only if there is a subprogram
+       declaration in a block or loop.
+
 2018-07-16  Ed Schonberg  <schonberg@adacore.com>
 
        * exp_ch4.adb (Expand_Set_Membership): Use New_Copy_Tree to perform a
index d14cd7ee3b8fa324fc93c912561be56a8548c30a..b1f2b436ec8a56656ebdc2cc000bfc15d45e06a5 100644 (file)
@@ -3994,6 +3994,34 @@ package body Exp_Ch7 is
       Elab_Call : Node_Id;
       Elab_Proc : Entity_Id;
       Stat      : Node_Id;
+      function Contains_Subprogram (Blk : Entity_Id) return Boolean;
+      --  Check recursively whether a loop or block contains a subprogram
+      --  that may need an activation record.
+
+      --------------------------
+      --  Contains_Subprogram --
+      --------------------------
+
+      function Contains_Subprogram (Blk : Entity_Id) return Boolean is
+         E : Entity_Id;
+      begin
+         E := First_Entity (Blk);
+
+         while Present (E) loop
+            if Is_Subprogram (E) then
+               return True;
+
+            elsif Ekind_In (E, E_Block, E_Loop)
+              and then Contains_Subprogram (E)
+            then
+               return True;
+            end if;
+
+            Next_Entity (E);
+         end loop;
+
+         return False;
+      end Contains_Subprogram;
 
    begin
       if Unnest_Subprogram_Mode
@@ -4002,8 +4030,10 @@ package body Exp_Ch7 is
       then
          Stat := First (Statements (Handled_Statement_Sequence (N)));
          while Present (Stat) loop
-            exit when Nkind (Stat) = N_Block_Statement
-              and then Present (Identifier (Stat));
+            exit when ((Nkind (Stat) = N_Block_Statement
+                         and then Present (Identifier (Stat)))
+                or else Nkind (Stat) = N_Loop_Statement)
+              and then Contains_Subprogram (Entity (Identifier (Stat)));
             Next (Stat);
          end loop;
 
@@ -4035,17 +4065,18 @@ package body Exp_Ch7 is
 
             Analyze (Elab_Call);
 
-            --  The scope of all blocks in the elaboration code is now the
-            --  constructed elaboration procedure. Nested subprograms within
-            --  those blocks will have activation records if they contain
-            --  references to entities in the enclosing block.
+            --  The scope of all blocks and loops in the elaboration code is
+            --  now the constructed elaboration procedure. Nested subprograms
+            --  within those blocks will have activation records if they
+            --  contain references to entities in the enclosing block.
 
             Stat :=
               First (Statements (Handled_Statement_Sequence (Elab_Body)));
 
             while Present (Stat) loop
-               if Nkind (Stat) = N_Block_Statement
-                 and then Present (Identifier (Stat))
+               if (Nkind (Stat) = N_Block_Statement
+                    and then Present (Identifier (Stat)))
+                 or else Nkind (Stat) = N_Loop_Statement
                then
                   Set_Scope (Entity (Identifier (Stat)), Elab_Proc);