diff options
Diffstat (limited to 'gcc/ada/sem_ch3.adb')
-rw-r--r-- | gcc/ada/sem_ch3.adb | 1415 |
1 files changed, 750 insertions, 665 deletions
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index a79e304..a3f036a 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -31,6 +31,7 @@ with Einfo; use Einfo; with Errout; use Errout; with Eval_Fat; use Eval_Fat; with Exp_Ch3; use Exp_Ch3; +with Exp_Disp; use Exp_Disp; with Exp_Dist; use Exp_Dist; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; @@ -253,9 +254,6 @@ package body Sem_Ch3 is -- view cannot itself have a full view (it would get clobbered during -- view exchanges). - procedure Check_Abstract_Interfaces (N : Node_Id; Def : Node_Id); - -- Check ARM rules 3.9.4 (15/2), 9.1 (9.d/2) and 9.4 (11.d/2) - procedure Check_Access_Discriminant_Requires_Limited (D : Node_Id; Loc : Node_Id); @@ -289,6 +287,9 @@ package body Sem_Ch3 is -- Validate the initialization of an object declaration. T is the required -- type, and Exp is the initialization expression. + procedure Check_Interfaces (N : Node_Id; Def : Node_Id); + -- Check ARM rules 3.9.4 (15/2), 9.1 (9.d/2) and 9.4 (11.d/2) + procedure Check_Or_Process_Discriminants (N : Node_Id; T : Entity_Id; @@ -486,14 +487,16 @@ package body Sem_Ch3 is -- appropriate semantic fields. If the full view of the parent is a record -- type, build constrained components of subtype. - procedure Derive_Interface_Subprograms + procedure Derive_Progenitor_Subprograms (Parent_Type : Entity_Id; - Tagged_Type : Entity_Id; - Ifaces_List : Elist_Id); - -- Ada 2005 (AI-251): Derive primitives of abstract interface types that - -- are not immediate ancestors of Tagged type and associate them their - -- aliased primitive. Ifaces_List contains the abstract interface - -- primitives that have been derived from Parent_Type. + Tagged_Type : Entity_Id); + -- Ada 2005 (AI-251): To complete type derivation, collect the primitive + -- operations of progenitors of Tagged_Type, and replace the subsidiary + -- subtypes with Tagged_Type, to build the specs of the inherited interface + -- primitives. The derived primitives are aliased to those of the + -- interface. This routine takes care also of transferring to the full-view + -- subprograms associated with the partial-view of Tagged_Type that cover + -- interface primitives. procedure Derived_Standard_Character (N : Node_Id; @@ -1273,36 +1276,12 @@ package body Sem_Ch3 is procedure Add_Interface_Tag_Components (N : Node_Id; Typ : Entity_Id) is Loc : constant Source_Ptr := Sloc (N); - Elmt : Elmt_Id; - Ext : Node_Id; L : List_Id; Last_Tag : Node_Id; - Comp : Node_Id; - - procedure Add_Sync_Iface_Tags (T : Entity_Id); - -- Local subprogram used to recursively climb through the parents - -- of T to add the tags of all the progenitor interfaces. procedure Add_Tag (Iface : Entity_Id); -- Add tag for one of the progenitor interfaces - ------------------------- - -- Add_Sync_Iface_Tags -- - ------------------------- - - procedure Add_Sync_Iface_Tags (T : Entity_Id) is - begin - if Etype (T) /= T then - Add_Sync_Iface_Tags (Etype (T)); - end if; - - Elmt := First_Elmt (Abstract_Interfaces (T)); - while Present (Elmt) loop - Add_Tag (Node (Elmt)); - Next_Elmt (Elmt); - end loop; - end Add_Sync_Iface_Tags; - ------------- -- Add_Tag -- ------------- @@ -1387,7 +1366,9 @@ package body Sem_Ch3 is -- Local variables - Iface_List : List_Id; + Elmt : Elmt_Id; + Ext : Node_Id; + Comp : Node_Id; -- Start of processing for Add_Interface_Tag_Components @@ -1403,8 +1384,8 @@ package body Sem_Ch3 is or else (Is_Concurrent_Record_Type (Typ) and then Is_Empty_List (Abstract_Interface_List (Typ))) or else (not Is_Concurrent_Record_Type (Typ) - and then No (Abstract_Interfaces (Typ)) - and then Is_Empty_Elmt_List (Abstract_Interfaces (Typ))) + and then No (Interfaces (Typ)) + and then Is_Empty_Elmt_List (Interfaces (Typ))) then return; end if; @@ -1458,16 +1439,8 @@ package body Sem_Ch3 is -- corresponding with all the interfaces that are not implemented -- by the parent. - if Is_Concurrent_Record_Type (Typ) then - Iface_List := Abstract_Interface_List (Typ); - - if Is_Non_Empty_List (Iface_List) then - Add_Sync_Iface_Tags (Etype (First (Iface_List))); - end if; - end if; - - if Present (Abstract_Interfaces (Typ)) then - Elmt := First_Elmt (Abstract_Interfaces (Typ)); + if Present (Interfaces (Typ)) then + Elmt := First_Elmt (Interfaces (Typ)); while Present (Elmt) loop Add_Tag (Node (Elmt)); Next_Elmt (Elmt); @@ -1993,18 +1966,18 @@ package body Sem_Ch3 is CW : constant Entity_Id := Class_Wide_Type (T); begin - Set_Is_Tagged_Type (T); + Set_Is_Tagged_Type (T); - Set_Is_Limited_Record (T, Limited_Present (Def) - or else Task_Present (Def) - or else Protected_Present (Def) - or else Synchronized_Present (Def)); + Set_Is_Limited_Record (T, Limited_Present (Def) + or else Task_Present (Def) + or else Protected_Present (Def) + or else Synchronized_Present (Def)); -- Type is abstract if full declaration carries keyword, or if previous -- partial view did. Set_Is_Abstract_Type (T); - Set_Is_Interface (T); + Set_Is_Interface (T); -- Type is a limited interface if it includes the keyword limited, task, -- protected, or synchronized. @@ -2015,8 +1988,8 @@ package body Sem_Ch3 is or else Synchronized_Present (Def) or else Task_Present (Def)); - Set_Is_Protected_Interface (T, Protected_Present (Def)); - Set_Is_Task_Interface (T, Task_Present (Def)); + Set_Is_Protected_Interface (T, Protected_Present (Def)); + Set_Is_Task_Interface (T, Task_Present (Def)); -- Type is a synchronized interface if it includes the keyword task, -- protected, or synchronized. @@ -2026,8 +1999,8 @@ package body Sem_Ch3 is or else Protected_Present (Def) or else Task_Present (Def)); - Set_Abstract_Interfaces (T, New_Elmt_List); - Set_Primitive_Operations (T, New_Elmt_List); + Set_Interfaces (T, New_Elmt_List); + Set_Primitive_Operations (T, New_Elmt_List); -- Complete the decoration of the class-wide entity if it was already -- built (i.e. during the creation of the limited view) @@ -3236,13 +3209,13 @@ package body Sem_Ch3 is -- The progenitors (if any) must be limited or synchronized -- interfaces. - if Present (Abstract_Interfaces (T)) then + if Present (Interfaces (T)) then declare Iface : Entity_Id; Iface_Elmt : Elmt_Id; begin - Iface_Elmt := First_Elmt (Abstract_Interfaces (T)); + Iface_Elmt := First_Elmt (Interfaces (T)); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); @@ -6770,7 +6743,7 @@ package body Sem_Ch3 is Analyze_Interface_Declaration (Derived_Type, Type_Def); end if; - Set_Abstract_Interfaces (Derived_Type, No_Elist); + Set_Interfaces (Derived_Type, No_Elist); end if; -- Fields inherited from the Parent_Type @@ -6804,9 +6777,9 @@ package body Sem_Ch3 is if Is_Record_Type (Derived_Type) then Set_OK_To_Reorder_Components - (Derived_Type, OK_To_Reorder_Components (Parent_Base)); + (Derived_Type, OK_To_Reorder_Components (Parent_Base)); Set_Reverse_Bit_Order - (Derived_Type, Reverse_Bit_Order (Parent_Base)); + (Derived_Type, Reverse_Bit_Order (Parent_Base)); end if; -- Direct controlled types do not inherit Finalize_Storage_Only flag @@ -6896,16 +6869,17 @@ package body Sem_Ch3 is -- Check ARM rules 3.9.4 (15/2), 9.1 (9.d/2) and 9.4 (11.d/2) - Check_Abstract_Interfaces (N, Type_Def); + Check_Interfaces (N, Type_Def); -- Ada 2005 (AI-251): Collect the list of progenitors that are -- not already in the parents. - Collect_Abstract_Interfaces - (T => Derived_Type, - Ifaces_List => Ifaces_List, - Exclude_Parent_Interfaces => True); - Set_Abstract_Interfaces (Derived_Type, Ifaces_List); + Collect_Interfaces + (T => Derived_Type, + Ifaces_List => Ifaces_List, + Exclude_Parents => True); + + Set_Interfaces (Derived_Type, Ifaces_List); end; end if; @@ -7003,7 +6977,7 @@ package body Sem_Ch3 is -- implemented interfaces if we are in expansion mode if Expander_Active - and then Has_Abstract_Interfaces (Derived_Type) + and then Has_Interfaces (Derived_Type) then Add_Interface_Tag_Components (N, Derived_Type); end if; @@ -7888,236 +7862,6 @@ package body Sem_Ch3 is end Build_Underlying_Full_View; ------------------------------- - -- Check_Abstract_Interfaces -- - ------------------------------- - - procedure Check_Abstract_Interfaces (N : Node_Id; Def : Node_Id) is - Parent_Type : constant Entity_Id := Etype (Defining_Identifier (N)); - - Iface : Node_Id; - Iface_Def : Node_Id; - Iface_Typ : Entity_Id; - Parent_Node : Node_Id; - - Is_Task : Boolean := False; - -- Set True if parent type or any progenitor is a task interface - - Is_Protected : Boolean := False; - -- Set True if parent type or any progenitor is a protected interface - - procedure Check_Ifaces (Iface_Def : Node_Id; Error_Node : Node_Id); - -- Check that a progenitor is compatible with declaration. - -- Error is posted on Error_Node. - - ------------------ - -- Check_Ifaces -- - ------------------ - - procedure Check_Ifaces (Iface_Def : Node_Id; Error_Node : Node_Id) is - Iface_Id : constant Entity_Id := - Defining_Identifier (Parent (Iface_Def)); - Type_Def : Node_Id; - - begin - if Nkind (N) = N_Private_Extension_Declaration then - Type_Def := N; - else - Type_Def := Type_Definition (N); - end if; - - if Is_Task_Interface (Iface_Id) then - Is_Task := True; - - elsif Is_Protected_Interface (Iface_Id) then - Is_Protected := True; - end if; - - -- Check that the characteristics of the progenitor are compatible - -- with the explicit qualifier in the declaration. - -- The check only applies to qualifiers that come from source. - -- Limited_Present also appears in the declaration of corresponding - -- records, and the check does not apply to them. - - if Limited_Present (Type_Def) - and then not - Is_Concurrent_Record_Type (Defining_Identifier (N)) - then - if Is_Limited_Interface (Parent_Type) - and then not Is_Limited_Interface (Iface_Id) - then - Error_Msg_NE - ("progenitor& must be limited interface", - Error_Node, Iface_Id); - - elsif - (Task_Present (Iface_Def) - or else Protected_Present (Iface_Def) - or else Synchronized_Present (Iface_Def)) - and then Nkind (N) /= N_Private_Extension_Declaration - then - Error_Msg_NE - ("progenitor& must be limited interface", - Error_Node, Iface_Id); - end if; - - -- Protected interfaces can only inherit from limited, synchronized - -- or protected interfaces. - - elsif Nkind (N) = N_Full_Type_Declaration - and then Protected_Present (Type_Def) - then - if Limited_Present (Iface_Def) - or else Synchronized_Present (Iface_Def) - or else Protected_Present (Iface_Def) - then - null; - - elsif Task_Present (Iface_Def) then - Error_Msg_N ("(Ada 2005) protected interface cannot inherit" - & " from task interface", Error_Node); - - else - Error_Msg_N ("(Ada 2005) protected interface cannot inherit" - & " from non-limited interface", Error_Node); - end if; - - -- Ada 2005 (AI-345): Synchronized interfaces can only inherit from - -- limited and synchronized. - - elsif Synchronized_Present (Type_Def) then - if Limited_Present (Iface_Def) - or else Synchronized_Present (Iface_Def) - then - null; - - elsif Protected_Present (Iface_Def) - and then Nkind (N) /= N_Private_Extension_Declaration - then - Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit" - & " from protected interface", Error_Node); - - elsif Task_Present (Iface_Def) - and then Nkind (N) /= N_Private_Extension_Declaration - then - Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit" - & " from task interface", Error_Node); - - elsif not Is_Limited_Interface (Iface_Id) then - Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit" - & " from non-limited interface", Error_Node); - end if; - - -- Ada 2005 (AI-345): Task interfaces can only inherit from limited, - -- synchronized or task interfaces. - - elsif Nkind (N) = N_Full_Type_Declaration - and then Task_Present (Type_Def) - then - if Limited_Present (Iface_Def) - or else Synchronized_Present (Iface_Def) - or else Task_Present (Iface_Def) - then - null; - - elsif Protected_Present (Iface_Def) then - Error_Msg_N ("(Ada 2005) task interface cannot inherit from" - & " protected interface", Error_Node); - - else - Error_Msg_N ("(Ada 2005) task interface cannot inherit from" - & " non-limited interface", Error_Node); - end if; - end if; - end Check_Ifaces; - - -- Start of processing for Check_Abstract_Interfaces - - begin - if Is_Interface (Parent_Type) then - if Is_Task_Interface (Parent_Type) then - Is_Task := True; - - elsif Is_Protected_Interface (Parent_Type) then - Is_Protected := True; - end if; - end if; - - if Nkind (N) = N_Private_Extension_Declaration then - - -- Check that progenitors are compatible with declaration - - Iface := First (Interface_List (Def)); - while Present (Iface) loop - Iface_Typ := Find_Type_Of_Subtype_Indic (Iface); - - Parent_Node := Parent (Base_Type (Iface_Typ)); - Iface_Def := Type_Definition (Parent_Node); - - if not Is_Interface (Iface_Typ) then - Error_Msg_NE ("(Ada 2005) & must be an interface", - Iface, Iface_Typ); - - else - Check_Ifaces (Iface_Def, Iface); - end if; - - Next (Iface); - end loop; - - if Is_Task and Is_Protected then - Error_Msg_N - ("type cannot derive from task and protected interface", N); - end if; - - return; - end if; - - -- Full type declaration of derived type. - -- Check compatibility with parent if it is interface type - - if Nkind (Type_Definition (N)) = N_Derived_Type_Definition - and then Is_Interface (Parent_Type) - then - Parent_Node := Parent (Parent_Type); - - -- More detailed checks for interface varieties - - Check_Ifaces - (Iface_Def => Type_Definition (Parent_Node), - Error_Node => Subtype_Indication (Type_Definition (N))); - end if; - - Iface := First (Interface_List (Def)); - - while Present (Iface) loop - Iface_Typ := Find_Type_Of_Subtype_Indic (Iface); - - Parent_Node := Parent (Base_Type (Iface_Typ)); - Iface_Def := Type_Definition (Parent_Node); - - if not Is_Interface (Iface_Typ) then - Error_Msg_NE ("(Ada 2005) & must be an interface", - Iface, Iface_Typ); - - else - -- "The declaration of a specific descendant of an interface - -- type freezes the interface type" RM 13.14 - - Freeze_Before (N, Iface_Typ); - Check_Ifaces (Iface_Def, Error_Node => Iface); - end if; - - Next (Iface); - end loop; - - if Is_Task and Is_Protected then - Error_Msg_N - ("type cannot derive from task and protected interface", N); - end if; - - end Check_Abstract_Interfaces; - - ------------------------------- -- Check_Abstract_Overriding -- ------------------------------- @@ -8162,13 +7906,20 @@ package body Sem_Ch3 is if Is_Null_Extension (T) and then Has_Controlling_Result (Subp) and then Ada_Version >= Ada_05 - and then Present (Alias (Subp)) + and then Present (Alias_Subp) and then not Comes_From_Source (Subp) - and then not Is_Abstract_Subprogram (Alias (Subp)) + and then not Is_Abstract_Subprogram (Alias_Subp) and then not Is_Access_Type (Etype (Subp)) then null; + -- Ada 2005 (AI-251): Internal entities of interfaces need no + -- processing because this check is done with the aliased + -- entity + + elsif Present (Interface_Alias (Subp)) then + null; + elsif (Is_Abstract_Subprogram (Subp) or else Requires_Overriding (Subp) or else @@ -8180,18 +7931,14 @@ package body Sem_Ch3 is and then not Is_TSS (Subp, TSS_Stream_Output) and then not Is_Abstract_Type (T) and then Convention (T) /= Convention_CIL - and then Chars (Subp) /= Name_uDisp_Asynchronous_Select - and then Chars (Subp) /= Name_uDisp_Conditional_Select - and then Chars (Subp) /= Name_uDisp_Get_Prim_Op_Kind - and then Chars (Subp) /= Name_uDisp_Requeue - and then Chars (Subp) /= Name_uDisp_Timed_Select + and then not Is_Predefined_Interface_Primitive (Subp) -- Ada 2005 (AI-251): Do not consider hidden entities associated -- with abstract interface types because the check will be done -- with the aliased entity (otherwise we generate a duplicated -- error message). - and then not Present (Abstract_Interface_Alias (Subp)) + and then not Present (Interface_Alias (Subp)) then if Present (Alias_Subp) then @@ -8222,13 +7969,15 @@ package body Sem_Ch3 is or else Requires_Overriding (Subp) or else Is_Access_Type (Etype (Subp))) then - -- The body of predefined primitives of tagged types derived - -- from interface types are generated later by Freeze_Type. - - if Is_Predefined_Dispatching_Operation (Subp) - and then Is_Abstract_Subprogram (Alias_Subp) - and then Is_Interface - (Root_Type (Find_Dispatching_Type (Subp))) + -- Avoid reporting error in case of abstract predefined + -- primitive inherited from interface type because the + -- body of internally generated predefined primitives + -- of tagged types are generated later by Freeze_Type + + if Is_Interface (Root_Type (T)) + and then Is_Abstract_Subprogram (Subp) + and then Is_Predefined_Dispatching_Operation (Subp) + and then not Comes_From_Source (Ultimate_Alias (Subp)) then null; @@ -8268,7 +8017,7 @@ package body Sem_Ch3 is -- abstract interfaces. elsif Is_Concurrent_Record_Type (T) - and then Present (Abstract_Interfaces (T)) + and then Present (Interfaces (T)) then -- The controlling formal of Subp must be of mode "out", -- "in out" or an access-to-variable to be overridden. @@ -8277,12 +8026,14 @@ package body Sem_Ch3 is -- in -gnatj mode) ??? if Ekind (First_Formal (Subp)) = E_In_Parameter then - Error_Msg_NE - ("first formal of & must be of mode `OUT`, `IN OUT` " & - "or access-to-variable", T, Subp); - Error_Msg_N - ("\to be overridden by protected procedure or " & - "entry (RM 9.4(11.9/2))", T); + if not Is_Predefined_Dispatching_Operation (Subp) then + Error_Msg_NE + ("first formal of & must be of mode `OUT`, " & + "`IN OUT` or access-to-variable", T, Subp); + Error_Msg_N + ("\to be overridden by protected procedure or " & + "entry (RM 9.4(11.9/2))", T); + end if; -- Some other kind of overriding failure @@ -8315,8 +8066,8 @@ package body Sem_Ch3 is if Ada_Version >= Ada_05 and then Is_Hidden (Subp) - and then Present (Abstract_Interface_Alias (Subp)) - and then Implemented_By_Entry (Abstract_Interface_Alias (Subp)) + and then Present (Interface_Alias (Subp)) + and then Implemented_By_Entry (Interface_Alias (Subp)) and then Present (Alias_Subp) and then (not Is_Primitive_Wrapper (Alias_Subp) @@ -8330,7 +8081,7 @@ package body Sem_Ch3 is Error_Ent := Corresponding_Concurrent_Type (Error_Ent); end if; - Error_Msg_Node_2 := Abstract_Interface_Alias (Subp); + Error_Msg_Node_2 := Interface_Alias (Subp); Error_Msg_NE ("type & must implement abstract subprogram & with an entry", Error_Ent, Error_Ent); @@ -8742,6 +8493,234 @@ package body Sem_Ch3 is end if; end Check_Initialization; + ---------------------- + -- Check_Interfaces -- + ---------------------- + + procedure Check_Interfaces (N : Node_Id; Def : Node_Id) is + Parent_Type : constant Entity_Id := Etype (Defining_Identifier (N)); + + Iface : Node_Id; + Iface_Def : Node_Id; + Iface_Typ : Entity_Id; + Parent_Node : Node_Id; + + Is_Task : Boolean := False; + -- Set True if parent type or any progenitor is a task interface + + Is_Protected : Boolean := False; + -- Set True if parent type or any progenitor is a protected interface + + procedure Check_Ifaces (Iface_Def : Node_Id; Error_Node : Node_Id); + -- Check that a progenitor is compatible with declaration. + -- Error is posted on Error_Node. + + ------------------ + -- Check_Ifaces -- + ------------------ + + procedure Check_Ifaces (Iface_Def : Node_Id; Error_Node : Node_Id) is + Iface_Id : constant Entity_Id := + Defining_Identifier (Parent (Iface_Def)); + Type_Def : Node_Id; + + begin + if Nkind (N) = N_Private_Extension_Declaration then + Type_Def := N; + else + Type_Def := Type_Definition (N); + end if; + + if Is_Task_Interface (Iface_Id) then + Is_Task := True; + + elsif Is_Protected_Interface (Iface_Id) then + Is_Protected := True; + end if; + + -- Check that the characteristics of the progenitor are compatible + -- with the explicit qualifier in the declaration. + -- The check only applies to qualifiers that come from source. + -- Limited_Present also appears in the declaration of corresponding + -- records, and the check does not apply to them. + + if Limited_Present (Type_Def) + and then not + Is_Concurrent_Record_Type (Defining_Identifier (N)) + then + if Is_Limited_Interface (Parent_Type) + and then not Is_Limited_Interface (Iface_Id) + then + Error_Msg_NE + ("progenitor& must be limited interface", + Error_Node, Iface_Id); + + elsif + (Task_Present (Iface_Def) + or else Protected_Present (Iface_Def) + or else Synchronized_Present (Iface_Def)) + and then Nkind (N) /= N_Private_Extension_Declaration + then + Error_Msg_NE + ("progenitor& must be limited interface", + Error_Node, Iface_Id); + end if; + + -- Protected interfaces can only inherit from limited, synchronized + -- or protected interfaces. + + elsif Nkind (N) = N_Full_Type_Declaration + and then Protected_Present (Type_Def) + then + if Limited_Present (Iface_Def) + or else Synchronized_Present (Iface_Def) + or else Protected_Present (Iface_Def) + then + null; + + elsif Task_Present (Iface_Def) then + Error_Msg_N ("(Ada 2005) protected interface cannot inherit" + & " from task interface", Error_Node); + + else + Error_Msg_N ("(Ada 2005) protected interface cannot inherit" + & " from non-limited interface", Error_Node); + end if; + + -- Ada 2005 (AI-345): Synchronized interfaces can only inherit from + -- limited and synchronized. + + elsif Synchronized_Present (Type_Def) then + if Limited_Present (Iface_Def) + or else Synchronized_Present (Iface_Def) + then + null; + + elsif Protected_Present (Iface_Def) + and then Nkind (N) /= N_Private_Extension_Declaration + then + Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit" + & " from protected interface", Error_Node); + + elsif Task_Present (Iface_Def) + and then Nkind (N) /= N_Private_Extension_Declaration + then + Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit" + & " from task interface", Error_Node); + + elsif not Is_Limited_Interface (Iface_Id) then + Error_Msg_N ("(Ada 2005) synchronized interface cannot inherit" + & " from non-limited interface", Error_Node); + end if; + + -- Ada 2005 (AI-345): Task interfaces can only inherit from limited, + -- synchronized or task interfaces. + + elsif Nkind (N) = N_Full_Type_Declaration + and then Task_Present (Type_Def) + then + if Limited_Present (Iface_Def) + or else Synchronized_Present (Iface_Def) + or else Task_Present (Iface_Def) + then + null; + + elsif Protected_Present (Iface_Def) then + Error_Msg_N ("(Ada 2005) task interface cannot inherit from" + & " protected interface", Error_Node); + + else + Error_Msg_N ("(Ada 2005) task interface cannot inherit from" + & " non-limited interface", Error_Node); + end if; + end if; + end Check_Ifaces; + + -- Start of processing for Check_Interfaces + + begin + if Is_Interface (Parent_Type) then + if Is_Task_Interface (Parent_Type) then + Is_Task := True; + + elsif Is_Protected_Interface (Parent_Type) then + Is_Protected := True; + end if; + end if; + + if Nkind (N) = N_Private_Extension_Declaration then + + -- Check that progenitors are compatible with declaration + + Iface := First (Interface_List (Def)); + while Present (Iface) loop + Iface_Typ := Find_Type_Of_Subtype_Indic (Iface); + + Parent_Node := Parent (Base_Type (Iface_Typ)); + Iface_Def := Type_Definition (Parent_Node); + + if not Is_Interface (Iface_Typ) then + Error_Msg_NE ("(Ada 2005) & must be an interface", + Iface, Iface_Typ); + + else + Check_Ifaces (Iface_Def, Iface); + end if; + + Next (Iface); + end loop; + + if Is_Task and Is_Protected then + Error_Msg_N + ("type cannot derive from task and protected interface", N); + end if; + + return; + end if; + + -- Full type declaration of derived type. + -- Check compatibility with parent if it is interface type + + if Nkind (Type_Definition (N)) = N_Derived_Type_Definition + and then Is_Interface (Parent_Type) + then + Parent_Node := Parent (Parent_Type); + + -- More detailed checks for interface varieties + + Check_Ifaces + (Iface_Def => Type_Definition (Parent_Node), + Error_Node => Subtype_Indication (Type_Definition (N))); + end if; + + Iface := First (Interface_List (Def)); + while Present (Iface) loop + Iface_Typ := Find_Type_Of_Subtype_Indic (Iface); + + Parent_Node := Parent (Base_Type (Iface_Typ)); + Iface_Def := Type_Definition (Parent_Node); + + if not Is_Interface (Iface_Typ) then + Error_Msg_NE ("(Ada 2005) & must be an interface", + Iface, Iface_Typ); + + else + -- "The declaration of a specific descendant of an interface + -- type freezes the interface type" RM 13.14 + + Freeze_Before (N, Iface_Typ); + Check_Ifaces (Iface_Def, Error_Node => Iface); + end if; + + Next (Iface); + end loop; + + if Is_Task and Is_Protected then + Error_Msg_N + ("type cannot derive from task and protected interface", N); + end if; + end Check_Interfaces; + ------------------------------------ -- Check_Or_Process_Discriminants -- ------------------------------------ @@ -11188,8 +11167,6 @@ package body Sem_Ch3 is Scale_Val : Uint; Bound_Val : Ureal; - -- Start of processing for Decimal_Fixed_Point_Type_Declaration - begin Check_Restriction (No_Fixed_Point, Def); @@ -11331,222 +11308,123 @@ package body Sem_Ch3 is Set_Is_Constrained (T); end Decimal_Fixed_Point_Type_Declaration; - ---------------------------------- - -- Derive_Interface_Subprograms -- - ---------------------------------- + ----------------------------------- + -- Derive_Progenitor_Subprograms -- + ----------------------------------- - procedure Derive_Interface_Subprograms + procedure Derive_Progenitor_Subprograms (Parent_Type : Entity_Id; - Tagged_Type : Entity_Id; - Ifaces_List : Elist_Id) + Tagged_Type : Entity_Id) is - function Collect_Interface_Primitives - (Tagged_Type : Entity_Id) return Elist_Id; - -- Ada 2005 (AI-251): Collect the primitives of all the implemented - -- interfaces. - - function In_List (L : Elist_Id; Subp : Entity_Id) return Boolean; - -- Determine if Subp already in the list L + E : Entity_Id; + Elmt : Elmt_Id; + Iface : Entity_Id; + Iface_Elmt : Elmt_Id; + Iface_Subp : Entity_Id; + New_Subp : Entity_Id := Empty; + Prim_Elmt : Elmt_Id; + Subp : Entity_Id; + Typ : Entity_Id; - procedure Remove_Homonym (E : Entity_Id); - -- Removes E from the homonym chain + begin + pragma Assert (Ada_Version >= Ada_05 + and then Is_Record_Type (Tagged_Type) + and then Is_Tagged_Type (Tagged_Type) + and then Has_Interfaces (Tagged_Type)); + + -- Step 1: Transfer to the full-view primitives asociated with the + -- partial-view that cover interface primitives. Conceptually this + -- work should be done later by Process_Full_View; done here to + -- simplify its implementation at later stages. It can be safely + -- done here because interfaces must be visible in the partial and + -- private view (RM 7.3(7.3/2)). + + -- Small optimization: This work is only required if the parent is + -- abstract. If the tagged type is not abstract, it cannot have + -- abstract primitives (the only entities in the list of primitives of + -- non-abstract tagged types that can reference abstract primitives + -- through its Alias attribute are the internal entities that have + -- attribute Interface_Alias, and these entities are generated later + -- by Freeze_Record_Type). - ---------------------------------- - -- Collect_Interface_Primitives -- - ---------------------------------- + if In_Private_Part (Current_Scope) + and then Is_Abstract_Type (Parent_Type) + then + Elmt := First_Elmt (Primitive_Operations (Tagged_Type)); + while Present (Elmt) loop + Subp := Node (Elmt); - function Collect_Interface_Primitives - (Tagged_Type : Entity_Id) return Elist_Id - is - Op_List : constant Elist_Id := New_Elmt_List; - Elmt : Elmt_Id; - Ifaces_List : Elist_Id; - Iface_Elmt : Elmt_Id; - Prim : Entity_Id; + -- At this stage it is not possible to have entities in the list + -- of primitives that have attribute Interface_Alias - begin - pragma Assert (Is_Tagged_Type (Tagged_Type) - and then Has_Abstract_Interfaces (Tagged_Type)); + pragma Assert (No (Interface_Alias (Subp))); - Collect_Abstract_Interfaces (Tagged_Type, Ifaces_List); + Typ := Find_Dispatching_Type (Ultimate_Alias (Subp)); - Iface_Elmt := First_Elmt (Ifaces_List); - while Present (Iface_Elmt) loop - Elmt := First_Elmt (Primitive_Operations (Node (Iface_Elmt))); - while Present (Elmt) loop - Prim := Node (Elmt); + if Is_Interface (Typ) then + E := Find_Primitive_Covering_Interface + (Tagged_Type => Tagged_Type, + Iface_Prim => Subp); - if not Is_Predefined_Dispatching_Operation (Prim) then - Append_Elmt (Prim, Op_List); + if Present (E) + and then Find_Dispatching_Type (Ultimate_Alias (E)) /= Typ + then + Replace_Elmt (Elmt, E); + Remove_Homonym (Subp); end if; - - Next_Elmt (Elmt); - end loop; - - Next_Elmt (Iface_Elmt); - end loop; - - return Op_List; - end Collect_Interface_Primitives; - - ------------- - -- In_List -- - ------------- - - function In_List (L : Elist_Id; Subp : Entity_Id) return Boolean is - Elmt : Elmt_Id; - - begin - Elmt := First_Elmt (L); - while Present (Elmt) loop - if Node (Elmt) = Subp then - return True; end if; Next_Elmt (Elmt); end loop; - - return False; - end In_List; - - -------------------- - -- Remove_Homonym -- - -------------------- - - procedure Remove_Homonym (E : Entity_Id) is - Prev : Entity_Id := Empty; - H : Entity_Id; - - begin - if E = Current_Entity (E) then - Set_Current_Entity (Homonym (E)); - else - H := Current_Entity (E); - while Present (H) and then H /= E loop - Prev := H; - H := Homonym (H); - end loop; - - Set_Homonym (Prev, Homonym (E)); - end if; - end Remove_Homonym; - - -- Local Variables - - E : Entity_Id; - Elmt : Elmt_Id; - Iface : Entity_Id; - Iface_Subp : Entity_Id; - New_Subp : Entity_Id := Empty; - Op_List : Elist_Id; - Parent_Base : Entity_Id; - Subp : Entity_Id; - - -- Start of processing for Derive_Interface_Subprograms - - begin - if Ada_Version < Ada_05 - or else not Is_Record_Type (Tagged_Type) - or else not Is_Tagged_Type (Tagged_Type) - or else not Has_Abstract_Interfaces (Tagged_Type) - then - return; end if; - -- Add to the list of interface subprograms all the primitives inherited - -- from abstract interfaces that are not immediate ancestors and also - -- add their derivation to the list of interface primitives. + -- Step 2: Add primitives of progenitors that are not implemented by + -- parents of Tagged_Type - Op_List := Collect_Interface_Primitives (Tagged_Type); + if Present (Interfaces (Tagged_Type)) then + Iface_Elmt := First_Elmt (Interfaces (Tagged_Type)); + while Present (Iface_Elmt) loop + Iface := Node (Iface_Elmt); - Elmt := First_Elmt (Op_List); - while Present (Elmt) loop - Subp := Node (Elmt); - Iface := Find_Dispatching_Type (Subp); + Prim_Elmt := First_Elmt (Primitive_Operations (Iface)); + while Present (Prim_Elmt) loop + Iface_Subp := Node (Prim_Elmt); - if Is_Concurrent_Record_Type (Tagged_Type) then - if not Present (Abstract_Interface_Alias (Subp)) then - Derive_Subprogram (New_Subp, Subp, Tagged_Type, Iface); - Append_Elmt (New_Subp, Ifaces_List); - end if; + if not Is_Predefined_Dispatching_Operation (Iface_Subp) then + E := Find_Primitive_Covering_Interface + (Tagged_Type => Tagged_Type, + Iface_Prim => Iface_Subp); - elsif not Is_Parent (Iface, Tagged_Type) then - Derive_Subprogram (New_Subp, Subp, Tagged_Type, Iface); - Append_Elmt (New_Subp, Ifaces_List); - end if; + -- If not found we derive a new primitive leaving its alias + -- attribute referencing the interface primitive - Next_Elmt (Elmt); - end loop; + if No (E) then + Derive_Subprogram + (New_Subp, Iface_Subp, Tagged_Type, Iface); - -- Complete the derivation of the interface subprograms. Assign to each - -- entity associated with abstract interfaces their aliased entity and - -- complete their decoration as hidden interface entities that will be - -- used later to build the secondary dispatch tables. + -- Propagate to the full view interface entities associated + -- with the partial view - if not Is_Empty_Elmt_List (Ifaces_List) then - if Ekind (Parent_Type) = E_Record_Type_With_Private - and then Has_Discriminants (Parent_Type) - and then Present (Full_View (Parent_Type)) - then - Parent_Base := Full_View (Parent_Type); - else - Parent_Base := Parent_Type; - end if; - - Elmt := First_Elmt (Ifaces_List); - while Present (Elmt) loop - Iface_Subp := Node (Elmt); - - -- Look for the first overriding entity in the homonym chain. - -- In this way if we are in the private part of a package spec - -- we get the last overriding subprogram. - - E := Current_Entity_In_Scope (Iface_Subp); - while Present (E) loop - if Is_Dispatching_Operation (E) - and then Scope (E) = Scope (Iface_Subp) - and then Type_Conformant (E, Iface_Subp) - and then not In_List (Ifaces_List, E) - then - exit; + elsif In_Private_Part (Current_Scope) + and then Present (Alias (E)) + and then Alias (E) = Iface_Subp + and then + List_Containing (Parent (E)) /= + Private_Declarations + (Specification + (Unit_Declaration_Node (Current_Scope))) + then + Append_Elmt (E, Primitive_Operations (Tagged_Type)); + end if; end if; - E := Homonym (E); + Next_Elmt (Prim_Elmt); end loop; - -- Create an overriding entity if not found in the homonym chain - - if not Present (E) then - Derive_Subprogram - (E, Alias (Iface_Subp), Tagged_Type, Parent_Base); - - elsif not In_List (Primitive_Operations (Tagged_Type), E) then - - -- Inherit the operation from the private view - - Append_Elmt (E, Primitive_Operations (Tagged_Type)); - end if; - - -- Complete the decoration of the hidden interface entity - - Set_Is_Hidden (Iface_Subp); - Set_Abstract_Interface_Alias (Iface_Subp, Alias (Iface_Subp)); - Set_Alias (Iface_Subp, E); - Set_Is_Abstract_Subprogram (Iface_Subp, - Is_Abstract_Subprogram (E)); - Remove_Homonym (Iface_Subp); - - -- Hidden entities associated with interfaces must have set the - -- Has_Delay_Freeze attribute to ensure that the corresponding - -- entry of the secondary dispatch table is filled when such - -- entity is frozen. - - Set_Has_Delayed_Freeze (Iface_Subp); - - Next_Elmt (Elmt); + Next_Elmt (Iface_Elmt); end loop; end if; - end Derive_Interface_Subprograms; + end Derive_Progenitor_Subprograms; ----------------------- -- Derive_Subprogram -- @@ -11764,6 +11642,10 @@ package body Sem_Ch3 is end if; end Set_Derived_Name; + -- Local variables + + Parent_Overrides_Interface_Primitive : Boolean := False; + -- Start of processing for Derive_Subprogram begin @@ -11771,6 +11653,23 @@ package body Sem_Ch3 is New_Entity (Nkind (Parent_Subp), Sloc (Derived_Type)); Set_Ekind (New_Subp, Ekind (Parent_Subp)); + -- Check whether the parent overrides an interface primitive + + if Is_Overriding_Operation (Parent_Subp) then + declare + E : Entity_Id := Parent_Subp; + begin + while Present (Overridden_Operation (E)) loop + E := Ultimate_Alias (Overridden_Operation (E)); + end loop; + + Parent_Overrides_Interface_Primitive := + Is_Dispatching_Operation (E) + and then Present (Find_Dispatching_Type (E)) + and then Is_Interface (Find_Dispatching_Type (E)); + end; + end if; + -- Check whether the inherited subprogram is a private operation that -- should be inherited but not yet made visible. Such subprograms can -- become visible at a later point (e.g., the private part of a public @@ -11816,10 +11715,11 @@ package body Sem_Ch3 is then Set_Derived_Name; - -- Ada 2005 (AI-251): Hidden entity associated with abstract interface - -- primitive + -- Ada 2005 (AI-251): Regular derivation if the parent subprogram + -- overrides an interface primitive because interface primitives + -- must be visible in the partial view of the parent (RM 7.3 (7.3/2)) - elsif Present (Abstract_Interface_Alias (Parent_Subp)) then + elsif Parent_Overrides_Interface_Primitive then Set_Derived_Name; -- The type is inheriting a private operation, so enter @@ -12035,17 +11935,102 @@ package body Sem_Ch3 is Derived_Type : Entity_Id; Generic_Actual : Entity_Id := Empty) is - Op_List : constant Elist_Id := - Collect_Primitive_Operations (Parent_Type); - Ifaces_List : constant Elist_Id := New_Elmt_List; - Predef_Prims : constant Elist_Id := New_Elmt_List; + Op_List : constant Elist_Id := + Collect_Primitive_Operations (Parent_Type); + + function Check_Derived_Type return Boolean; + -- Check that all primitive inherited from Parent_Type are found in + -- the list of primitives of Derived_Type exactly in the same order. + + function Check_Derived_Type return Boolean is + E : Entity_Id; + Elmt : Elmt_Id; + List : Elist_Id; + New_Subp : Entity_Id; + Op_Elmt : Elmt_Id; + Subp : Entity_Id; + + begin + -- Traverse list of entities in the current scope searching for + -- an incomplete type whose full-view is derived type + + E := First_Entity (Scope (Derived_Type)); + while Present (E) + and then E /= Derived_Type + loop + if Ekind (E) = E_Incomplete_Type + and then Present (Full_View (E)) + and then Full_View (E) = Derived_Type + then + -- Disable this test if Derived_Type completes an incomplete + -- type because in such case more primitives can be added + -- later to the list of primitives of Derived_Type by routine + -- Process_Incomplete_Dependents + + return True; + end if; + + E := Next_Entity (E); + end loop; + + List := Collect_Primitive_Operations (Derived_Type); + Elmt := First_Elmt (List); + + Op_Elmt := First_Elmt (Op_List); + while Present (Op_Elmt) loop + Subp := Node (Op_Elmt); + New_Subp := Node (Elmt); + + -- At this early stage Derived_Type has no entities with attribute + -- Interface_Alias. In addition, such primitives are always + -- located at the end of the list of primitives of Parent_Type. + -- Therefore, if found we can safely stop processing pending + -- entities. + + exit when Present (Interface_Alias (Subp)); + + -- Handle hidden entities + + if not Is_Predefined_Dispatching_Operation (Subp) + and then Is_Hidden (Subp) + then + if Present (New_Subp) + and then Primitive_Names_Match (Subp, New_Subp) + then + Next_Elmt (Elmt); + end if; + + else + if not Present (New_Subp) + or else Ekind (Subp) /= Ekind (New_Subp) + or else not Primitive_Names_Match (Subp, New_Subp) + then + return False; + end if; + + Next_Elmt (Elmt); + end if; + + Next_Elmt (Op_Elmt); + end loop; + + return True; + end Check_Derived_Type; + + -- Local variables + + Alias_Subp : Entity_Id; Act_List : Elist_Id; - Act_Elmt : Elmt_Id; + Act_Elmt : Elmt_Id := No_Elmt; + Act_Subp : Entity_Id := Empty; Elmt : Elmt_Id; + Need_Search : Boolean := False; New_Subp : Entity_Id := Empty; Parent_Base : Entity_Id; Subp : Entity_Id; + -- Start of processing for Derive_Subprograms + begin if Ekind (Parent_Type) = E_Record_Type_With_Private and then Has_Discriminants (Parent_Type) @@ -12056,126 +12041,266 @@ package body Sem_Ch3 is Parent_Base := Parent_Type; end if; - -- Derive primitives inherited from the parent. Note that if the generic - -- actual is present, this is not really a type derivation, it is a - -- completion within an instance. - if Present (Generic_Actual) then Act_List := Collect_Primitive_Operations (Generic_Actual); Act_Elmt := First_Elmt (Act_List); - else - Act_Elmt := No_Elmt; end if; - -- Literals are derived earlier in the process of building the derived - -- type, and are skipped here. + -- Derive primitives inherited from the parent. Note that if the generic + -- actual is present, this is not really a type derivation, it is a + -- completion within an instance. + + -- Case 1: Derived_Type does not implement interfaces - Elmt := First_Elmt (Op_List); - while Present (Elmt) loop - Subp := Node (Elmt); + if not Is_Tagged_Type (Derived_Type) + or else (not Has_Interfaces (Derived_Type) + and then not (Present (Generic_Actual) + and then + Has_Interfaces (Generic_Actual))) + then + Elmt := First_Elmt (Op_List); + while Present (Elmt) loop + Subp := Node (Elmt); - if Ekind (Subp) /= E_Enumeration_Literal then + -- Literals are derived earlier in the process of building the + -- derived type, and are skipped here. - if Ada_Version >= Ada_05 - and then Present (Abstract_Interface_Alias (Subp)) - then + if Ekind (Subp) = E_Enumeration_Literal then null; - -- We derive predefined primitives in a later round to ensure that - -- they are always added to the list of primitives after user - -- defined primitives (because predefined primitives have to be - -- skipped when matching the operations of a parent interface to - -- those of a concrete type). However it is unclear why those - -- primitives would be needed in an instantiation??? + -- The actual is a direct descendant and the common primitive + -- operations appear in the same order. - elsif Is_Predefined_Dispatching_Operation (Subp) then - Append_Elmt (Subp, Predef_Prims); + -- If the generic parent type is present, the derived type is an + -- instance of a formal derived type, and within the instance its + -- operations are those of the actual. We derive from the formal + -- type but make the inherited operations aliases of the + -- corresponding operations of the actual. - elsif No (Generic_Actual) then - Derive_Subprogram (New_Subp, Subp, Derived_Type, Parent_Base); + else + Derive_Subprogram + (New_Subp, Subp, Derived_Type, Parent_Base, Node (Act_Elmt)); - -- Ada 2005 (AI-251): Add derivation of an abstract interface - -- primitive to the list of entities to which we have to - -- associate an aliased entity. + if Present (Act_Elmt) then + Next_Elmt (Act_Elmt); + end if; + end if; - if Ada_Version >= Ada_05 - and then Is_Dispatching_Operation (Subp) - and then Present (Find_Dispatching_Type (Subp)) - and then Is_Interface (Find_Dispatching_Type (Subp)) - then - Append_Elmt (New_Subp, Ifaces_List); + Next_Elmt (Elmt); + end loop; + + -- Case 2: Derived_Type implements interfaces + + else + -- If the parent type has no predefined primitives we remove + -- predefined primitives from the list of primitives of generic + -- actual to simplify the complexity of this algorithm. + + if Present (Generic_Actual) then + declare + Has_Predefined_Primitives : Boolean := False; + + begin + -- Check if the parent type has predefined primitives + + Elmt := First_Elmt (Op_List); + while Present (Elmt) loop + Subp := Node (Elmt); + + if Is_Predefined_Dispatching_Operation (Subp) + and then not Comes_From_Source (Ultimate_Alias (Subp)) + then + Has_Predefined_Primitives := True; + exit; + end if; + + Next_Elmt (Elmt); + end loop; + + -- Remove predefined primitives of Generic_Actual. We must use + -- an auxiliary list because in case of tagged types the value + -- returned by Collect_Primitive_Operations is the value stored + -- in its Primitive_Operations attribute (and we don't want to + -- modify its current contents). + + if not Has_Predefined_Primitives then + declare + Aux_List : constant Elist_Id := New_Elmt_List; + + begin + Elmt := First_Elmt (Act_List); + while Present (Elmt) loop + Subp := Node (Elmt); + + if not Is_Predefined_Dispatching_Operation (Subp) + or else Comes_From_Source (Subp) + then + Append_Elmt (Subp, Aux_List); + end if; + + Next_Elmt (Elmt); + end loop; + + Act_List := Aux_List; + end; end if; - else - -- If the generic parent type is present, the derived type - -- is an instance of a formal derived type, and within the - -- instance its operations are those of the actual. We derive - -- from the formal type but make the inherited operations - -- aliases of the corresponding operations of the actual. - - if Is_Interface (Parent_Type) - and then Root_Type (Derived_Type) /= Parent_Type + Act_Elmt := First_Elmt (Act_List); + Act_Subp := Node (Act_Elmt); + end; + end if; + + -- Stage 1: If the generic actual is not present we derive the + -- primitives inherited from the parent type. If the generic parent + -- type is present, the derived type is an instance of a formal + -- derived type, and within the instance its operations are those of + -- the actual. We derive from the formal type but make the inherited + -- operations aliases of the corresponding operations of the actual. + + Elmt := First_Elmt (Op_List); + while Present (Elmt) loop + Subp := Node (Elmt); + Alias_Subp := Ultimate_Alias (Subp); + + -- At this early stage Derived_Type has no entities with attribute + -- Interface_Alias. In addition, such primitives are always + -- located at the end of the list of primitives of Parent_Type. + -- Therefore, if found we can safely stop processing pending + -- entities. + + exit when Present (Interface_Alias (Subp)); + + -- If the generic actual is present find the corresponding + -- operation in the generic actual. If the parent type is a + -- direct ancestor of the derived type then, even if it is an + -- interface, the operations are inherited from the primary + -- dispatch table and are in the proper order. If we detect here + -- that primitives are not in the same order we traverse the list + -- of primitive operations of the actual to find the one that + -- implements the interface primitive. + + if Need_Search + or else + (Present (Generic_Actual) + and then Present (Act_Subp) + and then not Primitive_Names_Match (Subp, Act_Subp)) + then + pragma Assert (not Is_Ancestor (Parent_Base, Generic_Actual)); + pragma Assert (Is_Interface (Parent_Base)); + + -- Remember that we need searching for all the pending + -- primitives + + Need_Search := True; + + -- Handle entities associated with interface primitives + + if Present (Alias (Subp)) + and then Is_Interface (Find_Dispatching_Type (Alias (Subp))) + and then not Is_Predefined_Dispatching_Operation (Subp) then - -- Find the corresponding operation in the generic actual. - -- Given that the actual is not a direct descendant of the - -- parent, as in Ada 95, the primitives are not necessarily - -- in the same order, so we have to traverse the list of - -- primitive operations of the actual to find the one that - -- implements the interface operation. - - -- Note that if the parent type is the direct ancestor of - -- the derived type, then even if it is an interface the - -- operations are inherited from the primary dispatch table - -- and are in the proper order. + Act_Subp := + Find_Primitive_Covering_Interface + (Tagged_Type => Generic_Actual, + Iface_Prim => Subp); + -- Handle predefined primitives plus the rest of user-defined + -- primitives + + else Act_Elmt := First_Elmt (Act_List); while Present (Act_Elmt) loop - exit when - Abstract_Interface_Alias (Node (Act_Elmt)) = Subp; + Act_Subp := Node (Act_Elmt); + + exit when Primitive_Names_Match (Subp, Act_Subp) + and then Type_Conformant (Subp, Act_Subp, + Skip_Controlling_Formals => True) + and then No (Interface_Alias (Act_Subp)); + Next_Elmt (Act_Elmt); end loop; end if; + end if; - -- If the formal is not an interface, the actual is a direct - -- descendant and the common primitive operations appear in - -- the same order. + -- Case 1: If the parent is a limited interface then it has the + -- predefined primitives of synchronized interfaces. However, the + -- actual type may be a non-limited type and hence it does not + -- have such primitives. - Derive_Subprogram - (New_Subp, Subp, Derived_Type, Parent_Base, Node (Act_Elmt)); + if Present (Generic_Actual) + and then not Present (Act_Subp) + and then Is_Limited_Interface (Parent_Base) + and then Is_Predefined_Interface_Primitive (Subp) + then + null; - if Present (Act_Elmt) then - Next_Elmt (Act_Elmt); + -- Case 2: Inherit entities associated with interfaces that + -- were not covered by the parent type. We exclude here null + -- interface primitives because they do not need special + -- management. + + elsif Present (Alias (Subp)) + and then Is_Interface (Find_Dispatching_Type (Alias_Subp)) + and then not + (Nkind (Parent (Alias_Subp)) = N_Procedure_Specification + and then Null_Present (Parent (Alias_Subp))) + then + Derive_Subprogram + (New_Subp => New_Subp, + Parent_Subp => Alias_Subp, + Derived_Type => Derived_Type, + Parent_Type => Find_Dispatching_Type (Alias_Subp), + Actual_Subp => Act_Subp); + + if No (Generic_Actual) then + Set_Alias (New_Subp, Subp); end if; - end if; - end if; - Next_Elmt (Elmt); - end loop; + -- Case 3: Common derivation - -- Inherit additional operations from progenitor interfaces. However, - -- if the derived type is a generic actual, there are not new primitive - -- operations for the type, because it has those of the actual, so - -- nothing needs to be done. The renamings generated above are not - -- primitive operations, and their purpose is simply to make the proper - -- operations visible within an instantiation. + else + Derive_Subprogram + (New_Subp => New_Subp, + Parent_Subp => Subp, + Derived_Type => Derived_Type, + Parent_Type => Parent_Base, + Actual_Subp => Act_Subp); + end if; - if Ada_Version >= Ada_05 - and then Is_Tagged_Type (Derived_Type) - and then No (Generic_Actual) - then - Derive_Interface_Subprograms (Parent_Type, Derived_Type, Ifaces_List); - end if; + -- No need to update Act_Elm if we must search for the + -- corresponding operation in the generic actual - -- Derive predefined primitives + if not Need_Search + and then Present (Act_Elmt) + then + Next_Elmt (Act_Elmt); + Act_Subp := Node (Act_Elmt); + end if; - if not Is_Empty_Elmt_List (Predef_Prims) then - Elmt := First_Elmt (Predef_Prims); - while Present (Elmt) loop - Derive_Subprogram - (New_Subp, Node (Elmt), Derived_Type, Parent_Base); Next_Elmt (Elmt); end loop; + + -- Inherit additional operations from progenitors. If the derived + -- type is a generic actual, there are not new primitive operations + -- for the type because it has those of the actual, and therefore + -- nothing needs to be done. The renamings generated above are not + -- primitive operations, and their purpose is simply to make the + -- proper operations visible within an instantiation. + + if No (Generic_Actual) then + Derive_Progenitor_Subprograms (Parent_Base, Derived_Type); + end if; end if; + + -- Final check: Direct descendants must have their primitives in the + -- same order. We exclude from this test non-tagged types and instances + -- of formal derived types. We skip this test if we have already + -- reported serious errors in the sources. + + pragma Assert (not Is_Tagged_Type (Derived_Type) + or else Present (Generic_Actual) + or else Serious_Errors_Detected > 0 + or else Check_Derived_Type); end Derive_Subprograms; -------------------------------- @@ -14046,48 +14171,9 @@ package body Sem_Ch3 is (Iface : Entity_Id; Typ : Entity_Id) return Boolean is - Iface_Elmt : Elmt_Id; - I_Name : Entity_Id; - begin - if No (Abstract_Interfaces (Typ)) then - return False; - - else - Iface_Elmt := First_Elmt (Abstract_Interfaces (Typ)); - while Present (Iface_Elmt) loop - I_Name := Node (Iface_Elmt); - if Base_Type (I_Name) = Base_Type (Iface) then - return True; - - elsif Is_Derived_Type (I_Name) - and then Is_Ancestor (Iface, I_Name) - then - return True; - - else - Next_Elmt (Iface_Elmt); - end if; - end loop; - - -- For concurrent record types, they have the interfaces of the - -- parent synchronized type. However these have no ancestors that - -- implement anything, so assume it is a progenitor. - -- Should be cleaned up in Collect_Abstract_Interfaces??? - - if Is_Concurrent_Record_Type (Typ) then - return Present (Abstract_Interfaces (Typ)); - end if; - - -- If type is a derived type, check recursively its ancestors - - if Is_Derived_Type (Typ) then - return Etype (Typ) = Iface - or else Is_Progenitor (Iface, Etype (Typ)); - else - return False; - end if; - end if; + return Implements_Interface (Typ, Iface, + Exclude_Parents => True); end Is_Progenitor; ------------------------------ @@ -15366,8 +15452,8 @@ package body Sem_Ch3 is -- Handle entities in the list of abstract interfaces - if Present (Abstract_Interfaces (Typ)) then - Iface_Elmt := First_Elmt (Abstract_Interfaces (Typ)); + if Present (Interfaces (Typ)) then + Iface_Elmt := First_Elmt (Interfaces (Typ)); while Present (Iface_Elmt) loop Iface := Node (Iface_Elmt); @@ -15697,6 +15783,9 @@ package body Sem_Ch3 is -- If the private view was tagged, copy the new primitive operations -- from the private view to the full view. + -- Note: Subprograms covering interface primitives were previously + -- propagated to the full view by Derive_Progenitor_Primitives + if Is_Tagged_Type (Full_T) and then not Is_Concurrent_Type (Full_T) then @@ -16902,11 +16991,11 @@ package body Sem_Ch3 is -- These flags must be initialized before calling Process_Discriminants -- because this routine makes use of them. - Set_Ekind (T, E_Record_Type); - Set_Etype (T, T); - Init_Size_Align (T); - Set_Abstract_Interfaces (T, No_Elist); - Set_Stored_Constraint (T, No_Elist); + Set_Ekind (T, E_Record_Type); + Set_Etype (T, T); + Init_Size_Align (T); + Set_Interfaces (T, No_Elist); + Set_Stored_Constraint (T, No_Elist); -- Normal case @@ -16952,7 +17041,7 @@ package body Sem_Ch3 is if Ada_Version >= Ada_05 and then Present (Interface_List (Def)) then - Check_Abstract_Interfaces (N, Def); + Check_Interfaces (N, Def); declare Ifaces_List : Elist_Id; @@ -16961,12 +17050,12 @@ package body Sem_Ch3 is -- Ada 2005 (AI-251): Collect the list of progenitors that are not -- already in the parents. - Collect_Abstract_Interfaces - (T => T, - Ifaces_List => Ifaces_List, - Exclude_Parent_Interfaces => True); + Collect_Interfaces + (T => T, + Ifaces_List => Ifaces_List, + Exclude_Parents => True); - Set_Abstract_Interfaces (T, Ifaces_List); + Set_Interfaces (T, Ifaces_List); end; end if; @@ -17013,7 +17102,7 @@ package body Sem_Ch3 is -- Ada 2005 (AI-251): Addition of the Tag corresponding to all the -- implemented interfaces. - if Has_Abstract_Interfaces (T) then + if Has_Interfaces (T) then Add_Interface_Tag_Components (N, T); end if; end if; @@ -17050,11 +17139,7 @@ package body Sem_Ch3 is if Is_Tagged and then not Is_Empty_List (Interface_List (Def)) then - declare - Ifaces_List : constant Elist_Id := New_Elmt_List; - begin - Derive_Interface_Subprograms (T, T, Ifaces_List); - end; + Derive_Progenitor_Subprograms (T, T); end if; end Record_Type_Declaration; |