diff options
author | Hristian Kirtchev <kirtchev@adacore.com> | 2007-12-13 11:30:41 +0100 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2007-12-13 11:30:41 +0100 |
commit | d469eabed98420f0bdd2895d47e11829e3bb76d9 (patch) | |
tree | 56de5248419355494b4be55b05ae58560c9ac855 /gcc | |
parent | 01b18343996b7145c23191fb574b3fae3e845d8d (diff) | |
download | gcc-d469eabed98420f0bdd2895d47e11829e3bb76d9.zip gcc-d469eabed98420f0bdd2895d47e11829e3bb76d9.tar.gz gcc-d469eabed98420f0bdd2895d47e11829e3bb76d9.tar.bz2 |
sem_ch4.adb (Analyze_Selected_Component): Include the requeue statement to the list of contexts where a selected...
2007-12-06 Hristian Kirtchev <kirtchev@adacore.com>
Ed Schonberg <schonberg@adacore.com>
* sem_ch4.adb (Analyze_Selected_Component): Include the requeue
statement to the list of contexts where a selected component with a
concurrent tagged type prefix should yield a primitive operation.
(Find_Primitive_Operation): Handle case of class-wide types.
(Analyze_Overloaded_Selected_Component): If type of prefix is
class-wide, use visible components of base type.
(Resolve_Selected_Component): Ditto.
(Try_Primitive_Operation, Collect_Generic_Type_Ops): If the type is a
formal of a generic subprogram. find candidate interpretations by
scanning the list of generic formal declarations.:
(Process_Implicit_Dereference_Prefix): If the prefix has an incomplete
type from a limited_with_clause, and the full view is available, use it
for subsequent semantic checks.
(Check_Misspelled_Selector): Use Namet.Sp.Is_Bad_Spelling_Of function
(Find_Primitive_Operation): New function.
(Analyze_Overloaded_Selected_Component): insert explicit dereference
only once if several interpretations of the prefix yield an access type.
(Try_Object_Operation): Code and comment cleanup.
(Analyze_Selected_Component): Reorder local variables. Minot comment and
code reformatting. When the type of the prefix is tagged concurrent, a
correct interpretation might be available in the primitive and
class-wide operations of the type.
From-SVN: r130853
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/sem_ch4.adb | 588 |
1 files changed, 397 insertions, 191 deletions
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 818d576..1627072 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -34,6 +34,7 @@ with Itypes; use Itypes; with Lib; use Lib; with Lib.Xref; use Lib.Xref; with Namet; use Namet; +with Namet.Sp; use Namet.Sp; with Nlists; use Nlists; with Nmake; use Nmake; with Opt; use Opt; @@ -43,6 +44,7 @@ with Rident; use Rident; with Sem; use Sem; with Sem_Cat; use Sem_Cat; with Sem_Ch3; use Sem_Ch3; +with Sem_Ch6; use Sem_Ch6; with Sem_Ch8; use Sem_Ch8; with Sem_Disp; use Sem_Disp; with Sem_Dist; use Sem_Dist; @@ -55,8 +57,6 @@ with Sinfo; use Sinfo; with Snames; use Snames; with Tbuild; use Tbuild; -with GNAT.Spelling_Checker; use GNAT.Spelling_Checker; - package body Sem_Ch4 is ----------------------- @@ -184,6 +184,10 @@ package body Sem_Ch4 is -- interpretation of the other operand. N can be an operator node, or -- a function call whose name is an operator designator. + function Find_Primitive_Operation (N : Node_Id) return Boolean; + -- Find candidate interpretations for the name Obj.Proc when it appears + -- in a subprogram renaming declaration. + procedure Find_Unary_Types (R : Node_Id; Op_Id : Entity_Id; @@ -219,14 +223,18 @@ package body Sem_Ch4 is -- type is not directly visible. The routine uses this type to emit a more -- informative message. - procedure Process_Implicit_Dereference_Prefix + function Process_Implicit_Dereference_Prefix (E : Entity_Id; - P : Node_Id); + P : Node_Id) return Entity_Id; -- Called when P is the prefix of an implicit dereference, denoting an - -- object E. If in semantics only mode (-gnatc or generic), record that is - -- a reference to E. Normally, such a reference is generated only when the - -- implicit dereference is expanded into an explicit one. E may be empty, - -- in which case this procedure does nothing. + -- object E. The function returns the designated type of the prefix, taking + -- into account that the designated type of an anonymous access type may be + -- a limited view, when the non-limited view is visible. + -- If in semantics only mode (-gnatc or generic), the function also records + -- that the prefix is a reference to E, if any. Normally, such a reference + -- is generated only when the implicit dereference is expanded into an + -- explicit one, but for consistency we must generate the reference when + -- expansion is disabled as well. procedure Remove_Abstract_Operations (N : Node_Id); -- Ada 2005: implementation of AI-310. An abstract non-dispatching @@ -303,9 +311,7 @@ package body Sem_Ch4 is if Nkind (N) in N_Membership_Test then Error_Msg_N ("ambiguous operands for membership", N); - elsif Nkind (N) = N_Op_Eq - or else Nkind (N) = N_Op_Ne - then + elsif Nkind_In (N, N_Op_Eq, N_Op_Ne) then Error_Msg_N ("ambiguous operands for equality", N); else @@ -349,7 +355,6 @@ package body Sem_Ch4 is Check_Restriction (No_Allocators, N); if Nkind (E) = N_Qualified_Expression then - Acc_Type := Create_Itype (E_Allocator_Type, N); Set_Etype (Acc_Type, Acc_Type); Init_Size_Align (Acc_Type); @@ -461,8 +466,8 @@ package body Sem_Ch4 is Subtype_Indication => Relocate_Node (E))); if Sav_Errs /= Serious_Errors_Detected - and then Nkind (Constraint (E)) - = N_Index_Or_Discriminant_Constraint + and then Nkind (Constraint (E)) = + N_Index_Or_Discriminant_Constraint then Error_Msg_N ("if qualified expression was meant, " & @@ -599,21 +604,18 @@ package body Sem_Ch4 is Analyze_Expression (L); Analyze_Expression (R); - -- If the entity is already set, the node is the instantiation of - -- a generic node with a non-local reference, or was manufactured - -- by a call to Make_Op_xxx. In either case the entity is known to - -- be valid, and we do not need to collect interpretations, instead - -- we just get the single possible interpretation. + -- If the entity is already set, the node is the instantiation of a + -- generic node with a non-local reference, or was manufactured by a + -- call to Make_Op_xxx. In either case the entity is known to be valid, + -- and we do not need to collect interpretations, instead we just get + -- the single possible interpretation. Op_Id := Entity (N); if Present (Op_Id) then if Ekind (Op_Id) = E_Operator then - if (Nkind (N) = N_Op_Divide or else - Nkind (N) = N_Op_Mod or else - Nkind (N) = N_Op_Multiply or else - Nkind (N) = N_Op_Rem) + if Nkind_In (N, N_Op_Divide, N_Op_Mod, N_Op_Multiply, N_Op_Rem) and then Treat_Fixed_As_Integer (N) then null; @@ -753,7 +755,6 @@ package body Sem_Ch4 is -- kinds of call into this form. elsif Nkind (Nam) = N_Indexed_Component then - if Nkind (Prefix (Nam)) = N_Selected_Component then Nam_Ent := Entity (Selector_Name (Prefix (Nam))); else @@ -794,8 +795,8 @@ package body Sem_Ch4 is -- Check for tasking cases where only an entry call will do elsif not L - and then (K = N_Entry_Call_Alternative - or else K = N_Triggering_Alternative) + and then Nkind_In (K, N_Entry_Call_Alternative, + N_Triggering_Alternative) then Error_Msg_N ("entry name expected", Nam); @@ -818,7 +819,7 @@ package body Sem_Ch4 is -- the return type of the access_to_subprogram. if Success - and then Nkind (Nam) = N_Explicit_Dereference + and then Nkind (Nam) = N_Explicit_Dereference and then Ekind (Etype (N)) = E_Incomplete_Type and then Present (Full_View (Etype (N))) then @@ -871,8 +872,8 @@ package body Sem_Ch4 is if Success then Set_Etype (Nam, It.Typ); - elsif Nkind (Name (N)) = N_Selected_Component - or else Nkind (Name (N)) = N_Function_Call + elsif Nkind_In (Name (N), N_Selected_Component, + N_Function_Call) then Remove_Interp (X); end if; @@ -971,9 +972,9 @@ package body Sem_Ch4 is if Ada_Version >= Ada_05 and then not Debug_Flag_Dot_L and then Is_Inherently_Limited_Type (Etype (N)) - and then (Nkind (Parent (N)) = N_Selected_Component - or else Nkind (Parent (N)) = N_Indexed_Component - or else Nkind (Parent (N)) = N_Slice + and then (Nkind_In (Parent (N), N_Selected_Component, + N_Indexed_Component, + N_Slice) or else (Nkind (Parent (N)) = N_Attribute_Reference and then Attribute_Name (Parent (N)) /= Name_Class)) @@ -1550,9 +1551,8 @@ package body Sem_Ch4 is -- account a possible implicit dereference. if Is_Access_Type (Array_Type) then - Array_Type := Designated_Type (Array_Type); Error_Msg_NW (Warn_On_Dereference, "?implicit dereference", N); - Process_Implicit_Dereference_Prefix (Pent, P); + Array_Type := Process_Implicit_Dereference_Prefix (Pent, P); end if; if Is_Array_Type (Array_Type) then @@ -1739,9 +1739,9 @@ package body Sem_Ch4 is -- Get name of array, function or type Analyze (P); - if Nkind (N) = N_Function_Call - or else Nkind (N) = N_Procedure_Call_Statement - then + + if Nkind_In (N, N_Function_Call, N_Procedure_Call_Statement) then + -- If P is an explicit dereference whose prefix is of a -- remote access-to-subprogram type, then N has already -- been rewritten as a subprogram call and analyzed. @@ -2025,8 +2025,9 @@ package body Sem_Ch4 is Success : out Boolean; Skip_First : Boolean := False) is - Actuals : constant List_Id := Parameter_Associations (N); - Prev_T : constant Entity_Id := Etype (N); + Actuals : constant List_Id := Parameter_Associations (N); + Prev_T : constant Entity_Id := Etype (N); + Must_Skip : constant Boolean := Skip_First or else Nkind (Original_Node (N)) = N_Selected_Component or else @@ -2496,6 +2497,14 @@ package body Sem_Ch4 is end if; if Is_Record_Type (T) then + + -- If the prefix is a class-wide type, the visible components are + -- those of the base type. + + if Is_Class_Wide_Type (T) then + T := Etype (T); + end if; + Comp := First_Entity (T); while Present (Comp) loop if Chars (Comp) = Chars (Sel) @@ -2532,9 +2541,12 @@ package body Sem_Ch4 is Set_Etype (Nam, It.Typ); -- For access type case, introduce explicit deference for - -- more uniform treatment of entry calls. + -- more uniform treatment of entry calls. Do this only + -- once if several interpretations yield an access type. - if Is_Access_Type (Etype (Nam)) then + if Is_Access_Type (Etype (Nam)) + and then Nkind (Nam) /= N_Explicit_Dereference + then Insert_Explicit_Dereference (Nam); Error_Msg_NW (Warn_On_Dereference, "?implicit dereference", N); @@ -2754,20 +2766,64 @@ package body Sem_Ch4 is -- later case, the selector must denote a visible entry. procedure Analyze_Selected_Component (N : Node_Id) is - Name : constant Node_Id := Prefix (N); - Sel : constant Node_Id := Selector_Name (N); - Comp : Entity_Id; - Prefix_Type : Entity_Id; + Name : constant Node_Id := Prefix (N); + Sel : constant Node_Id := Selector_Name (N); + Act_Decl : Node_Id; + Comp : Entity_Id; + Has_Candidate : Boolean := False; + In_Scope : Boolean; + Parent_N : Node_Id; + Pent : Entity_Id := Empty; + Prefix_Type : Entity_Id; Type_To_Use : Entity_Id; -- In most cases this is the Prefix_Type, but if the Prefix_Type is -- a class-wide type, we use its root type, whose components are -- present in the class-wide type. - Pent : Entity_Id := Empty; - Act_Decl : Node_Id; - In_Scope : Boolean; - Parent_N : Node_Id; + function Has_Mode_Conformant_Spec (Comp : Entity_Id) return Boolean; + -- It is known that the parent of N denotes a subprogram call. Comp + -- is an overloadable component of the concurrent type of the prefix. + -- Determine whether all formals of the parent of N and Comp are mode + -- conformant. + + ------------------------------ + -- Has_Mode_Conformant_Spec -- + ------------------------------ + + function Has_Mode_Conformant_Spec (Comp : Entity_Id) return Boolean is + Comp_Param : Entity_Id; + Param : Node_Id; + Param_Typ : Entity_Id; + + begin + Comp_Param := First_Formal (Comp); + Param := First (Parameter_Associations (Parent (N))); + while Present (Comp_Param) + and then Present (Param) + loop + Param_Typ := Find_Parameter_Type (Param); + + if Present (Param_Typ) + and then + not Conforming_Types + (Etype (Comp_Param), Param_Typ, Mode_Conformant) + then + return False; + end if; + + Next_Formal (Comp_Param); + Next (Param); + end loop; + + -- One of the specs has additional formals + + if Present (Comp_Param) or else Present (Param) then + return False; + end if; + + return True; + end Has_Mode_Conformant_Spec; -- Start of processing for Analyze_Selected_Component @@ -2814,11 +2870,8 @@ package body Sem_Ch4 is Pent := Entity (Selector_Name (Name)); end if; - Process_Implicit_Dereference_Prefix (Pent, Name); + Prefix_Type := Process_Implicit_Dereference_Prefix (Pent, Name); end if; - - Prefix_Type := Designated_Type (Prefix_Type); - end if; -- (Ada 2005): if the prefix is the limited view of a type, and @@ -2966,7 +3019,7 @@ package body Sem_Ch4 is if not Is_Packed (Etype (Comp)) and then ((Nkind (Parent_N) = N_Indexed_Component - and then Nkind (Name) /= N_Selected_Component) + and then Nkind (Name) /= N_Selected_Component) or else (Nkind (Parent_N) = N_Attribute_Reference and then (Attribute_Name (Parent_N) = Name_First @@ -3037,13 +3090,29 @@ package body Sem_Ch4 is Next_Entity (Comp); end loop; - -- Ada 2005 (AI-252) + -- Ada 2005 (AI-252): The selected component can be interpreted as + -- a prefixed view of a subprogram. Depending on the context, this is + -- either a name that can appear in a renaming declaration, or part + -- of an enclosing call given in prefix form. + + -- Ada 2005 (AI05-0030): In the case of dispatching requeue, the + -- selected component should resolve to a name. if Ada_Version >= Ada_05 and then Is_Tagged_Type (Prefix_Type) - and then Try_Object_Operation (N) + and then not Is_Concurrent_Type (Prefix_Type) then - return; + if Nkind (Parent (N)) = N_Generic_Association + or else Nkind (Parent (N)) = N_Requeue_Statement + or else Nkind (Parent (N)) = N_Subprogram_Renaming_Declaration + then + if Find_Primitive_Operation (N) then + return; + end if; + + elsif Try_Object_Operation (N) then + return; + end if; -- If the transformation fails, it will be necessary to redo the -- analysis with all errors enabled, to indicate candidate @@ -3052,6 +3121,7 @@ package body Sem_Ch4 is end if; elsif Is_Private_Type (Prefix_Type) then + -- Allow access only to discriminants of the type. If the type has -- no full view, gigi uses the parent type for the components, so we -- do the same here. @@ -3071,8 +3141,7 @@ package body Sem_Ch4 is Set_Etype (N, Etype (Comp)); if Is_Generic_Type (Prefix_Type) - or else - Is_Generic_Type (Root_Type (Prefix_Type)) + or else Is_Generic_Type (Root_Type (Prefix_Type)) then Set_Original_Discriminant (Sel, Comp); end if; @@ -3102,14 +3171,15 @@ package body Sem_Ch4 is elsif Is_Concurrent_Type (Prefix_Type) then - -- Prefix is concurrent type. Find visible operation with given name - -- For a task, this can only include entries or discriminants if the - -- task type is not an enclosing scope. If it is an enclosing scope - -- (e.g. in an inner task) then all entities are visible, but the - -- prefix must denote the enclosing scope, i.e. can only be a direct - -- name or an expanded name. + -- Find visible operation with given name. For a protected type, + -- the possible candidates are discriminants, entries or protected + -- procedures. For a task type, the set can only include entries or + -- discriminants if the task type is not an enclosing scope. If it + -- is an enclosing scope (e.g. in an inner task) then all entities + -- are visible, but the prefix must denote the enclosing scope, i.e. + -- can only be a direct name or an expanded name. - Set_Etype (Sel, Any_Type); + Set_Etype (Sel, Any_Type); In_Scope := In_Open_Scopes (Prefix_Type); while Present (Comp) loop @@ -3117,6 +3187,21 @@ package body Sem_Ch4 is if Is_Overloadable (Comp) then Add_One_Interp (Sel, Comp, Etype (Comp)); + -- If the prefix is tagged, the correct interpretation may + -- lie in the primitive or class-wide operations of the + -- type. Perform a simple conformance check to determine + -- whether Try_Object_Operation should be invoked even if + -- a visible entity is found. + + if Is_Tagged_Type (Prefix_Type) + and then + Nkind_In (Parent (N), N_Procedure_Call_Statement, + N_Function_Call) + and then Has_Mode_Conformant_Spec (Comp) + then + Has_Candidate := True; + end if; + elsif Ekind (Comp) = E_Discriminant or else Ekind (Comp) = E_Entry_Family or else (In_Scope @@ -3153,14 +3238,15 @@ package body Sem_Ch4 is Comp = First_Private_Entity (Base_Type (Prefix_Type)); end loop; - -- If there is no visible entry with the given name, and the task - -- implements an interface, check whether there is some other - -- primitive operation with that name. + -- If there is no visible entity with the given name or none of the + -- visible entities are plausible interpretations, check whether + -- there is some other primitive operation with that name. if Ada_Version >= Ada_05 and then Is_Tagged_Type (Prefix_Type) then - if Etype (N) = Any_Type + if (Etype (N) = Any_Type + or else not Has_Candidate) and then Try_Object_Operation (N) then return; @@ -3313,7 +3399,6 @@ package body Sem_Ch4 is Set_Etype (N, Any_Type); if not Is_Overloaded (L) then - if Root_Type (Etype (L)) = Standard_Boolean and then Has_Compatible_Type (R, Etype (L)) then @@ -3333,13 +3418,12 @@ package body Sem_Ch4 is end loop; end if; - -- Here we have failed to find an interpretation. Clearly we - -- know that it is not the case that both operands can have - -- an interpretation of Boolean, but this is by far the most - -- likely intended interpretation. So we simply resolve both - -- operands as Booleans, and at least one of these resolutions - -- will generate an error message, and we do not need to give - -- a further error message on the short circuit operation itself. + -- Here we have failed to find an interpretation. Clearly we know that + -- it is not the case that both operands can have an interpretation of + -- Boolean, but this is by far the most likely intended interpretation. + -- So we simply resolve both operands as Booleans, and at least one of + -- these resolutions will generate an error message, and we do not need + -- to give another error message on the short circuit operation itself. if Etype (N) = Any_Type then Resolve (L, Standard_Boolean); @@ -3884,44 +3968,34 @@ package body Sem_Ch4 is return; end if; - Get_Name_String (Chars (Sel)); - - declare - S : constant String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len); - - begin - Comp := First_Entity (Prefix); - while Nr_Of_Suggestions <= Max_Suggestions - and then Present (Comp) - loop - if Is_Visible_Component (Comp) then - Get_Name_String (Chars (Comp)); - - if Is_Bad_Spelling_Of (Name_Buffer (1 .. Name_Len), S) then - Nr_Of_Suggestions := Nr_Of_Suggestions + 1; - - case Nr_Of_Suggestions is - when 1 => Suggestion_1 := Comp; - when 2 => Suggestion_2 := Comp; - when others => exit; - end case; - end if; + Comp := First_Entity (Prefix); + while Nr_Of_Suggestions <= Max_Suggestions and then Present (Comp) loop + if Is_Visible_Component (Comp) then + if Is_Bad_Spelling_Of (Chars (Comp), Chars (Sel)) then + Nr_Of_Suggestions := Nr_Of_Suggestions + 1; + + case Nr_Of_Suggestions is + when 1 => Suggestion_1 := Comp; + when 2 => Suggestion_2 := Comp; + when others => exit; + end case; end if; + end if; - Comp := Next_Entity (Comp); - end loop; + Comp := Next_Entity (Comp); + end loop; - -- Report at most two suggestions + -- Report at most two suggestions - if Nr_Of_Suggestions = 1 then - Error_Msg_NE ("\possible misspelling of&", Sel, Suggestion_1); + if Nr_Of_Suggestions = 1 then + Error_Msg_NE + ("\possible misspelling of&", Sel, Suggestion_1); - elsif Nr_Of_Suggestions = 2 then - Error_Msg_Node_2 := Suggestion_2; - Error_Msg_NE ("\possible misspelling of& or&", - Sel, Suggestion_1); - end if; - end; + elsif Nr_Of_Suggestions = 2 then + Error_Msg_Node_2 := Suggestion_2; + Error_Msg_NE + ("\possible misspelling of& or&", Sel, Suggestion_1); + end if; end Check_Misspelled_Selector; ---------------------- @@ -4548,6 +4622,81 @@ package body Sem_Ch4 is end if; end Find_Negation_Types; + ------------------------------ + -- Find_Primitive_Operation -- + ------------------------------ + + function Find_Primitive_Operation (N : Node_Id) return Boolean is + Obj : constant Node_Id := Prefix (N); + Op : constant Node_Id := Selector_Name (N); + + Prim : Elmt_Id; + Prims : Elist_Id; + Typ : Entity_Id; + + begin + Set_Etype (Op, Any_Type); + + if Is_Access_Type (Etype (Obj)) then + Typ := Designated_Type (Etype (Obj)); + else + Typ := Etype (Obj); + end if; + + if Is_Class_Wide_Type (Typ) then + Typ := Root_Type (Typ); + end if; + + Prims := Primitive_Operations (Typ); + + Prim := First_Elmt (Prims); + while Present (Prim) loop + if Chars (Node (Prim)) = Chars (Op) then + Add_One_Interp (Op, Node (Prim), Etype (Node (Prim))); + Set_Etype (N, Etype (Node (Prim))); + end if; + + Next_Elmt (Prim); + end loop; + + -- Now look for class-wide operations of the type or any of its + -- ancestors by iterating over the homonyms of the selector. + + declare + Cls_Type : constant Entity_Id := Class_Wide_Type (Typ); + Hom : Entity_Id; + + begin + Hom := Current_Entity (Op); + while Present (Hom) loop + if (Ekind (Hom) = E_Procedure + or else + Ekind (Hom) = E_Function) + and then Scope (Hom) = Scope (Typ) + and then Present (First_Formal (Hom)) + and then + (Base_Type (Etype (First_Formal (Hom))) = Cls_Type + or else + (Is_Access_Type (Etype (First_Formal (Hom))) + and then + Ekind (Etype (First_Formal (Hom))) = + E_Anonymous_Access_Type + and then + Base_Type + (Designated_Type (Etype (First_Formal (Hom)))) = + Cls_Type)) + then + Add_One_Interp (Op, Hom, Etype (Hom)); + Set_Etype (N, Etype (Hom)); + end if; + + Hom := Homonym (Hom); + end loop; + end; + + return Etype (Op) /= Any_Type; + end Find_Primitive_Operation; + ---------------------- -- Find_Unary_Types -- ---------------------- @@ -4744,12 +4893,7 @@ package body Sem_Ch4 is -- pretty much know that the other operand should be Boolean, so -- resolve it that way (generating an error) - elsif Nkind (N) = N_Op_And - or else - Nkind (N) = N_Op_Or - or else - Nkind (N) = N_Op_Xor - then + elsif Nkind_In (N, N_Op_And, N_Op_Or, N_Op_Xor) then if Etype (L) = Standard_Boolean then Resolve (R, Standard_Boolean); return; @@ -4763,16 +4907,17 @@ package body Sem_Ch4 is -- is not the same numeric type. If it is a non-numeric type, -- then probably it is intended to match the other operand. - elsif Nkind (N) = N_Op_Add or else - Nkind (N) = N_Op_Divide or else - Nkind (N) = N_Op_Ge or else - Nkind (N) = N_Op_Gt or else - Nkind (N) = N_Op_Le or else - Nkind (N) = N_Op_Lt or else - Nkind (N) = N_Op_Mod or else - Nkind (N) = N_Op_Multiply or else - Nkind (N) = N_Op_Rem or else - Nkind (N) = N_Op_Subtract + elsif Nkind_In (N, N_Op_Add, + N_Op_Divide, + N_Op_Ge, + N_Op_Gt, + N_Op_Le) + or else + Nkind_In (N, N_Op_Lt, + N_Op_Mod, + N_Op_Multiply, + N_Op_Rem, + N_Op_Subtract) then if Is_Numeric_Type (Etype (L)) and then not Is_Numeric_Type (Etype (R)) @@ -4790,8 +4935,7 @@ package body Sem_Ch4 is -- Comparisons on A'Access are common enough to deserve a -- special message. - elsif (Nkind (N) = N_Op_Eq or else - Nkind (N) = N_Op_Ne) + elsif Nkind_In (N, N_Op_Eq, N_Op_Ne) and then Ekind (Etype (L)) = E_Access_Attribute_Type and then Ekind (Etype (R)) = E_Access_Attribute_Type then @@ -4903,11 +5047,12 @@ package body Sem_Ch4 is -- Process_Implicit_Dereference_Prefix -- ----------------------------------------- - procedure Process_Implicit_Dereference_Prefix + function Process_Implicit_Dereference_Prefix (E : Entity_Id; - P : Entity_Id) + P : Entity_Id) return Entity_Id is Ref : Node_Id; + Typ : constant Entity_Id := Designated_Type (Etype (P)); begin if Present (E) @@ -4922,6 +5067,24 @@ package body Sem_Ch4 is Set_Comes_From_Source (Ref, Comes_From_Source (P)); Generate_Reference (E, Ref); end if; + + -- An implicit dereference is a legal occurrence of an + -- incomplete type imported through a limited_with clause, + -- if the full view is visible. + + if From_With_Type (Typ) + and then not From_With_Type (Scope (Typ)) + and then + (Is_Immediately_Visible (Scope (Typ)) + or else + (Is_Child_Unit (Scope (Typ)) + and then Is_Visible_Child_Unit (Scope (Typ)))) + then + return Available_View (Typ); + else + return Typ; + end if; + end Process_Implicit_Dereference_Prefix; -------------------------------- @@ -5290,26 +5453,26 @@ package body Sem_Ch4 is function Try_Object_Operation (N : Node_Id) return Boolean is K : constant Node_Kind := Nkind (Parent (N)); + Is_Subprg_Call : constant Boolean := Nkind_In + (K, N_Procedure_Call_Statement, + N_Function_Call); Loc : constant Source_Ptr := Sloc (N); - Candidate : Entity_Id := Empty; - Is_Subprg_Call : constant Boolean := K = N_Procedure_Call_Statement - or else K = N_Function_Call; Obj : constant Node_Id := Prefix (N); Subprog : constant Node_Id := Make_Identifier (Sloc (Selector_Name (N)), Chars => Chars (Selector_Name (N))); -- Identifier on which possible interpretations will be collected - Success : Boolean := False; - Report_Error : Boolean := False; -- If no candidate interpretation matches the context, redo the -- analysis with error enabled to provide additional information. Actual : Node_Id; + Candidate : Entity_Id := Empty; New_Call_Node : Node_Id := Empty; Node_To_Replace : Node_Id; Obj_Type : Entity_Id := Etype (Obj); + Success : Boolean := False; function Valid_Candidate (Success : Boolean; @@ -5333,9 +5496,9 @@ package body Sem_Ch4 is (Call_Node : out Node_Id; Node_To_Replace : out Node_Id); -- Transform Obj.Operation (X, Y,,) into Operation (Obj, X, Y ..) - -- Call_Node is the resulting subprogram call, - -- Node_To_Replace is either N or the parent of N, and Subprog - -- is a reference to the subprogram we are trying to match. + -- Call_Node is the resulting subprogram call, Node_To_Replace is + -- either N or the parent of N, and Subprog is a reference to the + -- subprogram we are trying to match. function Try_Class_Wide_Operation (Call_Node : Node_Id; @@ -5376,14 +5539,14 @@ package body Sem_Ch4 is end if; end if; - -- If the call may be an indexed call, retrieve component type - -- of resulting expression, and add possible interpretation. + -- If the call may be an indexed call, retrieve component type of + -- resulting expression, and add possible interpretation. Comp_Type := Empty; if Nkind (Call) = N_Function_Call - and then Nkind (Parent (N)) = N_Indexed_Component - and then Needs_One_Actual (Subp) + and then Nkind (Parent (N)) = N_Indexed_Component + and then Needs_One_Actual (Subp) then if Is_Array_Type (Etype (Subp)) then Comp_Type := Component_Type (Etype (Subp)); @@ -5396,7 +5559,7 @@ package body Sem_Ch4 is end if; if Present (Comp_Type) - and then Etype (Subprog) /= Comp_Type + and then Etype (Subprog) /= Comp_Type then Add_One_Interp (Subprog, Subp, Comp_Type); end if; @@ -5472,9 +5635,9 @@ package body Sem_Ch4 is ("expect variable in call to&", Prefix (N), Entity (Subprog)); end if; - -- Conversely, if the formal is an access parameter and the - -- object is not, replace the actual with a 'Access reference. - -- Its analysis will check that the object is aliased. + -- Conversely, if the formal is an access parameter and the object + -- is not, replace the actual with a 'Access reference. Its analysis + -- will check that the object is aliased. elsif Is_Access_Type (Formal_Type) and then not Is_Access_Type (Etype (Obj)) @@ -5563,22 +5726,21 @@ package body Sem_Ch4 is (Call_Node : out Node_Id; Node_To_Replace : out Node_Id) is - Parent_Node : constant Node_Id := Parent (N); - Dummy : constant Node_Id := New_Copy (Obj); -- Placeholder used as a first parameter in the call, replaced -- eventually by the proper object. - Actuals : List_Id; + Parent_Node : constant Node_Id := Parent (N); + Actual : Node_Id; + Actuals : List_Id; begin -- Common case covering 1) Call to a procedure and 2) Call to a -- function that has some additional actuals. - if (Nkind (Parent_Node) = N_Function_Call - or else - Nkind (Parent_Node) = N_Procedure_Call_Statement) + if Nkind_In (Parent_Node, N_Function_Call, + N_Procedure_Call_Statement) -- N is a selected component node containing the name of the -- subprogram. If N is not the name of the parent node we must @@ -5614,7 +5776,7 @@ package body Sem_Ch4 is end if; - -- Before analysis, the function call appears as an indexed component + -- Before analysis, a function call appears as an indexed component -- if there are no named associations. elsif Nkind (Parent_Node) = N_Indexed_Component @@ -5637,7 +5799,7 @@ package body Sem_Ch4 is Name => New_Copy (Subprog), Parameter_Associations => Actuals); - -- Parameterless call: Obj.F is rewritten as F (Obj) + -- Parameterless call: Obj.F is rewritten as F (Obj) else Node_To_Replace := N; @@ -5666,8 +5828,8 @@ package body Sem_Ch4 is Error : out Boolean); -- Traverse the homonym chain of the subprogram searching for those -- homonyms whose first formal has the Anc_Type's class-wide type, - -- or an anonymous access type designating the class-wide type. If an - -- ambiguity is detected, then Error is set to True. + -- or an anonymous access type designating the class-wide type. If + -- an ambiguity is detected, then Error is set to True. procedure Traverse_Interfaces (Anc_Type : Entity_Id; @@ -5770,9 +5932,9 @@ package body Sem_Ch4 is (Anc_Type : Entity_Id; Error : out Boolean) is - Intface : Node_Id; Intface_List : constant List_Id := Abstract_Interface_List (Anc_Type); + Intface : Node_Id; begin Error := False; @@ -5807,10 +5969,10 @@ package body Sem_Ch4 is -- Start of processing for Try_Class_Wide_Operation begin - -- Loop through ancestor types (including interfaces), traversing the - -- homonym chain of the subprogram, and trying out those homonyms - -- whose first formal has the class-wide type of the ancestor, or an - -- anonymous access type designating the class-wide type. + -- Loop through ancestor types (including interfaces), traversing + -- the homonym chain of the subprogram, trying out those homonyms + -- whose first formal has the class-wide type of the ancestor, or + -- an anonymous access type designating the class-wide type. Anc_Type := Obj_Type; loop @@ -5921,6 +6083,10 @@ package body Sem_Ch4 is -- part) because the type itself carries no primitive operations, -- except for formal derived types that inherit the operations of -- the parent and progenitors. + -- If the context is a generic subprogram body, the generic formals + -- are visible by name, but are not in the entity list of the + -- subprogram because that list starts with the subprogram formals. + -- We retrieve the candidate operations from the generic declaration. function Valid_First_Argument_Of (Op : Entity_Id) return Boolean; -- Verify that the prefix, dereferenced if need be, is a valid @@ -5937,10 +6103,61 @@ package body Sem_Ch4 is Subp : Entity_Id; Formal : Entity_Id; + procedure Check_Candidate; + -- The operation is a candidate if its first parameter is a + -- controlling operand of the desired type. + + ----------------------- + -- Check_Candidate; -- + ----------------------- + + procedure Check_Candidate is + begin + Formal := First_Formal (Subp); + + if Present (Formal) + and then Is_Controlling_Formal (Formal) + and then + (Base_Type (Etype (Formal)) = Bas + or else + (Is_Access_Type (Etype (Formal)) + and then Designated_Type (Etype (Formal)) = Bas)) + then + Append_Elmt (Subp, Candidates); + end if; + end Check_Candidate; + + -- Start of processing for Collect_Generic_Type_Ops + begin if Is_Derived_Type (T) then return Primitive_Operations (T); + elsif Ekind (Scope (T)) = E_Procedure + or else Ekind (Scope (T)) = E_Function + then + -- Scan the list of generic formals to find subprograms + -- that may have a first controlling formal of the type. + + declare + Decl : Node_Id; + + begin + Decl := + First (Generic_Formal_Declarations + (Unit_Declaration_Node (Scope (T)))); + while Present (Decl) loop + if Nkind (Decl) in N_Formal_Subprogram_Declaration then + Subp := Defining_Entity (Decl); + Check_Candidate; + end if; + + Next (Decl); + end loop; + end; + + return Candidates; + else -- Scan the list of entities declared in the same scope as -- the type. In general this will be an open scope, given that @@ -5951,18 +6168,7 @@ package body Sem_Ch4 is Subp := First_Entity (Scope (T)); while Present (Subp) loop if Is_Overloadable (Subp) then - Formal := First_Formal (Subp); - - if Present (Formal) - and then Is_Controlling_Formal (Formal) - and then - (Base_Type (Etype (Formal)) = Bas - or else - (Is_Access_Type (Etype (Formal)) - and then Designated_Type (Etype (Formal)) = Bas)) - then - Append_Elmt (Subp, Candidates); - end if; + Check_Candidate; end if; Next_Entity (Subp); @@ -5980,12 +6186,11 @@ package body Sem_Ch4 is Typ : constant Entity_Id := Etype (First_Formal (Op)); begin - -- Simple case. Object may be a subtype of the tagged type - -- or may be the corresponding record of a synchronized type. + -- Simple case. Object may be a subtype of the tagged type or + -- may be the corresponding record of a synchronized type. return Obj_Type = Typ - or else Base_Type (Obj_Type) = Typ - + or else Base_Type (Obj_Type) = Typ or else Corr_Type = Typ -- Prefix can be dereferenced @@ -6005,11 +6210,11 @@ package body Sem_Ch4 is -- Start of processing for Try_Primitive_Operation begin - -- Look for subprograms in the list of primitive operations The name + -- Look for subprograms in the list of primitive operations. The name -- must be identical, and the kind of call indicates the expected -- kind of operation (function or procedure). If the type is a - -- (tagged) synchronized type, the primitive ops are attached to - -- the corresponding record type. + -- (tagged) synchronized type, the primitive ops are attached to the + -- corresponding record type. if Is_Concurrent_Type (Obj_Type) then Corr_Type := Corresponding_Record_Type (Obj_Type); @@ -6045,9 +6250,9 @@ package body Sem_Ch4 is (Alias (Prim_Op)), Corr_Type)) or else - -- Do not consider hidden primitives unless the type is - -- in an open scope or we are within an instance, where - -- visibility is known to be correct. + -- Do not consider hidden primitives unless the type is in an + -- open scope or we are within an instance, where visibility + -- is known to be correct. (Is_Hidden (Prim_Op) and then not Is_Immediately_Visible (Obj_Type) @@ -6077,12 +6282,11 @@ package body Sem_Ch4 is Matching_Op := Valid_Candidate (Success, Call_Node, Prim_Op); - else - - -- More than one interpretation, collect for subsequent - -- disambiguation. If this is a procedure call and there - -- is another match, report ambiguity now. + -- More than one interpretation, collect for subsequent + -- disambiguation. If this is a procedure call and there + -- is another match, report ambiguity now. + else Analyze_One_Call (N => Call_Node, Nam => Prim_Op, @@ -6165,7 +6369,7 @@ package body Sem_Ch4 is -- The argument list is not type correct. Re-analyze with error -- reporting enabled, and use one of the possible candidates. - -- In all_errors mode, re-analyze all failed interpretations. + -- In All_Errors_Mode, re-analyze all failed interpretations. if All_Errors_Mode then Report_Error := True; @@ -6190,7 +6394,9 @@ package body Sem_Ch4 is Skip_First => True); end if; - return True; -- No need for further errors. + -- No need for further errors + + return True; else -- There was no candidate operation, so report it as an error |