Patchwork [Ada] Ada2012-A179 labels at end of a sequence_of_statements

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 7, 2010, 9:09 a.m.
Message ID <20101007090913.GA28387@adacore.com>
Download mbox | patch
Permalink /patch/67013/
State New
Headers show

Comments

Arnaud Charlet - Oct. 7, 2010, 9:09 a.m.
This patch implements the Ada2012 rule that a label can end a sequence of
statements, but the sequence cannot contain only labels.
The following must compile and execute quietly in Ada2012 mode:

procedure C5112lab is
   X : Integer := 0;
begin
   for I in 1 .. 20 loop
      if I > 7 then
          goto Continue;
      end if;

      X := X + 1;
  <<Continue>>
  end loop;

  pragma Assert (X = 7);
end C5112lab;
--

The following must be rejected with error messages where indicated:

procedure B5112lab is
begin
   if True then
     <<whatever>>   --  ERROR : statement expected
   end if;

   for I in 1 ..10 loop
     <<go_on>>
     <<continue>>   --  ERROR : statement expected
   end loop;

   for J in Standard.Character loop
      <<and_then>> null;
      <<nothing_else>>
   end loop;

   for J in Boolean loop
      exit;
      <<done>>
      <<finished>>
   end loop;
end B5112lab;

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

2010-10-07  Ed Schonberg  <schonberg@adacore.com>

	* par-ch5.adb (P_Sequence_Of_Statements): In Ada2012 a label can end a
	sequence of statements.

Patch

Index: par-ch5.adb
===================================================================
--- par-ch5.adb	(revision 165080)
+++ par-ch5.adb	(working copy)
@@ -83,7 +83,8 @@  package body Ch5 is
    -- 5.1  Sequence of Statements --
    ---------------------------------
 
-   --  SEQUENCE_OF_STATEMENTS ::= STATEMENT {STATEMENT}
+   --  SEQUENCE_OF_STATEMENTS ::= STATEMENT {STATEMENT} {LABEL}
+   --  Note: the final label is an Ada2012 addition.
 
    --  STATEMENT ::=
    --    {LABEL} SIMPLE_STATEMENT | {LABEL} COMPOUND_STATEMENT
@@ -149,6 +150,12 @@  package body Ch5 is
       --  is required. It is initialized from the Sreq flag, and modified as
       --  statements are scanned (a statement turns it off, and a label turns
       --  it back on again since a statement must follow a label).
+      --  Note : this final requirement is lifted in Ada2012.
+
+      Statement_Seen : Boolean;
+      --  In Ada2012 a label can end a sequence of statements, but the sequence
+      --  cannot contain only labels. This flag is set whenever a label is
+      --  encountered, to enforce this rule at the end of a sequence.
 
       Declaration_Found : Boolean := False;
       --  This flag is set True if a declaration is encountered, so that the
@@ -222,8 +229,10 @@  package body Ch5 is
 
             if Ada_Version >= Ada_2012
               and then not Is_Empty_List (Statement_List)
-              and then (Nkind (Last (Statement_List)) = N_Label
-                          or else All_Pragmas)
+              and then
+                ((Nkind (Last (Statement_List)) = N_Label
+                   and then Statement_Seen)
+                or else All_Pragmas)
             then
                declare
                   Null_Stm : constant Node_Id :=
@@ -233,8 +242,6 @@  package body Ch5 is
                   Append_To (Statement_List, Null_Stm);
                end;
 
-            --  All pragmas is OK on
-
             --  If not Ada 2012, or not special case above, give error message
 
             else
@@ -249,6 +256,7 @@  package body Ch5 is
    begin
       Statement_List := New_List;
       Statement_Required := SS_Flags.Sreq;
+      Statement_Seen     := False;
 
       loop
          Ignore (Tok_Semicolon);
@@ -765,8 +773,15 @@  package body Ch5 is
                   Statement_Required := False;
 
                --  Label starting with << which must precede real statement
+               --  Note: in Ada2012, the label may end the sequence.
 
                when Tok_Less_Less =>
+                  if Present (Last (Statement_List))
+                    and then Nkind (Last (Statement_List)) /= N_Label
+                  then
+                     Statement_Seen := True;
+                  end if;
+
                   Append_To (Statement_List, P_Label);
                   Statement_Required := True;