diff mbox

[Ada] Legality of null dependence items

Message ID 20131014133922.GA5462@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Oct. 14, 2013, 1:39 p.m. UTC
This patch catches two syntax errors related to the use of null items in aspect
or pragma [Refined_]Depends. The patch also streamlines the error messages of
various aspects or pragmas that deal with null and non-null items.

------------
-- Source --
------------

--  depends_illegal.ads

package Depends_Illegal is
   procedure P1 (Par1 : Integer)
      with Depends => (null =>+ Par1);

   procedure P2 (Par1 : Integer ; Par2 : out Integer)
      with Depends => (Par2 => (Par1, null));
end Depends_Illegal;

----------------------------
-- Compilation and output --
----------------------------

$ gcc -c -gnatd.V depends_legal.ads
depends_illegal.ads:3:24: useless dependence, null depends on itself
depends_illegal.ads:6:39: cannot mix null and non-null dependency items

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

2013-10-14  Hristian Kirtchev  <kirtchev@adacore.com>

	* sem_prag.adb (Analyze_Dependency_Clause): Add new local variable
	Non_Null_Output_Seen.  Update the call to Analyze_Input_Output.
	(Analyze_Input_Item): Streamline the detection mechanism of null and
	non-null items.
	(Analyze_Input_List): Add new local variable
	Non_Null_Input_Seen. Update all calls to Analyze_Input_Output.
	(Analyze_Input_Output): Add new formal parameter Non_Null_Seen
	and update the related comment on usage. Update the
	recursive call to itself. Attribute 'Result is now treated
	as a non-null item. Detect mixes of null and non-null items.
	(Analyze_Initialization_Item): Streamline the detection mechanism
	of null and non-null items.
diff mbox

Patch

Index: sem_prag.adb
===================================================================
--- sem_prag.adb	(revision 203551)
+++ sem_prag.adb	(working copy)
@@ -555,12 +555,13 @@ 
          --  Verify the legality of a single input list
 
          procedure Analyze_Input_Output
-           (Item      : Node_Id;
-            Is_Input  : Boolean;
-            Self_Ref  : Boolean;
-            Top_Level : Boolean;
-            Seen      : in out Elist_Id;
-            Null_Seen : in out Boolean);
+           (Item          : Node_Id;
+            Is_Input      : Boolean;
+            Self_Ref      : Boolean;
+            Top_Level     : Boolean;
+            Seen          : in out Elist_Id;
+            Null_Seen     : in out Boolean;
+            Non_Null_Seen : in out Boolean);
          --  Verify the legality of a single input or output item. Flag
          --  Is_Input should be set whenever Item is an input, False when it
          --  denotes an output. Flag Self_Ref should be set when the item is an
@@ -568,7 +569,8 @@ 
          --  be set whenever Item appears immediately within an input or output
          --  list. Seen is a collection of all abstract states, variables and
          --  formals processed so far. Flag Null_Seen denotes whether a null
-         --  input or output has been encountered.
+         --  input or output has been encountered. Flag Non_Null_Seen denotes
+         --  whether a non-null input or output has been encountered.
 
          ------------------------
          -- Analyze_Input_List --
@@ -579,8 +581,9 @@ 
             --  A list containing the entities of all inputs that appear in the
             --  current input list.
 
-            Null_Input_Seen : Boolean := False;
-            --  A flag used to track the legality of a null input
+            Non_Null_Input_Seen : Boolean := False;
+            Null_Input_Seen     : Boolean := False;
+            --  Flags used to check the legality of an input list
 
             Input : Node_Id;
 
@@ -596,12 +599,13 @@ 
                   Input := First (Expressions (Inputs));
                   while Present (Input) loop
                      Analyze_Input_Output
-                       (Item      => Input,
-                        Is_Input  => True,
-                        Self_Ref  => False,
-                        Top_Level => False,
-                        Seen      => Inputs_Seen,
-                        Null_Seen => Null_Input_Seen);
+                       (Item          => Input,
+                        Is_Input      => True,
+                        Self_Ref      => False,
+                        Top_Level     => False,
+                        Seen          => Inputs_Seen,
+                        Null_Seen     => Null_Input_Seen,
+                        Non_Null_Seen => Non_Null_Input_Seen);
 
                      Next (Input);
                   end loop;
@@ -614,12 +618,13 @@ 
 
             else
                Analyze_Input_Output
-                 (Item      => Inputs,
-                  Is_Input  => True,
-                  Self_Ref  => False,
-                  Top_Level => False,
-                  Seen      => Inputs_Seen,
-                  Null_Seen => Null_Input_Seen);
+                 (Item          => Inputs,
+                  Is_Input      => True,
+                  Self_Ref      => False,
+                  Top_Level     => False,
+                  Seen          => Inputs_Seen,
+                  Null_Seen     => Null_Input_Seen,
+                  Non_Null_Seen => Non_Null_Input_Seen);
             end if;
 
             --  Detect an illegal dependency clause of the form
@@ -638,12 +643,13 @@ 
          --------------------------
 
          procedure Analyze_Input_Output
-           (Item      : Node_Id;
-            Is_Input  : Boolean;
-            Self_Ref  : Boolean;
-            Top_Level : Boolean;
-            Seen      : in out Elist_Id;
-            Null_Seen : in out Boolean)
+           (Item          : Node_Id;
+            Is_Input      : Boolean;
+            Self_Ref      : Boolean;
+            Top_Level     : Boolean;
+            Seen          : in out Elist_Id;
+            Null_Seen     : in out Boolean;
+            Non_Null_Seen : in out Boolean)
          is
             Is_Output : constant Boolean := not Is_Input;
             Grouped   : Node_Id;
@@ -666,12 +672,13 @@ 
                   Grouped := First (Expressions (Item));
                   while Present (Grouped) loop
                      Analyze_Input_Output
-                       (Item      => Grouped,
-                        Is_Input  => Is_Input,
-                        Self_Ref  => Self_Ref,
-                        Top_Level => False,
-                        Seen      => Seen,
-                        Null_Seen => Null_Seen);
+                       (Item          => Grouped,
+                        Is_Input      => Is_Input,
+                        Self_Ref      => Self_Ref,
+                        Top_Level     => False,
+                        Seen          => Seen,
+                        Null_Seen     => Null_Seen,
+                        Non_Null_Seen => Non_Null_Seen);
 
                      Next (Grouped);
                   end loop;
@@ -683,6 +690,7 @@ 
             --  Process Function'Result in the context of a dependency clause
 
             elsif Is_Attribute_Result (Item) then
+               Non_Null_Seen := True;
 
                --  It is sufficent to analyze the prefix of 'Result in order to
                --  establish legality of the attribute.
@@ -707,6 +715,10 @@ 
                elsif Is_Input then
                   Error_Msg_N ("function result cannot act as input", Item);
 
+               elsif Null_Seen then
+                  Error_Msg_N
+                    ("cannot mix null and non-null dependency items", Item);
+
                else
                   Result_Seen := True;
                end if;
@@ -719,19 +731,39 @@ 
                if Null_Seen then
                   Error_Msg_N
                     ("multiple null dependency relations not allowed", Item);
+
+               elsif Non_Null_Seen then
+                  Error_Msg_N
+                    ("cannot mix null and non-null dependency items", Item);
+
                else
                   Null_Seen := True;
 
-                  if Is_Output and then not Is_Last then
-                     Error_Msg_N
-                       ("null output list must be the last clause in a "
-                        & "dependency relation", Item);
+                  if Is_Output then
+                     if not Is_Last then
+                        Error_Msg_N
+                          ("null output list must be the last clause in a "
+                           & "dependency relation", Item);
+
+                     --  Catch a useless dependence of the form:
+                     --    null =>+ ...
+
+                     elsif Self_Ref then
+                        Error_Msg_N
+                          ("useless dependence, null depends on itself", Item);
+                     end if;
                   end if;
                end if;
 
             --  Default case
 
             else
+               Non_Null_Seen := True;
+
+               if Null_Seen then
+                  Error_Msg_N ("cannot mix null and non-null items", Item);
+               end if;
+
                Analyze (Item);
 
                --  Find the entity of the item. If this is a renaming, climb
@@ -845,6 +877,9 @@ 
          Output   : Node_Id;
          Self_Ref : Boolean;
 
+         Non_Null_Output_Seen : Boolean := False;
+         --  Flag used to check the legality of an output list
+
       --  Start of processing for Analyze_Dependency_Clause
 
       begin
@@ -864,12 +899,13 @@ 
          Output := First (Choices (Clause));
          while Present (Output) loop
             Analyze_Input_Output
-              (Item      => Output,
-               Is_Input  => False,
-               Self_Ref  => Self_Ref,
-               Top_Level => True,
-               Seen      => All_Outputs_Seen,
-               Null_Seen => Null_Output_Seen);
+              (Item          => Output,
+               Is_Input      => False,
+               Self_Ref      => Self_Ref,
+               Top_Level     => True,
+               Seen          => All_Outputs_Seen,
+               Null_Seen     => Null_Output_Seen,
+               Non_Null_Seen => Non_Null_Output_Seen);
 
             Next (Output);
          end loop;
@@ -2192,22 +2228,15 @@ 
          Item_Id : Entity_Id;
 
       begin
-         --  A package with null initialization list is not allowed to have
-         --  additional initializations.
-
-         if Null_Seen then
-            Error_Msg_NE ("package & has null initialization", Item, Pack_Id);
-
          --  Null initialization list
 
-         elsif Nkind (Item) = N_Null then
+         if Nkind (Item) = N_Null then
+            if Null_Seen then
+               Error_Msg_N ("multiple null initializations not allowed", Item);
 
-            --  Catch a case where a null initialization item appears in a list
-            --  of non-null items.
-
-            if Non_Null_Seen then
-               Error_Msg_NE
-                 ("package & has non-null initialization", Item, Pack_Id);
+            elsif Non_Null_Seen then
+               Error_Msg_N
+                 ("cannot mix null and non-null initialization items", Item);
             else
                Null_Seen := True;
             end if;
@@ -2217,6 +2246,11 @@ 
          else
             Non_Null_Seen := True;
 
+            if Null_Seen then
+               Error_Msg_N
+                 ("cannot mix null and non-null initialization items", Item);
+            end if;
+
             Analyze (Item);
 
             if Is_Entity_Name (Item) then
@@ -2287,21 +2321,16 @@ 
             Input_Id : Entity_Id;
 
          begin
-            --  An initialization item with null inputs is not allowed to have
-            --  assitional inputs.
-
-            if Null_Seen then
-               Error_Msg_N ("item has null input list", Item);
-
             --  Null input list
 
-            elsif Nkind (Input) = N_Null then
+            if Nkind (Input) = N_Null then
+               if Null_Seen then
+                  Error_Msg_N
+                    ("multiple null initializations not allowed", Item);
 
-               --  Catch a case where a null input appears in a list of non-
-               --  null inpits.
-
-               if Non_Null_Seen then
-                  Error_Msg_N ("item has non-null input list", Item);
+               elsif Non_Null_Seen then
+                  Error_Msg_N
+                    ("cannot mix null and non-null initialization item", Item);
                else
                   Null_Seen := True;
                end if;
@@ -2311,6 +2340,11 @@ 
             else
                Non_Null_Seen := True;
 
+               if Null_Seen then
+                  Error_Msg_N
+                    ("cannot mix null and non-null initialization item", Item);
+               end if;
+
                Analyze (Input);
 
                if Is_Entity_Name (Input) then
@@ -9299,7 +9333,7 @@ 
 
                elsif Nkind (State) = N_Null then
                   Name := New_Internal_Name ('S');
-                  Is_Null := True;
+                  Is_Null   := True;
                   Null_Seen := True;
 
                   --  Catch a case where a null state appears in a list of
@@ -19946,7 +19980,7 @@ 
                   Dep_Id := Entity_Of (Dep_Input);
 
                   --  Inspect all inputs of the refinement clause and attempt
-                  --  to match against the inputs of the dependance clause.
+                  --  to match against the inputs of the dependence clause.
 
                   Ref_Input := First (Ref_Inputs);
                   while Present (Ref_Input) loop
@@ -20256,7 +20290,7 @@ 
       begin
          --  The analysis of pragma Depends should produce normalized clauses
          --  with exactly one output. This is important because output items
-         --  are unique in the whole dependance relation and can be used as
+         --  are unique in the whole dependence relation and can be used as
          --  keys.
 
          pragma Assert (No (Next (Dep_Output)));