diff --git a/gcc/ada/a-tags.adb b/gcc/ada/a-tags.adb index 33f0be3a6be..47e76ffac3e 100644 --- a/gcc/ada/a-tags.adb +++ b/gcc/ada/a-tags.adb @@ -279,7 +279,7 @@ package body Ada.Tags is TSD : constant Type_Specific_Data_Ptr := To_Type_Specific_Data_Ptr (TSD_Ptr.all); begin - return TSD.HT_Link; + return TSD.HT_Link.all; end Get_HT_Link; ---------- @@ -304,7 +304,7 @@ package body Ada.Tags is TSD : constant Type_Specific_Data_Ptr := To_Type_Specific_Data_Ptr (TSD_Ptr.all); begin - TSD.HT_Link := Next; + TSD.HT_Link.all := Next; end Set_HT_Link; end HTable_Subprograms; diff --git a/gcc/ada/a-tags.ads b/gcc/ada/a-tags.ads index a41ae9d1240..6630743dcca 100644 --- a/gcc/ada/a-tags.ads +++ b/gcc/ada/a-tags.ads @@ -218,6 +218,26 @@ private -- type. This construct is used in the handling of dispatching triggers -- in select statements. + type Address_Array is array (Positive range <>) of System.Address; + + subtype Dispatch_Table is Address_Array (1 .. 1); + -- Used by GDB to identify the _tags and traverse the run-time structure + -- associated with tagged types. For compatibility with older versions of + -- gdb, its name must not be changed. + + type Tag is access all Dispatch_Table; + pragma No_Strict_Aliasing (Tag); + + type Interface_Tag is access all Dispatch_Table; + + No_Tag : constant Tag := null; + + -- The expander ensures that Tag objects reference the Prims_Ptr component + -- of the wrapper. + + type Tag_Ptr is access all Tag; + pragma No_Strict_Aliasing (Tag_Ptr); + type Tag_Table is array (Natural range <>) of Tag; type Type_Specific_Data (Idepth : Natural) is record @@ -237,7 +257,7 @@ private Expanded_Name : Cstring_Ptr; External_Tag : Cstring_Ptr; - HT_Link : Tag; + HT_Link : Tag_Ptr; -- Components used to support to the Ada.Tags subprograms in RM 3.9 -- Note: Expanded_Name is referenced by GDB to determine the actual name @@ -291,8 +311,6 @@ private TK_Tagged, TK_Task); - type Address_Array is array (Positive range <>) of System.Address; - type Dispatch_Table_Wrapper (Num_Prims : Natural) is record Signature : Signature_Kind; Tag_Kind : Tagged_Kind; @@ -315,24 +333,6 @@ private -- actual array size, allocates the Dispatch_Table record accordingly. end record; - subtype Dispatch_Table is Address_Array (1 .. 1); - -- Used by GDB to identify the _tags and traverse the run-time structure - -- associated with tagged types. For compatibility with older versions of - -- gdb, its name must not be changed. - - type Tag is access all Dispatch_Table; - pragma No_Strict_Aliasing (Tag); - - type Interface_Tag is access all Dispatch_Table; - - No_Tag : constant Tag := null; - - -- The expander ensures that Tag objects reference the Prims_Ptr component - -- of the wrapper. - - type Tag_Ptr is access all Tag; - pragma No_Strict_Aliasing (Tag_Ptr); - type Dispatch_Table_Ptr is access all Dispatch_Table_Wrapper; pragma No_Strict_Aliasing (Dispatch_Table_Ptr); diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index c625afb695b..4a55947d4f7 100644 --- a/gcc/ada/decl.c +++ b/gcc/ada/decl.c @@ -500,7 +500,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) bool used_by_ref = false; bool const_flag = ((kind == E_Constant || kind == E_Variable) - && !Is_Statically_Allocated (gnat_entity) && Is_True_Constant (gnat_entity) && (((Nkind (Declaration_Node (gnat_entity)) == N_Object_Declaration) @@ -732,7 +731,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) the object volatile. We also interpret 13.3(19) conservatively and disallow any optimizations for an object covered by it. */ if ((Treat_As_Volatile (gnat_entity) - || Is_Exported (gnat_entity) + || (Is_Exported (gnat_entity) + /* Exclude exported constants created by the compiler, + which should boil down to static dispatch tables and + make it possible to put them in read-only memory.  */ + && (Comes_From_Source (gnat_entity) || !const_flag)) || Is_Imported (gnat_entity) || Present (Address_Clause (gnat_entity))) && !TYPE_VOLATILE (gnu_type)) @@ -4447,6 +4450,8 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech, tree gnu_param_name = get_entity_name (gnat_param); tree gnu_param_type = gnat_to_gnu_type (Etype (gnat_param)); bool in_param = (Ekind (gnat_param) == E_In_Parameter); + /* The parameter can be indirectly modified if its address is taken. */ + bool ro_param = in_param && !Address_Taken (gnat_param); bool by_return = false, by_component_ptr = false, by_ref = false; tree gnu_param; @@ -4473,11 +4478,11 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech, gnu_param_type = unpadded_type; } - /* If this is an IN parameter, it is read-only, so make a variant of the - type that is read-only. ??? However, if this is an unconstrained array, - that type can be very complex, so skip it for now. Likewise for any - other self-referential type. */ - if (in_param + /* If this is a read-only parameter, make a variant of the type that is + read-only. ??? However, if this is an unconstrained array, that type + can be very complex, so skip it for now. Likewise for any other + self-referential type. */ + if (ro_param && TREE_CODE (gnu_param_type) != UNCONSTRAINED_ARRAY_TYPE && !CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_param_type))) gnu_param_type = build_qualified_type (gnu_param_type, @@ -4511,7 +4516,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech, by_component_ptr = true; gnu_param_type = TREE_TYPE (gnu_param_type); - if (in_param) + if (ro_param) gnu_param_type = build_qualified_type (gnu_param_type, (TYPE_QUALS (gnu_param_type) | TYPE_QUAL_CONST)); @@ -4584,12 +4589,12 @@ gnat_to_gnu_param (Entity_Id gnat_param, Mechanism_Type mech, return gnu_param_type; gnu_param = create_param_decl (gnu_param_name, gnu_param_type, - by_ref || by_component_ptr || in_param); + ro_param || by_ref || by_component_ptr); DECL_BY_REF_P (gnu_param) = by_ref; DECL_BY_COMPONENT_PTR_P (gnu_param) = by_component_ptr; DECL_BY_DESCRIPTOR_P (gnu_param) = (mech == By_Descriptor); DECL_POINTS_TO_READONLY_P (gnu_param) - = (in_param && (by_ref || by_component_ptr)); + = (ro_param && (by_ref || by_component_ptr)); /* If no Mechanism was specified, indicate what we're using, then back-annotate it. */ diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index 2d663baf6c2..54e08c6142c 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -66,10 +66,6 @@ package body Exp_Disp is -- Local Subprograms -- ----------------------- - function Building_Static_DT (Typ : Entity_Id) return Boolean; - pragma Inline (Building_Static_DT); - -- Returns true when building statically allocated dispatch tables - function Default_Prim_Op_Position (E : Entity_Id) return Uint; -- Ada 2005 (AI-251): Returns the fixed position in the dispatch table -- of the default primitive operations. @@ -104,7 +100,13 @@ package body Exp_Disp is function Building_Static_DT (Typ : Entity_Id) return Boolean is begin return Static_Dispatch_Tables - and then Is_Library_Level_Tagged_Type (Typ); + and then Is_Library_Level_Tagged_Type (Typ) + + -- If the type is derived from a CPP class we cannot statically + -- build the dispatch tables because we must inherit primitives + -- from the CPP side. + + and then not Is_CPP_Class (Root_Type (Typ)); end Building_Static_DT; ---------------------------------- @@ -742,7 +744,7 @@ package body Exp_Disp is Operand_Typ := Base_Type (Corresponding_Record_Type (Operand_Typ)); end if; - -- Handle access types to interfaces + -- Handle access to class-wide interface types if Is_Access_Type (Iface_Typ) then Iface_Typ := Etype (Directly_Designated_Type (Iface_Typ)); @@ -881,11 +883,9 @@ package body Exp_Disp is -- end Func; declare - Decls : List_Id; Desig_Typ : Entity_Id; Fent : Entity_Id; New_Typ_Decl : Node_Id; - New_Obj_Decl : Node_Id; Stats : List_Id; begin @@ -895,6 +895,10 @@ package body Exp_Disp is Desig_Typ := Directly_Designated_Type (Desig_Typ); end if; + if Is_Concurrent_Type (Desig_Typ) then + Desig_Typ := Base_Type (Corresponding_Record_Type (Desig_Typ)); + end if; + New_Typ_Decl := Make_Full_Type_Declaration (Loc, Defining_Identifier => @@ -907,22 +911,6 @@ package body Exp_Disp is Subtype_Indication => New_Reference_To (Desig_Typ, Loc))); - New_Obj_Decl := - Make_Object_Declaration (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, - New_Internal_Name ('S')), - Constant_Present => True, - Object_Definition => - New_Reference_To (Defining_Identifier (New_Typ_Decl), Loc), - Expression => - Unchecked_Convert_To (Defining_Identifier (New_Typ_Decl), - Make_Identifier (Loc, Name_uO))); - - Decls := New_List ( - New_Typ_Decl, - New_Obj_Decl); - Stats := New_List ( Make_Simple_Return_Statement (Loc, Unchecked_Convert_To (Etype (N), @@ -930,9 +918,9 @@ package body Exp_Disp is Prefix => Make_Selected_Component (Loc, Prefix => - New_Reference_To - (Defining_Identifier (New_Obj_Decl), - Loc), + Unchecked_Convert_To + (Defining_Identifier (New_Typ_Decl), + Make_Identifier (Loc, Name_uO)), Selector_Name => New_Occurrence_Of (Iface_Tag, Loc)), Attribute_Name => Name_Address)))); @@ -975,7 +963,7 @@ package body Exp_Disp is Result_Definition => New_Reference_To (Etype (N), Loc)), - Declarations => Decls, + Declarations => New_List (New_Typ_Decl), Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, Stats)); @@ -991,20 +979,17 @@ package body Exp_Disp is if Is_Access_Type (Etype (Expression (N))) then - -- Generate: Operand_Typ!(Expression.all)'Address + -- Generate: Func (Address!(Expression)) Rewrite (N, Make_Function_Call (Loc, Name => New_Reference_To (Fent, Loc), Parameter_Associations => New_List ( - Make_Attribute_Reference (Loc, - Prefix => Unchecked_Convert_To (Operand_Typ, - Make_Explicit_Dereference (Loc, - Relocate_Node (Expression (N)))), - Attribute_Name => Name_Address)))); + Unchecked_Convert_To (RTE (RE_Address), + Relocate_Node (Expression (N)))))); else - -- Generate: Operand_Typ!(Expression)'Address + -- Generate: Func (Operand_Typ!(Expression)'Address) Rewrite (N, Make_Function_Call (Loc, @@ -1409,6 +1394,8 @@ package body Exp_Disp is Make_Defining_Identifier (Loc, Chars => New_Internal_Name ('T')); + Set_Is_Thunk (Thunk_Id); + if Ekind (Target) = E_Procedure then Thunk_Code := Make_Subprogram_Body (Loc, @@ -3064,6 +3051,8 @@ package body Exp_Disp is New_External_Name (Tname, 'T', Suffix_Index => -1); Name_Exname : constant Name_Id := New_External_Name (Tname, 'E', Suffix_Index => -1); + Name_HT_Link : constant Name_Id := + New_External_Name (Tname, 'H', Suffix_Index => -1); Name_Predef_Prims : constant Name_Id := New_External_Name (Tname, 'R', Suffix_Index => -1); Name_SSD : constant Name_Id := @@ -3077,6 +3066,8 @@ package body Exp_Disp is Make_Defining_Identifier (Loc, Name_DT); Exname : constant Entity_Id := Make_Defining_Identifier (Loc, Name_Exname); + HT_Link : constant Entity_Id := + Make_Defining_Identifier (Loc, Name_HT_Link); Predef_Prims : constant Entity_Id := Make_Defining_Identifier (Loc, Name_Predef_Prims); SSD : constant Entity_Id := @@ -3213,6 +3204,7 @@ package body Exp_Disp is Set_Is_Statically_Allocated (DT); Set_Is_Statically_Allocated (SSD); Set_Is_Statically_Allocated (TSD); + Set_Is_Statically_Allocated (Predef_Prims); -- Generate code to define the boolean that controls registration, in -- order to avoid multiple registrations for tagged types defined in @@ -3353,6 +3345,15 @@ package body Exp_Disp is Set_Is_Statically_Allocated (Exname); Set_Is_True_Constant (Exname); + -- Declare the object used by Ada.Tags.Register_Tag + + if RTE_Available (RE_Register_Tag) then + Append_To (Result, + Make_Object_Declaration (Loc, + Defining_Identifier => HT_Link, + Object_Definition => New_Reference_To (RTE (RE_Tag), Loc))); + end if; + -- 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.adb). @@ -3362,7 +3363,7 @@ package body Exp_Disp is -- Access_Level => Type_Access_Level (Typ), -- Expanded_Name => Cstring_Ptr!(Exname'Address)) -- External_Tag => Cstring_Ptr!(Exname'Address)) - -- HT_Link => null, + -- HT_Link => HT_Link'Address, -- Transportable => <>, -- RC_Offset => <>, -- [ Interfaces_Table => <> ] @@ -3590,9 +3591,17 @@ package body Exp_Disp is -- HT_Link - Append_To (TSD_Aggr_List, - Unchecked_Convert_To (RTE (RE_Tag), - New_Reference_To (RTE (RE_Null_Address), Loc))); + if RTE_Available (RE_Register_Tag) then + Append_To (TSD_Aggr_List, + Unchecked_Convert_To (RTE (RE_Tag_Ptr), + Make_Attribute_Reference (Loc, + Prefix => New_Reference_To (HT_Link, Loc), + Attribute_Name => Name_Address))); + else + Append_To (TSD_Aggr_List, + Unchecked_Convert_To (RTE (RE_Tag_Ptr), + New_Reference_To (RTE (RE_Null_Address), Loc))); + end if; -- Transportable: Set for types that can be used in remote calls -- with respect to E.4(18) legality rules. @@ -4734,9 +4743,7 @@ package body Exp_Disp is -- Import the forward declaration of the Dispatch Table wrapper record -- (Make_DT will take care of its exportation) - if Building_Static_DT (Typ) - and then not Is_CPP_Class (Typ) - then + if Building_Static_DT (Typ) then DT := Make_Defining_Identifier (Loc, New_External_Name (Tname, 'T')); @@ -4746,9 +4753,6 @@ package body Exp_Disp is Set_Is_Imported (DT); - -- Set_Is_True_Constant (DT); - -- Why is the above commented out??? - -- The scope must be set now to call Get_External_Name Set_Scope (DT, Current_Scope); @@ -4840,6 +4844,7 @@ package body Exp_Disp is end if; Set_Is_True_Constant (DT_Ptr); + Set_Is_Statically_Allocated (DT_Ptr); end if; pragma Assert (No (Access_Disp_Table (Typ))); diff --git a/gcc/ada/exp_disp.ads b/gcc/ada/exp_disp.ads index 99a275be1df..ee78c81b05a 100644 --- a/gcc/ada/exp_disp.ads +++ b/gcc/ada/exp_disp.ads @@ -164,6 +164,10 @@ package Exp_Disp is -- Exp_Disp.Default_Prim_Op_Position - indirect use -- Exp_Disp.Set_All_DT_Position - direct use + function Building_Static_DT (Typ : Entity_Id) return Boolean; + pragma Inline (Building_Static_DT); + -- Returns true when building statically allocated dispatch tables + procedure Build_Static_Dispatch_Tables (N : Node_Id); -- N is a library level package declaration or package body. Build the -- static dispatch table of the tagged types defined at library level. In diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb index 9862f7a64b9..5924039e6f9 100644 --- a/gcc/ada/sem_disp.adb +++ b/gcc/ada/sem_disp.adb @@ -740,9 +740,27 @@ package body Sem_Disp is Set_DT_Position (Subp, DT_Position (Old_Subp)); if not Restriction_Active (No_Dispatching_Calls) then - Register_Primitive (Sloc (Subp_Body), - Prim => Subp, - Ins_Nod => Subp_Body); + if Building_Static_DT (Tagged_Type) then + + -- If the static dispatch table has not been + -- built then there is nothing else to do now; + -- otherwise we notify that we cannot build the + -- static dispatch table. + + if Has_Dispatch_Table (Tagged_Type) then + Error_Msg_N + ("overriding of& is too late for building" & + " static dispatch tables!", Subp); + Error_Msg_N + ("\spec should appear immediately after" & + " the type!", Subp); + end if; + + else + Register_Primitive (Sloc (Subp_Body), + Prim => Subp, + Ins_Nod => Subp_Body); + end if; end if; end if; end if; @@ -789,6 +807,7 @@ package body Sem_Disp is if Present (Old_Subp) then Check_Subtype_Conformant (Subp, Old_Subp); + if (Chars (Subp) = Name_Initialize or else Chars (Subp) = Name_Adjust or else Chars (Subp) = Name_Finalize) diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index e6f9ef8f8d6..36177e281ca 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -626,7 +626,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) Is_Aliased (gnat_temp)); if (!object || !parent_requires_lvalue) - gnu_result = DECL_INITIAL (gnu_result); + gnu_result = unshare_expr (DECL_INITIAL (gnu_result)); } *gnu_result_type_p = gnu_result_type;