summaryrefslogtreecommitdiff
path: root/gcc/ada/sem_prag.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_prag.adb')
-rw-r--r--gcc/ada/sem_prag.adb205
1 files changed, 169 insertions, 36 deletions
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 8cafd56df25..534681a8294 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -245,10 +245,13 @@ package body Sem_Prag is
-- Determine whether dependency clause Clause is surrounded by extra
-- parentheses. If this is the case, issue an error message.
- function Is_CCT_Instance (Ref : Node_Id) return Boolean;
+ function Is_CCT_Instance
+ (Ref_Id : Entity_Id;
+ Context_Id : Entity_Id) return Boolean;
-- Subsidiary to the analysis of pragmas [Refined_]Depends and [Refined_]
- -- Global. Determine whether reference Ref denotes the current instance of
- -- a concurrent type.
+ -- Global. Determine whether entity Ref_Id denotes the current instance of
+ -- a concurrent type. Context_Id denotes the associated context where the
+ -- pragma appears.
function Is_Unconstrained_Or_Tagged_Item (Item : Entity_Id) return Boolean;
-- Subsidiary to Collect_Subprogram_Inputs_Outputs and the analysis of
@@ -559,6 +562,10 @@ package body Sem_Prag is
-- Two lists containing the full set of inputs and output of the related
-- subprograms. Note that these lists contain both nodes and entities.
+ Task_Input_Seen : Boolean := False;
+ Task_Output_Seen : Boolean := False;
+ -- Flags used to track the implicit dependence of a task unit on itself
+
procedure Add_Item_To_Name_Buffer (Item_Id : Entity_Id);
-- Subsidiary routine to Check_Role and Check_Usage. Add the item kind
-- to the name buffer. The individual kinds are as follows:
@@ -590,7 +597,7 @@ package body Sem_Prag is
Item_Id : Entity_Id;
Is_Input : Boolean;
Self_Ref : Boolean);
- -- Ensure that an item fulfils its designated input and/or output role
+ -- Ensure that an item fulfills its designated input and/or output role
-- as specified by pragma Global (if any) or the enclosing context. If
-- this is not the case, emit an error. Item and Item_Id denote the
-- attributes of an item. Flag Is_Input should be set when item comes
@@ -763,10 +770,31 @@ package body Sem_Prag is
Null_Seen : in out Boolean;
Non_Null_Seen : in out Boolean)
is
+ procedure Current_Task_Instance_Seen;
+ -- Set the appropriate global flag when the current instance of a
+ -- task unit is encountered.
+
+ --------------------------------
+ -- Current_Task_Instance_Seen --
+ --------------------------------
+
+ procedure Current_Task_Instance_Seen is
+ begin
+ if Is_Input then
+ Task_Input_Seen := True;
+ else
+ Task_Output_Seen := True;
+ end if;
+ end Current_Task_Instance_Seen;
+
+ -- Local variables
+
Is_Output : constant Boolean := not Is_Input;
Grouped : Node_Id;
Item_Id : Entity_Id;
+ -- Start of processing for Analyze_Input_Output
+
begin
-- Multiple input or output items appear as an aggregate
@@ -899,18 +927,45 @@ package body Sem_Prag is
Ekind_In (Item_Id, E_Abstract_State, E_Variable)
then
- -- The item denotes a concurrent type, but it is not the
- -- current instance of an enclosing concurrent type.
+ -- The item denotes a concurrent type. Note that single
+ -- protected/task types are not considered here because
+ -- they behave as objects in the context of pragma
+ -- [Refined_]Depends.
+
+ if Ekind_In (Item_Id, E_Protected_Type, E_Task_Type) then
+
+ -- This use is legal as long as the concurrent type is
+ -- the current instance of an enclosing type.
+
+ if Is_CCT_Instance (Item_Id, Spec_Id) then
- if Ekind_In (Item_Id, E_Protected_Type, E_Task_Type)
- and then not Is_CCT_Instance (Item)
+ -- The dependence of a task unit on itself is
+ -- implicit and may or may not be explicitly
+ -- specified (SPARK RM 6.1.4).
+
+ if Ekind (Item_Id) = E_Task_Type then
+ Current_Task_Instance_Seen;
+ end if;
+
+ -- Otherwise this is not the current instance
+
+ else
+ SPARK_Msg_N
+ ("invalid use of subtype mark in dependency "
+ & "relation", Item);
+ end if;
+
+ -- The dependency of a task unit on itself is implicit
+ -- and may or may not be explicitly specified
+ -- (SPARK RM 6.1.4).
+
+ elsif Is_Single_Task_Object (Item_Id)
+ and then Is_CCT_Instance (Item_Id, Spec_Id)
then
- SPARK_Msg_N
- ("invalid use of subtype mark in dependency "
- & "relation", Item);
+ Current_Task_Instance_Seen;
end if;
- -- Ensure that the item fulfils its role as input and/or
+ -- Ensure that the item fulfills its role as input and/or
-- output as specified by pragma Global or the enclosing
-- context.
@@ -1427,14 +1482,31 @@ package body Sem_Prag is
if Present (Item_Id)
and then not Contains (Used_Items, Item_Id)
then
- -- The current instance of a concurrent type behaves as a
- -- formal parameter (SPARK RM 6.1.4).
+ if Is_Formal (Item_Id) then
+ Usage_Error (Item_Id);
- if Is_Formal (Item_Id)
- or else Ekind_In (Item_Id, E_Protected_Type, E_Task_Type)
+ -- The current instance of a protected type behaves as a formal
+ -- parameter (SPARK RM 6.1.4).
+
+ elsif Ekind (Item_Id) = E_Protected_Type
+ or else Is_Single_Protected_Object (Item_Id)
then
Usage_Error (Item_Id);
+ -- The current instance of a task type behaves as a formal
+ -- parameter (SPARK RM 6.1.4).
+
+ elsif Ekind (Item_Id) = E_Task_Type
+ or else Is_Single_Task_Object (Item_Id)
+ then
+ -- The dependence of a task unit on itself is implicit and
+ -- may or may not be explicitly specified (SPARK RM 6.1.4).
+ -- Emit an error if only one input/output is present.
+
+ if Task_Input_Seen /= Task_Output_Seen then
+ Usage_Error (Item_Id);
+ end if;
+
-- States and global objects are not used properly only when
-- the subprogram is subject to pragma Global.
@@ -2036,20 +2108,18 @@ package body Sem_Prag is
end if;
-- A global item may denote a concurrent type as long as it is
- -- the current instance of an enclosing concurrent type
+ -- the current instance of an enclosing protected or task type
-- (SPARK RM 6.1.4).
elsif Ekind_In (Item_Id, E_Protected_Type, E_Task_Type) then
- if Is_CCT_Instance (Item) then
+ if Is_CCT_Instance (Item_Id, Spec_Id) then
-- Pragma [Refined_]Global associated with a protected
-- subprogram cannot mention the current instance of a
-- protected type because the instance behaves as a
-- formal parameter.
- if Ekind (Item_Id) = E_Protected_Type
- and then Scope (Spec_Id) = Item_Id
- then
+ if Ekind (Item_Id) = E_Protected_Type then
Error_Msg_Name_1 := Chars (Item_Id);
SPARK_Msg_NE
(Fix_Msg (Spec_Id, "global item of subprogram & "
@@ -2061,9 +2131,7 @@ package body Sem_Prag is
-- cannot mention the current instance of a task type
-- because the instance behaves as a formal parameter.
- elsif Ekind (Item_Id) = E_Task_Type
- and then Spec_Id = Item_Id
- then
+ else pragma Assert (Ekind (Item_Id) = E_Task_Type);
Error_Msg_Name_1 := Chars (Item_Id);
SPARK_Msg_NE
(Fix_Msg (Spec_Id, "global item of subprogram & "
@@ -2081,6 +2149,39 @@ package body Sem_Prag is
return;
end if;
+ -- A global item may denote the anonymous object created for a
+ -- single protected/task type as long as the current instance
+ -- is the same single type (SPARK RM 6.1.4).
+
+ elsif Is_Single_Concurrent_Object (Item_Id)
+ and then Is_CCT_Instance (Item_Id, Spec_Id)
+ then
+ -- Pragma [Refined_]Global associated with a protected
+ -- subprogram cannot mention the current instance of a
+ -- protected type because the instance behaves as a formal
+ -- parameter.
+
+ if Is_Single_Protected_Object (Item_Id) then
+ Error_Msg_Name_1 := Chars (Item_Id);
+ SPARK_Msg_NE
+ (Fix_Msg (Spec_Id, "global item of subprogram & cannot "
+ & "reference current instance of protected type %"),
+ Item, Spec_Id);
+ return;
+
+ -- Pragma [Refined_]Global associated with a task type
+ -- cannot mention the current instance of a task type
+ -- because the instance behaves as a formal parameter.
+
+ else pragma Assert (Is_Single_Task_Object (Item_Id));
+ Error_Msg_Name_1 := Chars (Item_Id);
+ SPARK_Msg_NE
+ (Fix_Msg (Spec_Id, "global item of subprogram & cannot "
+ & "reference current instance of task type %"),
+ Item, Spec_Id);
+ return;
+ end if;
+
-- A formal object may act as a global item inside a generic
elsif Is_Formal_Object (Item_Id) then
@@ -27455,23 +27556,55 @@ package body Sem_Prag is
-- Is_CCT_Instance --
---------------------
- function Is_CCT_Instance (Ref : Node_Id) return Boolean is
- Ref_Id : constant Entity_Id := Entity (Ref);
- S : Entity_Id;
+ function Is_CCT_Instance
+ (Ref_Id : Entity_Id;
+ Context_Id : Entity_Id) return Boolean
+ is
+ S : Entity_Id;
+ Typ : Entity_Id;
begin
- -- Climb the scope chain looking for an enclosing concurrent type that
- -- matches the referenced entity.
+ -- When the reference denotes a single protected type, the context is
+ -- either a protected subprogram or its body.
- S := Current_Scope;
- while Present (S) and then S /= Standard_Standard loop
- if Ekind_In (S, E_Protected_Type, E_Task_Type) and then S = Ref_Id
- then
- return True;
+ if Is_Single_Protected_Object (Ref_Id) then
+ Typ := Scope (Context_Id);
+
+ return
+ Ekind (Typ) = E_Protected_Type
+ and then Present (Anonymous_Object (Typ))
+ and then Anonymous_Object (Typ) = Ref_Id;
+
+ -- When the reference denotes a single task type, the context is either
+ -- the same type or if inside the body, the anonymous task type.
+
+ elsif Is_Single_Task_Object (Ref_Id) then
+ if Ekind (Context_Id) = E_Task_Type then
+ return
+ Present (Anonymous_Object (Context_Id))
+ and then Anonymous_Object (Context_Id) = Ref_Id;
+ else
+ return Ref_Id = Context_Id;
end if;
- S := Scope (S);
- end loop;
+ -- Otherwise the reference denotes a protected or a task type. Climb the
+ -- scope chain looking for an enclosing concurrent type that matches the
+ -- referenced entity.
+
+ else
+ pragma Assert (Ekind_In (Ref_Id, E_Protected_Type, E_Task_Type));
+
+ S := Current_Scope;
+ while Present (S) and then S /= Standard_Standard loop
+ if Ekind_In (S, E_Protected_Type, E_Task_Type)
+ and then S = Ref_Id
+ then
+ return True;
+ end if;
+
+ S := Scope (S);
+ end loop;
+ end if;
return False;
end Is_CCT_Instance;