aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/exp_ch3.adb239
1 files changed, 171 insertions, 68 deletions
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 6be11a7..eae2c2f 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -237,8 +237,11 @@ package body Exp_Ch3 is
procedure Make_Predefined_Primitive_Specs
(Tag_Typ : Entity_Id;
Predef_List : out List_Id;
- Renamed_Eq : out Node_Id);
+ Renamed_Eq : out Entity_Id);
-- Create a list with the specs of the predefined primitive operations.
+ -- For tagged types that are interfaces all these primitives are defined
+ -- abstract.
+ --
-- The following entries are present for all tagged types, and provide
-- the results of the corresponding attribute applied to the object.
-- Dispatching is required in general, since the result of the attribute
@@ -328,7 +331,7 @@ package body Exp_Ch3 is
function Predefined_Primitive_Bodies
(Tag_Typ : Entity_Id;
- Renamed_Eq : Node_Id) return List_Id;
+ Renamed_Eq : Entity_Id) return List_Id;
-- Create the bodies of the predefined primitives that are described in
-- Predefined_Primitive_Specs. When not empty, Renamed_Eq must denote
-- the defining unit name of the type's predefined equality as returned
@@ -797,9 +800,8 @@ package body Exp_Ch3 is
-- If we fall off the top, we are at the outer level, and the
-- environment task is our effective master, so nothing to mark.
- if Nkind (Par) = N_Task_Body
- or else Nkind (Par) = N_Block_Statement
- or else Nkind (Par) = N_Subprogram_Body
+ if Nkind_In
+ (Par, N_Task_Body, N_Block_Statement, N_Subprogram_Body)
then
Set_Is_Task_Master (Par, True);
exit;
@@ -2120,10 +2122,13 @@ package body Exp_Ch3 is
begin
-- Offset_To_Top_Functions are built only for derivations of types
-- with discriminants that cover interface types.
+ -- Nothing is needed either in case of virtual machines, since
+ -- interfaces are handled directly by the VM.
if not Is_Tagged_Type (Rec_Type)
or else Etype (Rec_Type) = Rec_Type
or else not Has_Discriminants (Etype (Rec_Type))
+ or else VM_Target /= No_VM
then
return;
end if;
@@ -4343,7 +4348,9 @@ package body Exp_Ch3 is
end if;
-- Ada 2005 (AI-251): Rewrite the expression that initializes a
- -- class-wide object to ensure that we copy the full object.
+ -- class-wide object to ensure that we copy the full object,
+ -- unless we're targetting a VM where interfaces are handled by
+ -- VM itself.
-- Replace
-- CW : I'Class := Obj;
@@ -4354,6 +4361,7 @@ package body Exp_Ch3 is
if Is_Interface (Typ)
and then Is_Class_Wide_Type (Etype (Expr))
and then Comes_From_Source (Def_Id)
+ and then VM_Target = No_VM
then
declare
Decl_1 : Node_Id;
@@ -4523,10 +4531,15 @@ package body Exp_Ch3 is
end if;
end if;
- -- If validity checking on copies, validate initial expression
+ -- If validity checking on copies, validate initial expression.
+ -- But skip this if declaration is for a generic type, since it
+ -- makes no sense to validate generic types. Not clear if this
+ -- can happen for legal programs, but it definitely can arise
+ -- from previous instantiation errors.
if Validity_Checks_On
- and then Validity_Check_Copies
+ and then Validity_Check_Copies
+ and then not Is_Generic_Type (Etype (Def_Id))
then
Ensure_Valid (Expr);
Set_Is_Known_Valid (Def_Id);
@@ -4588,10 +4601,7 @@ package body Exp_Ch3 is
Validity_Check_Range (Range_Expression (Constraint (N)));
end if;
- if Nkind (Parent (N)) = N_Constrained_Array_Definition
- or else
- Nkind (Parent (N)) = N_Slice
- then
+ if Nkind_In (Parent (N), N_Constrained_Array_Definition, N_Slice) then
Apply_Range_Check (Ran, Typ);
end if;
end Expand_N_Subtype_Indication;
@@ -4628,11 +4638,13 @@ package body Exp_Ch3 is
begin
-- Find all access types declared in the current scope, whose
- -- designated type is Def_Id.
+ -- designated type is Def_Id. If it does not have a Master_Id,
+ -- create one now.
while Present (T) loop
if Is_Access_Type (T)
and then Designated_Type (T) = Def_Id
+ and then No (Master_Id (T))
then
Build_Master_Entity (Def_Id);
Build_Master_Renaming (Parent (Def_Id), T);
@@ -4727,7 +4739,7 @@ package body Exp_Ch3 is
-- between the secondary tag and its adjacent component.
or else Present
- (Related_Interface
+ (Related_Type
(Defining_Identifier (First_Comp))))
loop
Next (First_Comp);
@@ -5258,7 +5270,11 @@ package body Exp_Ch3 is
-- access components whose designated type is potentially controlled.
Renamed_Eq : Node_Id := Empty;
- -- Could use some comments ???
+ -- Defining unit name for the predefined equality function in the case
+ -- where the type has a primitive operation that is a renaming of
+ -- predefined equality (but only if there is also an overriding
+ -- user-defined equality function). Used to pass this entity from
+ -- Make_Predefined_Primitive_Specs to Predefined_Primitive_Bodies.
Wrapper_Decl_List : List_Id := No_List;
Wrapper_Body_List : List_Id := No_List;
@@ -5587,11 +5603,16 @@ package body Exp_Ch3 is
Build_Record_Init_Proc (Type_Decl, Def_Id);
end if;
- -- For tagged type, build bodies of primitive operations. Note that we
- -- do this after building the record initialization experiment, since
- -- the primitive operations may need the initialization routine
+ -- For tagged type that are not interfaces, build bodies of primitive
+ -- operations. Note that we do this after building the record
+ -- initialization procedure, since the primitive operations may need
+ -- the initialization routine. There is no need to add predefined
+ -- primitives of interfaces because all their predefined primitives
+ -- are abstract.
- if Is_Tagged_Type (Def_Id) then
+ if Is_Tagged_Type (Def_Id)
+ and then not Is_Interface (Def_Id)
+ then
-- Do not add the body of the predefined primitives if we are
-- compiling under restriction No_Dispatching_Calls
@@ -6118,9 +6139,7 @@ package body Exp_Ch3 is
-- Similarly, if it is an aggregate it must be qualified, because an
-- unchecked conversion does not provide a context for it.
- if Nkind (Val) = N_Null
- or else Nkind (Val) = N_Aggregate
- then
+ if Nkind_In (Val, N_Null, N_Aggregate) then
Val :=
Make_Qualified_Expression (Loc,
Subtype_Mark =>
@@ -6821,12 +6840,14 @@ package body Exp_Ch3 is
while Present (Idx) loop
if Nkind (Idx) = N_Range then
if (Nkind (Low_Bound (Idx)) = N_Identifier
- and then Present (Entity (Low_Bound (Idx)))
- and then Ekind (Entity (Low_Bound (Idx))) /= E_Constant)
+ and then Present (Entity (Low_Bound (Idx)))
+ and then
+ Ekind (Entity (Low_Bound (Idx))) /= E_Constant)
or else
(Nkind (High_Bound (Idx)) = N_Identifier
- and then Present (Entity (High_Bound (Idx)))
- and then Ekind (Entity (High_Bound (Idx))) /= E_Constant)
+ and then Present (Entity (High_Bound (Idx)))
+ and then
+ Ekind (Entity (High_Bound (Idx))) /= E_Constant)
then
return True;
end if;
@@ -7267,7 +7288,7 @@ package body Exp_Ch3 is
procedure Make_Predefined_Primitive_Specs
(Tag_Typ : Entity_Id;
Predef_List : out List_Id;
- Renamed_Eq : out Node_Id)
+ Renamed_Eq : out Entity_Id)
is
Loc : constant Source_Ptr := Sloc (Tag_Typ);
Res : constant List_Id := New_List;
@@ -7342,13 +7363,12 @@ package body Exp_Ch3 is
end loop;
end;
- -- Spec of "=" if expanded if the type is not limited and if a
+ -- Spec of "=" is expanded if the type is not limited and if a
-- user defined "=" was not already declared for the non-full
-- view of a private extension
if not Is_Limited_Type (Tag_Typ) then
Eq_Needed := True;
-
Prim := First_Elmt (Primitive_Operations (Tag_Typ));
while Present (Prim) loop
@@ -7364,6 +7384,8 @@ package body Exp_Ch3 is
if Is_Predefined_Eq_Renaming (Node (Prim)) then
Eq_Name := New_External_Name (Chars (Node (Prim)), 'E');
+ -- User-defined equality
+
elsif Chars (Node (Prim)) = Name_Op_Eq
and then (No (Alias (Node (Prim)))
or else Nkind (Unit_Declaration_Node (Node (Prim))) =
@@ -7371,15 +7393,16 @@ package body Exp_Ch3 is
and then Etype (First_Formal (Node (Prim))) =
Etype (Next_Formal (First_Formal (Node (Prim))))
and then Base_Type (Etype (Node (Prim))) = Standard_Boolean
-
then
Eq_Needed := False;
exit;
- -- If the parent equality is abstract, the inherited equality is
- -- abstract as well, and no body can be created for for it.
+ -- If the parent is not an interface type and has an abstract
+ -- equality function, the inherited equality is abstract as well,
+ -- and no body can be created for it.
elsif Chars (Node (Prim)) = Name_Op_Eq
+ and then not Is_Interface (Etype (Tag_Typ))
and then Present (Alias (Node (Prim)))
and then Is_Abstract_Subprogram (Alias (Node (Prim)))
then
@@ -7469,11 +7492,12 @@ package body Exp_Ch3 is
-- operations for limited interfaces and synchronized types that
-- implement a limited interface.
- -- disp_asynchronous_select
- -- disp_conditional_select
- -- disp_get_prim_op_kind
- -- disp_get_task_id
- -- disp_timed_select
+ -- Disp_Asynchronous_Select
+ -- Disp_Conditional_Select
+ -- Disp_Get_Prim_Op_Kind
+ -- Disp_Get_Task_Id
+ -- Disp_Requeue
+ -- Disp_Timed_Select
-- These operations cannot be implemented on VM targets, so we simply
-- disable their generation in this case. We also disable generation
@@ -7481,35 +7505,83 @@ package body Exp_Ch3 is
if Ada_Version >= Ada_05
and then VM_Target = No_VM
- and then
- ((Is_Interface (Tag_Typ) and then Is_Limited_Record (Tag_Typ))
- or else (Is_Concurrent_Record_Type (Tag_Typ)
- and then Has_Abstract_Interfaces (Tag_Typ)))
then
- Append_To (Res,
- Make_Subprogram_Declaration (Loc,
- Specification =>
- Make_Disp_Asynchronous_Select_Spec (Tag_Typ)));
+ -- These primitives are defined abstract in interface types
- Append_To (Res,
- Make_Subprogram_Declaration (Loc,
- Specification =>
- Make_Disp_Conditional_Select_Spec (Tag_Typ)));
+ if Is_Interface (Tag_Typ)
+ and then Is_Limited_Record (Tag_Typ)
+ then
+ Append_To (Res,
+ Make_Abstract_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Asynchronous_Select_Spec (Tag_Typ)));
- Append_To (Res,
- Make_Subprogram_Declaration (Loc,
- Specification =>
- Make_Disp_Get_Prim_Op_Kind_Spec (Tag_Typ)));
+ Append_To (Res,
+ Make_Abstract_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Conditional_Select_Spec (Tag_Typ)));
- Append_To (Res,
- Make_Subprogram_Declaration (Loc,
- Specification =>
- Make_Disp_Get_Task_Id_Spec (Tag_Typ)));
+ Append_To (Res,
+ Make_Abstract_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Get_Prim_Op_Kind_Spec (Tag_Typ)));
- Append_To (Res,
- Make_Subprogram_Declaration (Loc,
- Specification =>
- Make_Disp_Timed_Select_Spec (Tag_Typ)));
+ Append_To (Res,
+ Make_Abstract_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Get_Task_Id_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Abstract_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Requeue_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Abstract_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Timed_Select_Spec (Tag_Typ)));
+
+ -- If the ancestor is an interface type we declare non-abstract
+ -- primitives to override the abstract primitives of the interface
+ -- type.
+
+ elsif (not Is_Interface (Tag_Typ)
+ and then Is_Interface (Etype (Tag_Typ))
+ and then Is_Limited_Record (Etype (Tag_Typ)))
+ or else
+ (Is_Concurrent_Record_Type (Tag_Typ)
+ and then Has_Abstract_Interfaces (Tag_Typ))
+ then
+ Append_To (Res,
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Asynchronous_Select_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Conditional_Select_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Get_Prim_Op_Kind_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Get_Task_Id_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Requeue_Spec (Tag_Typ)));
+
+ Append_To (Res,
+ Make_Subprogram_Declaration (Loc,
+ Specification =>
+ Make_Disp_Timed_Select_Spec (Tag_Typ)));
+ end if;
end if;
-- Specs for finalization actions that may be required in case a future
@@ -7696,12 +7768,15 @@ package body Exp_Ch3 is
New_Reference_To (Ret_Type, Loc));
end if;
+ if Is_Interface (Tag_Typ) then
+ return Make_Abstract_Subprogram_Declaration (Loc, Spec);
+
-- If body case, return empty subprogram body. Note that this is ill-
-- formed, because there is not even a null statement, and certainly not
-- a return in the function case. The caller is expected to do surgery
-- on the body to add the appropriate stuff.
- if For_Body then
+ elsif For_Body then
return Make_Subprogram_Body (Loc, Spec, Empty_List, Empty);
-- For the case of an Input attribute predefined for an abstract type,
@@ -7754,7 +7829,7 @@ package body Exp_Ch3 is
function Predefined_Primitive_Bodies
(Tag_Typ : Entity_Id;
- Renamed_Eq : Node_Id) return List_Id
+ Renamed_Eq : Entity_Id) return List_Id
is
Loc : constant Source_Ptr := Sloc (Tag_Typ);
Res : constant List_Id := New_List;
@@ -7767,12 +7842,35 @@ package body Exp_Ch3 is
pragma Warnings (Off, Ent);
begin
+ pragma Assert (not Is_Interface (Tag_Typ));
+
-- See if we have a predefined "=" operator
if Present (Renamed_Eq) then
Eq_Needed := True;
Eq_Name := Chars (Renamed_Eq);
+ -- If the parent is an interface type then it has defined all the
+ -- predefined primitives abstract and we need to check if the type
+ -- has some user defined "=" function to avoid generating it.
+
+ elsif Is_Interface (Etype (Tag_Typ)) then
+ Eq_Needed := True;
+ Eq_Name := Name_Op_Eq;
+
+ Prim := First_Elmt (Primitive_Operations (Tag_Typ));
+ while Present (Prim) loop
+ if Chars (Node (Prim)) = Name_Op_Eq
+ and then not Is_Internal (Node (Prim))
+ then
+ Eq_Needed := False;
+ Eq_Name := No_Name;
+ exit;
+ end if;
+
+ Next_Elmt (Prim);
+ end loop;
+
else
Eq_Needed := False;
Eq_Name := No_Name;
@@ -7784,6 +7882,7 @@ package body Exp_Ch3 is
then
Eq_Needed := True;
Eq_Name := Name_Op_Eq;
+ exit;
end if;
Next_Elmt (Prim);
@@ -7893,20 +7992,24 @@ package body Exp_Ch3 is
if Ada_Version >= Ada_05
and then VM_Target = No_VM
and then not Restriction_Active (No_Dispatching_Calls)
+ and then not Is_Interface (Tag_Typ)
and then
- ((Is_Interface (Tag_Typ) and then Is_Limited_Record (Tag_Typ))
- or else (Is_Concurrent_Record_Type (Tag_Typ)
- and then Has_Abstract_Interfaces (Tag_Typ)))
+ ((Is_Interface (Etype (Tag_Typ))
+ and then Is_Limited_Record (Etype (Tag_Typ)))
+ or else (Is_Concurrent_Record_Type (Tag_Typ)
+ and then Has_Abstract_Interfaces (Tag_Typ)))
then
Append_To (Res, Make_Disp_Asynchronous_Select_Body (Tag_Typ));
Append_To (Res, Make_Disp_Conditional_Select_Body (Tag_Typ));
Append_To (Res, Make_Disp_Get_Prim_Op_Kind_Body (Tag_Typ));
Append_To (Res, Make_Disp_Get_Task_Id_Body (Tag_Typ));
+ Append_To (Res, Make_Disp_Requeue_Body (Tag_Typ));
Append_To (Res, Make_Disp_Timed_Select_Body (Tag_Typ));
end if;
- if not Is_Limited_Type (Tag_Typ) then
-
+ if not Is_Limited_Type (Tag_Typ)
+ and then not Is_Interface (Tag_Typ)
+ then
-- Body for equality
if Eq_Needed then