+++ /dev/null
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S E M _ T Y P E --
--- --
--- B o d y --
--- --
--- $Revision: 1.3.10.1 $
--- --
--- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 2, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
--- for more details. You should have received a copy of the GNU General --
--- Public License distributed with GNAT; see file COPYING. If not, write --
--- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
--- MA 02111-1307, USA. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-with Atree; use Atree;
-with Debug; use Debug;
-with Einfo; use Einfo;
-with Errout; use Errout;
-with Lib; use Lib;
-with Opt; use Opt;
-with Output; use Output;
-with Sem; use Sem;
-with Sem_Ch6; use Sem_Ch6;
-with Sem_Ch8; use Sem_Ch8;
-with Sem_Util; use Sem_Util;
-with Stand; use Stand;
-with Sinfo; use Sinfo;
-with Snames; use Snames;
-with Uintp; use Uintp;
-
-package body Sem_Type is
-
- -------------------------------------
- -- Handling of Overload Resolution --
- -------------------------------------
-
- -- Overload resolution uses two passes over the syntax tree of a complete
- -- context. In the first, bottom-up pass, the types of actuals in calls
- -- are used to resolve possibly overloaded subprogram and operator names.
- -- In the second top-down pass, the type of the context (for example the
- -- condition in a while statement) is used to resolve a possibly ambiguous
- -- call, and the unique subprogram name in turn imposes a specific context
- -- on each of its actuals.
-
- -- Most expressions are in fact unambiguous, and the bottom-up pass is
- -- sufficient to resolve most everything. To simplify the common case,
- -- names and expressions carry a flag Is_Overloaded to indicate whether
- -- they have more than one interpretation. If the flag is off, then each
- -- name has already a unique meaning and type, and the bottom-up pass is
- -- sufficient (and much simpler).
-
- --------------------------
- -- Operator Overloading --
- --------------------------
-
- -- The visibility of operators is handled differently from that of
- -- other entities. We do not introduce explicit versions of primitive
- -- operators for each type definition. As a result, there is only one
- -- entity corresponding to predefined addition on all numeric types, etc.
- -- The back-end resolves predefined operators according to their type.
- -- The visibility of primitive operations then reduces to the visibility
- -- of the resulting type: (a + b) is a legal interpretation of some
- -- primitive operator + if the type of the result (which must also be
- -- the type of a and b) is directly visible (i.e. either immediately
- -- visible or use-visible.)
-
- -- User-defined operators are treated like other functions, but the
- -- visibility of these user-defined operations must be special-cased
- -- to determine whether they hide or are hidden by predefined operators.
- -- The form P."+" (x, y) requires additional handling.
- --
- -- Concatenation is treated more conventionally: for every one-dimensional
- -- array type we introduce a explicit concatenation operator. This is
- -- necessary to handle the case of (element & element => array) which
- -- cannot be handled conveniently if there is no explicit instance of
- -- resulting type of the operation.
-
- -----------------------
- -- Local Subprograms --
- -----------------------
-
- procedure All_Overloads;
- pragma Warnings (Off, All_Overloads);
- -- Debugging procedure: list full contents of Overloads table.
-
- function Universal_Interpretation (Opnd : Node_Id) return Entity_Id;
- -- Yields universal_Integer or Universal_Real if this is a candidate.
-
- function Specific_Type (T1, T2 : Entity_Id) return Entity_Id;
- -- If T1 and T2 are compatible, return the one that is not
- -- universal or is not a "class" type (any_character, etc).
-
- --------------------
- -- Add_One_Interp --
- --------------------
-
- procedure Add_One_Interp
- (N : Node_Id;
- E : Entity_Id;
- T : Entity_Id;
- Opnd_Type : Entity_Id := Empty)
- is
- Vis_Type : Entity_Id;
-
- procedure Add_Entry (Name : Entity_Id; Typ : Entity_Id);
- -- Add one interpretation to node. Node is already known to be
- -- overloaded. Add new interpretation if not hidden by previous
- -- one, and remove previous one if hidden by new one.
-
- function Is_Universal_Operation (Op : Entity_Id) return Boolean;
- -- True if the entity is a predefined operator and the operands have
- -- a universal Interpretation.
-
- ---------------
- -- Add_Entry --
- ---------------
-
- procedure Add_Entry (Name : Entity_Id; Typ : Entity_Id) is
- Index : Interp_Index;
- It : Interp;
-
- begin
- Get_First_Interp (N, Index, It);
-
- while Present (It.Nam) loop
-
- -- A user-defined subprogram hides another declared at an outer
- -- level, or one that is use-visible. So return if previous
- -- definition hides new one (which is either in an outer
- -- scope, or use-visible). Note that for functions use-visible
- -- is the same as potentially use-visible. If new one hides
- -- previous one, replace entry in table of interpretations.
- -- If this is a universal operation, retain the operator in case
- -- preference rule applies.
-
- if (((Ekind (Name) = E_Function or else Ekind (Name) = E_Procedure)
- and then Ekind (Name) = Ekind (It.Nam))
- or else (Ekind (Name) = E_Operator
- and then Ekind (It.Nam) = E_Function))
-
- and then Is_Immediately_Visible (It.Nam)
- and then Type_Conformant (Name, It.Nam)
- and then Base_Type (It.Typ) = Base_Type (T)
- then
- if Is_Universal_Operation (Name) then
- exit;
-
- -- If node is an operator symbol, we have no actuals with
- -- which to check hiding, and this is done in full in the
- -- caller (Analyze_Subprogram_Renaming) so we include the
- -- predefined operator in any case.
-
- elsif Nkind (N) = N_Operator_Symbol
- or else (Nkind (N) = N_Expanded_Name
- and then
- Nkind (Selector_Name (N)) = N_Operator_Symbol)
- then
- exit;
-
- elsif not In_Open_Scopes (Scope (Name))
- or else Scope_Depth (Scope (Name))
- <= Scope_Depth (Scope (It.Nam))
- then
- -- If ambiguity within instance, and entity is not an
- -- implicit operation, save for later disambiguation.
-
- if Scope (Name) = Scope (It.Nam)
- and then not Is_Inherited_Operation (Name)
- and then In_Instance
- then
- exit;
- else
- return;
- end if;
-
- else
- All_Interp.Table (Index).Nam := Name;
- return;
- end if;
-
- -- Avoid making duplicate entries in overloads
-
- elsif Name = It.Nam
- and then Base_Type (It.Typ) = Base_Type (T)
- then
- return;
-
- -- Otherwise keep going
-
- else
- Get_Next_Interp (Index, It);
- end if;
-
- end loop;
-
- -- On exit, enter new interpretation. The context, or a preference
- -- rule, will resolve the ambiguity on the second pass.
-
- All_Interp.Table (All_Interp.Last) := (Name, Typ);
- All_Interp.Increment_Last;
- All_Interp.Table (All_Interp.Last) := No_Interp;
-
- end Add_Entry;
-
- ----------------------------
- -- Is_Universal_Operation --
- ----------------------------
-
- function Is_Universal_Operation (Op : Entity_Id) return Boolean is
- Arg : Node_Id;
-
- begin
- if Ekind (Op) /= E_Operator then
- return False;
-
- elsif Nkind (N) in N_Binary_Op then
- return Present (Universal_Interpretation (Left_Opnd (N)))
- and then Present (Universal_Interpretation (Right_Opnd (N)));
-
- elsif Nkind (N) in N_Unary_Op then
- return Present (Universal_Interpretation (Right_Opnd (N)));
-
- elsif Nkind (N) = N_Function_Call then
- Arg := First_Actual (N);
-
- while Present (Arg) loop
-
- if No (Universal_Interpretation (Arg)) then
- return False;
- end if;
-
- Next_Actual (Arg);
- end loop;
-
- return True;
-
- else
- return False;
- end if;
- end Is_Universal_Operation;
-
- -- Start of processing for Add_One_Interp
-
- begin
- -- If the interpretation is a predefined operator, verify that the
- -- result type is visible, or that the entity has already been
- -- resolved (case of an instantiation node that refers to a predefined
- -- operation, or an internally generated operator node, or an operator
- -- given as an expanded name). If the operator is a comparison or
- -- equality, it is the type of the operand that matters to determine
- -- whether the operator is visible. In an instance, the check is not
- -- performed, given that the operator was visible in the generic.
-
- if Ekind (E) = E_Operator then
-
- if Present (Opnd_Type) then
- Vis_Type := Opnd_Type;
- else
- Vis_Type := Base_Type (T);
- end if;
-
- if In_Open_Scopes (Scope (Vis_Type))
- or else Is_Potentially_Use_Visible (Vis_Type)
- or else In_Use (Vis_Type)
- or else (In_Use (Scope (Vis_Type))
- and then not Is_Hidden (Vis_Type))
- or else Nkind (N) = N_Expanded_Name
- or else (Nkind (N) in N_Op and then E = Entity (N))
- or else In_Instance
- then
- null;
-
- -- If the node is given in functional notation and the prefix
- -- is an expanded name, then the operator is visible if the
- -- prefix is the scope of the result type as well. If the
- -- operator is (implicitly) defined in an extension of system,
- -- it is know to be valid (see Defined_In_Scope, sem_ch4.adb).
-
- elsif Nkind (N) = N_Function_Call
- and then Nkind (Name (N)) = N_Expanded_Name
- and then (Entity (Prefix (Name (N))) = Scope (Base_Type (T))
- or else Entity (Prefix (Name (N))) = Scope (Vis_Type)
- or else Scope (Vis_Type) = System_Aux_Id)
- then
- null;
-
- -- Save type for subsequent error message, in case no other
- -- interpretation is found.
-
- else
- Candidate_Type := Vis_Type;
- return;
- end if;
-
- -- In an instance, an abstract non-dispatching operation cannot
- -- be a candidate interpretation, because it could not have been
- -- one in the generic (it may be a spurious overloading in the
- -- instance).
-
- elsif In_Instance
- and then Is_Abstract (E)
- and then not Is_Dispatching_Operation (E)
- then
- return;
- end if;
-
- -- If this is the first interpretation of N, N has type Any_Type.
- -- In that case place the new type on the node. If one interpretation
- -- already exists, indicate that the node is overloaded, and store
- -- both the previous and the new interpretation in All_Interp. If
- -- this is a later interpretation, just add it to the set.
-
- if Etype (N) = Any_Type then
- if Is_Type (E) then
- Set_Etype (N, T);
-
- else
- -- Record both the operator or subprogram name, and its type.
-
- if Nkind (N) in N_Op or else Is_Entity_Name (N) then
- Set_Entity (N, E);
- end if;
-
- Set_Etype (N, T);
- end if;
-
- -- Either there is no current interpretation in the table for any
- -- node or the interpretation that is present is for a different
- -- node. In both cases add a new interpretation to the table.
-
- elsif Interp_Map.Last < 0
- or else Interp_Map.Table (Interp_Map.Last).Node /= N
- then
- New_Interps (N);
-
- if (Nkind (N) in N_Op or else Is_Entity_Name (N))
- and then Present (Entity (N))
- then
- Add_Entry (Entity (N), Etype (N));
-
- elsif (Nkind (N) = N_Function_Call
- or else Nkind (N) = N_Procedure_Call_Statement)
- and then (Nkind (Name (N)) = N_Operator_Symbol
- or else Is_Entity_Name (Name (N)))
- then
- Add_Entry (Entity (Name (N)), Etype (N));
-
- else
- -- Overloaded prefix in indexed or selected component,
- -- or call whose name is an expression or another call.
-
- Add_Entry (Etype (N), Etype (N));
- end if;
-
- Add_Entry (E, T);
-
- else
- Add_Entry (E, T);
- end if;
- end Add_One_Interp;
-
- -------------------
- -- All_Overloads --
- -------------------
-
- procedure All_Overloads is
- begin
- for J in All_Interp.First .. All_Interp.Last loop
-
- if Present (All_Interp.Table (J).Nam) then
- Write_Entity_Info (All_Interp.Table (J). Nam, " ");
- else
- Write_Str ("No Interp");
- end if;
-
- Write_Str ("=================");
- Write_Eol;
- end loop;
- end All_Overloads;
-
- ---------------------
- -- Collect_Interps --
- ---------------------
-
- procedure Collect_Interps (N : Node_Id) is
- Ent : constant Entity_Id := Entity (N);
- H : Entity_Id;
- First_Interp : Interp_Index;
-
- begin
- New_Interps (N);
-
- -- Unconditionally add the entity that was initially matched
-
- First_Interp := All_Interp.Last;
- Add_One_Interp (N, Ent, Etype (N));
-
- -- For expanded name, pick up all additional entities from the
- -- same scope, since these are obviously also visible. Note that
- -- these are not necessarily contiguous on the homonym chain.
-
- if Nkind (N) = N_Expanded_Name then
- H := Homonym (Ent);
- while Present (H) loop
- if Scope (H) = Scope (Entity (N)) then
- Add_One_Interp (N, H, Etype (H));
- end if;
-
- H := Homonym (H);
- end loop;
-
- -- Case of direct name
-
- else
- -- First, search the homonym chain for directly visible entities
-
- H := Current_Entity (Ent);
- while Present (H) loop
- exit when (not Is_Overloadable (H))
- and then Is_Immediately_Visible (H);
-
- if Is_Immediately_Visible (H)
- and then H /= Ent
- then
- -- Only add interpretation if not hidden by an inner
- -- immediately visible one.
-
- for J in First_Interp .. All_Interp.Last - 1 loop
-
- -- Current homograph is not hidden. Add to overloads.
-
- if not Is_Immediately_Visible (All_Interp.Table (J).Nam) then
- exit;
-
- -- Homograph is hidden, unless it is a predefined operator.
-
- elsif Type_Conformant (H, All_Interp.Table (J).Nam) then
-
- -- A homograph in the same scope can occur within an
- -- instantiation, the resulting ambiguity has to be
- -- resolved later.
-
- if Scope (H) = Scope (Ent)
- and then In_Instance
- and then not Is_Inherited_Operation (H)
- then
- All_Interp.Table (All_Interp.Last) := (H, Etype (H));
- All_Interp.Increment_Last;
- All_Interp.Table (All_Interp.Last) := No_Interp;
- goto Next_Homograph;
-
- elsif Scope (H) /= Standard_Standard then
- goto Next_Homograph;
- end if;
- end if;
- end loop;
-
- -- On exit, we know that current homograph is not hidden.
-
- Add_One_Interp (N, H, Etype (H));
-
- if Debug_Flag_E then
- Write_Str ("Add overloaded Interpretation ");
- Write_Int (Int (H));
- Write_Eol;
- end if;
- end if;
-
- <<Next_Homograph>>
- H := Homonym (H);
- end loop;
-
- -- Scan list of homographs for use-visible entities only.
-
- H := Current_Entity (Ent);
-
- while Present (H) loop
- if Is_Potentially_Use_Visible (H)
- and then H /= Ent
- and then Is_Overloadable (H)
- then
- for J in First_Interp .. All_Interp.Last - 1 loop
-
- if not Is_Immediately_Visible (All_Interp.Table (J).Nam) then
- exit;
-
- elsif Type_Conformant (H, All_Interp.Table (J).Nam) then
- goto Next_Use_Homograph;
- end if;
- end loop;
-
- Add_One_Interp (N, H, Etype (H));
- end if;
-
- <<Next_Use_Homograph>>
- H := Homonym (H);
- end loop;
- end if;
-
- if All_Interp.Last = First_Interp + 1 then
-
- -- The original interpretation is in fact not overloaded.
-
- Set_Is_Overloaded (N, False);
- end if;
- end Collect_Interps;
-
- ------------
- -- Covers --
- ------------
-
- function Covers (T1, T2 : Entity_Id) return Boolean is
- begin
- pragma Assert (Present (T1) and Present (T2));
-
- -- Simplest case: same types are compatible, and types that have the
- -- same base type and are not generic actuals are compatible. Generic
- -- actuals belong to their class but are not compatible with other
- -- types of their class, and in particular with other generic actuals.
- -- They are however compatible with their own subtypes, and itypes
- -- with the same base are compatible as well. Similary, constrained
- -- subtypes obtained from expressions of an unconstrained nominal type
- -- are compatible with the base type (may lead to spurious ambiguities
- -- in obscure cases ???)
-
- -- Generic actuals require special treatment to avoid spurious ambi-
- -- guities in an instance, when two formal types are instantiated with
- -- the same actual, so that different subprograms end up with the same
- -- signature in the instance.
-
- if T1 = T2 then
- return True;
-
- elsif Base_Type (T1) = Base_Type (T2) then
- if not Is_Generic_Actual_Type (T1) then
- return True;
- else
- return (not Is_Generic_Actual_Type (T2)
- or else Is_Itype (T1)
- or else Is_Itype (T2)
- or else Is_Constr_Subt_For_U_Nominal (T1)
- or else Is_Constr_Subt_For_U_Nominal (T2)
- or else Scope (T1) /= Scope (T2));
- end if;
-
- -- Literals are compatible with types in a given "class"
-
- elsif (T2 = Universal_Integer and then Is_Integer_Type (T1))
- or else (T2 = Universal_Real and then Is_Real_Type (T1))
- or else (T2 = Universal_Fixed and then Is_Fixed_Point_Type (T1))
- or else (T2 = Any_Fixed and then Is_Fixed_Point_Type (T1))
- or else (T2 = Any_String and then Is_String_Type (T1))
- or else (T2 = Any_Character and then Is_Character_Type (T1))
- or else (T2 = Any_Access and then Is_Access_Type (T1))
- then
- return True;
-
- -- The context may be class wide.
-
- elsif Is_Class_Wide_Type (T1)
- and then Is_Ancestor (Root_Type (T1), T2)
- then
- return True;
-
- elsif Is_Class_Wide_Type (T1)
- and then Is_Class_Wide_Type (T2)
- and then Base_Type (Etype (T1)) = Base_Type (Etype (T2))
- then
- return True;
-
- -- In a dispatching call the actual may be class-wide
-
- elsif Is_Class_Wide_Type (T2)
- and then Base_Type (Root_Type (T2)) = Base_Type (T1)
- then
- return True;
-
- -- Some contexts require a class of types rather than a specific type
-
- elsif (T1 = Any_Integer and then Is_Integer_Type (T2))
- or else (T1 = Any_Boolean and then Is_Boolean_Type (T2))
- or else (T1 = Any_Real and then Is_Real_Type (T2))
- or else (T1 = Any_Fixed and then Is_Fixed_Point_Type (T2))
- or else (T1 = Any_Discrete and then Is_Discrete_Type (T2))
- then
- return True;
-
- -- An aggregate is compatible with an array or record type
-
- elsif T2 = Any_Composite
- and then Ekind (T1) in E_Array_Type .. E_Record_Subtype
- then
- return True;
-
- -- If the expected type is an anonymous access, the designated
- -- type must cover that of the expression.
-
- elsif Ekind (T1) = E_Anonymous_Access_Type
- and then Is_Access_Type (T2)
- and then Covers (Designated_Type (T1), Designated_Type (T2))
- then
- return True;
-
- -- An Access_To_Subprogram is compatible with itself, or with an
- -- anonymous type created for an attribute reference Access.
-
- elsif (Ekind (Base_Type (T1)) = E_Access_Subprogram_Type
- or else
- Ekind (Base_Type (T1)) = E_Access_Protected_Subprogram_Type)
- and then Is_Access_Type (T2)
- and then (not Comes_From_Source (T1)
- or else not Comes_From_Source (T2))
- and then (Is_Overloadable (Designated_Type (T2))
- or else
- Ekind (Designated_Type (T2)) = E_Subprogram_Type)
- and then
- Type_Conformant (Designated_Type (T1), Designated_Type (T2))
- and then
- Mode_Conformant (Designated_Type (T1), Designated_Type (T2))
- then
- return True;
-
- elsif Is_Record_Type (T1)
- and then (Is_Remote_Call_Interface (T1)
- or else Is_Remote_Types (T1))
- and then Present (Corresponding_Remote_Type (T1))
- then
- return Covers (Corresponding_Remote_Type (T1), T2);
-
- elsif Ekind (T2) = E_Access_Attribute_Type
- and then (Ekind (Base_Type (T1)) = E_General_Access_Type
- or else Ekind (Base_Type (T1)) = E_Access_Type)
- and then Covers (Designated_Type (T1), Designated_Type (T2))
- then
- -- If the target type is a RACW type while the source is an access
- -- attribute type, we are building a RACW that may be exported.
-
- if Is_Remote_Access_To_Class_Wide_Type (Base_Type (T1)) then
- Set_Has_RACW (Current_Sem_Unit);
- end if;
-
- return True;
-
- elsif Ekind (T2) = E_Allocator_Type
- and then Is_Access_Type (T1)
- and then Covers (Designated_Type (T1), Designated_Type (T2))
- then
- return True;
-
- -- A boolean operation on integer literals is compatible with a
- -- modular context.
-
- elsif T2 = Any_Modular
- and then Is_Modular_Integer_Type (T1)
- then
- return True;
-
- -- The actual type may be the result of a previous error
-
- elsif Base_Type (T2) = Any_Type then
- return True;
-
- -- A packed array type covers its corresponding non-packed type.
- -- This is not legitimate Ada, but allows the omission of a number
- -- of otherwise useless unchecked conversions, and since this can
- -- only arise in (known correct) expanded code, no harm is done
-
- elsif Is_Array_Type (T2)
- and then Is_Packed (T2)
- and then T1 = Packed_Array_Type (T2)
- then
- return True;
-
- -- Similarly an array type covers its corresponding packed array type
-
- elsif Is_Array_Type (T1)
- and then Is_Packed (T1)
- and then T2 = Packed_Array_Type (T1)
- then
- return True;
-
- -- In an instance the proper view may not always be correct for
- -- private types, but private and full view are compatible. This
- -- removes spurious errors from nested instantiations that involve,
- -- among other things, types derived from privated types.
-
- elsif In_Instance
- and then Is_Private_Type (T1)
- and then ((Present (Full_View (T1))
- and then Covers (Full_View (T1), T2))
- or else Base_Type (T1) = T2
- or else Base_Type (T2) = T1)
- then
- return True;
-
- -- In the expansion of inlined bodies, types are compatible if they
- -- are structurally equivalent.
-
- elsif In_Inlined_Body
- and then (Underlying_Type (T1) = Underlying_Type (T2)
- or else (Is_Access_Type (T1)
- and then Is_Access_Type (T2)
- and then
- Designated_Type (T1) = Designated_Type (T2))
- or else (T1 = Any_Access
- and then Is_Access_Type (Underlying_Type (T2))))
- then
- return True;
-
- -- Otherwise it doesn't cover!
-
- else
- return False;
- end if;
- end Covers;
-
- ------------------
- -- Disambiguate --
- ------------------
-
- function Disambiguate
- (N : Node_Id;
- I1, I2 : Interp_Index;
- Typ : Entity_Id)
- return Interp
- is
- I : Interp_Index;
- It : Interp;
- It1, It2 : Interp;
- Nam1, Nam2 : Entity_Id;
- Predef_Subp : Entity_Id;
- User_Subp : Entity_Id;
-
- function Matches (Actual, Formal : Node_Id) return Boolean;
- -- Look for exact type match in an instance, to remove spurious
- -- ambiguities when two formal types have the same actual.
-
- function Standard_Operator return Boolean;
-
- function Remove_Conversions return Interp;
- -- Last chance for pathological cases involving comparisons on
- -- literals, and user overloadings of the same operator. Such
- -- pathologies have been removed from the ACVC, but still appear in
- -- two DEC tests, with the following notable quote from Ben Brosgol:
- --
- -- [Note: I disclaim all credit/responsibility/blame for coming up with
- -- this example; Robert Dewar brought it to our attention, since it
- -- is apparently found in the ACVC 1.5. I did not attempt to find
- -- the reason in the Reference Manual that makes the example legal,
- -- since I was too nauseated by it to want to pursue it further.]
- --
- -- Accordingly, this is not a fully recursive solution, but it handles
- -- DEC tests c460vsa, c460vsb. It also handles ai00136a, which pushes
- -- pathology in the other direction with calls whose multiple overloaded
- -- actuals make them truly unresolvable.
-
- -------------
- -- Matches --
- -------------
-
- function Matches (Actual, Formal : Node_Id) return Boolean is
- T1 : constant Entity_Id := Etype (Actual);
- T2 : constant Entity_Id := Etype (Formal);
-
- begin
- return T1 = T2
- or else
- (Is_Numeric_Type (T2)
- and then
- (T1 = Universal_Real or else T1 = Universal_Integer));
- end Matches;
-
- ------------------------
- -- Remove_Conversions --
- ------------------------
-
- function Remove_Conversions return Interp is
- I : Interp_Index;
- It : Interp;
- It1 : Interp;
- F1 : Entity_Id;
- Act1 : Node_Id;
- Act2 : Node_Id;
-
- begin
- It1 := No_Interp;
- Get_First_Interp (N, I, It);
-
- while Present (It.Typ) loop
-
- if not Is_Overloadable (It.Nam) then
- return No_Interp;
- end if;
-
- F1 := First_Formal (It.Nam);
-
- if No (F1) then
- return It1;
-
- else
- if Nkind (N) = N_Function_Call
- or else Nkind (N) = N_Procedure_Call_Statement
- then
- Act1 := First_Actual (N);
-
- if Present (Act1) then
- Act2 := Next_Actual (Act1);
- else
- Act2 := Empty;
- end if;
-
- elsif Nkind (N) in N_Unary_Op then
- Act1 := Right_Opnd (N);
- Act2 := Empty;
-
- elsif Nkind (N) in N_Binary_Op then
- Act1 := Left_Opnd (N);
- Act2 := Right_Opnd (N);
-
- else
- return It1;
- end if;
-
- if Nkind (Act1) in N_Op
- and then Is_Overloaded (Act1)
- and then (Nkind (Right_Opnd (Act1)) = N_Integer_Literal
- or else Nkind (Right_Opnd (Act1)) = N_Real_Literal)
- and then Has_Compatible_Type (Act1, Standard_Boolean)
- and then Etype (F1) = Standard_Boolean
- then
-
- if It1 /= No_Interp then
- return No_Interp;
-
- elsif Present (Act2)
- and then Nkind (Act2) in N_Op
- and then Is_Overloaded (Act2)
- and then (Nkind (Right_Opnd (Act1)) = N_Integer_Literal
- or else
- Nkind (Right_Opnd (Act1)) = N_Real_Literal)
- and then Has_Compatible_Type (Act2, Standard_Boolean)
- then
- -- The preference rule on the first actual is not
- -- sufficient to disambiguate.
-
- goto Next_Interp;
-
- else
- It1 := It;
- end if;
- end if;
- end if;
-
- <<Next_Interp>>
- Get_Next_Interp (I, It);
- end loop;
-
- if Errors_Detected > 0 then
-
- -- After some error, a formal may have Any_Type and yield
- -- a spurious match. To avoid cascaded errors if possible,
- -- check for such a formal in either candidate.
-
- declare
- Formal : Entity_Id;
-
- begin
- Formal := First_Formal (Nam1);
- while Present (Formal) loop
- if Etype (Formal) = Any_Type then
- return Disambiguate.It2;
- end if;
-
- Next_Formal (Formal);
- end loop;
-
- Formal := First_Formal (Nam2);
- while Present (Formal) loop
- if Etype (Formal) = Any_Type then
- return Disambiguate.It1;
- end if;
-
- Next_Formal (Formal);
- end loop;
- end;
- end if;
-
- return It1;
- end Remove_Conversions;
-
- -----------------------
- -- Standard_Operator --
- -----------------------
-
- function Standard_Operator return Boolean is
- Nam : Node_Id;
-
- begin
- if Nkind (N) in N_Op then
- return True;
-
- elsif Nkind (N) = N_Function_Call then
- Nam := Name (N);
-
- if Nkind (Nam) /= N_Expanded_Name then
- return True;
- else
- return Entity (Prefix (Nam)) = Standard_Standard;
- end if;
- else
- return False;
- end if;
- end Standard_Operator;
-
- -- Start of processing for Disambiguate
-
- begin
- -- Recover the two legal interpretations.
-
- Get_First_Interp (N, I, It);
-
- while I /= I1 loop
- Get_Next_Interp (I, It);
- end loop;
-
- It1 := It;
- Nam1 := It.Nam;
-
- while I /= I2 loop
- Get_Next_Interp (I, It);
- end loop;
-
- It2 := It;
- Nam2 := It.Nam;
-
- -- If the context is universal, the predefined operator is preferred.
- -- This includes bounds in numeric type declarations, and expressions
- -- in type conversions. If no interpretation yields a universal type,
- -- then we must check whether the user-defined entity hides the prede-
- -- fined one.
-
- if Chars (Nam1) in Any_Operator_Name
- and then Standard_Operator
- then
- if Typ = Universal_Integer
- or else Typ = Universal_Real
- or else Typ = Any_Integer
- or else Typ = Any_Discrete
- or else Typ = Any_Real
- or else Typ = Any_Type
- then
- -- Find an interpretation that yields the universal type, or else
- -- a predefined operator that yields a predefined numeric type.
-
- declare
- Candidate : Interp := No_Interp;
- begin
- Get_First_Interp (N, I, It);
-
- while Present (It.Typ) loop
- if (Covers (Typ, It.Typ)
- or else Typ = Any_Type)
- and then
- (It.Typ = Universal_Integer
- or else It.Typ = Universal_Real)
- then
- return It;
-
- elsif Covers (Typ, It.Typ)
- and then Scope (It.Typ) = Standard_Standard
- and then Scope (It.Nam) = Standard_Standard
- and then Is_Numeric_Type (It.Typ)
- then
- Candidate := It;
- end if;
-
- Get_Next_Interp (I, It);
- end loop;
-
- if Candidate /= No_Interp then
- return Candidate;
- end if;
- end;
-
- elsif Chars (Nam1) /= Name_Op_Not
- and then (Typ = Standard_Boolean
- or else Typ = Any_Boolean)
- then
- -- Equality or comparison operation. Choose predefined operator
- -- if arguments are universal. The node may be an operator, a
- -- name, or a function call, so unpack arguments accordingly.
-
- declare
- Arg1, Arg2 : Node_Id;
-
- begin
- if Nkind (N) in N_Op then
- Arg1 := Left_Opnd (N);
- Arg2 := Right_Opnd (N);
-
- elsif Is_Entity_Name (N)
- or else Nkind (N) = N_Operator_Symbol
- then
- Arg1 := First_Entity (Entity (N));
- Arg2 := Next_Entity (Arg1);
-
- else
- Arg1 := First_Actual (N);
- Arg2 := Next_Actual (Arg1);
- end if;
-
- if Present (Arg2)
- and then Present (Universal_Interpretation (Arg1))
- and then Universal_Interpretation (Arg2) =
- Universal_Interpretation (Arg1)
- then
- Get_First_Interp (N, I, It);
-
- while Scope (It.Nam) /= Standard_Standard loop
- Get_Next_Interp (I, It);
- end loop;
-
- return It;
- end if;
- end;
- end if;
- end if;
-
- -- If no universal interpretation, check whether user-defined operator
- -- hides predefined one, as well as other special cases. If the node
- -- is a range, then one or both bounds are ambiguous. Each will have
- -- to be disambiguated w.r.t. the context type. The type of the range
- -- itself is imposed by the context, so we can return either legal
- -- interpretation.
-
- if Ekind (Nam1) = E_Operator then
- Predef_Subp := Nam1;
- User_Subp := Nam2;
-
- elsif Ekind (Nam2) = E_Operator then
- Predef_Subp := Nam2;
- User_Subp := Nam1;
-
- elsif Nkind (N) = N_Range then
- return It1;
-
- -- If two user defined-subprograms are visible, it is a true ambiguity,
- -- unless one of them is an entry and the context is a conditional or
- -- timed entry call, or unless we are within an instance and this is
- -- results from two formals types with the same actual.
-
- else
- if Nkind (N) = N_Procedure_Call_Statement
- and then Nkind (Parent (N)) = N_Entry_Call_Alternative
- and then N = Entry_Call_Statement (Parent (N))
- then
- if Ekind (Nam2) = E_Entry then
- return It2;
- elsif Ekind (Nam1) = E_Entry then
- return It1;
- else
- return No_Interp;
- end if;
-
- -- If the ambiguity occurs within an instance, it is due to several
- -- formal types with the same actual. Look for an exact match
- -- between the types of the formals of the overloadable entities,
- -- and the actuals in the call, to recover the unambiguous match
- -- in the original generic.
-
- elsif In_Instance then
- if (Nkind (N) = N_Function_Call
- or else Nkind (N) = N_Procedure_Call_Statement)
- then
- declare
- Actual : Node_Id;
- Formal : Entity_Id;
-
- begin
- Actual := First_Actual (N);
- Formal := First_Formal (Nam1);
- while Present (Actual) loop
- if Etype (Actual) /= Etype (Formal) then
- return It2;
- end if;
-
- Next_Actual (Actual);
- Next_Formal (Formal);
- end loop;
-
- return It1;
- end;
-
- elsif Nkind (N) in N_Binary_Op then
-
- if Matches (Left_Opnd (N), First_Formal (Nam1))
- and then
- Matches (Right_Opnd (N), Next_Formal (First_Formal (Nam1)))
- then
- return It1;
- else
- return It2;
- end if;
-
- elsif Nkind (N) in N_Unary_Op then
-
- if Etype (Right_Opnd (N)) = Etype (First_Formal (Nam1)) then
- return It1;
- else
- return It2;
- end if;
-
- else
- return Remove_Conversions;
- end if;
- else
- return Remove_Conversions;
- end if;
- end if;
-
- -- an implicit concatenation operator on a string type cannot be
- -- disambiguated from the predefined concatenation. This can only
- -- happen with concatenation of string literals.
-
- if Chars (User_Subp) = Name_Op_Concat
- and then Ekind (User_Subp) = E_Operator
- and then Is_String_Type (Etype (First_Formal (User_Subp)))
- then
- return No_Interp;
-
- -- If the user-defined operator is in an open scope, or in the scope
- -- of the resulting type, or given by an expanded name that names its
- -- scope, it hides the predefined operator for the type. Exponentiation
- -- has to be special-cased because the implicit operator does not have
- -- a symmetric signature, and may not be hidden by the explicit one.
-
- elsif (Nkind (N) = N_Function_Call
- and then Nkind (Name (N)) = N_Expanded_Name
- and then (Chars (Predef_Subp) /= Name_Op_Expon
- or else Hides_Op (User_Subp, Predef_Subp))
- and then Scope (User_Subp) = Entity (Prefix (Name (N))))
- or else Hides_Op (User_Subp, Predef_Subp)
- then
- if It1.Nam = User_Subp then
- return It1;
- else
- return It2;
- end if;
-
- -- Otherwise, the predefined operator has precedence, or if the
- -- user-defined operation is directly visible we have a true ambiguity.
- -- If this is a fixed-point multiplication and division in Ada83 mode,
- -- exclude the universal_fixed operator, which often causes ambiguities
- -- in legacy code.
-
- else
- if (In_Open_Scopes (Scope (User_Subp))
- or else Is_Potentially_Use_Visible (User_Subp))
- and then not In_Instance
- then
- if Is_Fixed_Point_Type (Typ)
- and then (Chars (Nam1) = Name_Op_Multiply
- or else Chars (Nam1) = Name_Op_Divide)
- and then Ada_83
- then
- if It2.Nam = Predef_Subp then
- return It1;
-
- else
- return It2;
- end if;
- else
- return No_Interp;
- end if;
-
- elsif It1.Nam = Predef_Subp then
- return It1;
-
- else
- return It2;
- end if;
- end if;
-
- end Disambiguate;
-
- ---------------------
- -- End_Interp_List --
- ---------------------
-
- procedure End_Interp_List is
- begin
- All_Interp.Table (All_Interp.Last) := No_Interp;
- All_Interp.Increment_Last;
- end End_Interp_List;
-
- -------------------------
- -- Entity_Matches_Spec --
- -------------------------
-
- function Entity_Matches_Spec (Old_S, New_S : Entity_Id) return Boolean is
- begin
- -- Simple case: same entity kinds, type conformance is required.
- -- A parameterless function can also rename a literal.
-
- if Ekind (Old_S) = Ekind (New_S)
- or else (Ekind (New_S) = E_Function
- and then Ekind (Old_S) = E_Enumeration_Literal)
- then
- return Type_Conformant (New_S, Old_S);
-
- elsif Ekind (New_S) = E_Function
- and then Ekind (Old_S) = E_Operator
- then
- return Operator_Matches_Spec (Old_S, New_S);
-
- elsif Ekind (New_S) = E_Procedure
- and then Is_Entry (Old_S)
- then
- return Type_Conformant (New_S, Old_S);
-
- else
- return False;
- end if;
- end Entity_Matches_Spec;
-
- ----------------------
- -- Find_Unique_Type --
- ----------------------
-
- function Find_Unique_Type (L : Node_Id; R : Node_Id) return Entity_Id is
- I : Interp_Index;
- It : Interp;
- T : Entity_Id := Etype (L);
- TR : Entity_Id := Any_Type;
-
- begin
- if Is_Overloaded (R) then
- Get_First_Interp (R, I, It);
-
- while Present (It.Typ) loop
- if Covers (T, It.Typ) or else Covers (It.Typ, T) then
-
- -- If several interpretations are possible and L is universal,
- -- apply preference rule.
-
- if TR /= Any_Type then
-
- if (T = Universal_Integer or else T = Universal_Real)
- and then It.Typ = T
- then
- TR := It.Typ;
- end if;
-
- else
- TR := It.Typ;
- end if;
- end if;
-
- Get_Next_Interp (I, It);
- end loop;
-
- Set_Etype (R, TR);
-
- -- In the non-overloaded case, the Etype of R is already set
- -- correctly.
-
- else
- null;
- end if;
-
- -- If one of the operands is Universal_Fixed, the type of the
- -- other operand provides the context.
-
- if Etype (R) = Universal_Fixed then
- return T;
-
- elsif T = Universal_Fixed then
- return Etype (R);
-
- else
- return Specific_Type (T, Etype (R));
- end if;
-
- end Find_Unique_Type;
-
- ----------------------
- -- Get_First_Interp --
- ----------------------
-
- procedure Get_First_Interp
- (N : Node_Id;
- I : out Interp_Index;
- It : out Interp)
- is
- Int_Ind : Interp_Index;
- O_N : Node_Id;
-
- begin
- -- If a selected component is overloaded because the selector has
- -- multiple interpretations, the node is a call to a protected
- -- operation or an indirect call. Retrieve the interpretation from
- -- the selector name. The selected component may be overloaded as well
- -- if the prefix is overloaded. That case is unchanged.
-
- if Nkind (N) = N_Selected_Component
- and then Is_Overloaded (Selector_Name (N))
- then
- O_N := Selector_Name (N);
- else
- O_N := N;
- end if;
-
- for Index in 0 .. Interp_Map.Last loop
- if Interp_Map.Table (Index).Node = O_N then
- Int_Ind := Interp_Map.Table (Index).Index;
- It := All_Interp.Table (Int_Ind);
- I := Int_Ind;
- return;
- end if;
- end loop;
-
- -- Procedure should never be called if the node has no interpretations
-
- raise Program_Error;
- end Get_First_Interp;
-
- ----------------------
- -- Get_Next_Interp --
- ----------------------
-
- procedure Get_Next_Interp (I : in out Interp_Index; It : out Interp) is
- begin
- I := I + 1;
- It := All_Interp.Table (I);
- end Get_Next_Interp;
-
- -------------------------
- -- Has_Compatible_Type --
- -------------------------
-
- function Has_Compatible_Type
- (N : Node_Id;
- Typ : Entity_Id)
- return Boolean
- is
- I : Interp_Index;
- It : Interp;
-
- begin
- if N = Error then
- return False;
- end if;
-
- if Nkind (N) = N_Subtype_Indication
- or else not Is_Overloaded (N)
- then
- return Covers (Typ, Etype (N))
- or else (not Is_Tagged_Type (Typ)
- and then Ekind (Typ) /= E_Anonymous_Access_Type
- and then Covers (Etype (N), Typ));
-
- else
- Get_First_Interp (N, I, It);
-
- while Present (It.Typ) loop
- if Covers (Typ, It.Typ)
- or else (not Is_Tagged_Type (Typ)
- and then Ekind (Typ) /= E_Anonymous_Access_Type
- and then Covers (It.Typ, Typ))
- then
- return True;
- end if;
-
- Get_Next_Interp (I, It);
- end loop;
-
- return False;
- end if;
- end Has_Compatible_Type;
-
- --------------
- -- Hides_Op --
- --------------
-
- function Hides_Op (F : Entity_Id; Op : Entity_Id) return Boolean is
- Btyp : constant Entity_Id := Base_Type (Etype (First_Formal (F)));
-
- begin
- return Operator_Matches_Spec (Op, F)
- and then (In_Open_Scopes (Scope (F))
- or else Scope (F) = Scope (Btyp)
- or else (not In_Open_Scopes (Scope (Btyp))
- and then not In_Use (Btyp)
- and then not In_Use (Scope (Btyp))));
- end Hides_Op;
-
- ------------------------
- -- Init_Interp_Tables --
- ------------------------
-
- procedure Init_Interp_Tables is
- begin
- All_Interp.Init;
- Interp_Map.Init;
- end Init_Interp_Tables;
-
- ---------------------
- -- Intersect_Types --
- ---------------------
-
- function Intersect_Types (L, R : Node_Id) return Entity_Id is
- Index : Interp_Index;
- It : Interp;
- Typ : Entity_Id;
-
- function Check_Right_Argument (T : Entity_Id) return Entity_Id;
- -- Find interpretation of right arg that has type compatible with T
-
- --------------------------
- -- Check_Right_Argument --
- --------------------------
-
- function Check_Right_Argument (T : Entity_Id) return Entity_Id is
- Index : Interp_Index;
- It : Interp;
- T2 : Entity_Id;
-
- begin
- if not Is_Overloaded (R) then
- return Specific_Type (T, Etype (R));
-
- else
- Get_First_Interp (R, Index, It);
-
- loop
- T2 := Specific_Type (T, It.Typ);
-
- if T2 /= Any_Type then
- return T2;
- end if;
-
- Get_Next_Interp (Index, It);
- exit when No (It.Typ);
- end loop;
-
- return Any_Type;
- end if;
- end Check_Right_Argument;
-
- -- Start processing for Intersect_Types
-
- begin
- if Etype (L) = Any_Type or else Etype (R) = Any_Type then
- return Any_Type;
- end if;
-
- if not Is_Overloaded (L) then
- Typ := Check_Right_Argument (Etype (L));
-
- else
- Typ := Any_Type;
- Get_First_Interp (L, Index, It);
-
- while Present (It.Typ) loop
- Typ := Check_Right_Argument (It.Typ);
- exit when Typ /= Any_Type;
- Get_Next_Interp (Index, It);
- end loop;
-
- end if;
-
- -- If Typ is Any_Type, it means no compatible pair of types was found
-
- if Typ = Any_Type then
-
- if Nkind (Parent (L)) in N_Op then
- Error_Msg_N ("incompatible types for operator", Parent (L));
-
- elsif Nkind (Parent (L)) = N_Range then
- Error_Msg_N ("incompatible types given in constraint", Parent (L));
-
- else
- Error_Msg_N ("incompatible types", Parent (L));
- end if;
- end if;
-
- return Typ;
- end Intersect_Types;
-
- -----------------
- -- Is_Ancestor --
- -----------------
-
- function Is_Ancestor (T1, T2 : Entity_Id) return Boolean is
- Par : Entity_Id;
-
- begin
- if Base_Type (T1) = Base_Type (T2) then
- return True;
-
- elsif Is_Private_Type (T1)
- and then Present (Full_View (T1))
- and then Base_Type (T2) = Base_Type (Full_View (T1))
- then
- return True;
-
- else
- Par := Etype (T2);
-
- loop
- if Base_Type (T1) = Base_Type (Par)
- or else (Is_Private_Type (T1)
- and then Present (Full_View (T1))
- and then Base_Type (Par) = Base_Type (Full_View (T1)))
- then
- return True;
-
- elsif Is_Private_Type (Par)
- and then Present (Full_View (Par))
- and then Full_View (Par) = Base_Type (T1)
- then
- return True;
-
- elsif Etype (Par) /= Par then
- Par := Etype (Par);
- else
- return False;
- end if;
- end loop;
- end if;
- end Is_Ancestor;
-
- -------------------
- -- Is_Subtype_Of --
- -------------------
-
- function Is_Subtype_Of (T1 : Entity_Id; T2 : Entity_Id) return Boolean is
- S : Entity_Id;
-
- begin
- S := Ancestor_Subtype (T1);
- while Present (S) loop
- if S = T2 then
- return True;
- else
- S := Ancestor_Subtype (S);
- end if;
- end loop;
-
- return False;
- end Is_Subtype_Of;
-
- -----------------
- -- New_Interps --
- -----------------
-
- procedure New_Interps (N : Node_Id) is
- begin
- Interp_Map.Increment_Last;
- All_Interp.Increment_Last;
- Interp_Map.Table (Interp_Map.Last) := (N, All_Interp.Last);
- All_Interp.Table (All_Interp.Last) := No_Interp;
- Set_Is_Overloaded (N, True);
- end New_Interps;
-
- ---------------------------
- -- Operator_Matches_Spec --
- ---------------------------
-
- function Operator_Matches_Spec (Op, New_S : Entity_Id) return Boolean is
- Op_Name : constant Name_Id := Chars (Op);
- T : constant Entity_Id := Etype (New_S);
- New_F : Entity_Id;
- Old_F : Entity_Id;
- Num : Int;
- T1 : Entity_Id;
- T2 : Entity_Id;
-
- begin
- -- To verify that a predefined operator matches a given signature,
- -- do a case analysis of the operator classes. Function can have one
- -- or two formals and must have the proper result type.
-
- New_F := First_Formal (New_S);
- Old_F := First_Formal (Op);
- Num := 0;
-
- while Present (New_F) and then Present (Old_F) loop
- Num := Num + 1;
- Next_Formal (New_F);
- Next_Formal (Old_F);
- end loop;
-
- -- Definite mismatch if different number of parameters
-
- if Present (Old_F) or else Present (New_F) then
- return False;
-
- -- Unary operators
-
- elsif Num = 1 then
- T1 := Etype (First_Formal (New_S));
-
- if Op_Name = Name_Op_Subtract
- or else Op_Name = Name_Op_Add
- or else Op_Name = Name_Op_Abs
- then
- return Base_Type (T1) = Base_Type (T)
- and then Is_Numeric_Type (T);
-
- elsif Op_Name = Name_Op_Not then
- return Base_Type (T1) = Base_Type (T)
- and then Valid_Boolean_Arg (Base_Type (T));
-
- else
- return False;
- end if;
-
- -- Binary operators
-
- else
- T1 := Etype (First_Formal (New_S));
- T2 := Etype (Next_Formal (First_Formal (New_S)));
-
- if Op_Name = Name_Op_And or else Op_Name = Name_Op_Or
- or else Op_Name = Name_Op_Xor
- then
- return Base_Type (T1) = Base_Type (T2)
- and then Base_Type (T1) = Base_Type (T)
- and then Valid_Boolean_Arg (Base_Type (T));
-
- elsif Op_Name = Name_Op_Eq or else Op_Name = Name_Op_Ne then
- return Base_Type (T1) = Base_Type (T2)
- and then not Is_Limited_Type (T1)
- and then Is_Boolean_Type (T);
-
- elsif Op_Name = Name_Op_Lt or else Op_Name = Name_Op_Le
- or else Op_Name = Name_Op_Gt or else Op_Name = Name_Op_Ge
- then
- return Base_Type (T1) = Base_Type (T2)
- and then Valid_Comparison_Arg (T1)
- and then Is_Boolean_Type (T);
-
- elsif Op_Name = Name_Op_Add or else Op_Name = Name_Op_Subtract then
- return Base_Type (T1) = Base_Type (T2)
- and then Base_Type (T1) = Base_Type (T)
- and then Is_Numeric_Type (T);
-
- -- for division and multiplication, a user-defined function does
- -- not match the predefined universal_fixed operation, except in
- -- Ada83 mode.
-
- elsif Op_Name = Name_Op_Divide then
- return (Base_Type (T1) = Base_Type (T2)
- and then Base_Type (T1) = Base_Type (T)
- and then Is_Numeric_Type (T)
- and then (not Is_Fixed_Point_Type (T)
- or else Ada_83))
-
- -- Mixed_Mode operations on fixed-point types.
-
- or else (Base_Type (T1) = Base_Type (T)
- and then Base_Type (T2) = Base_Type (Standard_Integer)
- and then Is_Fixed_Point_Type (T))
-
- -- A user defined operator can also match (and hide) a mixed
- -- operation on universal literals.
-
- or else (Is_Integer_Type (T2)
- and then Is_Floating_Point_Type (T1)
- and then Base_Type (T1) = Base_Type (T));
-
- elsif Op_Name = Name_Op_Multiply then
- return (Base_Type (T1) = Base_Type (T2)
- and then Base_Type (T1) = Base_Type (T)
- and then Is_Numeric_Type (T)
- and then (not Is_Fixed_Point_Type (T)
- or else Ada_83))
-
- -- Mixed_Mode operations on fixed-point types.
-
- or else (Base_Type (T1) = Base_Type (T)
- and then Base_Type (T2) = Base_Type (Standard_Integer)
- and then Is_Fixed_Point_Type (T))
-
- or else (Base_Type (T2) = Base_Type (T)
- and then Base_Type (T1) = Base_Type (Standard_Integer)
- and then Is_Fixed_Point_Type (T))
-
- or else (Is_Integer_Type (T2)
- and then Is_Floating_Point_Type (T1)
- and then Base_Type (T1) = Base_Type (T))
-
- or else (Is_Integer_Type (T1)
- and then Is_Floating_Point_Type (T2)
- and then Base_Type (T2) = Base_Type (T));
-
- elsif Op_Name = Name_Op_Mod or else Op_Name = Name_Op_Rem then
- return Base_Type (T1) = Base_Type (T2)
- and then Base_Type (T1) = Base_Type (T)
- and then Is_Integer_Type (T);
-
- elsif Op_Name = Name_Op_Expon then
- return Base_Type (T1) = Base_Type (T)
- and then Is_Numeric_Type (T)
- and then Base_Type (T2) = Base_Type (Standard_Integer);
-
- elsif Op_Name = Name_Op_Concat then
- return Is_Array_Type (T)
- and then (Base_Type (T) = Base_Type (Etype (Op)))
- and then (Base_Type (T1) = Base_Type (T)
- or else
- Base_Type (T1) = Base_Type (Component_Type (T)))
- and then (Base_Type (T2) = Base_Type (T)
- or else
- Base_Type (T2) = Base_Type (Component_Type (T)));
-
- else
- return False;
- end if;
- end if;
- end Operator_Matches_Spec;
-
- -------------------
- -- Remove_Interp --
- -------------------
-
- procedure Remove_Interp (I : in out Interp_Index) is
- II : Interp_Index;
-
- begin
- -- Find end of Interp list and copy downward to erase the discarded one
-
- II := I + 1;
-
- while Present (All_Interp.Table (II).Typ) loop
- II := II + 1;
- end loop;
-
- for J in I + 1 .. II loop
- All_Interp.Table (J - 1) := All_Interp.Table (J);
- end loop;
-
- -- Back up interp. index to insure that iterator will pick up next
- -- available interpretation.
-
- I := I - 1;
- end Remove_Interp;
-
- ------------------
- -- Save_Interps --
- ------------------
-
- procedure Save_Interps (Old_N : Node_Id; New_N : Node_Id) is
- begin
- if Is_Overloaded (Old_N) then
- for Index in 0 .. Interp_Map.Last loop
- if Interp_Map.Table (Index).Node = Old_N then
- Interp_Map.Table (Index).Node := New_N;
- exit;
- end if;
- end loop;
- end if;
- end Save_Interps;
-
- -------------------
- -- Specific_Type --
- -------------------
-
- function Specific_Type (T1, T2 : Entity_Id) return Entity_Id is
- B1 : constant Entity_Id := Base_Type (T1);
- B2 : constant Entity_Id := Base_Type (T2);
-
- function Is_Remote_Access (T : Entity_Id) return Boolean;
- -- Check whether T is the equivalent type of a remote access type.
- -- If distribution is enabled, T is a legal context for Null.
-
- ----------------------
- -- Is_Remote_Access --
- ----------------------
-
- function Is_Remote_Access (T : Entity_Id) return Boolean is
- begin
- return Is_Record_Type (T)
- and then (Is_Remote_Call_Interface (T)
- or else Is_Remote_Types (T))
- and then Present (Corresponding_Remote_Type (T))
- and then Is_Access_Type (Corresponding_Remote_Type (T));
- end Is_Remote_Access;
-
- -- Start of processing for Specific_Type
-
- begin
- if (T1 = Any_Type or else T2 = Any_Type) then
- return Any_Type;
- end if;
-
- if B1 = B2 then
- return B1;
-
- elsif (T1 = Universal_Integer and then Is_Integer_Type (T2))
- or else (T1 = Universal_Real and then Is_Real_Type (T2))
- or else (T1 = Any_Fixed and then Is_Fixed_Point_Type (T2))
- then
- return B2;
-
- elsif (T2 = Universal_Integer and then Is_Integer_Type (T1))
- or else (T2 = Universal_Real and then Is_Real_Type (T1))
- or else (T2 = Any_Fixed and then Is_Fixed_Point_Type (T1))
- then
- return B1;
-
- elsif (T2 = Any_String and then Is_String_Type (T1)) then
- return B1;
-
- elsif (T1 = Any_String and then Is_String_Type (T2)) then
- return B2;
-
- elsif (T2 = Any_Character and then Is_Character_Type (T1)) then
- return B1;
-
- elsif (T1 = Any_Character and then Is_Character_Type (T2)) then
- return B2;
-
- elsif (T1 = Any_Access
- and then (Is_Access_Type (T2) or else Is_Remote_Access (T2)))
- then
- return T2;
-
- elsif (T2 = Any_Access
- and then (Is_Access_Type (T1) or else Is_Remote_Access (T1)))
- then
- return T1;
-
- elsif (T2 = Any_Composite
- and then Ekind (T1) in E_Array_Type .. E_Record_Subtype)
- then
- return T1;
-
- elsif (T1 = Any_Composite
- and then Ekind (T2) in E_Array_Type .. E_Record_Subtype)
- then
- return T2;
-
- elsif (T1 = Any_Modular and then Is_Modular_Integer_Type (T2)) then
- return T2;
-
- elsif (T2 = Any_Modular and then Is_Modular_Integer_Type (T1)) then
- return T1;
-
- -- Special cases for equality operators (all other predefined
- -- operators can never apply to tagged types)
-
- elsif Is_Class_Wide_Type (T1)
- and then Is_Ancestor (Root_Type (T1), T2)
- then
- return T1;
-
- elsif Is_Class_Wide_Type (T2)
- and then Is_Ancestor (Root_Type (T2), T1)
- then
- return T2;
-
- elsif (Ekind (B1) = E_Access_Subprogram_Type
- or else
- Ekind (B1) = E_Access_Protected_Subprogram_Type)
- and then Ekind (Designated_Type (B1)) /= E_Subprogram_Type
- and then Is_Access_Type (T2)
- then
- return T2;
-
- elsif (Ekind (B2) = E_Access_Subprogram_Type
- or else
- Ekind (B2) = E_Access_Protected_Subprogram_Type)
- and then Ekind (Designated_Type (B2)) /= E_Subprogram_Type
- and then Is_Access_Type (T1)
- then
- return T1;
-
- elsif (Ekind (T1) = E_Allocator_Type
- or else Ekind (T1) = E_Access_Attribute_Type
- or else Ekind (T1) = E_Anonymous_Access_Type)
- and then Is_Access_Type (T2)
- then
- return T2;
-
- elsif (Ekind (T2) = E_Allocator_Type
- or else Ekind (T2) = E_Access_Attribute_Type
- or else Ekind (T2) = E_Anonymous_Access_Type)
- and then Is_Access_Type (T1)
- then
- return T1;
-
- -- If none of the above cases applies, types are not compatible.
-
- else
- return Any_Type;
- end if;
- end Specific_Type;
-
- ------------------------------
- -- Universal_Interpretation --
- ------------------------------
-
- function Universal_Interpretation (Opnd : Node_Id) return Entity_Id is
- Index : Interp_Index;
- It : Interp;
-
- begin
- -- The argument may be a formal parameter of an operator or subprogram
- -- with multiple interpretations, or else an expression for an actual.
-
- if Nkind (Opnd) = N_Defining_Identifier
- or else not Is_Overloaded (Opnd)
- then
- if Etype (Opnd) = Universal_Integer
- or else Etype (Opnd) = Universal_Real
- then
- return Etype (Opnd);
- else
- return Empty;
- end if;
-
- else
- Get_First_Interp (Opnd, Index, It);
-
- while Present (It.Typ) loop
-
- if It.Typ = Universal_Integer
- or else It.Typ = Universal_Real
- then
- return It.Typ;
- end if;
-
- Get_Next_Interp (Index, It);
- end loop;
-
- return Empty;
- end if;
- end Universal_Interpretation;
-
- -----------------------
- -- Valid_Boolean_Arg --
- -----------------------
-
- -- In addition to booleans and arrays of booleans, we must include
- -- aggregates as valid boolean arguments, because in the first pass
- -- of resolution their components are not examined. If it turns out not
- -- to be an aggregate of booleans, this will be diagnosed in Resolve.
- -- Any_Composite must be checked for prior to the array type checks
- -- because Any_Composite does not have any associated indexes.
-
- function Valid_Boolean_Arg (T : Entity_Id) return Boolean is
- begin
- return Is_Boolean_Type (T)
- or else T = Any_Composite
- or else (Is_Array_Type (T)
- and then T /= Any_String
- and then Number_Dimensions (T) = 1
- and then Is_Boolean_Type (Component_Type (T))
- and then (not Is_Private_Composite (T)
- or else In_Instance)
- and then (not Is_Limited_Composite (T)
- or else In_Instance))
- or else Is_Modular_Integer_Type (T)
- or else T = Universal_Integer;
- end Valid_Boolean_Arg;
-
- --------------------------
- -- Valid_Comparison_Arg --
- --------------------------
-
- function Valid_Comparison_Arg (T : Entity_Id) return Boolean is
- begin
- return Is_Discrete_Type (T)
- or else Is_Real_Type (T)
- or else (Is_Array_Type (T) and then Number_Dimensions (T) = 1
- and then Is_Discrete_Type (Component_Type (T))
- and then (not Is_Private_Composite (T)
- or else In_Instance)
- and then (not Is_Limited_Composite (T)
- or else In_Instance))
- or else Is_String_Type (T);
- end Valid_Comparison_Arg;
-
- ---------------------
- -- Write_Overloads --
- ---------------------
-
- procedure Write_Overloads (N : Node_Id) is
- I : Interp_Index;
- It : Interp;
- Nam : Entity_Id;
-
- begin
- if not Is_Overloaded (N) then
- Write_Str ("Non-overloaded entity ");
- Write_Eol;
- Write_Entity_Info (Entity (N), " ");
-
- else
- Get_First_Interp (N, I, It);
- Write_Str ("Overloaded entity ");
- Write_Eol;
- Nam := It.Nam;
-
- while Present (Nam) loop
- Write_Entity_Info (Nam, " ");
- Write_Str ("=================");
- Write_Eol;
- Get_Next_Interp (I, It);
- Nam := It.Nam;
- end loop;
- end if;
- end Write_Overloads;
-
-end Sem_Type;