This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] Exit statement in loops over iterable objects


This patch fixes an omission in the expansion of loops over GNAT-specific
iterable objects. If the source includes an explicit name for the loop,
that name has to be preserved in the expanded code to allow exit statements
to mention it.

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

2018-05-21  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

	* exp_ch5.adb (Build_Formal_Container_Iteration): If source has
	explicit name for iterator loop, preserve that name in expanded
	construct, for possible use in exit statements.

gcc/testsuite/

	* gnat.dg/exit1.adb: New testcase.
--- gcc/ada/exp_ch5.adb
+++ gcc/ada/exp_ch5.adb
@@ -237,6 +237,15 @@ package body Exp_Ch5 is
                     New_Occurrence_Of (Cursor, Loc)))),
           Statements => Stats,
           End_Label  => Empty);
+
+      --  If the contruct has a specified loop name, preserve it in the
+      --  new loop, for possible use in exit statements.
+
+      if Present (Identifier (N))
+        and then Comes_From_Source (Identifier (N))
+      then
+         Set_Identifier (New_Loop, Identifier (N));
+      end if;
    end Build_Formal_Container_Iteration;
 
    ------------------------------

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/exit1.adb
@@ -0,0 +1,45 @@
+--  { dg-do run }
+--  { dg-output "1 2 3 4 5 6 7 \| 1- 1 2 3 2- 1 2 3 3- 1 2 3 4- 1 2 3 5- 1 2 3" }
+
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Exit1 is
+   type Int_Range is record
+      First, Last : Integer;
+   end record
+      with Iterable => (First => First,
+                        Next => Next,
+                        Previous => Previous,
+                        Last => Last,
+                        Has_Element => Has_Element,
+                        Element => Element);
+
+   function First (IR : Int_Range) return Integer is (IR.First);
+   function Last (IR : Int_Range) return Integer is (IR.Last);
+   function Next (IR : Int_Range; N : Integer) return Integer is (N + 1);
+   function Previous (IR : Int_Range; N : Integer) return Integer is (N - 1);
+   function Has_Element (IR : Int_Range; N : Integer) return Boolean is
+     (N in IR.First ..IR.Last);
+   function Element (IR : Int_Range; N : Integer) return Integer is (N);
+
+   IR : Int_Range := (1, 10);
+
+begin
+A_Loop:   for I of IR loop
+      Put (I'Img);
+      exit A_Loop when I = 7;
+   end loop A_Loop;
+   Put (" | ");
+
+B_Loop:   for I of IR loop
+      Put (I'Img & '-');
+  C_Loop : for J of IR loop
+         Put (J'Img);
+         exit when J = 3;
+      end loop C_Loop;
+
+      exit B_Loop when I = 5;
+   end loop B_Loop;
+   New_Line;
+
+end Exit1;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]