Commit 3ccd9410 by Hristian Kirtchev Committed by Arnaud Charlet

sem_ch9.adb (Analyze_Requeue): Add a local flag to capture whether a requeue…

sem_ch9.adb (Analyze_Requeue): Add a local flag to capture whether a requeue statement is dispatching.

2007-12-06  Hristian Kirtchev  <kirtchev@adacore.com>
	    Gary Dismukes  <dismukes@adacore.com>

	* sem_ch9.adb (Analyze_Requeue): Add a local flag to capture whether a
	requeue statement is dispatching. Do not emit an error when the name is
	not an entry and the context is a dispatching select. Add code to
	perform subtype conformance between the formals of the current entry
	and those of the target interface primitive.
	(Analyze_Asynchronous_Select, Analyze_Conditional_Entry_Call, Analyze_
	Timed_Entry_Call): Analyze the triggering statement as the first step of
	the processing. If this is a dispatching select, postpone the analysis
	of all select statements until the Expander transforms the select. This
	approach avoids generating duplicate identifiers after the Expander has
	replicated some of the select statements. In case the Expander is
	disabled, perform regular analysis.
	(Check_Triggering_Statement): New routine.
	(Analyze_Requeue): Exclude any interpretations that are not entries when
	checking overloaded names in a requeue. Also test type conformance for
	matching interpretations rather than requiring subtype conformance at
	that point to conform with the RM's resolution rule for requeues.

From-SVN: r130855
parent 294ccb21
...@@ -73,6 +73,15 @@ package body Sem_Ch9 is ...@@ -73,6 +73,15 @@ package body Sem_Ch9 is
-- N is an N_Protected_Type_Declaration or N_Task_Type_Declaration node. -- N is an N_Protected_Type_Declaration or N_Task_Type_Declaration node.
-- Complete decoration of T and check legality of the covered interfaces. -- Complete decoration of T and check legality of the covered interfaces.
procedure Check_Triggering_Statement
(Trigger : Node_Id;
Error_Node : Node_Id;
Is_Dispatching : out Boolean);
-- Examine the triggering statement of a select statement, conditional or
-- timed entry call. If Trigger is a dispatching call, return its status
-- in Is_Dispatching and check whether the primitive belongs to a limited
-- interface. If it does not, emit an error at Error_Node.
function Find_Concurrent_Spec (Body_Id : Entity_Id) return Entity_Id; function Find_Concurrent_Spec (Body_Id : Entity_Id) return Entity_Id;
-- Find entity in corresponding task or protected declaration. Use full -- Find entity in corresponding task or protected declaration. Use full
-- view if first declaration was for an incomplete type. -- view if first declaration was for an incomplete type.
...@@ -166,6 +175,10 @@ package body Sem_Ch9 is ...@@ -166,6 +175,10 @@ package body Sem_Ch9 is
-- a new index type where a discriminant is replaced by the local -- a new index type where a discriminant is replaced by the local
-- variable that renames it in the task body. -- variable that renames it in the task body.
-----------------------
-- Actual_Index_Type --
-----------------------
function Actual_Index_Type (E : Entity_Id) return Entity_Id is function Actual_Index_Type (E : Entity_Id) return Entity_Id is
Typ : constant Entity_Id := Entry_Index_Type (E); Typ : constant Entity_Id := Entry_Index_Type (E);
Lo : constant Node_Id := Type_Low_Bound (Typ); Lo : constant Node_Id := Type_Low_Bound (Typ);
...@@ -404,19 +417,20 @@ package body Sem_Ch9 is ...@@ -404,19 +417,20 @@ package body Sem_Ch9 is
-- Set Never_Set_In_Source and clear Is_True_Constant/Current_Value -- Set Never_Set_In_Source and clear Is_True_Constant/Current_Value
-- fields on all entry formals (this loop ignores all other entities). -- fields on all entry formals (this loop ignores all other entities).
-- Reset Referenced, Referenced_As_LHS and Has_Pragma_Unreferenced as -- Reset Referenced, Referenced_As_xxx and Has_Pragma_Unreferenced as
-- well, so that we can post accurate warnings on each accept statement -- well, so that we can post accurate warnings on each accept statement
-- for the same entry. -- for the same entry.
E := First_Entity (Entry_Nam); E := First_Entity (Entry_Nam);
while Present (E) loop while Present (E) loop
if Is_Formal (E) then if Is_Formal (E) then
Set_Never_Set_In_Source (E, True); Set_Never_Set_In_Source (E, True);
Set_Is_True_Constant (E, False); Set_Is_True_Constant (E, False);
Set_Current_Value (E, Empty); Set_Current_Value (E, Empty);
Set_Referenced (E, False); Set_Referenced (E, False);
Set_Referenced_As_LHS (E, False); Set_Referenced_As_LHS (E, False);
Set_Has_Pragma_Unreferenced (E, False); Set_Referenced_As_Out_Parameter (E, False);
Set_Has_Pragma_Unreferenced (E, False);
end if; end if;
Next_Entity (E); Next_Entity (E);
...@@ -447,8 +461,8 @@ package body Sem_Ch9 is ...@@ -447,8 +461,8 @@ package body Sem_Ch9 is
--------------------------------- ---------------------------------
procedure Analyze_Asynchronous_Select (N : Node_Id) is procedure Analyze_Asynchronous_Select (N : Node_Id) is
Param : Node_Id; Is_Disp_Select : Boolean := False;
Trigger : Node_Id; Trigger : Node_Id;
begin begin
Tasking_Used := True; Tasking_Used := True;
...@@ -460,39 +474,30 @@ package body Sem_Ch9 is ...@@ -460,39 +474,30 @@ package body Sem_Ch9 is
Analyze (Trigger); Analyze (Trigger);
-- The trigger is a dispatching procedure. Postpone the analysis of -- Ada 2005 (AI-345): Check for a potential dispatching select
-- the triggering and abortable statements until the expansion of
-- this asynchronous select in Expand_N_Asynchronous_Select. This
-- action is required since otherwise we would get a gigi abort from
-- the code replication in Expand_N_Asynchronous_Select of an already
-- analyzed statement list.
if Expander_Active Check_Triggering_Statement (Trigger, N, Is_Disp_Select);
and then Nkind (Trigger) = N_Procedure_Call_Statement end if;
and then Present (Parameter_Associations (Trigger))
then
Param := First (Parameter_Associations (Trigger));
if Is_Controlling_Actual (Param) -- Ada 2005 (AI-345): The expansion of the dispatching asynchronous
and then Is_Interface (Etype (Param)) -- select will have to duplicate the triggering statements. Postpone
then -- the analysis of the statements till expansion. Analyze only if the
if Is_Limited_Record (Etype (Param)) then -- expander is disabled in order to catch any semantic errors.
return;
else if Is_Disp_Select then
Error_Msg_N if not Expander_Active then
("dispatching operation of limited or synchronized " & Analyze_Statements (Statements (Abortable_Part (N)));
"interface required (RM 9.7.2(3))!", N); Analyze (Triggering_Alternative (N));
end if;
end if;
end if; end if;
end if;
-- Analyze the statements. We analyze statements in the abortable part, -- Analyze the statements. We analyze statements in the abortable part,
-- because this is the section that is executed first, and that way our -- because this is the section that is executed first, and that way our
-- remembering of saved values and checks is accurate. -- remembering of saved values and checks is accurate.
Analyze_Statements (Statements (Abortable_Part (N))); else
Analyze (Triggering_Alternative (N)); Analyze_Statements (Statements (Abortable_Part (N)));
Analyze (Triggering_Alternative (N));
end if;
end Analyze_Asynchronous_Select; end Analyze_Asynchronous_Select;
------------------------------------ ------------------------------------
...@@ -500,21 +505,45 @@ package body Sem_Ch9 is ...@@ -500,21 +505,45 @@ package body Sem_Ch9 is
------------------------------------ ------------------------------------
procedure Analyze_Conditional_Entry_Call (N : Node_Id) is procedure Analyze_Conditional_Entry_Call (N : Node_Id) is
Trigger : constant Node_Id :=
Entry_Call_Statement (Entry_Call_Alternative (N));
Is_Disp_Select : Boolean := False;
begin begin
Check_Restriction (No_Select_Statements, N); Check_Restriction (No_Select_Statements, N);
Tasking_Used := True; Tasking_Used := True;
Analyze (Entry_Call_Alternative (N));
-- Ada 2005 (AI-345): The trigger may be a dispatching call
if Ada_Version >= Ada_05 then
Analyze (Trigger);
Check_Triggering_Statement (Trigger, N, Is_Disp_Select);
end if;
if List_Length (Else_Statements (N)) = 1 if List_Length (Else_Statements (N)) = 1
and then Nkind (First (Else_Statements (N))) in N_Delay_Statement and then Nkind (First (Else_Statements (N))) in N_Delay_Statement
then then
Error_Msg_N Error_Msg_N
("suspicious form of conditional entry call?", N); ("suspicious form of conditional entry call?!", N);
Error_Msg_N Error_Msg_N
("\`SELECT OR` may be intended rather than `SELECT ELSE`", N); ("\`SELECT OR` may be intended rather than `SELECT ELSE`!", N);
end if; end if;
Analyze_Statements (Else_Statements (N)); -- Postpone the analysis of the statements till expansion. Analyze only
-- if the expander is disabled in order to catch any semantic errors.
if Is_Disp_Select then
if not Expander_Active then
Analyze (Entry_Call_Alternative (N));
Analyze_Statements (Else_Statements (N));
end if;
-- Regular select analysis
else
Analyze (Entry_Call_Alternative (N));
Analyze_Statements (Else_Statements (N));
end if;
end Analyze_Conditional_Entry_Call; end Analyze_Conditional_Entry_Call;
-------------------------------- --------------------------------
...@@ -533,9 +562,7 @@ package body Sem_Ch9 is ...@@ -533,9 +562,7 @@ package body Sem_Ch9 is
Analyze_List (Pragmas_Before (N)); Analyze_List (Pragmas_Before (N));
end if; end if;
if Nkind (Parent (N)) = N_Selective_Accept if Nkind_In (Parent (N), N_Selective_Accept, N_Timed_Entry_Call) then
or else Nkind (Parent (N)) = N_Timed_Entry_Call
then
Expr := Expression (Delay_Statement (N)); Expr := Expression (Delay_Statement (N));
-- Defer full analysis until the statement is expanded, to insure -- Defer full analysis until the statement is expanded, to insure
...@@ -791,8 +818,7 @@ package body Sem_Ch9 is ...@@ -791,8 +818,7 @@ package body Sem_Ch9 is
end loop; end loop;
-- If no matching body entity, then we already had a detected -- If no matching body entity, then we already had a detected
-- error of some kind, so just forget about worrying about these -- error of some kind, so just don't worry about these warnings.
-- warnings.
if No (E2) then if No (E2) then
goto Continue; goto Continue;
...@@ -994,9 +1020,9 @@ package body Sem_Ch9 is ...@@ -994,9 +1020,9 @@ package body Sem_Ch9 is
Ref_Id : Entity_Id; Ref_Id : Entity_Id;
-- This is the entity of the protected object or protected type -- This is the entity of the protected object or protected type
-- involved, and is the entity used for cross-reference purposes -- involved, and is the entity used for cross-reference purposes (it
-- (it differs from Spec_Id in the case of a single protected -- differs from Spec_Id in the case of a single protected object, since
-- object, since Spec_Id is set to the protected type in this case). -- Spec_Id is set to the protected type in this case).
begin begin
Tasking_Used := True; Tasking_Used := True;
...@@ -1156,9 +1182,8 @@ package body Sem_Ch9 is ...@@ -1156,9 +1182,8 @@ package body Sem_Ch9 is
Set_Is_Constrained (T, not Has_Discriminants (T)); Set_Is_Constrained (T, not Has_Discriminants (T));
-- Perform minimal expansion of the protected type while inside of a -- Perform minimal expansion of protected type while inside a generic.
-- generic. The corresponding record is needed for various semantic -- The corresponding record is needed for various semantic checks.
-- checks.
if Ada_Version >= Ada_05 if Ada_Version >= Ada_05
and then Inside_A_Generic and then Inside_A_Generic
...@@ -1231,15 +1256,16 @@ package body Sem_Ch9 is ...@@ -1231,15 +1256,16 @@ package body Sem_Ch9 is
--------------------- ---------------------
procedure Analyze_Requeue (N : Node_Id) is procedure Analyze_Requeue (N : Node_Id) is
Count : Natural := 0; Count : Natural := 0;
Entry_Name : Node_Id := Name (N); Entry_Name : Node_Id := Name (N);
Entry_Id : Entity_Id; Entry_Id : Entity_Id;
I : Interp_Index; I : Interp_Index;
It : Interp; Is_Disp_Req : Boolean;
Enclosing : Entity_Id; It : Interp;
Target_Obj : Node_Id := Empty; Enclosing : Entity_Id;
Req_Scope : Entity_Id; Target_Obj : Node_Id := Empty;
Outer_Ent : Entity_Id; Req_Scope : Entity_Id;
Outer_Ent : Entity_Id;
begin begin
Check_Restriction (No_Requeue_Statements, N); Check_Restriction (No_Requeue_Statements, N);
...@@ -1313,10 +1339,20 @@ package body Sem_Ch9 is ...@@ -1313,10 +1339,20 @@ package body Sem_Ch9 is
if Is_Overloaded (Entry_Name) then if Is_Overloaded (Entry_Name) then
Entry_Id := Empty; Entry_Id := Empty;
-- Loop over candidate interpretations and filter out any that are
-- not parameterless, are not type conformant, are not entries, or
-- do not come from source.
Get_First_Interp (Entry_Name, I, It); Get_First_Interp (Entry_Name, I, It);
while Present (It.Nam) loop while Present (It.Nam) loop
if No (First_Formal (It.Nam))
or else Subtype_Conformant (Enclosing, It.Nam) -- Note: we test type conformance here, not subtype conformance.
-- Subtype conformance will be tested later on, but it is better
-- for error output in some cases not to do that here.
if (No (First_Formal (It.Nam))
or else (Type_Conformant (Enclosing, It.Nam)))
and then Ekind (It.Nam) = E_Entry
then then
-- Ada 2005 (AI-345): Since protected and task types have -- Ada 2005 (AI-345): Since protected and task types have
-- primitive entry wrappers, we only consider source entries. -- primitive entry wrappers, we only consider source entries.
...@@ -1384,11 +1420,28 @@ package body Sem_Ch9 is ...@@ -1384,11 +1420,28 @@ package body Sem_Ch9 is
Entry_Id := Entity (Entry_Name); Entry_Id := Entity (Entry_Name);
end if; end if;
-- Ada 2005 (AI05-0030): Potential dispatching requeue statement. The
-- target type must be a concurrent interface class-wide type and the
-- entry name must be a procedure, flagged by pragma Implemented_By_
-- Entry.
Is_Disp_Req :=
Ada_Version >= Ada_05
and then Present (Target_Obj)
and then Is_Class_Wide_Type (Etype (Target_Obj))
and then Is_Concurrent_Interface (Etype (Target_Obj))
and then Ekind (Entry_Id) = E_Procedure
and then Implemented_By_Entry (Entry_Id);
-- Resolve entry, and check that it is subtype conformant with the -- Resolve entry, and check that it is subtype conformant with the
-- enclosing construct if this construct has formals (RM 9.5.4(5)). -- enclosing construct if this construct has formals (RM 9.5.4(5)).
-- Ada 2005 (AI05-0030): Do not emit an error for this specific case.
if not Is_Entry (Entry_Id) then if not Is_Entry (Entry_Id)
and then not Is_Disp_Req
then
Error_Msg_N ("expect entry name in requeue statement", Name (N)); Error_Msg_N ("expect entry name in requeue statement", Name (N));
elsif Ekind (Entry_Id) = E_Entry_Family elsif Ekind (Entry_Id) = E_Entry_Family
and then Nkind (Entry_Name) /= N_Indexed_Component and then Nkind (Entry_Name) /= N_Indexed_Component
then then
...@@ -1406,7 +1459,39 @@ package body Sem_Ch9 is ...@@ -1406,7 +1459,39 @@ package body Sem_Ch9 is
return; return;
end if; end if;
Check_Subtype_Conformant (Enclosing, Entry_Id, Name (N)); -- Ada 2005 (AI05-0030): Perform type conformance after skipping
-- the first parameter of Entry_Id since it is the interface
-- controlling formal.
if Is_Disp_Req then
declare
Enclosing_Formal : Entity_Id;
Target_Formal : Entity_Id;
begin
Enclosing_Formal := First_Formal (Enclosing);
Target_Formal := Next_Formal (First_Formal (Entry_Id));
while Present (Enclosing_Formal)
and then Present (Target_Formal)
loop
if not Conforming_Types
(T1 => Etype (Enclosing_Formal),
T2 => Etype (Target_Formal),
Ctype => Subtype_Conformant)
then
Error_Msg_Node_2 := Target_Formal;
Error_Msg_NE
("formal & is not subtype conformant with &" &
"in dispatching requeue", N, Enclosing_Formal);
end if;
Next_Formal (Enclosing_Formal);
Next_Formal (Target_Formal);
end loop;
end;
else
Check_Subtype_Conformant (Enclosing, Entry_Id, Name (N));
end if;
-- Processing for parameters accessed by the requeue -- Processing for parameters accessed by the requeue
...@@ -1887,7 +1972,7 @@ package body Sem_Ch9 is ...@@ -1887,7 +1972,7 @@ package body Sem_Ch9 is
if Has_Discriminants (T) then if Has_Discriminants (T) then
-- Install discriminants. Also, verify conformance of -- Install discriminants. Also, verify conformance of
-- discriminants of previous and current view. ??? -- discriminants of previous and current view. ???
Install_Declarations (T); Install_Declarations (T);
else else
...@@ -1965,11 +2050,36 @@ package body Sem_Ch9 is ...@@ -1965,11 +2050,36 @@ package body Sem_Ch9 is
------------------------------ ------------------------------
procedure Analyze_Timed_Entry_Call (N : Node_Id) is procedure Analyze_Timed_Entry_Call (N : Node_Id) is
Trigger : constant Node_Id :=
Entry_Call_Statement (Entry_Call_Alternative (N));
Is_Disp_Select : Boolean := False;
begin begin
Check_Restriction (No_Select_Statements, N); Check_Restriction (No_Select_Statements, N);
Tasking_Used := True; Tasking_Used := True;
Analyze (Entry_Call_Alternative (N));
Analyze (Delay_Alternative (N)); -- Ada 2005 (AI-345): The trigger may be a dispatching call
if Ada_Version >= Ada_05 then
Analyze (Trigger);
Check_Triggering_Statement (Trigger, N, Is_Disp_Select);
end if;
-- Postpone the analysis of the statements till expansion. Analyze only
-- if the expander is disabled in order to catch any semantic errors.
if Is_Disp_Select then
if not Expander_Active then
Analyze (Entry_Call_Alternative (N));
Analyze (Delay_Alternative (N));
end if;
-- Regular select analysis
else
Analyze (Entry_Call_Alternative (N));
Analyze (Delay_Alternative (N));
end if;
end Analyze_Timed_Entry_Call; end Analyze_Timed_Entry_Call;
------------------------------------ ------------------------------------
...@@ -2113,8 +2223,8 @@ package body Sem_Ch9 is ...@@ -2113,8 +2223,8 @@ package body Sem_Ch9 is
Iface_Typ : Entity_Id; Iface_Typ : Entity_Id;
begin begin
pragma Assert (Nkind (N) = N_Protected_Type_Declaration pragma Assert
or else Nkind (N) = N_Task_Type_Declaration); (Nkind_In (N, N_Protected_Type_Declaration, N_Task_Type_Declaration));
if Present (Interface_List (N)) then if Present (Interface_List (N)) then
Set_Is_Tagged_Type (T); Set_Is_Tagged_Type (T);
...@@ -2221,14 +2331,14 @@ package body Sem_Ch9 is ...@@ -2221,14 +2331,14 @@ package body Sem_Ch9 is
then then
Error_Msg_N Error_Msg_N
("(Ada 2005) full view must be a synchronized tagged " & ("(Ada 2005) full view must be a synchronized tagged " &
"type ('R'M 7.3 (7.2/2))", Priv_T); "type (RM 7.3 (7.2/2))", Priv_T);
elsif Is_Synchronized_Tagged_Type (T) elsif Is_Synchronized_Tagged_Type (T)
and then not Is_Synchronized_Tagged_Type (Priv_T) and then not Is_Synchronized_Tagged_Type (Priv_T)
then then
Error_Msg_N Error_Msg_N
("(Ada 2005) partial view must be a synchronized tagged " & ("(Ada 2005) partial view must be a synchronized tagged " &
"type ('R'M 7.3 (7.2/2))", T); "type (RM 7.3 (7.2/2))", T);
end if; end if;
-- RM 7.3 (7.3/2): The partial view shall be a descendant of an -- RM 7.3 (7.3/2): The partial view shall be a descendant of an
...@@ -2267,6 +2377,43 @@ package body Sem_Ch9 is ...@@ -2267,6 +2377,43 @@ package body Sem_Ch9 is
end; end;
end Check_Interfaces; end Check_Interfaces;
--------------------------------
-- Check_Triggering_Statement --
--------------------------------
procedure Check_Triggering_Statement
(Trigger : Node_Id;
Error_Node : Node_Id;
Is_Dispatching : out Boolean)
is
Param : Node_Id;
begin
Is_Dispatching := False;
-- It is not possible to have a dispatching trigger if we are not in
-- Ada 2005 mode.
if Ada_Version >= Ada_05
and then Nkind (Trigger) = N_Procedure_Call_Statement
and then Present (Parameter_Associations (Trigger))
then
Param := First (Parameter_Associations (Trigger));
if Is_Controlling_Actual (Param)
and then Is_Interface (Etype (Param))
then
if Is_Limited_Record (Etype (Param)) then
Is_Dispatching := True;
else
Error_Msg_N
("dispatching operation of limited or synchronized " &
"interface required (RM 9.7.2(3))!", Error_Node);
end if;
end if;
end if;
end Check_Triggering_Statement;
-------------------------- --------------------------
-- Find_Concurrent_Spec -- -- Find_Concurrent_Spec --
-------------------------- --------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment