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 <kirtc...@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.
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)));