This patch reimplements part of the support for AI05-0071 which deals with generic/instance scenarios involving a formal type with unknown discriminants, a generic primitive operation of the formal type declared with a box and an actual class-wide type.
------------ -- Source -- ------------ -- types.ads package Types is type T1 is tagged null record; procedure Prim_Op (Param : T1); type T2 is tagged null record; procedure Prim_Op (Param : T2'Class); type T3 is tagged null record; procedure Prim_Op (Param : T3); procedure Prim_Op (Param : T3'Class); type T4 is tagged null record; end Types; -- gen.ads generic type Formal_Typ (<>) is private; with procedure Prim_Op (Param : Formal_Typ) is <>; package Gen is end Gen; -- instances.ads with Gen; with Types; use Types; package Instances is package Inst1 is new Gen (T1'Class); -- OK package Inst2 is new Gen (T2'Class); -- OK package Inst3 is new Gen (T3'Class); -- ERROR, two primitives visible package Inst4 is new Gen (T4'Class); -- ERROR, no primitives visible end Instances; ---------------------------- -- Compilation and output -- ---------------------------- $ gcc -c instances.ads instances.ads:7:04: instantiation error at gen.ads:3 instances.ads:7:04: ambiguous actual for generic subprogram "Prim_Op" instances.ads:7:04: possible interpretation: "Prim_Op" defined at types.ads:10 instances.ads:7:04: possible interpretation: "Prim_Op" defined at types.ads:9 instances.ads:8:04: instantiation error at gen.ads:3 instances.ads:8:04: no visible subprogram matches the specification for "Prim_Op" Tested on x86_64-pc-linux-gnu, committed on trunk 2014-08-01 Hristian Kirtchev <kirtc...@adacore.com> * sem_ch8.adb (Analyze_Subprogram_Renaming): Alphabetize globals and move certain variables to the "local variable" section. Call Build_Class_Wide_Wrapper when renaming a default actual subprogram with a class-wide actual. (Build_Class_Wide_Wrapper): New routine. (Check_Class_Wide_Actual): Removed. (Find_Renamed_Entity): Code reformatting. (Has_Class_Wide_Actual): Alphabetize. Change the logic of the predicate as the renamed name may not necessarely denote the correct subprogram.
Index: sem_ch8.adb =================================================================== --- sem_ch8.adb (revision 213464) +++ sem_ch8.adb (working copy) @@ -1812,18 +1812,51 @@ --------------------------------- procedure Analyze_Subprogram_Renaming (N : Node_Id) is - Formal_Spec : constant Node_Id := Corresponding_Formal_Spec (N); - Is_Actual : constant Boolean := Present (Formal_Spec); - Inst_Node : Node_Id := Empty; + Formal_Spec : constant Entity_Id := Corresponding_Formal_Spec (N); + Is_Actual : constant Boolean := Present (Formal_Spec); Nam : constant Node_Id := Name (N); - New_S : Entity_Id; - Old_S : Entity_Id := Empty; - Rename_Spec : Entity_Id; Save_AV : constant Ada_Version_Type := Ada_Version; Save_AVP : constant Node_Id := Ada_Version_Pragma; Save_AV_Exp : constant Ada_Version_Type := Ada_Version_Explicit; Spec : constant Node_Id := Specification (N); + Old_S : Entity_Id := Empty; + Rename_Spec : Entity_Id; + + procedure Build_Class_Wide_Wrapper + (Ren_Id : out Entity_Id; + Wrap_Id : out Entity_Id); + -- Ada 2012 (AI05-0071): A generic/instance scenario involving a formal + -- type with unknown discriminants and a generic primitive operation of + -- the said type with a box require special processing when the actual + -- is a class-wide type: + + -- generic + -- type Formal_Typ (<>) is private; + -- with procedure Prim_Op (Param : Formal_Typ) is <>; + -- package Gen is ... + + -- package Inst is new Gen (Actual_Typ'Class); + + -- In this case the general renaming mechanism used in the prologue of + -- an instance no longer applies: + + -- procedure Prim_Op (Param : Formal_Typ) renames Prim_Op; + + -- The above is replaced the following wrapper/renaming combination: + + -- procedure Prim_Op (Param : Formal_Typ) is -- wrapper + -- begin + -- Prim_Op (Param); -- primitive + -- end Wrapper; + + -- procedure Dummy (Param : Formal_Typ) renames Prim_Op; + + -- This transformation applies only if there is no explicit visible + -- class-wide operation at the point of the instantiation. Ren_Id is + -- the entity of the renaming declaration. Wrap_Id is the entity of + -- the generated class-wide wrapper (or Any_Id). + procedure Check_Null_Exclusion (Ren : Entity_Id; Sub : Entity_Id); @@ -1845,6 +1878,11 @@ -- types: a callable entity freezes its profile, unless it has an -- incomplete untagged formal (RM 13.14(10.2/3)). + function Has_Class_Wide_Actual return Boolean; + -- Ada 2012 (AI05-071, AI05-0131): True if N is the renaming for a + -- defaulted formal subprogram where the actual for the controlling + -- formal type is class-wide. + function Original_Subprogram (Subp : Entity_Id) return Entity_Id; -- Find renamed entity when the declaration is a renaming_as_body and -- the renamed entity may itself be a renaming_as_body. Used to enforce @@ -1852,188 +1890,406 @@ -- before the subprogram it completes is frozen, and renaming indirectly -- renames the subprogram itself.(Defect Report 8652/0027). - function Check_Class_Wide_Actual return Entity_Id; - -- AI05-0071: In an instance, if the actual for a formal type FT with - -- unknown discriminants is a class-wide type CT, and the generic has - -- a formal subprogram with a box for a primitive operation of FT, - -- then the corresponding actual subprogram denoted by the default is a - -- class-wide operation whose body is a dispatching call. We replace the - -- generated renaming declaration: - -- - -- procedure P (X : CT) renames P; - -- - -- by a different renaming and a class-wide operation: - -- - -- procedure Pr (X : T) renames P; -- renames primitive operation - -- procedure P (X : CT); -- class-wide operation - -- ... - -- procedure P (X : CT) is begin Pr (X); end; -- dispatching call - -- - -- This rule only applies if there is no explicit visible class-wide - -- operation at the point of the instantiation. + ------------------------------ + -- Build_Class_Wide_Wrapper -- + ------------------------------ - function Has_Class_Wide_Actual return Boolean; - -- Ada 2012 (AI05-071, AI05-0131): True if N is the renaming for a - -- defaulted formal subprogram when the actual for the controlling - -- formal type is class-wide. + procedure Build_Class_Wide_Wrapper + (Ren_Id : out Entity_Id; + Wrap_Id : out Entity_Id) + is + Loc : constant Source_Ptr := Sloc (N); - ----------------------------- - -- Check_Class_Wide_Actual -- - ----------------------------- + function Build_Call + (Subp_Id : Entity_Id; + Params : List_Id) return Node_Id; + -- Create a dispatching call to invoke routine Subp_Id with actuals + -- built from the parameter specifications of list Params. - function Check_Class_Wide_Actual return Entity_Id is - Loc : constant Source_Ptr := Sloc (N); + function Build_Spec (Subp_Id : Entity_Id) return Node_Id; + -- Create a subprogram specification based on the subprogram profile + -- of Subp_Id. - F : Entity_Id; - Formal_Type : Entity_Id; - Actual_Type : Entity_Id; - New_Body : Node_Id; - New_Decl : Node_Id; - Result : Entity_Id; + function Find_Primitive (Typ : Entity_Id) return Entity_Id; + -- Find a primitive subprogram of type Typ which matches the profile + -- of the renaming declaration. - function Make_Call (Prim_Op : Entity_Id) return Node_Id; - -- Build dispatching call for body of class-wide operation + procedure Interpretation_Error (Subp_Id : Entity_Id); + -- Emit a continuation error message suggesting subprogram Subp_Id as + -- a possible interpretation. - function Make_Spec return Node_Id; - -- Create subprogram specification for declaration and body of - -- class-wide operation, using signature of renaming declaration. + ---------------- + -- Build_Call -- + ---------------- - --------------- - -- Make_Call -- - --------------- + function Build_Call + (Subp_Id : Entity_Id; + Params : List_Id) return Node_Id + is + Actuals : constant List_Id := New_List; + Call_Ref : constant Node_Id := New_Occurrence_Of (Subp_Id, Loc); + Formal : Node_Id; - function Make_Call (Prim_Op : Entity_Id) return Node_Id is - Actuals : List_Id; - F : Node_Id; + begin + -- Build the actual parameters of the call - begin - Actuals := New_List; - F := First (Parameter_Specifications (Specification (New_Decl))); - while Present (F) loop + Formal := First (Params); + while Present (Formal) loop Append_To (Actuals, - Make_Identifier (Loc, Chars (Defining_Identifier (F)))); - Next (F); + Make_Identifier (Loc, Chars (Defining_Identifier (Formal)))); + + Next (Formal); end loop; - if Ekind_In (Prim_Op, E_Function, E_Operator) then - return Make_Simple_Return_Statement (Loc, - Expression => - Make_Function_Call (Loc, - Name => New_Occurrence_Of (Prim_Op, Loc), - Parameter_Associations => Actuals)); + -- Generate: + -- return Subp_Id (Actuals); + + if Ekind_In (Subp_Id, E_Function, E_Operator) then + return + Make_Simple_Return_Statement (Loc, + Expression => + Make_Function_Call (Loc, + Name => Call_Ref, + Parameter_Associations => Actuals)); + + -- Generate: + -- Subp_Id (Actuals); + else return Make_Procedure_Call_Statement (Loc, - Name => New_Occurrence_Of (Prim_Op, Loc), - Parameter_Associations => Actuals); + Name => Call_Ref, + Parameter_Associations => Actuals); end if; - end Make_Call; + end Build_Call; - --------------- - -- Make_Spec -- - --------------- + ---------------- + -- Build_Spec -- + ---------------- - function Make_Spec return Node_Id is - Param_Specs : constant List_Id := Copy_Parameter_List (New_S); + function Build_Spec (Subp_Id : Entity_Id) return Node_Id is + Params : constant List_Id := Copy_Parameter_List (Subp_Id); + Spec_Id : constant Entity_Id := + Make_Defining_Identifier (Loc, Chars (Subp_Id)); begin - if Ekind (New_S) = E_Procedure then + if Ekind (Formal_Spec) = E_Procedure then return Make_Procedure_Specification (Loc, - Defining_Unit_Name => - Make_Defining_Identifier (Loc, - Chars (Defining_Unit_Name (Spec))), - Parameter_Specifications => Param_Specs); + Defining_Unit_Name => Spec_Id, + Parameter_Specifications => Params); else return - Make_Function_Specification (Loc, - Defining_Unit_Name => - Make_Defining_Identifier (Loc, - Chars (Defining_Unit_Name (Spec))), - Parameter_Specifications => Param_Specs, - Result_Definition => - New_Copy_Tree (Result_Definition (Spec))); + Make_Function_Specification (Loc, + Defining_Unit_Name => Spec_Id, + Parameter_Specifications => Params, + Result_Definition => + New_Copy_Tree (Result_Definition (Spec))); end if; - end Make_Spec; + end Build_Spec; - -- Start of processing for Check_Class_Wide_Actual + -------------------- + -- Find_Primitive -- + -------------------- + function Find_Primitive (Typ : Entity_Id) return Entity_Id is + procedure Replace_Parameter_Types (Spec : Node_Id); + -- Given a specification Spec, replace all class-wide parameter + -- types with reference to type Typ. + + ----------------------------- + -- Replace_Parameter_Types -- + ----------------------------- + + procedure Replace_Parameter_Types (Spec : Node_Id) is + Formal : Node_Id; + Formal_Id : Entity_Id; + Formal_Typ : Node_Id; + + begin + Formal := First (Parameter_Specifications (Spec)); + while Present (Formal) loop + Formal_Id := Defining_Identifier (Formal); + Formal_Typ := Parameter_Type (Formal); + + -- Create a new entity for each class-wide formal to prevent + -- aliasing with the original renaming. Replace the type of + -- such a parameter with the candidate type. + + if Nkind (Formal_Typ) = N_Identifier + and then Is_Class_Wide_Type (Etype (Formal_Typ)) + then + Set_Defining_Identifier (Formal, + Make_Defining_Identifier (Loc, Chars (Formal_Id))); + + Set_Parameter_Type (Formal, New_Occurrence_Of (Typ, Loc)); + end if; + + Next (Formal); + end loop; + end Replace_Parameter_Types; + + -- Local variables + + Alt_Ren : constant Node_Id := New_Copy_Tree (N); + Alt_Nam : constant Node_Id := Name (Alt_Ren); + Alt_Spec : constant Node_Id := Specification (Alt_Ren); + Subp_Id : Entity_Id; + + -- Start of processing for Find_Primitive + + begin + -- Each attempt to find a suitable primitive of a particular type + -- operates on its own copy of the original renaming. As a result + -- the original renaming is kept decoration and side-effect free. + + -- Inherit the overloaded status of the renamed subprogram name + + if Is_Overloaded (Nam) then + Set_Is_Overloaded (Alt_Nam); + Save_Interps (Nam, Alt_Nam); + end if; + + -- The copied renaming is hidden from visibility to prevent the + -- pollution of the enclosing context. + + Set_Defining_Unit_Name (Alt_Spec, Make_Temporary (Loc, 'R')); + + -- The types of all class-wide parameters must be changed to the + -- candidate type. + + Replace_Parameter_Types (Alt_Spec); + + -- Try to find a suitable primitive which matches the altered + -- profile of the renaming specification. + + Subp_Id := + Find_Renamed_Entity + (N => Alt_Ren, + Nam => Name (Alt_Ren), + New_S => Analyze_Subprogram_Specification (Alt_Spec), + Is_Actual => Is_Actual); + + -- Do not return Any_Id if the resolion of the altered profile + -- failed as this complicates further checks on the caller side, + -- return Empty instead. + + if Subp_Id = Any_Id then + return Empty; + else + return Subp_Id; + end if; + end Find_Primitive; + + -------------------------- + -- Interpretation_Error -- + -------------------------- + + procedure Interpretation_Error (Subp_Id : Entity_Id) is + begin + Error_Msg_Sloc := Sloc (Subp_Id); + Error_Msg_NE + ("\\possible interpretation: & defined #", Spec, Formal_Spec); + end Interpretation_Error; + + -- Local variables + + Actual_Typ : Entity_Id := Empty; + -- The actual class-wide type for Formal_Typ + + CW_Prim_Op : Entity_Id; + -- The class-wide primitive (if any) which corresponds to the renamed + -- generic formal subprogram. + + Formal_Typ : Entity_Id := Empty; + -- The generic formal type (if any) with unknown discriminants + + Root_Prim_Op : Entity_Id; + -- The root type primitive (if any) which corresponds to the renamed + -- generic formal subprogram. + + Body_Decl : Node_Id; + Formal : Node_Id; + Prim_Op : Entity_Id; + Spec_Decl : Node_Id; + + -- Start of processing for Build_Class_Wide_Wrapper + begin - Result := Any_Id; - Formal_Type := Empty; - Actual_Type := Empty; + -- Analyze the specification of the renaming in case the generation + -- of the class-wide wrapper fails. - F := First_Formal (Formal_Spec); - while Present (F) loop - if Has_Unknown_Discriminants (Etype (F)) - and then not Is_Class_Wide_Type (Etype (F)) - and then Is_Class_Wide_Type (Get_Instance_Of (Etype (F))) + Ren_Id := Analyze_Subprogram_Specification (Spec); + Wrap_Id := Any_Id; + + -- Do not attempt to build a wrapper if the renaming is in error + + if Error_Posted (Nam) then + return; + end if; + + -- Analyze the renamed name, but do not resolve it. The resolution is + -- completed once a suitable primitive is found. + + Analyze (Nam); + + -- Step 1: Find the generic formal type with unknown discriminants + -- and its corresponding class-wide actual type from the renamed + -- generic formal subprogram. + + Formal := First_Formal (Formal_Spec); + while Present (Formal) loop + if Has_Unknown_Discriminants (Etype (Formal)) + and then not Is_Class_Wide_Type (Etype (Formal)) + and then Is_Class_Wide_Type (Get_Instance_Of (Etype (Formal))) then - Formal_Type := Etype (F); - Actual_Type := Etype (Get_Instance_Of (Formal_Type)); + Formal_Typ := Etype (Formal); + Actual_Typ := Get_Instance_Of (Formal_Typ); exit; end if; - Next_Formal (F); + Next_Formal (Formal); end loop; - if Present (Formal_Type) then + -- The specification of the generic formal subprogram should always + -- contain a formal type with unknown discriminants whose actual is + -- a class-wide type, otherwise this indicates a failure in routine + -- Has_Class_Wide_Actual. - -- Create declaration and body for class-wide operation + pragma Assert (Present (Formal_Typ)); - New_Decl := - Make_Subprogram_Declaration (Loc, Specification => Make_Spec); + -- Step 2: Find the proper primitive which corresponds to the renamed + -- generic formal subprogram. - New_Body := - Make_Subprogram_Body (Loc, - Specification => Make_Spec, - Declarations => No_List, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, New_List)); + CW_Prim_Op := Find_Primitive (Actual_Typ); + Root_Prim_Op := Find_Primitive (Etype (Actual_Typ)); - -- Modify Spec and create internal name for renaming of primitive - -- operation. + -- The class-wide actual type has two primitives which correspond to + -- the renamed generic formal subprogram: - Set_Defining_Unit_Name (Spec, Make_Temporary (Loc, 'R')); - F := First (Parameter_Specifications (Spec)); - while Present (F) loop - if Nkind (Parameter_Type (F)) = N_Identifier - and then Is_Class_Wide_Type (Entity (Parameter_Type (F))) + -- with procedure Prim_Op (Param : Formal_Typ); + + -- procedure Prim_Op (Param : Actual_Typ); -- may be inherited + -- procedure Prim_Op (Param : Actual_Typ'Class); + + -- Even though the declaration of the two primitives is legal, a call + -- to either one is ambiguous and therefore illegal. + + if Present (CW_Prim_Op) and then Present (Root_Prim_Op) then + + -- Deal with abstract primitives + + if Is_Abstract_Subprogram (CW_Prim_Op) + or else Is_Abstract_Subprogram (Root_Prim_Op) + then + -- An abstract subprogram cannot act as a generic actual, but + -- the partial parameterization of the instance may hide the + -- true nature of the actual. Emit an error when both options + -- are abstract. + + if Is_Abstract_Subprogram (CW_Prim_Op) + and then Is_Abstract_Subprogram (Root_Prim_Op) then - Set_Parameter_Type (F, New_Occurrence_Of (Actual_Type, Loc)); + Error_Msg_NE + ("abstract subprogram not allowed as generic actual", + Spec, Formal_Spec); + Interpretation_Error (CW_Prim_Op); + Interpretation_Error (Root_Prim_Op); + return; + + -- Otherwise choose the non-abstract version + + elsif Is_Abstract_Subprogram (Root_Prim_Op) then + Prim_Op := CW_Prim_Op; + + else pragma Assert (Is_Abstract_Subprogram (CW_Prim_Op)); + Prim_Op := Root_Prim_Op; end if; - Next (F); - end loop; - New_S := Analyze_Subprogram_Specification (Spec); - Result := Find_Renamed_Entity (N, Name (N), New_S, Is_Actual); - end if; + -- If one of the candidate primitives is intrinsic, choose the + -- other (which may also be intrinsic). Preference is given to + -- the primitive of the root type. - if Result /= Any_Id then - Insert_Before (N, New_Decl); - Analyze (New_Decl); + elsif Is_Intrinsic_Subprogram (CW_Prim_Op) then + Prim_Op := Root_Prim_Op; - -- Add dispatching call to body of class-wide operation + elsif Is_Intrinsic_Subprogram (Root_Prim_Op) then + Prim_Op := CW_Prim_Op; - Append (Make_Call (Result), - Statements (Handled_Statement_Sequence (New_Body))); + elsif CW_Prim_Op = Root_Prim_Op then + Prim_Op := Root_Prim_Op; - -- The generated body does not freeze. It is analyzed when the - -- generated operation is frozen. This body is only needed if - -- expansion is enabled. + -- Otherwise there are two perfectly good candidates which satisfy + -- the profile of the renamed generic formal subprogram. - if Expander_Active then - Append_Freeze_Action (Defining_Entity (New_Decl), New_Body); + else + Error_Msg_NE + ("ambiguous actual for generic subprogram &", + Spec, Formal_Spec); + Interpretation_Error (CW_Prim_Op); + Interpretation_Error (Root_Prim_Op); + return; end if; - Result := Defining_Entity (New_Decl); + elsif Present (CW_Prim_Op) then + Prim_Op := CW_Prim_Op; + + elsif Present (Root_Prim_Op) then + Prim_Op := Root_Prim_Op; + + -- Otherwise there are no candidate primitives. Let the caller + -- diagnose the error. + + else + return; end if; - -- Return the class-wide operation if one was created + -- Set the proper entity of the renamed generic formal subprogram + -- and reset its overloaded status now that resolution has finally + -- taken place. - return Result; - end Check_Class_Wide_Actual; + Set_Entity (Nam, Prim_Op); + Set_Is_Overloaded (Nam, False); + -- Step 3: Create the declaration and the body of the wrapper, insert + -- all the pieces into the tree. + + Spec_Decl := + Make_Subprogram_Declaration (Loc, + Specification => Build_Spec (Ren_Id)); + + Body_Decl := + Make_Subprogram_Body (Loc, + Specification => Build_Spec (Ren_Id), + Declarations => New_List, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List ( + Build_Call + (Subp_Id => Prim_Op, + Params => + Parameter_Specifications + (Specification (Spec_Decl)))))); + + Insert_Before_And_Analyze (N, Spec_Decl); + Wrap_Id := Defining_Entity (Spec_Decl); + + -- The generated body does not freeze and must be analyzed when the + -- class-wide wrapper is frozen. The body is only needed if expansion + -- is enabled. + + if Expander_Active then + Append_Freeze_Action (Wrap_Id, Body_Decl); + end if; + + -- Step 4: Once the proper actual type and primitive operation are + -- known, hide the renaming declaration from visibility by giving it + -- a dummy name. + + Set_Defining_Unit_Name (Spec, Make_Temporary (Loc, 'R')); + Ren_Id := Analyze_Subprogram_Specification (Spec); + end Build_Class_Wide_Wrapper; + -------------------------- -- Check_Null_Exclusion -- -------------------------- @@ -2118,7 +2374,6 @@ if Is_Incomplete_Or_Private_Type (Etype (F)) and then No (Underlying_Type (Etype (F))) then - -- Exclude generic types, or types derived from them. -- They will be frozen in the enclosing instance. @@ -2144,28 +2399,23 @@ --------------------------- function Has_Class_Wide_Actual return Boolean is - F_Nam : Entity_Id; - F_Spec : Entity_Id; + Formal : Entity_Id; + Formal_Typ : Entity_Id; begin - if Is_Actual - and then Nkind (Nam) in N_Has_Entity - and then Present (Entity (Nam)) - and then Is_Dispatching_Operation (Entity (Nam)) - then - F_Nam := First_Entity (Entity (Nam)); - F_Spec := First_Formal (Formal_Spec); - while Present (F_Nam) and then Present (F_Spec) loop - if Is_Controlling_Formal (F_Nam) - and then Has_Unknown_Discriminants (Etype (F_Spec)) - and then not Is_Class_Wide_Type (Etype (F_Spec)) - and then Is_Class_Wide_Type (Get_Instance_Of (Etype (F_Spec))) + if Is_Actual then + Formal := First_Formal (Formal_Spec); + while Present (Formal) loop + Formal_Typ := Etype (Formal); + + if Has_Unknown_Discriminants (Formal_Typ) + and then not Is_Class_Wide_Type (Formal_Typ) + and then Is_Class_Wide_Type (Get_Instance_Of (Formal_Typ)) then return True; end if; - Next_Entity (F_Nam); - Next_Formal (F_Spec); + Next_Formal (Formal); end loop; end if; @@ -2215,11 +2465,16 @@ end if; end Original_Subprogram; + -- Local variables + CW_Actual : constant Boolean := Has_Class_Wide_Actual; -- Ada 2012 (AI05-071, AI05-0131): True if the renaming is for a -- defaulted formal subprogram when the actual for a related formal -- type is class-wide. + Inst_Node : Node_Id := Empty; + New_S : Entity_Id; + -- Start of processing for Analyze_Subprogram_Renaming begin @@ -2344,9 +2599,8 @@ -- Check whether the renaming is for a defaulted actual subprogram -- with a class-wide actual. - if CW_Actual then - New_S := Analyze_Subprogram_Specification (Spec); - Old_S := Check_Class_Wide_Actual; + if CW_Actual and then Box_Present (Inst_Node) then + Build_Class_Wide_Wrapper (New_S, Old_S); elsif Is_Entity_Name (Nam) and then Present (Entity (Nam)) @@ -2623,8 +2877,8 @@ Analyze_Renamed_Character (N, New_S, Present (Rename_Spec)); return; - -- Only remaining case is where we have a non-entity name, or a - -- renaming of some other non-overloadable entity. + -- Only remaining case is where we have a non-entity name, or a renaming + -- of some other non-overloadable entity. elsif not Is_Entity_Name (Nam) or else not Is_Overloadable (Entity (Nam)) @@ -3939,7 +4193,6 @@ else Pop_Scope; end if; - end End_Scope; --------------------- @@ -5916,31 +6169,11 @@ Old_S := Any_Id; Candidate_Renaming := Empty; - if not Is_Overloaded (Nam) then - if Is_Actual and then Present (Enclosing_Instance) then - Old_S := Entity (Nam); - - elsif Entity_Matches_Spec (Entity (Nam), New_S) then - Candidate_Renaming := New_S; - - if Is_Visible_Operation (Entity (Nam)) then - Old_S := Entity (Nam); - end if; - - elsif - Present (First_Formal (Entity (Nam))) - and then Present (First_Formal (New_S)) - and then (Base_Type (Etype (First_Formal (Entity (Nam)))) = - Base_Type (Etype (First_Formal (New_S)))) - then - Candidate_Renaming := Entity (Nam); - end if; - - else + if Is_Overloaded (Nam) then Get_First_Interp (Nam, Ind, It); while Present (It.Nam) loop if Entity_Matches_Spec (It.Nam, New_S) - and then Is_Visible_Operation (It.Nam) + and then Is_Visible_Operation (It.Nam) then if Old_S /= Any_Id then @@ -6009,6 +6242,27 @@ if Old_S /= Any_Id then Set_Is_Overloaded (Nam, False); end if; + + -- Non-overloaded case + + else + if Is_Actual and then Present (Enclosing_Instance) then + Old_S := Entity (Nam); + + elsif Entity_Matches_Spec (Entity (Nam), New_S) then + Candidate_Renaming := New_S; + + if Is_Visible_Operation (Entity (Nam)) then + Old_S := Entity (Nam); + end if; + + elsif Present (First_Formal (Entity (Nam))) + and then Present (First_Formal (New_S)) + and then (Base_Type (Etype (First_Formal (Entity (Nam)))) = + Base_Type (Etype (First_Formal (New_S)))) + then + Candidate_Renaming := Entity (Nam); + end if; end if; return Old_S;