-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
with Elists; use Elists;
with Errout; use Errout;
with Exp_Atag; use Exp_Atag;
-with Exp_Ch7; use Exp_Ch7;
+with Exp_Ch6; use Exp_Ch6;
with Exp_CG; use Exp_CG;
with Exp_Dbug; use Exp_Dbug;
with Exp_Tss; use Exp_Tss;
with Stand; use Stand;
with Stringt; use Stringt;
with SCIL_LL; use SCIL_LL;
+with Targparm; use Targparm;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
-- Ada 2005 (AI-251): Returns the fixed position in the dispatch table
-- of the default primitive operations.
+ function Find_Specific_Type (CW : Entity_Id) return Entity_Id;
+ -- Find specific type of a class-wide type, and handle the case of an
+ -- incomplete type coming either from a limited_with clause or from an
+ -- incomplete type declaration. Shouldn't this be in Sem_Util? It seems
+ -- like a general purpose semantic routine ???
+
function Has_DT (Typ : Entity_Id) return Boolean;
pragma Inline (Has_DT);
-- Returns true if we generate a dispatch table for tagged type Typ
CW_Typ := Class_Wide_Type (Ctrl_Typ);
end if;
- Typ := Root_Type (CW_Typ);
-
- if Ekind (Typ) = E_Incomplete_Type then
- Typ := Non_Limited_View (Typ);
- end if;
+ Typ := Find_Specific_Type (CW_Typ);
if not Is_Limited_Type (Typ) then
Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
return Static_Dispatch_Tables
and then Is_Library_Level_Tagged_Type (Typ)
+ and then VM_Target = No_VM
-- If the type is derived from a CPP class we cannot statically
-- build the dispatch tables because we must inherit primitives
if Chars (E) = Name_uSize then
return Uint_1;
- elsif Chars (E) = Name_uAlignment then
+ elsif TSS_Name = TSS_Stream_Read then
return Uint_2;
- elsif TSS_Name = TSS_Stream_Read then
+ elsif TSS_Name = TSS_Stream_Write then
return Uint_3;
- elsif TSS_Name = TSS_Stream_Write then
+ elsif TSS_Name = TSS_Stream_Input then
return Uint_4;
- elsif TSS_Name = TSS_Stream_Input then
+ elsif TSS_Name = TSS_Stream_Output then
return Uint_5;
- elsif TSS_Name = TSS_Stream_Output then
+ elsif Chars (E) = Name_Op_Eq then
return Uint_6;
- elsif Chars (E) = Name_Op_Eq then
+ elsif Chars (E) = Name_uAssign then
return Uint_7;
- elsif Chars (E) = Name_uAssign then
+ elsif TSS_Name = TSS_Deep_Adjust then
return Uint_8;
- elsif TSS_Name = TSS_Deep_Adjust then
+ elsif TSS_Name = TSS_Deep_Finalize then
return Uint_9;
- elsif TSS_Name = TSS_Deep_Finalize then
- return Uint_10;
+ -- In VM targets unconditionally allow obtaining the position associated
+ -- with predefined interface primitives since in these platforms any
+ -- tagged type has these primitives.
- elsif Ada_Version >= Ada_2005 then
+ elsif Ada_Version >= Ada_2005 or else not Tagged_Type_Expansion then
if Chars (E) = Name_uDisp_Asynchronous_Select then
- return Uint_11;
+ return Uint_10;
elsif Chars (E) = Name_uDisp_Conditional_Select then
- return Uint_12;
+ return Uint_11;
elsif Chars (E) = Name_uDisp_Get_Prim_Op_Kind then
- return Uint_13;
+ return Uint_12;
elsif Chars (E) = Name_uDisp_Get_Task_Id then
- return Uint_14;
+ return Uint_13;
elsif Chars (E) = Name_uDisp_Requeue then
- return Uint_15;
+ return Uint_14;
elsif Chars (E) = Name_uDisp_Timed_Select then
- return Uint_16;
+ return Uint_15;
end if;
end if;
end if;
-- Expand_Dispatching_Call is called directly from the semantics,
- -- so we need a check to see whether expansion is active before
- -- proceeding. In addition, there is no need to expand the call
- -- if we are compiling under restriction No_Dispatching_Calls;
- -- the semantic analyzer has previously notified the violation
- -- of this restriction.
+ -- so we only proceed if the expander is active.
+
+ if not Full_Expander_Active
+
+ -- And there is no need to expand the call if we are compiling under
+ -- restriction No_Dispatching_Calls; the semantic analyzer has
+ -- previously notified the violation of this restriction.
- if not Expander_Active
or else Restriction_Active (No_Dispatching_Calls)
then
return;
CW_Typ := Class_Wide_Type (Ctrl_Typ);
end if;
- Typ := Root_Type (CW_Typ);
-
- if Ekind (Typ) = E_Incomplete_Type then
- Typ := Non_Limited_View (Typ);
- end if;
+ Typ := Find_Specific_Type (CW_Typ);
if not Is_Limited_Type (Typ) then
Eq_Prim_Op := Find_Prim_Op (Typ, Name_Op_Eq);
Subp_Ptr_Typ := Create_Itype (E_Access_Subprogram_Type, Call_Node);
Set_Etype (Subp_Typ, Res_Typ);
Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp));
+ Set_Convention (Subp_Typ, Convention (Subp));
+
+ -- Notify gigi that the designated type is a dispatching primitive
+
+ Set_Is_Dispatch_Table_Entity (Subp_Typ);
-- Create a new list of parameters which is a copy of the old formal
-- list including the creation of a new set of matching entities.
else
Build_Get_Prim_Op_Address (Loc,
- Typ => Find_Dispatching_Type (Subp),
+ Typ => Underlying_Type (Find_Dispatching_Type (Subp)),
Tag_Node => Controlling_Tag,
Position => DT_Position (Subp),
New_Node => New_Node);
Parent (Entity (Prefix (Controlling_Tag))));
-- For a direct reference of the tag of the type the SCIL node
- -- references the the internal object declaration containing the tag
+ -- references the internal object declaration containing the tag
-- of the type.
elsif Nkind (Controlling_Tag) = N_Attribute_Reference
Iface_Typ := Corresponding_Record_Type (Iface_Typ);
end if;
+ -- Handle private types
+
+ Iface_Typ := Underlying_Type (Iface_Typ);
+
-- Freeze the entity associated with the target interface to have
-- available the attribute Access_Disp_Table.
and then Is_Interface (Iface_Typ)));
if not Tagged_Type_Expansion then
+ if VM_Target /= No_VM then
+ if Is_Access_Type (Operand_Typ) then
+ Operand_Typ := Designated_Type (Operand_Typ);
+ end if;
- -- For VM, just do a conversion ???
+ if Is_Class_Wide_Type (Operand_Typ) then
+ Operand_Typ := Root_Type (Operand_Typ);
+ end if;
+
+ if not Is_Static
+ and then Operand_Typ /= Iface_Typ
+ then
+ Insert_Action (N,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Occurrence_Of
+ (RTE (RE_Check_Interface_Conversion), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => Duplicate_Subexpr (Expression (N)),
+ Attribute_Name => Name_Tag),
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Iface_Typ, Loc),
+ Attribute_Name => Name_Tag))));
+ end if;
+
+ -- Just do a conversion ???
+
+ Rewrite (N, Unchecked_Convert_To (Etype (N), N));
+ Analyze (N);
+ end if;
- Rewrite (N, Unchecked_Convert_To (Etype (N), N));
- Analyze (N);
return;
end if;
and then Is_Class_Wide_Type (Formal_Typ)
then
-- No need to displace the pointer if the type of the actual
- -- coindices with the type of the formal.
+ -- coincides with the type of the formal.
if Actual_Typ = Formal_Typ then
null;
-- a parent of the type of the actual because in this case the
-- interface primitives are located in the primary dispatch table.
- elsif Is_Ancestor (Formal_Typ, Actual_Typ) then
+ elsif Is_Ancestor (Formal_Typ, Actual_Typ,
+ Use_Full_View => True)
+ then
null;
-- Implicit conversion to the class-wide formal type to force
-- the displacement of the pointer.
else
+ -- Normally, expansion of actuals for calls to build-in-place
+ -- functions happens as part of Expand_Actuals, but in this
+ -- case the call will be wrapped in a conversion and soon after
+ -- expanded further to handle the displacement for a class-wide
+ -- interface conversion, so if this is a BIP call then we need
+ -- to handle it now.
+
+ if Ada_Version >= Ada_2005
+ and then Is_Build_In_Place_Function_Call (Actual)
+ then
+ Make_Build_In_Place_Call_In_Anonymous_Context (Actual);
+ end if;
+
Conversion := Convert_To (Formal_Typ, Relocate_Node (Actual));
Rewrite (Actual, Conversion);
Analyze_And_Resolve (Actual, Formal_Typ);
-- a parent of the type of the actual because in this case the
-- interface primitives are located in the primary dispatch table.
- elsif Is_Ancestor (Formal_DDT, Actual_DDT) then
+ elsif Is_Ancestor (Formal_DDT, Actual_DDT,
+ Use_Full_View => True)
+ then
null;
else
Thunk_Id := Make_Temporary (Loc, 'T');
Set_Is_Thunk (Thunk_Id);
+ Set_Convention (Thunk_Id, Convention (Prim));
-- Procedure case
end if;
end Expand_Interface_Thunk;
+ ------------------------
+ -- Find_Specific_Type --
+ ------------------------
+
+ function Find_Specific_Type (CW : Entity_Id) return Entity_Id is
+ Typ : Entity_Id := Root_Type (CW);
+
+ begin
+ if Ekind (Typ) = E_Incomplete_Type then
+ if From_With_Type (Typ) then
+ Typ := Non_Limited_View (Typ);
+ else
+ Typ := Full_View (Typ);
+ end if;
+ end if;
+
+ return Typ;
+ end Find_Specific_Type;
+
--------------------------
-- Has_CPP_Constructors --
--------------------------
TSS_Name := TSS_Name_Type (Name_Buffer (Name_Len - TSS_Name'Length + 1
.. Name_Len));
if Chars (E) = Name_uSize
- or else Chars (E) = Name_uAlignment
or else TSS_Name = TSS_Stream_Read
or else TSS_Name = TSS_Stream_Write
or else TSS_Name = TSS_Stream_Input
(Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len));
if Chars (E) = Name_uSize
- or else Chars (E) = Name_uAlignment
or else
(Chars (E) = Name_Op_Eq
and then Etype (First_Formal (E)) = Etype (Last_Formal (E)))
function Is_Predefined_Interface_Primitive (E : Entity_Id) return Boolean is
begin
- return Ada_Version >= Ada_2005
+ -- In VM targets we don't restrict the functionality of this test to
+ -- compiling in Ada 2005 mode since in VM targets any tagged type has
+ -- these primitives
+
+ return (Ada_Version >= Ada_2005 or else not Tagged_Type_Expansion)
and then (Chars (E) = Name_uDisp_Asynchronous_Select or else
Chars (E) = Name_uDisp_Conditional_Select or else
Chars (E) = Name_uDisp_Get_Prim_Op_Kind or else
-- F : out Boolean)
-- is
-- begin
- -- null;
+ -- F := False;
+ -- C := Ada.Tags.POK_Function;
-- end _Disp_Asynchronous_Select;
-- For protected types, generate:
Com_Block : Entity_Id;
Conc_Typ : Entity_Id := Empty;
Decls : constant List_Id := New_List;
- DT_Ptr : Entity_Id;
Loc : constant Source_Ptr := Sloc (Typ);
Obj_Ref : Node_Id;
Stmts : constant List_Id := New_List;
+ Tag_Node : Node_Id;
begin
pragma Assert (not Restriction_Active (No_Dispatching_Calls));
if Is_Interface (Typ) then
return
Make_Subprogram_Body (Loc,
- Specification =>
- Make_Disp_Asynchronous_Select_Spec (Typ),
- Declarations =>
- New_List,
+ Specification => Make_Disp_Asynchronous_Select_Spec (Typ),
+ Declarations => New_List,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- New_List (Make_Null_Statement (Loc))));
+ New_List (Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)))));
end if;
- DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
-
if Is_Concurrent_Record_Type (Typ) then
Conc_Typ := Corresponding_Concurrent_Type (Typ);
-- where I will be used to capture the entry index of the primitive
-- wrapper at position S.
+ if Tagged_Type_Expansion then
+ Tag_Node :=
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Typ))), Loc));
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag);
+ end if;
+
Append_To (Decls,
Make_Object_Declaration (Loc,
Defining_Identifier =>
New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
Parameter_Associations =>
New_List (
- Unchecked_Convert_To (RTE (RE_Tag),
- New_Reference_To (DT_Ptr, Loc)),
+ Tag_Node,
Make_Identifier (Loc, Name_uS)))));
if Ekind (Conc_Typ) = E_Protected_Type then
Make_Unchecked_Type_Conversion (Loc, -- entry index
Subtype_Mark =>
New_Reference_To
- (RTE (RE_Protected_Entry_Index), Loc),
+ (RTE (RE_Protected_Entry_Index), Loc),
Expression => Make_Identifier (Loc, Name_uI)),
Make_Identifier (Loc, Name_uP), -- parameter block
- New_Reference_To ( -- Asynchronous_Call
- RTE (RE_Asynchronous_Call), Loc),
+ New_Reference_To -- Asynchronous_Call
+ (RTE (RE_Asynchronous_Call), Loc),
New_Reference_To (Com_Block, Loc)))); -- comm block
Obj_Ref,
Make_Attribute_Reference (Loc,
- Prefix => Make_Identifier (Loc, Name_uP),
+ Prefix => Make_Identifier (Loc, Name_uP),
Attribute_Name => Name_Address),
New_Reference_To
Append_To (Stmts,
Make_Assignment_Statement (Loc,
- Name =>
- Make_Identifier (Loc, Name_uB),
+ Name => Make_Identifier (Loc, Name_uB),
Expression =>
Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark =>
Expression =>
New_Reference_To (Com_Block, Loc))));
+ -- Generate:
+ -- F := False;
+
+ Append_To (Stmts,
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)));
+
else
pragma Assert (Ekind (Conc_Typ) = E_Task_Type);
Parameter_Associations =>
New_List (
Make_Selected_Component (Loc, -- T._task_id
- Prefix =>
- Make_Identifier (Loc, Name_uT),
- Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id)),
+ Prefix => Make_Identifier (Loc, Name_uT),
+ Selector_Name => Make_Identifier (Loc, Name_uTask_Id)),
Make_Unchecked_Type_Conversion (Loc, -- entry index
Subtype_Mark =>
New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uI)),
+ Expression => Make_Identifier (Loc, Name_uI)),
Make_Identifier (Loc, Name_uP), -- parameter block
- New_Reference_To ( -- Asynchronous_Call
- RTE (RE_Asynchronous_Call), Loc),
+ New_Reference_To -- Asynchronous_Call
+ (RTE (RE_Asynchronous_Call), Loc),
Make_Identifier (Loc, Name_uF)))); -- status flag
end if;
else
-- Ensure that the statements list is non-empty
- Append_To (Stmts, Make_Null_Statement (Loc));
+ Append_To (Stmts,
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)));
end if;
return
Make_Subprogram_Body (Loc,
- Specification =>
+ Specification =>
Make_Disp_Asynchronous_Select_Spec (Typ),
- Declarations =>
- Decls,
+ Declarations => Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Stmts));
end Make_Disp_Asynchronous_Select_Body;
-- F : out Boolean)
-- is
-- begin
- -- null;
+ -- F := False;
+ -- C := Ada.Tags.POK_Function;
-- end _Disp_Conditional_Select;
-- For protected types, generate:
Blk_Nam : Entity_Id;
Conc_Typ : Entity_Id := Empty;
Decls : constant List_Id := New_List;
- DT_Ptr : Entity_Id;
Obj_Ref : Node_Id;
Stmts : constant List_Id := New_List;
+ Tag_Node : Node_Id;
begin
pragma Assert (not Restriction_Active (No_Dispatching_Calls));
No_List,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- New_List (Make_Null_Statement (Loc))));
+ New_List (Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)))));
end if;
- DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
-
if Is_Concurrent_Record_Type (Typ) then
Conc_Typ := Corresponding_Concurrent_Type (Typ);
-- return;
-- end if;
- Build_Common_Dispatching_Select_Statements (Loc, DT_Ptr, Stmts);
+ Build_Common_Dispatching_Select_Statements (Typ, Stmts);
-- Generate:
-- Bnn : Communication_Block;
-- I is the entry index and S is the dispatch table slot
+ if Tagged_Type_Expansion then
+ Tag_Node :=
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Typ))), Loc));
+
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag);
+ end if;
+
Append_To (Stmts,
Make_Assignment_Statement (Loc,
- Name =>
- Make_Identifier (Loc, Name_uI),
+ Name => Make_Identifier (Loc, Name_uI),
Expression =>
Make_Function_Call (Loc,
Name =>
New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
Parameter_Associations =>
New_List (
- Unchecked_Convert_To (RTE (RE_Tag),
- New_Reference_To (DT_Ptr, Loc)),
+ Tag_Node,
Make_Identifier (Loc, Name_uS)))));
if Ekind (Conc_Typ) = E_Protected_Type then
Obj_Ref,
Make_Attribute_Reference (Loc,
- Prefix => Make_Identifier (Loc, Name_uP),
+ Prefix => Make_Identifier (Loc, Name_uP),
Attribute_Name => Name_Address),
New_Reference_To
Append_To (Stmts,
Make_Assignment_Statement (Loc,
- Name =>
- Make_Identifier (Loc, Name_uF),
+ Name => Make_Identifier (Loc, Name_uF),
Expression =>
Make_Op_Not (Loc,
Right_Opnd =>
New_List (
Make_Selected_Component (Loc, -- T._task_id
- Prefix =>
- Make_Identifier (Loc, Name_uT),
- Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id)),
+ Prefix => Make_Identifier (Loc, Name_uT),
+ Selector_Name => Make_Identifier (Loc, Name_uTask_Id)),
Make_Unchecked_Type_Conversion (Loc, -- entry index
Subtype_Mark =>
New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uI)),
+ Expression => Make_Identifier (Loc, Name_uI)),
Make_Identifier (Loc, Name_uP), -- parameter block
- New_Reference_To ( -- Conditional_Call
- RTE (RE_Conditional_Call), Loc),
+ New_Reference_To -- Conditional_Call
+ (RTE (RE_Conditional_Call), Loc),
Make_Identifier (Loc, Name_uF)))); -- status flag
end if;
else
- -- Ensure that the statements list is non-empty
+ -- Initialize out parameters
- Append_To (Stmts, Make_Null_Statement (Loc));
+ Append_To (Stmts,
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)));
+ Append_To (Stmts,
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uC),
+ Expression => New_Reference_To (RTE (RE_POK_Function), Loc)));
end if;
return
Make_Subprogram_Body (Loc,
- Specification =>
+ Specification =>
Make_Disp_Conditional_Select_Spec (Typ),
- Declarations =>
- Decls,
+ Declarations => Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Stmts));
end Make_Disp_Conditional_Select_Body;
function Make_Disp_Get_Prim_Op_Kind_Body
(Typ : Entity_Id) return Node_Id
is
- Loc : constant Source_Ptr := Sloc (Typ);
- DT_Ptr : Entity_Id;
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Tag_Node : Node_Id;
begin
pragma Assert (not Restriction_Active (No_Dispatching_Calls));
New_List (Make_Null_Statement (Loc))));
end if;
- DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
-
-- Generate:
-- C := get_prim_op_kind (tag! (<type>VP), S);
-- where C is the out parameter capturing the call kind and S is the
-- dispatch table slot number.
+ if Tagged_Type_Expansion then
+ Tag_Node :=
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Typ))), Loc));
+
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag);
+ end if;
+
return
Make_Subprogram_Body (Loc,
Specification =>
Name =>
New_Reference_To (RTE (RE_Get_Prim_Op_Kind), Loc),
Parameter_Associations => New_List (
- Unchecked_Convert_To (RTE (RE_Tag),
- New_Reference_To (DT_Ptr, Loc)),
- Make_Identifier (Loc, Name_uS)))))));
+ Tag_Node,
+ Make_Identifier (Loc, Name_uS)))))));
end Make_Disp_Get_Prim_Op_Kind_Body;
-------------------------------------
New_Reference_To (RTE (RE_Address), Loc),
Expression =>
Make_Selected_Component (Loc,
- Prefix =>
- Make_Identifier (Loc, Name_uT),
- Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id))));
+ Prefix => Make_Identifier (Loc, Name_uT),
+ Selector_Name => Make_Identifier (Loc, Name_uTask_Id))));
-- A null body is constructed for non-task types
else
Append_To (Stmts,
Make_If_Statement (Loc,
- Condition =>
- Make_Identifier (Loc, Name_uF),
+ Condition => Make_Identifier (Loc, Name_uF),
Then_Statements =>
New_List (
Name_Unchecked_Access,
Prefix =>
Make_Selected_Component (Loc,
- Prefix =>
+ Prefix =>
Make_Identifier (Loc, Name_uO),
Selector_Name =>
Make_Identifier (Loc, Name_uObject))),
Subtype_Mark =>
New_Reference_To (
RTE (RE_Protected_Entry_Index), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uI)),
+ Expression => Make_Identifier (Loc, Name_uI)),
Make_Identifier (Loc, Name_uA)))), -- abort status
Append_To (Stmts,
Make_If_Statement (Loc,
- Condition =>
- Make_Identifier (Loc, Name_uF),
+ Condition => Make_Identifier (Loc, Name_uF),
- Then_Statements =>
- New_List (
+ Then_Statements => New_List (
- -- Call to Requeue_Protected_To_Task_Entry
+ -- Call to Requeue_Protected_To_Task_Entry
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Reference_To (
- RTE (RE_Requeue_Protected_To_Task_Entry), Loc),
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Reference_To
+ (RTE (RE_Requeue_Protected_To_Task_Entry), Loc),
- Parameter_Associations =>
- New_List (
+ Parameter_Associations => New_List (
- Make_Unchecked_Type_Conversion (Loc, -- PEA (P)
- Subtype_Mark =>
- New_Reference_To (
- RTE (RE_Protection_Entries_Access), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uP)),
+ Make_Unchecked_Type_Conversion (Loc, -- PEA (P)
+ Subtype_Mark =>
+ New_Reference_To
+ (RTE (RE_Protection_Entries_Access), Loc),
+ Expression => Make_Identifier (Loc, Name_uP)),
- Make_Selected_Component (Loc, -- O._task_id
- Prefix =>
- Make_Identifier (Loc, Name_uO),
- Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id)),
+ Make_Selected_Component (Loc, -- O._task_id
+ Prefix => Make_Identifier (Loc, Name_uO),
+ Selector_Name => Make_Identifier (Loc, Name_uTask_Id)),
- Make_Unchecked_Type_Conversion (Loc, -- entry index
- Subtype_Mark =>
- New_Reference_To (
- RTE (RE_Task_Entry_Index), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uI)),
+ Make_Unchecked_Type_Conversion (Loc, -- entry index
+ Subtype_Mark =>
+ New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
+ Expression => Make_Identifier (Loc, Name_uI)),
- Make_Identifier (Loc, Name_uA)))), -- abort status
+ Make_Identifier (Loc, Name_uA)))), -- abort status
- Else_Statements =>
- New_List (
+ Else_Statements => New_List (
- -- Call to Requeue_Task_Entry
+ -- Call to Requeue_Task_Entry
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Reference_To (RTE (RE_Requeue_Task_Entry), Loc),
-
- Parameter_Associations =>
- New_List (
-
- Make_Selected_Component (Loc, -- O._task_id
- Prefix =>
- Make_Identifier (Loc, Name_uO),
- Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id)),
-
- Make_Unchecked_Type_Conversion (Loc, -- entry index
- Subtype_Mark =>
- New_Reference_To (
- RTE (RE_Task_Entry_Index), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uI)),
-
- Make_Identifier (Loc, Name_uA)))))); -- abort status
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Requeue_Task_Entry), Loc),
+
+ Parameter_Associations => New_List (
+
+ Make_Selected_Component (Loc, -- O._task_id
+ Prefix => Make_Identifier (Loc, Name_uO),
+ Selector_Name => Make_Identifier (Loc, Name_uTask_Id)),
+
+ Make_Unchecked_Type_Conversion (Loc, -- entry index
+ Subtype_Mark =>
+ New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
+ Expression => Make_Identifier (Loc, Name_uI)),
+
+ Make_Identifier (Loc, Name_uA)))))); -- abort status
end if;
-- Even though no declarations are needed in both cases, we allocate
-- F : out Boolean)
-- is
-- begin
- -- null;
+ -- F := False;
+ -- C := Ada.Tags.POK_Function;
-- end _Disp_Timed_Select;
-- For protected types, generate:
-- P,
-- D,
-- M,
- -- D);
+ -- F);
-- end _Disp_Time_Select;
function Make_Disp_Timed_Select_Body
Loc : constant Source_Ptr := Sloc (Typ);
Conc_Typ : Entity_Id := Empty;
Decls : constant List_Id := New_List;
- DT_Ptr : Entity_Id;
Obj_Ref : Node_Id;
Stmts : constant List_Id := New_List;
+ Tag_Node : Node_Id;
begin
pragma Assert (not Restriction_Active (No_Dispatching_Calls));
New_List,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc,
- New_List (Make_Null_Statement (Loc))));
+ New_List (
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)))));
end if;
- DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
-
if Is_Concurrent_Record_Type (Typ) then
Conc_Typ := Corresponding_Concurrent_Type (Typ);
Append_To (Decls,
Make_Object_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_uI),
- Object_Definition =>
- New_Reference_To (Standard_Integer, Loc)));
+ Defining_Identifier => Make_Defining_Identifier (Loc, Name_uI),
+ Object_Definition => New_Reference_To (Standard_Integer, Loc)));
-- Generate:
-- C := Get_Prim_Op_Kind (tag! (<type>VP), S);
-- return;
-- end if;
- Build_Common_Dispatching_Select_Statements (Loc, DT_Ptr, Stmts);
+ Build_Common_Dispatching_Select_Statements (Typ, Stmts);
-- Generate:
-- I := Get_Entry_Index (tag! (<type>VP), S);
-- I is the entry index and S is the dispatch table slot
+ if Tagged_Type_Expansion then
+ Tag_Node :=
+ Unchecked_Convert_To (RTE (RE_Tag),
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Typ))), Loc));
+
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag);
+ end if;
+
Append_To (Stmts,
Make_Assignment_Statement (Loc,
- Name =>
- Make_Identifier (Loc, Name_uI),
+ Name => Make_Identifier (Loc, Name_uI),
Expression =>
Make_Function_Call (Loc,
- Name =>
- New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
+ Name => New_Reference_To (RTE (RE_Get_Entry_Index), Loc),
Parameter_Associations =>
New_List (
- Unchecked_Convert_To (RTE (RE_Tag),
- New_Reference_To (DT_Ptr, Loc)),
+ Tag_Node,
Make_Identifier (Loc, Name_uS)))));
-- Protected case
New_List (
Make_Selected_Component (Loc, -- T._task_id
- Prefix =>
- Make_Identifier (Loc, Name_uT),
- Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id)),
+ Prefix => Make_Identifier (Loc, Name_uT),
+ Selector_Name => Make_Identifier (Loc, Name_uTask_Id)),
Make_Unchecked_Type_Conversion (Loc, -- entry index
Subtype_Mark =>
New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
- Expression =>
- Make_Identifier (Loc, Name_uI)),
+ Expression => Make_Identifier (Loc, Name_uI)),
Make_Identifier (Loc, Name_uP), -- parameter block
Make_Identifier (Loc, Name_uD), -- delay
end if;
else
- -- Ensure that the statements list is non-empty
+ -- Initialize out parameters
- Append_To (Stmts, Make_Null_Statement (Loc));
+ Append_To (Stmts,
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uF),
+ Expression => New_Reference_To (Standard_False, Loc)));
+ Append_To (Stmts,
+ Make_Assignment_Statement (Loc,
+ Name => Make_Identifier (Loc, Name_uC),
+ Expression => New_Reference_To (RTE (RE_POK_Function), Loc)));
end if;
return
Make_Subprogram_Body (Loc,
- Specification =>
- Make_Disp_Timed_Select_Spec (Typ),
- Declarations =>
- Decls,
+ Specification => Make_Disp_Timed_Select_Spec (Typ),
+ Declarations => Decls,
Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Stmts));
end Make_Disp_Timed_Select_Body;
DT_Aggr : constant Elist_Id := New_Elmt_List;
-- Entities marked with attribute Is_Dispatch_Table_Entity
- procedure Check_Premature_Freezing (Subp : Entity_Id; Typ : Entity_Id);
+ procedure Check_Premature_Freezing
+ (Subp : Entity_Id;
+ Tagged_Type : Entity_Id;
+ Typ : Entity_Id);
-- Verify that all non-tagged types in the profile of a subprogram
-- are frozen at the point the subprogram is frozen. This enforces
-- the rule on RM 13.14 (14) as modified by AI05-019. At the point a
-- Typical violation of the rule involves an object declaration that
-- freezes a tagged type, when one of its primitive operations has a
-- type in its profile whose full view has not been analyzed yet.
+ -- More complex cases involve composite types that have one private
+ -- unfrozen subcomponent.
procedure Export_DT (Typ : Entity_Id; DT : Entity_Id; Index : Nat := 0);
-- Export the dispatch table DT of tagged type Typ. Required to generate
-- calls through interface types; the latter secondary table is
-- generated when Build_Thunks is False, and provides support for
-- Generic Dispatching Constructors that dispatch calls through
- -- interface types. When constructing this latter table the value
- -- of Suffix_Index is -1 to indicate that there is no need to export
- -- such table when building statically allocated dispatch tables; a
- -- positive value of Suffix_Index must match the Suffix_Index value
- -- assigned to this secondary dispatch table by Make_Tags when its
- -- unique external name was generated.
+ -- interface types. When constructing this latter table the value of
+ -- Suffix_Index is -1 to indicate that there is no need to export such
+ -- table when building statically allocated dispatch tables; a positive
+ -- value of Suffix_Index must match the Suffix_Index value assigned to
+ -- this secondary dispatch table by Make_Tags when its unique external
+ -- name was generated.
------------------------------
-- Check_Premature_Freezing --
------------------------------
- procedure Check_Premature_Freezing (Subp : Entity_Id; Typ : Entity_Id) is
+ procedure Check_Premature_Freezing
+ (Subp : Entity_Id;
+ Tagged_Type : Entity_Id;
+ Typ : Entity_Id)
+ is
+ Comp : Entity_Id;
+
+ function Is_Actual_For_Formal_Incomplete_Type
+ (T : Entity_Id) return Boolean;
+ -- In Ada 2012, if a nested generic has an incomplete formal type,
+ -- the actual may be (and usually is) a private type whose completion
+ -- appears later. It is safe to build the dispatch table in this
+ -- case, gigi will have full views available.
+
+ ------------------------------------------
+ -- Is_Actual_For_Formal_Incomplete_Type --
+ ------------------------------------------
+
+ function Is_Actual_For_Formal_Incomplete_Type
+ (T : Entity_Id) return Boolean
+ is
+ Gen_Par : Entity_Id;
+ F : Node_Id;
+
+ begin
+ if not Is_Generic_Instance (Current_Scope)
+ or else not Used_As_Generic_Actual (T)
+ then
+ return False;
+
+ else
+ Gen_Par := Generic_Parent (Parent (Current_Scope));
+ end if;
+
+ F :=
+ First
+ (Generic_Formal_Declarations
+ (Unit_Declaration_Node (Gen_Par)));
+ while Present (F) loop
+ if Ekind (Defining_Identifier (F)) = E_Incomplete_Type then
+ return True;
+ end if;
+
+ Next (F);
+ end loop;
+
+ return False;
+ end Is_Actual_For_Formal_Incomplete_Type;
+
+ -- Start of processing for Check_Premature_Freezing
+
begin
+ -- Note that if the type is a (subtype of) a generic actual, the
+ -- actual will have been frozen by the instantiation.
+
if Present (N)
- and then Is_Private_Type (Typ)
+ and then Is_Private_Type (Typ)
and then No (Full_View (Typ))
and then not Is_Generic_Type (Typ)
and then not Is_Tagged_Type (Typ)
and then not Is_Frozen (Typ)
+ and then not Is_Generic_Actual_Type (Typ)
then
Error_Msg_Sloc := Sloc (Subp);
Error_Msg_NE
("declaration must appear after completion of type &", N, Typ);
Error_Msg_NE
("\which is an untagged type in the profile of"
- & " primitive operation & declared#",
- N, Subp);
+ & " primitive operation & declared#", N, Subp);
+
+ else
+ Comp := Private_Component (Typ);
+
+ if not Is_Tagged_Type (Typ)
+ and then Present (Comp)
+ and then not Is_Frozen (Comp)
+ and then
+ not Is_Actual_For_Formal_Incomplete_Type (Comp)
+ then
+ Error_Msg_Sloc := Sloc (Subp);
+ Error_Msg_Node_2 := Subp;
+ Error_Msg_Name_1 := Chars (Tagged_Type);
+ Error_Msg_NE
+ ("declaration must appear after completion of type &",
+ N, Comp);
+ Error_Msg_NE
+ ("\which is a component of untagged type& in the profile of"
+ & " primitive & of type % that is frozen by the declaration ",
+ N, Typ);
+ end if;
end if;
end Check_Premature_Freezing;
-- Tagged_Type. Otherwise the DT associated with the
-- interface is the primary DT.
- and then not Is_Ancestor (Iface, Typ)
+ and then not Is_Ancestor (Iface, Typ,
+ Use_Full_View => True)
then
if not Build_Thunks then
Prim_Pos :=
end if;
-- Ensure that the value of Max_Predef_Prims defined in a-tags is
- -- correct. Valid values are 10 under configurable runtime or 16
+ -- correct. Valid values are 9 under configurable runtime or 15
-- with full runtime.
if RTE_Available (RE_Interface_Data) then
- if Max_Predef_Prims /= 16 then
+ if Max_Predef_Prims /= 15 then
Error_Msg_N ("run-time library configuration error", Typ);
return Result;
end if;
else
- if Max_Predef_Prims /= 10 then
+ if Max_Predef_Prims /= 9 then
Error_Msg_N ("run-time library configuration error", Typ);
Error_Msg_CRT ("tagged types", Typ);
return Result;
begin
F := First_Formal (Prim);
while Present (F) loop
- Check_Premature_Freezing (Prim, Etype (F));
+ Check_Premature_Freezing (Prim, Typ, Etype (F));
Next_Formal (F);
end loop;
- Check_Premature_Freezing (Prim, Etype (Prim));
+ Check_Premature_Freezing (Prim, Typ, Etype (Prim));
end;
if Present (Frnodes) then
-- TSD : Type_Specific_Data (I_Depth) :=
-- (Idepth => I_Depth,
-- Access_Level => Type_Access_Level (Typ),
+ -- Alignment => Typ'Alignment,
-- Expanded_Name => Cstring_Ptr!(Exname'Address))
-- External_Tag => Cstring_Ptr!(Exname'Address))
-- HT_Link => HT_Link'Address,
-- Transportable => <<boolean-value>>,
-- Type_Is_Abstract => <<boolean-value>>,
- -- RC_Offset => <<integer-value>>,
- -- [ Size_Func => Size_Prim'Access ]
- -- [ Interfaces_Table => <<access-value>> ]
+ -- Needs_Finalization => <<boolean-value>>,
+ -- [ Size_Func => Size_Prim'Access, ]
+ -- [ Interfaces_Table => <<access-value>>, ]
-- [ SSD => SSD_Table'Address ]
-- Tags_Table => (0 => null,
-- 1 => Parent'Tag
Append_To (TSD_Aggr_List,
Make_Integer_Literal (Loc, Type_Access_Level (Typ)));
+ -- Alignment
+
+ -- For CPP types we cannot rely on the value of 'Alignment provided
+ -- by the backend to initialize this TSD field.
+
+ if Convention (Typ) = Convention_CPP
+ or else Is_CPP_Class (Root_Type (Typ))
+ then
+ Append_To (TSD_Aggr_List,
+ Make_Integer_Literal (Loc, 0));
+ else
+ Append_To (TSD_Aggr_List,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Alignment));
+ end if;
+
-- Expanded_Name
Append_To (TSD_Aggr_List,
Unchecked_Convert_To (RTE (RE_Cstring_Ptr),
Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Exname, Loc),
+ Prefix => New_Reference_To (Exname, Loc),
Attribute_Name => Name_Address)));
-- External_Tag of a local tagged type
end;
end if;
- -- RC_Offset: These are the valid values and their meaning:
-
- -- >0: For simple types with controlled components is
- -- type._record_controller'position
-
- -- 0: For types with no controlled components
-
- -- -1: For complex types with controlled components where the position
- -- of the record controller is not statically computable but there
- -- are controlled components at this level. The _Controller field
- -- is available right after the _parent.
-
- -- -2: There are no controlled components at this level. We need to
- -- get the position from the parent.
+ -- Needs_Finalization: Set if the type is controlled or has controlled
+ -- components.
declare
- RC_Offset_Node : Node_Id;
+ Needs_Fin : Entity_Id;
begin
- if not Has_Controlled_Component (Typ) then
- RC_Offset_Node := Make_Integer_Literal (Loc, 0);
-
- elsif Etype (Typ) /= Typ
- and then Has_Discriminants (Parent_Typ)
- then
- if Has_New_Controlled_Component (Typ) then
- RC_Offset_Node := Make_Integer_Literal (Loc, -1);
- else
- RC_Offset_Node := Make_Integer_Literal (Loc, -2);
- end if;
- else
- RC_Offset_Node :=
- Make_Attribute_Reference (Loc,
- Prefix =>
- Make_Selected_Component (Loc,
- Prefix => New_Reference_To (Typ, Loc),
- Selector_Name =>
- New_Reference_To (Controller_Component (Typ), Loc)),
- Attribute_Name => Name_Position);
-
- -- This is not proper Ada code to use the attribute 'Position
- -- on something else than an object but this is supported by
- -- the back end (see comment on the Bit_Component attribute in
- -- sem_attr). So we avoid semantic checking here.
-
- -- Is this documented in sinfo.ads??? it should be!
-
- Set_Analyzed (RC_Offset_Node);
- Set_Etype (Prefix (RC_Offset_Node), RTE (RE_Record_Controller));
- Set_Etype (Prefix (Prefix (RC_Offset_Node)), Typ);
- Set_Etype (Selector_Name (Prefix (RC_Offset_Node)),
- RTE (RE_Record_Controller));
- Set_Etype (RC_Offset_Node, RTE (RE_Storage_Offset));
- end if;
-
- Append_To (TSD_Aggr_List, RC_Offset_Node);
+ Needs_Fin := Boolean_Literals (Needs_Finalization (Typ));
+ Append_To (TSD_Aggr_List, New_Occurrence_Of (Needs_Fin, Loc));
end;
-- Size_Func
begin
AI := First_Elmt (Typ_Ifaces);
while Present (AI) loop
- if Is_Ancestor (Node (AI), Typ) then
+ if Is_Ancestor (Node (AI), Typ, Use_Full_View => True) then
Sec_DT_Tag :=
New_Reference_To (DT_Ptr, Loc);
else
while Is_Tag (Node (Elmt))
and then not
- Is_Ancestor (Node (AI), Related_Type (Node (Elmt)))
+ Is_Ancestor (Node (AI), Related_Type (Node (Elmt)),
+ Use_Full_View => True)
loop
pragma Assert (Has_Thunks (Node (Elmt)));
Next_Elmt (Elmt);
end if;
end if;
+ -- If the type has a representation clause which specifies its external
+ -- tag then generate code to check if the external tag of this type is
+ -- the same as the external tag of some other declaration.
+
+ -- Check_TSD (TSD'Unrestricted_Access);
+
+ -- This check is a consequence of AI05-0113-1/06, so it officially
+ -- applies to Ada 2005 (and Ada 2012). It might be argued that it is
+ -- a desirable check to add in Ada 95 mode, but we hesitate to make
+ -- this change, as it would be incompatible, and could conceivably
+ -- cause a problem in existing Aa 95 code.
+
+ -- We check for No_Run_Time_Mode here, because we do not want to pick
+ -- up the RE_Check_TSD entity and call it in No_Run_Time mode.
+
+ if not No_Run_Time_Mode
+ and then Ada_Version >= Ada_2005
+ and then Has_External_Tag_Rep_Clause (Typ)
+ and then RTE_Available (RE_Check_TSD)
+ and then not Debug_Flag_QQ
+ then
+ Append_To (Elab_Code,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Check_TSD), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (TSD, Loc),
+ Attribute_Name => Name_Unchecked_Access))));
+ end if;
+
-- Generate code to register the Tag in the External_Tag hash table for
-- the pure Ada type only.
return Result;
end Make_DT;
- -------------------------------------
- -- Make_Select_Specific_Data_Table --
- -------------------------------------
-
- function Make_Select_Specific_Data_Table
- (Typ : Entity_Id) return List_Id
- is
- Assignments : constant List_Id := New_List;
- Loc : constant Source_Ptr := Sloc (Typ);
+ -----------------
+ -- Make_VM_TSD --
+ -----------------
- Conc_Typ : Entity_Id;
- Decls : List_Id;
- DT_Ptr : Entity_Id;
- Prim : Entity_Id;
- Prim_Als : Entity_Id;
- Prim_Elmt : Elmt_Id;
- Prim_Pos : Uint;
- Nb_Prim : Nat := 0;
+ function Make_VM_TSD (Typ : Entity_Id) return List_Id is
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Result : constant List_Id := New_List;
- type Examined_Array is array (Int range <>) of Boolean;
+ function Count_Primitives (Typ : Entity_Id) return Nat;
+ -- Count the non-predefined primitive operations of Typ
+
+ ----------------------
+ -- Count_Primitives --
+ ----------------------
+
+ function Count_Primitives (Typ : Entity_Id) return Nat is
+ Nb_Prim : Nat;
+ Prim_Elmt : Elmt_Id;
+ Prim : Entity_Id;
+
+ begin
+ Nb_Prim := 0;
+
+ Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ if Is_Predefined_Dispatching_Operation (Prim)
+ or else Is_Predefined_Dispatching_Alias (Prim)
+ then
+ null;
+
+ elsif Present (Interface_Alias (Prim)) then
+ null;
+
+ else
+ Nb_Prim := Nb_Prim + 1;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+
+ return Nb_Prim;
+ end Count_Primitives;
+
+ --------------
+ -- Make_OSD --
+ --------------
+
+ function Make_OSD (Iface : Entity_Id) return Node_Id;
+ -- Generate the Object Specific Data table required to dispatch calls
+ -- through synchronized interfaces. Returns a node that references the
+ -- generated OSD object.
+
+ function Make_OSD (Iface : Entity_Id) return Node_Id is
+ Nb_Prim : constant Nat := Count_Primitives (Iface);
+ OSD : Entity_Id;
+ OSD_Aggr_List : List_Id;
+
+ begin
+ -- Generate
+ -- OSD : Ada.Tags.Object_Specific_Data (Nb_Prims) :=
+ -- (OSD_Table => (1 => <value>,
+ -- ...
+ -- N => <value>));
+
+ if Nb_Prim = 0
+ or else Is_Abstract_Type (Typ)
+ or else Is_Controlled (Typ)
+ or else Restriction_Active (No_Dispatching_Calls)
+ or else not Is_Limited_Type (Typ)
+ or else not Has_Interfaces (Typ)
+ or else not RTE_Record_Component_Available (RE_OSD_Table)
+ then
+ -- No OSD table required
+
+ return Make_Null (Loc);
+
+ else
+ OSD_Aggr_List := New_List;
+
+ declare
+ Prim_Table : array (Nat range 1 .. Nb_Prim) of Entity_Id;
+ Prim : Entity_Id;
+ Prim_Alias : Entity_Id;
+ Prim_Elmt : Elmt_Id;
+ E : Entity_Id;
+ Count : Nat := 0;
+ Pos : Nat;
+
+ begin
+ Prim_Table := (others => Empty);
+ Prim_Alias := Empty;
+
+ Prim_Elmt := First_Elmt (Primitive_Operations (Typ));
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+
+ if Present (Interface_Alias (Prim))
+ and then Find_Dispatching_Type
+ (Interface_Alias (Prim)) = Iface
+ then
+ Prim_Alias := Interface_Alias (Prim);
+ E := Ultimate_Alias (Prim);
+ Pos := UI_To_Int (DT_Position (Prim_Alias));
+
+ if Present (Prim_Table (Pos)) then
+ pragma Assert (Prim_Table (Pos) = E);
+ null;
+
+ else
+ Prim_Table (Pos) := E;
+
+ Append_To (OSD_Aggr_List,
+ Make_Component_Association (Loc,
+ Choices => New_List (
+ Make_Integer_Literal (Loc,
+ DT_Position (Prim_Alias))),
+ Expression =>
+ Make_Integer_Literal (Loc,
+ DT_Position (Alias (Prim)))));
+
+ Count := Count + 1;
+ end if;
+ end if;
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+ pragma Assert (Count = Nb_Prim);
+ end;
+
+ OSD := Make_Temporary (Loc, 'I');
+
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => OSD,
+ Aliased_Present => True,
+ Constant_Present => True,
+ Object_Definition =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Reference_To (RTE (RE_Object_Specific_Data), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (
+ Make_Integer_Literal (Loc, Nb_Prim)))),
+
+ Expression =>
+ Make_Aggregate (Loc,
+ Component_Associations => New_List (
+ Make_Component_Association (Loc,
+ Choices => New_List (
+ New_Occurrence_Of
+ (RTE_Record_Component (RE_OSD_Num_Prims), Loc)),
+ Expression =>
+ Make_Integer_Literal (Loc, Nb_Prim)),
+
+ Make_Component_Association (Loc,
+ Choices => New_List (
+ New_Occurrence_Of
+ (RTE_Record_Component (RE_OSD_Table), Loc)),
+ Expression => Make_Aggregate (Loc,
+ Component_Associations => OSD_Aggr_List))))));
+
+ return
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (OSD, Loc),
+ Attribute_Name => Name_Unchecked_Access);
+ end if;
+ end Make_OSD;
+
+ -- Local variables
+
+ Nb_Prim : constant Nat := Count_Primitives (Typ);
+ AI : Elmt_Id;
+ I_Depth : Nat;
+ Iface_Table_Node : Node_Id;
+ Num_Ifaces : Nat;
+ TSD_Aggr_List : List_Id;
+ Typ_Ifaces : Elist_Id;
+ TSD_Tags_List : List_Id;
+
+ Tname : constant Name_Id := Chars (Typ);
+ Name_SSD : constant Name_Id :=
+ New_External_Name (Tname, 'S', Suffix_Index => -1);
+ Name_TSD : constant Name_Id :=
+ New_External_Name (Tname, 'B', Suffix_Index => -1);
+ SSD : constant Entity_Id :=
+ Make_Defining_Identifier (Loc, Name_SSD);
+ TSD : constant Entity_Id :=
+ Make_Defining_Identifier (Loc, Name_TSD);
+ begin
+ -- Generate code to create the storage for the type specific data object
+ -- with enough space to store the tags of the ancestors plus the tags
+ -- of all the implemented interfaces (as described in a-tags.ads).
+
+ -- TSD : Type_Specific_Data (I_Depth) :=
+ -- (Idepth => I_Depth,
+ -- Tag_Kind => <tag_kind-value>,
+ -- Access_Level => Type_Access_Level (Typ),
+ -- Alignment => Typ'Alignment,
+ -- HT_Link => null,
+ -- Type_Is_Abstract => <<boolean-value>>,
+ -- Type_Is_Library_Level => <<boolean-value>>,
+ -- Interfaces_Table => <<access-value>>
+ -- SSD => SSD_Table'Address
+ -- Tags_Table => (0 => Typ'Tag,
+ -- 1 => Parent'Tag
+ -- ...));
+
+ TSD_Aggr_List := New_List;
+
+ -- Idepth: Count ancestors to compute the inheritance depth. For private
+ -- extensions, always go to the full view in order to compute the real
+ -- inheritance depth.
+
+ declare
+ Current_Typ : Entity_Id;
+ Parent_Typ : Entity_Id;
+
+ begin
+ I_Depth := 0;
+ Current_Typ := Typ;
+ loop
+ Parent_Typ := Etype (Current_Typ);
+
+ if Is_Private_Type (Parent_Typ) then
+ Parent_Typ := Full_View (Base_Type (Parent_Typ));
+ end if;
+
+ exit when Parent_Typ = Current_Typ;
+
+ I_Depth := I_Depth + 1;
+ Current_Typ := Parent_Typ;
+ end loop;
+ end;
+
+ -- I_Depth
+
+ Append_To (TSD_Aggr_List,
+ Make_Integer_Literal (Loc, I_Depth));
+
+ -- Tag_Kind
+
+ Append_To (TSD_Aggr_List, Tagged_Kind (Typ));
+
+ -- Access_Level
+
+ Append_To (TSD_Aggr_List,
+ Make_Integer_Literal (Loc, Type_Access_Level (Typ)));
+
+ -- Alignment
+
+ -- For CPP types we cannot rely on the value of 'Alignment provided
+ -- by the backend to initialize this TSD field. Why not???
+
+ if Convention (Typ) = Convention_CPP
+ or else Is_CPP_Class (Root_Type (Typ))
+ then
+ Append_To (TSD_Aggr_List,
+ Make_Integer_Literal (Loc, 0));
+ else
+ Append_To (TSD_Aggr_List,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Alignment));
+ end if;
+
+ -- HT_Link
+
+ Append_To (TSD_Aggr_List,
+ Make_Null (Loc));
+
+ -- Type_Is_Abstract (Ada 2012: AI05-0173)
+
+ declare
+ Type_Is_Abstract : Entity_Id;
+
+ begin
+ Type_Is_Abstract :=
+ Boolean_Literals (Is_Abstract_Type (Typ));
+
+ Append_To (TSD_Aggr_List,
+ New_Occurrence_Of (Type_Is_Abstract, Loc));
+ end;
+
+ -- Type_Is_Library_Level
+
+ declare
+ Type_Is_Library_Level : Entity_Id;
+ begin
+ Type_Is_Library_Level :=
+ Boolean_Literals (Is_Library_Level_Entity (Typ));
+ Append_To (TSD_Aggr_List,
+ New_Occurrence_Of (Type_Is_Library_Level, Loc));
+ end;
+
+ -- Interfaces_Table (required for AI-405)
+
+ if RTE_Record_Component_Available (RE_Interfaces_Table) then
+
+ -- Count the number of interface types implemented by Typ
+
+ Collect_Interfaces (Typ, Typ_Ifaces);
+
+ Num_Ifaces := 0;
+ AI := First_Elmt (Typ_Ifaces);
+ while Present (AI) loop
+ Num_Ifaces := Num_Ifaces + 1;
+ Next_Elmt (AI);
+ end loop;
+
+ if Num_Ifaces = 0 then
+ Iface_Table_Node := Make_Null (Loc);
+
+ -- Generate the Interface_Table object
+
+ else
+ declare
+ TSD_Ifaces_List : constant List_Id := New_List;
+ Iface : Entity_Id;
+ ITable : Node_Id;
+
+ begin
+ AI := First_Elmt (Typ_Ifaces);
+ while Present (AI) loop
+ Iface := Node (AI);
+
+ Append_To (TSD_Ifaces_List,
+ Make_Aggregate (Loc,
+ Expressions => New_List (
+
+ -- Iface_Tag
+
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Iface, Loc),
+ Attribute_Name => Name_Tag),
+
+ -- OSD
+
+ Make_OSD (Iface))));
+
+ Next_Elmt (AI);
+ end loop;
+
+ ITable := Make_Temporary (Loc, 'I');
+
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => ITable,
+ Aliased_Present => True,
+ Constant_Present => True,
+ Object_Definition =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Reference_To (RTE (RE_Interface_Data), Loc),
+ Constraint => Make_Index_Or_Discriminant_Constraint
+ (Loc,
+ Constraints => New_List (
+ Make_Integer_Literal (Loc, Num_Ifaces)))),
+
+ Expression => Make_Aggregate (Loc,
+ Expressions => New_List (
+ Make_Integer_Literal (Loc, Num_Ifaces),
+ Make_Aggregate (Loc,
+ Expressions => TSD_Ifaces_List)))));
+
+ Iface_Table_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (ITable, Loc),
+ Attribute_Name => Name_Unchecked_Access);
+ end;
+ end if;
+
+ Append_To (TSD_Aggr_List, Iface_Table_Node);
+ end if;
+
+ -- Generate the Select Specific Data table for synchronized types that
+ -- implement synchronized interfaces. The size of the table is
+ -- constrained by the number of non-predefined primitive operations.
+
+ if RTE_Record_Component_Available (RE_SSD) then
+ if Ada_Version >= Ada_2005
+ and then Has_DT (Typ)
+ and then Is_Concurrent_Record_Type (Typ)
+ and then Has_Interfaces (Typ)
+ and then Nb_Prim > 0
+ and then not Is_Abstract_Type (Typ)
+ and then not Is_Controlled (Typ)
+ and then not Restriction_Active (No_Dispatching_Calls)
+ and then not Restriction_Active (No_Select_Statements)
+ then
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => SSD,
+ Aliased_Present => True,
+ Object_Definition =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark => New_Reference_To (
+ RTE (RE_Select_Specific_Data), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (
+ Make_Integer_Literal (Loc, Nb_Prim))))));
+
+ -- This table is initialized by Make_Select_Specific_Data_Table,
+ -- which calls Set_Entry_Index and Set_Prim_Op_Kind.
+
+ Append_To (TSD_Aggr_List,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (SSD, Loc),
+ Attribute_Name => Name_Unchecked_Access));
+ else
+ Append_To (TSD_Aggr_List, Make_Null (Loc));
+ end if;
+ end if;
+
+ -- Initialize the table of ancestor tags. In case of interface types
+ -- this table is not needed.
+
+ TSD_Tags_List := New_List;
+
+ -- Fill position 0 with Typ'Tag
+
+ Append_To (TSD_Tags_List,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag));
+
+ -- Fill the rest of the table with the tags of the ancestors
+
+ declare
+ Current_Typ : Entity_Id;
+ Parent_Typ : Entity_Id;
+ Pos : Nat;
+
+ begin
+ Pos := 1;
+ Current_Typ := Typ;
+
+ loop
+ Parent_Typ := Etype (Current_Typ);
+
+ if Is_Private_Type (Parent_Typ) then
+ Parent_Typ := Full_View (Base_Type (Parent_Typ));
+ end if;
+
+ exit when Parent_Typ = Current_Typ;
+
+ Append_To (TSD_Tags_List,
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Parent_Typ, Loc),
+ Attribute_Name => Name_Tag));
+
+ Pos := Pos + 1;
+ Current_Typ := Parent_Typ;
+ end loop;
+
+ pragma Assert (Pos = I_Depth + 1);
+ end;
+
+ Append_To (TSD_Aggr_List,
+ Make_Aggregate (Loc,
+ Expressions => TSD_Tags_List));
+
+ -- Build the TSD object
+
+ Append_To (Result,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => TSD,
+ Aliased_Present => True,
+ Constant_Present => True,
+ Object_Definition =>
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark => New_Reference_To (
+ RTE (RE_Type_Specific_Data), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => New_List (
+ Make_Integer_Literal (Loc, I_Depth)))),
+
+ Expression => Make_Aggregate (Loc,
+ Expressions => TSD_Aggr_List)));
+
+ -- Generate:
+ -- Check_TSD
+ -- (TSD => TSD'Unrestricted_Access);
+
+ if Ada_Version >= Ada_2005
+ and then Is_Library_Level_Entity (Typ)
+ and then Has_External_Tag_Rep_Clause (Typ)
+ and then RTE_Available (RE_Check_TSD)
+ and then not Debug_Flag_QQ
+ then
+ Append_To (Result,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Check_TSD), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (TSD, Loc),
+ Attribute_Name => Name_Unrestricted_Access))));
+ end if;
+
+ -- Generate:
+ -- Register_TSD (TSD'Unrestricted_Access);
+
+ Append_To (Result,
+ Make_Procedure_Call_Statement (Loc,
+ Name => New_Reference_To (RTE (RE_Register_TSD), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (TSD, Loc),
+ Attribute_Name => Name_Unrestricted_Access))));
+
+ -- Populate the two auxiliary tables used for dispatching asynchronous,
+ -- conditional and timed selects for synchronized types that implement
+ -- a limited interface. Skip this step in Ravenscar profile or when
+ -- general dispatching is forbidden.
+
+ if Ada_Version >= Ada_2005
+ and then Is_Concurrent_Record_Type (Typ)
+ and then Has_Interfaces (Typ)
+ and then not Restriction_Active (No_Dispatching_Calls)
+ and then not Restriction_Active (No_Select_Statements)
+ then
+ Append_List_To (Result,
+ Make_Select_Specific_Data_Table (Typ));
+ end if;
+
+ return Result;
+ end Make_VM_TSD;
+
+ -------------------------------------
+ -- Make_Select_Specific_Data_Table --
+ -------------------------------------
+
+ function Make_Select_Specific_Data_Table
+ (Typ : Entity_Id) return List_Id
+ is
+ Assignments : constant List_Id := New_List;
+ Loc : constant Source_Ptr := Sloc (Typ);
+
+ Conc_Typ : Entity_Id;
+ Decls : List_Id;
+ Prim : Entity_Id;
+ Prim_Als : Entity_Id;
+ Prim_Elmt : Elmt_Id;
+ Prim_Pos : Uint;
+ Nb_Prim : Nat := 0;
+
+ type Examined_Array is array (Int range <>) of Boolean;
function Find_Entry_Index (E : Entity_Id) return Uint;
-- Given an entry, find its index in the visible declarations of the
return Uint_0;
end Find_Entry_Index;
+ -- Local variables
+
+ Tag_Node : Node_Id;
+
-- Start of processing for Make_Select_Specific_Data_Table
begin
pragma Assert (not Restriction_Active (No_Dispatching_Calls));
- DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
-
if Present (Corresponding_Concurrent_Type (Typ)) then
Conc_Typ := Corresponding_Concurrent_Type (Typ);
if Present (Interface_Alias (Prim))
and then not
Is_Ancestor
- (Find_Dispatching_Type (Interface_Alias (Prim)), Typ)
+ (Find_Dispatching_Type (Interface_Alias (Prim)), Typ,
+ Use_Full_View => True)
and then not Examined (UI_To_Int (DT_Position (Alias (Prim))))
then
Prim_Pos := DT_Position (Alias (Prim));
-- type. Generate:
-- Ada.Tags.Set_Prim_Op_Kind (DT_Ptr, <position>, <kind>);
+ if Tagged_Type_Expansion then
+ Tag_Node :=
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Typ))), Loc);
+
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag);
+ end if;
+
Append_To (Assignments,
Make_Procedure_Call_Statement (Loc,
Name => New_Reference_To (RTE (RE_Set_Prim_Op_Kind), Loc),
Parameter_Associations => New_List (
- New_Reference_To (DT_Ptr, Loc),
+ Tag_Node,
Make_Integer_Literal (Loc, Prim_Pos),
Prim_Op_Kind (Alias (Prim), Typ))));
-- Ada.Tags.Set_Entry_Index
-- (DT_Ptr, <position>, <index>);
+ if Tagged_Type_Expansion then
+ Tag_Node :=
+ New_Reference_To
+ (Node (First_Elmt (Access_Disp_Table (Typ))), Loc);
+ else
+ Tag_Node :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Typ, Loc),
+ Attribute_Name => Name_Tag);
+ end if;
+
Append_To (Assignments,
Make_Procedure_Call_Statement (Loc,
Name =>
New_Reference_To (RTE (RE_Set_Entry_Index), Loc),
Parameter_Associations => New_List (
- New_Reference_To (DT_Ptr, Loc),
+ Tag_Node,
Make_Integer_Literal (Loc, Prim_Pos),
Make_Integer_Literal (Loc,
Find_Entry_Index (Wrapped_Entity (Prim_Als))))));
Defining_Identifier => DT_Ptr,
Constant_Present => True,
Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
- Expression =>
+ Expression =>
Unchecked_Convert_To (RTE (RE_Tag),
Make_Attribute_Reference (Loc,
- Prefix =>
+ Prefix =>
Make_Selected_Component (Loc,
- Prefix => New_Reference_To (DT, Loc),
- Selector_Name =>
- New_Occurrence_Of
- (RTE_Record_Component (RE_Prims_Ptr), Loc)),
+ Prefix => New_Reference_To (DT, Loc),
+ Selector_Name =>
+ New_Occurrence_Of
+ (RTE_Record_Component (RE_Prims_Ptr), Loc)),
Attribute_Name => Name_Address))));
-- Generate the SCIL node for the previous object declaration
Make_Object_Declaration (Loc,
Defining_Identifier => Predef_Prims_Ptr,
Constant_Present => True,
- Object_Definition => New_Reference_To
- (RTE (RE_Address), Loc),
- Expression =>
+ Object_Definition =>
+ New_Reference_To (RTE (RE_Address), Loc),
+ Expression =>
Make_Attribute_Reference (Loc,
- Prefix =>
+ Prefix =>
Make_Selected_Component (Loc,
- Prefix => New_Reference_To (DT, Loc),
- Selector_Name =>
- New_Occurrence_Of
- (RTE_Record_Component (RE_Predef_Prims), Loc)),
+ Prefix => New_Reference_To (DT, Loc),
+ Selector_Name =>
+ New_Occurrence_Of
+ (RTE_Record_Component (RE_Predef_Prims), Loc)),
Attribute_Name => Name_Address)));
-- No dispatch table required
Defining_Identifier => DT_Ptr,
Constant_Present => True,
Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
- Expression =>
+ Expression =>
Unchecked_Convert_To (RTE (RE_Tag),
Make_Attribute_Reference (Loc,
- Prefix =>
+ Prefix =>
Make_Selected_Component (Loc,
Prefix => New_Reference_To (DT, Loc),
- Selector_Name =>
- New_Occurrence_Of
- (RTE_Record_Component (RE_NDT_Prims_Ptr), Loc)),
+ Selector_Name =>
+ New_Occurrence_Of
+ (RTE_Record_Component (RE_NDT_Prims_Ptr),
+ Loc)),
Attribute_Name => Name_Address))));
end if;
Constant_Present => True,
Object_Definition => New_Reference_To
(RTE (RE_Interface_Tag), Loc),
- Expression =>
+ Expression =>
Unchecked_Convert_To (RTE (RE_Interface_Tag),
Make_Attribute_Reference (Loc,
- Prefix =>
+ Prefix =>
Make_Selected_Component (Loc,
- Prefix => New_Reference_To (Iface_DT, Loc),
- Selector_Name =>
- New_Occurrence_Of
- (RTE_Record_Component (RE_Prims_Ptr), Loc)),
+ Prefix =>
+ New_Reference_To (Iface_DT, Loc),
+ Selector_Name =>
+ New_Occurrence_Of
+ (RTE_Record_Component (RE_Prims_Ptr),
+ Loc)),
Attribute_Name => Name_Address))));
end if;
-- to simplify the expansion associated with dispatching calls.
Analyze_List (Result);
- Set_Suppress_Init_Proc (Base_Type (DT_Prims));
+ Set_Suppress_Initialization (Base_Type (DT_Prims));
-- Disable backend optimizations based on assumptions about the
-- aliasing status of objects designated by the access to the
begin
pragma Assert (not Restriction_Active (No_Dispatching_Calls));
+ pragma Assert (VM_Target = No_VM);
-- Do not register in the dispatch table eliminated primitives
Address_Node =>
Unchecked_Convert_To (RTE (RE_Prim_Ptr),
Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Prim, Loc),
+ Prefix => New_Reference_To (Prim, Loc),
Attribute_Name => Name_Unrestricted_Access))));
-- Register copy of the pointer to the 'size primitive in the TSD
Address_Node =>
Unchecked_Convert_To (RTE (RE_Prim_Ptr),
Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Prim, Loc),
+ Prefix => New_Reference_To (Prim, Loc),
Attribute_Name => Name_Unrestricted_Access))));
end if;
end if;
-- No action needed for interfaces that are ancestors of Typ because
-- their primitives are located in the primary dispatch table.
- if Is_Ancestor (Iface_Typ, Tag_Typ) then
+ if Is_Ancestor (Iface_Typ, Tag_Typ, Use_Full_View => True) then
return L;
-- No action needed for primitives located in the C++ part of the
Expand_Interface_Thunk (Prim, Thunk_Id, Thunk_Code);
- if not Is_Ancestor (Iface_Typ, Tag_Typ)
+ if not Is_Ancestor (Iface_Typ, Tag_Typ, Use_Full_View => True)
and then Present (Thunk_Code)
then
-- Generate the code necessary to fill the appropriate entry of
Address_Node =>
Unchecked_Convert_To (RTE (RE_Prim_Ptr),
Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Alias (Prim), Loc),
+ Prefix =>
+ New_Reference_To (Alias (Prim), Loc),
Attribute_Name => Name_Unrestricted_Access))));
else
Address_Node =>
Unchecked_Convert_To (RTE (RE_Prim_Ptr),
Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Alias (Prim), Loc),
+ Prefix =>
+ New_Reference_To (Alias (Prim), Loc),
Attribute_Name => Name_Unrestricted_Access))));
end if;
procedure Set_All_DT_Position (Typ : Entity_Id) is
+ function In_Predef_Prims_DT (Prim : Entity_Id) return Boolean;
+ -- Returns True if Prim is located in the dispatch table of
+ -- predefined primitives
+
procedure Validate_Position (Prim : Entity_Id);
-- Check that the position assigned to Prim is completely safe
-- (it has not been assigned to a previously defined primitive
-- operation of Typ)
+ ------------------------
+ -- In_Predef_Prims_DT --
+ ------------------------
+
+ function In_Predef_Prims_DT (Prim : Entity_Id) return Boolean is
+ E : Entity_Id;
+
+ begin
+ -- Predefined primitives
+
+ if Is_Predefined_Dispatching_Operation (Prim) then
+ return True;
+
+ -- Renamings of predefined primitives
+
+ elsif Present (Alias (Prim))
+ and then Is_Predefined_Dispatching_Operation (Ultimate_Alias (Prim))
+ then
+ if Chars (Ultimate_Alias (Prim)) /= Name_Op_Eq then
+ return True;
+
+ -- User-defined renamings of predefined equality have their own
+ -- slot in the primary dispatch table
+
+ else
+ E := Prim;
+ while Present (Alias (E)) loop
+ if Comes_From_Source (E) then
+ return False;
+ end if;
+
+ E := Alias (E);
+ end loop;
+
+ return not Comes_From_Source (E);
+ end if;
+
+ -- User-defined primitives
+
+ else
+ return False;
+ end if;
+ end In_Predef_Prims_DT;
+
-----------------------
-- Validate_Position --
-----------------------
First_Prim : constant Elmt_Id := First_Elmt (Primitive_Operations (Typ));
The_Tag : constant Entity_Id := First_Tag_Component (Typ);
- Adjusted : Boolean := False;
- Finalized : Boolean := False;
+ Adjusted : Boolean := False;
+ Finalized : Boolean := False;
Count_Prim : Nat;
DT_Length : Nat;
-- Predefined primitives have a separate dispatch table
- if not (Is_Predefined_Dispatching_Operation (Prim)
- or else
- Is_Predefined_Dispatching_Alias (Prim))
- then
+ if not In_Predef_Prims_DT (Prim) then
Count_Prim := Count_Prim + 1;
end if;
(Nkind (Parent (Typ)) = N_Private_Extension_Declaration
and then Is_Generic_Type (Typ)))
and then In_Open_Scopes (Scope (Etype (Typ)))
- and then Typ = Base_Type (Typ)
+ and then Is_Base_Type (Typ)
then
Handle_Inherited_Private_Subprograms (Typ);
end if;
-- Predefined primitives have a separate table and all its
-- entries are at predefined fixed positions.
- if Is_Predefined_Dispatching_Operation (Prim) then
- Set_DT_Position (Prim, Default_Prim_Op_Position (Prim));
+ if In_Predef_Prims_DT (Prim) then
+ if Is_Predefined_Dispatching_Operation (Prim) then
+ Set_DT_Position (Prim, Default_Prim_Op_Position (Prim));
- elsif Is_Predefined_Dispatching_Alias (Prim) then
- Set_DT_Position (Prim,
- Default_Prim_Op_Position (Ultimate_Alias (Prim)));
+ else pragma Assert (Present (Alias (Prim)));
+ Set_DT_Position (Prim,
+ Default_Prim_Op_Position (Ultimate_Alias (Prim)));
+ end if;
-- Overriding primitives of ancestor abstract interfaces
elsif Present (Interface_Alias (Prim))
and then Is_Ancestor
- (Find_Dispatching_Type (Interface_Alias (Prim)), Typ)
+ (Find_Dispatching_Type (Interface_Alias (Prim)), Typ,
+ Use_Full_View => True)
then
pragma Assert (DT_Position (Prim) = No_Uint
and then Present (DTC_Entity (Interface_Alias (Prim))));
and then Chars (Prim) = Chars (Alias (Prim))
and then Find_Dispatching_Type (Alias (Prim)) /= Typ
and then Is_Ancestor
- (Find_Dispatching_Type (Alias (Prim)), Typ)
+ (Find_Dispatching_Type (Alias (Prim)), Typ,
+ Use_Full_View => True)
and then Present (DTC_Entity (Alias (Prim)))
then
E := Alias (Prim);
-- Check if this entry will be placed in the primary DT
if Is_Ancestor
- (Find_Dispatching_Type (Interface_Alias (Prim)), Typ)
+ (Find_Dispatching_Type (Interface_Alias (Prim)), Typ,
+ Use_Full_View => True)
then
pragma Assert (DT_Position (Alias (Prim)) /= No_Uint);
Set_DT_Position (Prim, DT_Position (Alias (Prim)));
-- Calculate real size of the dispatch table
- if not (Is_Predefined_Dispatching_Operation (Prim)
- or else Is_Predefined_Dispatching_Alias (Prim))
+ if not In_Predef_Prims_DT (Prim)
and then UI_To_Int (DT_Position (Prim)) > DT_Length
then
DT_Length := UI_To_Int (DT_Position (Prim));
-- Ensure that the assigned position to non-predefined
-- dispatching operations in the dispatch table is correct.
- if not (Is_Predefined_Dispatching_Operation (Prim)
- or else Is_Predefined_Dispatching_Alias (Prim))
+ if not Is_Predefined_Dispatching_Operation (Prim)
+ and then not Is_Predefined_Dispatching_Alias (Prim)
then
Validate_Position (Prim);
end if;
-- excluded from this check because interfaces must be visible in
-- the public and private part (RM 7.3 (7.3/2))
- -- We disable this check in CodePeer mode, to accomodate legacy
+ -- We disable this check in CodePeer mode, to accommodate legacy
-- Ada code.
if not CodePeer_Mode
Set_Init_Proc (Typ, Init);
Set_Is_Imported (Init);
+ Set_Is_Constructor (Init);
Set_Interface_Name (Init, Interface_Name (E));
- Set_Convention (Init, Convention_C);
+ Set_Convention (Init, Convention_CPP);
Set_Is_Public (Init);
Set_Has_Completion (Init);
end if;
Parameter_Specifications => Parms));
Set_Is_Imported (Constructor_Id);
+ Set_Is_Constructor (Constructor_Id);
Set_Interface_Name (Constructor_Id, Interface_Name (E));
- Set_Convention (Constructor_Id, Convention_C);
+ Set_Convention (Constructor_Id, Convention_CPP);
Set_Is_Public (Constructor_Id);
Set_Has_Completion (Constructor_Id);
New_Reference_To (Node (Tag_Elmt), Loc),
Expression =>
Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
+ Prefix =>
+ Make_Identifier (Loc, Name_uInit),
Selector_Name =>
New_Reference_To (Tag_Comp, Loc))));