aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/gcc/ada/sem_disp.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/gcc/ada/sem_disp.adb')
-rw-r--r--gcc-4.4.3/gcc/ada/sem_disp.adb1692
1 files changed, 0 insertions, 1692 deletions
diff --git a/gcc-4.4.3/gcc/ada/sem_disp.adb b/gcc-4.4.3/gcc/ada/sem_disp.adb
deleted file mode 100644
index a8eb3df52..000000000
--- a/gcc-4.4.3/gcc/ada/sem_disp.adb
+++ /dev/null
@@ -1,1692 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT COMPILER COMPONENTS --
--- --
--- S E M _ D I S P --
--- --
--- B o d y --
--- --
--- Copyright (C) 1992-2008, 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 3, 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 COPYING3. If not, go to --
--- http://www.gnu.org/licenses for a complete copy of the license. --
--- --
--- 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 Elists; use Elists;
-with Einfo; use Einfo;
-with Exp_Disp; use Exp_Disp;
-with Exp_Ch7; use Exp_Ch7;
-with Exp_Tss; use Exp_Tss;
-with Errout; use Errout;
-with Lib.Xref; use Lib.Xref;
-with Namet; use Namet;
-with Nlists; use Nlists;
-with Nmake; use Nmake;
-with Opt; use Opt;
-with Output; use Output;
-with Restrict; use Restrict;
-with Rident; use Rident;
-with Sem; use Sem;
-with Sem_Ch6; use Sem_Ch6;
-with Sem_Eval; use Sem_Eval;
-with Sem_Type; use Sem_Type;
-with Sem_Util; use Sem_Util;
-with Snames; use Snames;
-with Stand; use Stand;
-with Sinfo; use Sinfo;
-with Targparm; use Targparm;
-with Tbuild; use Tbuild;
-with Uintp; use Uintp;
-
-package body Sem_Disp is
-
- -----------------------
- -- Local Subprograms --
- -----------------------
-
- procedure Add_Dispatching_Operation
- (Tagged_Type : Entity_Id;
- New_Op : Entity_Id);
- -- Add New_Op in the list of primitive operations of Tagged_Type
-
- function Check_Controlling_Type
- (T : Entity_Id;
- Subp : Entity_Id) return Entity_Id;
- -- T is the tagged type of a formal parameter or the result of Subp.
- -- If the subprogram has a controlling parameter or result that matches
- -- the type, then returns the tagged type of that parameter or result
- -- (returning the designated tagged type in the case of an access
- -- parameter); otherwise returns empty.
-
- -------------------------------
- -- Add_Dispatching_Operation --
- -------------------------------
-
- procedure Add_Dispatching_Operation
- (Tagged_Type : Entity_Id;
- New_Op : Entity_Id)
- is
- List : constant Elist_Id := Primitive_Operations (Tagged_Type);
-
- begin
- -- The dispatching operation may already be on the list, if it the
- -- wrapper for an inherited function of a null extension (see exp_ch3
- -- for the construction of function wrappers). The list of primitive
- -- operations must not contain duplicates.
-
- Append_Unique_Elmt (New_Op, List);
- end Add_Dispatching_Operation;
-
- -------------------------------
- -- Check_Controlling_Formals --
- -------------------------------
-
- procedure Check_Controlling_Formals
- (Typ : Entity_Id;
- Subp : Entity_Id)
- is
- Formal : Entity_Id;
- Ctrl_Type : Entity_Id;
-
- begin
- Formal := First_Formal (Subp);
-
- while Present (Formal) loop
- Ctrl_Type := Check_Controlling_Type (Etype (Formal), Subp);
-
- if Present (Ctrl_Type) then
-
- -- When the controlling type is concurrent and declared within a
- -- generic or inside an instance, use its corresponding record
- -- type.
-
- if Is_Concurrent_Type (Ctrl_Type)
- and then Present (Corresponding_Record_Type (Ctrl_Type))
- then
- Ctrl_Type := Corresponding_Record_Type (Ctrl_Type);
- end if;
-
- if Ctrl_Type = Typ then
- Set_Is_Controlling_Formal (Formal);
-
- -- Ada 2005 (AI-231): Anonymous access types used in
- -- controlling parameters exclude null because it is necessary
- -- to read the tag to dispatch, and null has no tag.
-
- if Ekind (Etype (Formal)) = E_Anonymous_Access_Type then
- Set_Can_Never_Be_Null (Etype (Formal));
- Set_Is_Known_Non_Null (Etype (Formal));
- end if;
-
- -- Check that the parameter's nominal subtype statically
- -- matches the first subtype.
-
- if Ekind (Etype (Formal)) = E_Anonymous_Access_Type then
- if not Subtypes_Statically_Match
- (Typ, Designated_Type (Etype (Formal)))
- then
- Error_Msg_N
- ("parameter subtype does not match controlling type",
- Formal);
- end if;
-
- elsif not Subtypes_Statically_Match (Typ, Etype (Formal)) then
- Error_Msg_N
- ("parameter subtype does not match controlling type",
- Formal);
- end if;
-
- if Present (Default_Value (Formal)) then
-
- -- In Ada 2005, access parameters can have defaults
-
- if Ekind (Etype (Formal)) = E_Anonymous_Access_Type
- and then Ada_Version < Ada_05
- then
- Error_Msg_N
- ("default not allowed for controlling access parameter",
- Default_Value (Formal));
-
- elsif not Is_Tag_Indeterminate (Default_Value (Formal)) then
- Error_Msg_N
- ("default expression must be a tag indeterminate" &
- " function call", Default_Value (Formal));
- end if;
- end if;
-
- elsif Comes_From_Source (Subp) then
- Error_Msg_N
- ("operation can be dispatching in only one type", Subp);
- end if;
- end if;
-
- Next_Formal (Formal);
- end loop;
-
- if Present (Etype (Subp)) then
- Ctrl_Type := Check_Controlling_Type (Etype (Subp), Subp);
-
- if Present (Ctrl_Type) then
- if Ctrl_Type = Typ then
- Set_Has_Controlling_Result (Subp);
-
- -- Check that result subtype statically matches first subtype
- -- (Ada 2005) : Subp may have a controlling access result.
-
- if Subtypes_Statically_Match (Typ, Etype (Subp))
- or else (Ekind (Etype (Subp)) = E_Anonymous_Access_Type
- and then
- Subtypes_Statically_Match
- (Typ, Designated_Type (Etype (Subp))))
- then
- null;
-
- else
- Error_Msg_N
- ("result subtype does not match controlling type", Subp);
- end if;
-
- elsif Comes_From_Source (Subp) then
- Error_Msg_N
- ("operation can be dispatching in only one type", Subp);
- end if;
- end if;
- end if;
- end Check_Controlling_Formals;
-
- ----------------------------
- -- Check_Controlling_Type --
- ----------------------------
-
- function Check_Controlling_Type
- (T : Entity_Id;
- Subp : Entity_Id) return Entity_Id
- is
- Tagged_Type : Entity_Id := Empty;
-
- begin
- if Is_Tagged_Type (T) then
- if Is_First_Subtype (T) then
- Tagged_Type := T;
- else
- Tagged_Type := Base_Type (T);
- end if;
-
- elsif Ekind (T) = E_Anonymous_Access_Type
- and then Is_Tagged_Type (Designated_Type (T))
- then
- if Ekind (Designated_Type (T)) /= E_Incomplete_Type then
- if Is_First_Subtype (Designated_Type (T)) then
- Tagged_Type := Designated_Type (T);
- else
- Tagged_Type := Base_Type (Designated_Type (T));
- end if;
-
- -- Ada 2005 : an incomplete type can be tagged. An operation with
- -- an access parameter of the type is dispatching.
-
- elsif Scope (Designated_Type (T)) = Current_Scope then
- Tagged_Type := Designated_Type (T);
-
- -- Ada 2005 (AI-50217)
-
- elsif From_With_Type (Designated_Type (T))
- and then Present (Non_Limited_View (Designated_Type (T)))
- then
- if Is_First_Subtype (Non_Limited_View (Designated_Type (T))) then
- Tagged_Type := Non_Limited_View (Designated_Type (T));
- else
- Tagged_Type := Base_Type (Non_Limited_View
- (Designated_Type (T)));
- end if;
- end if;
- end if;
-
- if No (Tagged_Type)
- or else Is_Class_Wide_Type (Tagged_Type)
- then
- return Empty;
-
- -- The dispatching type and the primitive operation must be defined
- -- in the same scope, except in the case of internal operations and
- -- formal abstract subprograms.
-
- elsif ((Scope (Subp) = Scope (Tagged_Type) or else Is_Internal (Subp))
- and then (not Is_Generic_Type (Tagged_Type)
- or else not Comes_From_Source (Subp)))
- or else
- (Is_Formal_Subprogram (Subp) and then Is_Abstract_Subprogram (Subp))
- or else
- (Nkind (Parent (Parent (Subp))) = N_Subprogram_Renaming_Declaration
- and then
- Present (Corresponding_Formal_Spec (Parent (Parent (Subp))))
- and then
- Is_Abstract_Subprogram (Subp))
- then
- return Tagged_Type;
-
- else
- return Empty;
- end if;
- end Check_Controlling_Type;
-
- ----------------------------
- -- Check_Dispatching_Call --
- ----------------------------
-
- procedure Check_Dispatching_Call (N : Node_Id) is
- Loc : constant Source_Ptr := Sloc (N);
- Actual : Node_Id;
- Formal : Entity_Id;
- Control : Node_Id := Empty;
- Func : Entity_Id;
- Subp_Entity : Entity_Id;
- Indeterm_Ancestor_Call : Boolean := False;
- Indeterm_Ctrl_Type : Entity_Id;
-
- Static_Tag : Node_Id := Empty;
- -- If a controlling formal has a statically tagged actual, the tag of
- -- this actual is to be used for any tag-indeterminate actual
-
- procedure Check_Dispatching_Context;
- -- If the call is tag-indeterminate and the entity being called is
- -- abstract, verify that the context is a call that will eventually
- -- provide a tag for dispatching, or has provided one already.
-
- -------------------------------
- -- Check_Dispatching_Context --
- -------------------------------
-
- procedure Check_Dispatching_Context is
- Subp : constant Entity_Id := Entity (Name (N));
- Par : Node_Id;
-
- begin
- if Is_Abstract_Subprogram (Subp)
- and then No (Controlling_Argument (N))
- then
- if Present (Alias (Subp))
- and then not Is_Abstract_Subprogram (Alias (Subp))
- and then No (DTC_Entity (Subp))
- then
- -- Private overriding of inherited abstract operation,
- -- call is legal.
-
- Set_Entity (Name (N), Alias (Subp));
- return;
-
- else
- Par := Parent (N);
-
- while Present (Par) loop
-
- if (Nkind (Par) = N_Function_Call or else
- Nkind (Par) = N_Procedure_Call_Statement or else
- Nkind (Par) = N_Assignment_Statement or else
- Nkind (Par) = N_Op_Eq or else
- Nkind (Par) = N_Op_Ne)
- and then Is_Tagged_Type (Etype (Subp))
- then
- return;
-
- elsif Nkind (Par) = N_Qualified_Expression
- or else Nkind (Par) = N_Unchecked_Type_Conversion
- then
- Par := Parent (Par);
-
- else
- if Ekind (Subp) = E_Function then
- Error_Msg_N
- ("call to abstract function must be dispatching", N);
-
- -- This error can occur for a procedure in the case of a
- -- call to an abstract formal procedure with a statically
- -- tagged operand.
-
- else
- Error_Msg_N
- ("call to abstract procedure must be dispatching",
- N);
- end if;
-
- return;
- end if;
- end loop;
- end if;
- end if;
- end Check_Dispatching_Context;
-
- -- Start of processing for Check_Dispatching_Call
-
- begin
- -- Find a controlling argument, if any
-
- if Present (Parameter_Associations (N)) then
- Actual := First_Actual (N);
-
- Subp_Entity := Entity (Name (N));
- Formal := First_Formal (Subp_Entity);
-
- while Present (Actual) loop
- Control := Find_Controlling_Arg (Actual);
- exit when Present (Control);
-
- -- Check for the case where the actual is a tag-indeterminate call
- -- whose result type is different than the tagged type associated
- -- with the containing call, but is an ancestor of the type.
-
- if Is_Controlling_Formal (Formal)
- and then Is_Tag_Indeterminate (Actual)
- and then Base_Type (Etype (Actual)) /= Base_Type (Etype (Formal))
- and then Is_Ancestor (Etype (Actual), Etype (Formal))
- then
- Indeterm_Ancestor_Call := True;
- Indeterm_Ctrl_Type := Etype (Formal);
-
- -- If the formal is controlling but the actual is not, the type
- -- of the actual is statically known, and may be used as the
- -- controlling tag for some other-indeterminate actual.
-
- elsif Is_Controlling_Formal (Formal)
- and then Is_Entity_Name (Actual)
- and then Is_Tagged_Type (Etype (Actual))
- then
- Static_Tag := Actual;
- end if;
-
- Next_Actual (Actual);
- Next_Formal (Formal);
- end loop;
-
- -- If the call doesn't have a controlling actual but does have
- -- an indeterminate actual that requires dispatching treatment,
- -- then an object is needed that will serve as the controlling
- -- argument for a dispatching call on the indeterminate actual.
- -- This can only occur in the unusual situation of a default
- -- actual given by a tag-indeterminate call and where the type
- -- of the call is an ancestor of the type associated with a
- -- containing call to an inherited operation (see AI-239).
- -- Rather than create an object of the tagged type, which would
- -- be problematic for various reasons (default initialization,
- -- discriminants), the tag of the containing call's associated
- -- tagged type is directly used to control the dispatching.
-
- if No (Control)
- and then Indeterm_Ancestor_Call
- and then No (Static_Tag)
- then
- Control :=
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Indeterm_Ctrl_Type, Loc),
- Attribute_Name => Name_Tag);
-
- Analyze (Control);
- end if;
-
- if Present (Control) then
-
- -- Verify that no controlling arguments are statically tagged
-
- if Debug_Flag_E then
- Write_Str ("Found Dispatching call");
- Write_Int (Int (N));
- Write_Eol;
- end if;
-
- Actual := First_Actual (N);
-
- while Present (Actual) loop
- if Actual /= Control then
-
- if not Is_Controlling_Actual (Actual) then
- null; -- Can be anything
-
- elsif Is_Dynamically_Tagged (Actual) then
- null; -- Valid parameter
-
- elsif Is_Tag_Indeterminate (Actual) then
-
- -- The tag is inherited from the enclosing call (the
- -- node we are currently analyzing). Explicitly expand
- -- the actual, since the previous call to Expand
- -- (from Resolve_Call) had no way of knowing about
- -- the required dispatching.
-
- Propagate_Tag (Control, Actual);
-
- else
- Error_Msg_N
- ("controlling argument is not dynamically tagged",
- Actual);
- return;
- end if;
- end if;
-
- Next_Actual (Actual);
- end loop;
-
- -- Mark call as a dispatching call
-
- Set_Controlling_Argument (N, Control);
- Check_Restriction (No_Dispatching_Calls, N);
-
- -- If there is a statically tagged actual and a tag-indeterminate
- -- call to a function of the ancestor (such as that provided by a
- -- default), then treat this as a dispatching call and propagate
- -- the tag to the tag-indeterminate call(s).
-
- elsif Present (Static_Tag) and then Indeterm_Ancestor_Call then
- Control :=
- Make_Attribute_Reference (Loc,
- Prefix =>
- New_Occurrence_Of (Etype (Static_Tag), Loc),
- Attribute_Name => Name_Tag);
-
- Analyze (Control);
-
- Actual := First_Actual (N);
- Formal := First_Formal (Subp_Entity);
- while Present (Actual) loop
- if Is_Tag_Indeterminate (Actual)
- and then Is_Controlling_Formal (Formal)
- then
- Propagate_Tag (Control, Actual);
- end if;
-
- Next_Actual (Actual);
- Next_Formal (Formal);
- end loop;
-
- Check_Dispatching_Context;
-
- else
- -- The call is not dispatching, so check that there aren't any
- -- tag-indeterminate abstract calls left.
-
- Actual := First_Actual (N);
- while Present (Actual) loop
- if Is_Tag_Indeterminate (Actual) then
-
- -- Function call case
-
- if Nkind (Original_Node (Actual)) = N_Function_Call then
- Func := Entity (Name (Original_Node (Actual)));
-
- -- If the actual is an attribute then it can't be abstract
- -- (the only current case of a tag-indeterminate attribute
- -- is the stream Input attribute).
-
- elsif
- Nkind (Original_Node (Actual)) = N_Attribute_Reference
- then
- Func := Empty;
-
- -- Only other possibility is a qualified expression whose
- -- constituent expression is itself a call.
-
- else
- Func :=
- Entity (Name
- (Original_Node
- (Expression (Original_Node (Actual)))));
- end if;
-
- if Present (Func) and then Is_Abstract_Subprogram (Func) then
- Error_Msg_N (
- "call to abstract function must be dispatching", N);
- end if;
- end if;
-
- Next_Actual (Actual);
- end loop;
-
- Check_Dispatching_Context;
- end if;
-
- else
- -- If dispatching on result, the enclosing call, if any, will
- -- determine the controlling argument. Otherwise this is the
- -- primitive operation of the root type.
-
- Check_Dispatching_Context;
- end if;
- end Check_Dispatching_Call;
-
- ---------------------------------
- -- Check_Dispatching_Operation --
- ---------------------------------
-
- procedure Check_Dispatching_Operation (Subp, Old_Subp : Entity_Id) is
- Tagged_Type : Entity_Id;
- Has_Dispatching_Parent : Boolean := False;
- Body_Is_Last_Primitive : Boolean := False;
-
- function Is_Visibly_Controlled (T : Entity_Id) return Boolean;
- -- Check whether T is derived from a visibly controlled type.
- -- This is true if the root type is declared in Ada.Finalization.
- -- If T is derived instead from a private type whose full view
- -- is controlled, an explicit Initialize/Adjust/Finalize subprogram
- -- does not override the inherited one.
-
- ---------------------------
- -- Is_Visibly_Controlled --
- ---------------------------
-
- function Is_Visibly_Controlled (T : Entity_Id) return Boolean is
- Root : constant Entity_Id := Root_Type (T);
- begin
- return Chars (Scope (Root)) = Name_Finalization
- and then Chars (Scope (Scope (Root))) = Name_Ada
- and then Scope (Scope (Scope (Root))) = Standard_Standard;
- end Is_Visibly_Controlled;
-
- -- Start of processing for Check_Dispatching_Operation
-
- begin
- if Ekind (Subp) /= E_Procedure and then Ekind (Subp) /= E_Function then
- return;
- end if;
-
- Set_Is_Dispatching_Operation (Subp, False);
- Tagged_Type := Find_Dispatching_Type (Subp);
-
- -- Ada 2005 (AI-345)
-
- if Ada_Version = Ada_05
- and then Present (Tagged_Type)
- and then Is_Concurrent_Type (Tagged_Type)
- then
- -- Protect the frontend against previously detected errors
-
- if No (Corresponding_Record_Type (Tagged_Type)) then
- return;
- end if;
-
- Tagged_Type := Corresponding_Record_Type (Tagged_Type);
- end if;
-
- -- (AI-345): The task body procedure is not a primitive of the tagged
- -- type
-
- if Present (Tagged_Type)
- and then Is_Concurrent_Record_Type (Tagged_Type)
- and then Present (Corresponding_Concurrent_Type (Tagged_Type))
- and then Is_Task_Type (Corresponding_Concurrent_Type (Tagged_Type))
- and then Subp = Get_Task_Body_Procedure
- (Corresponding_Concurrent_Type (Tagged_Type))
- then
- return;
- end if;
-
- -- If Subp is derived from a dispatching operation then it should
- -- always be treated as dispatching. In this case various checks
- -- below will be bypassed. Makes sure that late declarations for
- -- inherited private subprograms are treated as dispatching, even
- -- if the associated tagged type is already frozen.
-
- Has_Dispatching_Parent :=
- Present (Alias (Subp))
- and then Is_Dispatching_Operation (Alias (Subp));
-
- if No (Tagged_Type) then
-
- -- Ada 2005 (AI-251): Check that Subp is not a primitive associated
- -- with an abstract interface type unless the interface acts as a
- -- parent type in a derivation. If the interface type is a formal
- -- type then the operation is not primitive and therefore legal.
-
- declare
- E : Entity_Id;
- Typ : Entity_Id;
-
- begin
- E := First_Entity (Subp);
- while Present (E) loop
-
- -- For an access parameter, check designated type.
-
- if Ekind (Etype (E)) = E_Anonymous_Access_Type then
- Typ := Designated_Type (Etype (E));
- else
- Typ := Etype (E);
- end if;
-
- if Comes_From_Source (Subp)
- and then Is_Interface (Typ)
- and then not Is_Class_Wide_Type (Typ)
- and then not Is_Derived_Type (Typ)
- and then not Is_Generic_Type (Typ)
- and then not In_Instance
- then
- Error_Msg_N ("?declaration of& is too late!", Subp);
- Error_Msg_NE
- ("\spec should appear immediately after declaration of &!",
- Subp, Typ);
- exit;
- end if;
-
- Next_Entity (E);
- end loop;
-
- -- In case of functions check also the result type
-
- if Ekind (Subp) = E_Function then
- if Is_Access_Type (Etype (Subp)) then
- Typ := Designated_Type (Etype (Subp));
- else
- Typ := Etype (Subp);
- end if;
-
- if not Is_Class_Wide_Type (Typ)
- and then Is_Interface (Typ)
- and then not Is_Derived_Type (Typ)
- then
- Error_Msg_N ("?declaration of& is too late!", Subp);
- Error_Msg_NE
- ("\spec should appear immediately after declaration of &!",
- Subp, Typ);
- end if;
- end if;
- end;
-
- return;
-
- -- The subprograms build internally after the freezing point (such as
- -- the Init procedure) are not primitives
-
- elsif Is_Frozen (Tagged_Type)
- and then not Comes_From_Source (Subp)
- and then not Has_Dispatching_Parent
- then
- return;
-
- -- The operation may be a child unit, whose scope is the defining
- -- package, but which is not a primitive operation of the type.
-
- elsif Is_Child_Unit (Subp) then
- return;
-
- -- If the subprogram is not defined in a package spec, the only case
- -- where it can be a dispatching op is when it overrides an operation
- -- before the freezing point of the type.
-
- elsif ((not Is_Package_Or_Generic_Package (Scope (Subp)))
- or else In_Package_Body (Scope (Subp)))
- and then not Has_Dispatching_Parent
- then
- if not Comes_From_Source (Subp)
- or else (Present (Old_Subp) and then not Is_Frozen (Tagged_Type))
- then
- null;
-
- -- If the type is already frozen, the overriding is not allowed
- -- except when Old_Subp is not a dispatching operation (which
- -- can occur when Old_Subp was inherited by an untagged type).
- -- However, a body with no previous spec freezes the type "after"
- -- its declaration, and therefore is a legal overriding (unless
- -- the type has already been frozen). Only the first such body
- -- is legal.
-
- elsif Present (Old_Subp)
- and then Is_Dispatching_Operation (Old_Subp)
- then
- if Comes_From_Source (Subp)
- and then
- (Nkind (Unit_Declaration_Node (Subp)) = N_Subprogram_Body
- or else Nkind (Unit_Declaration_Node (Subp)) in N_Body_Stub)
- then
- declare
- Subp_Body : constant Node_Id := Unit_Declaration_Node (Subp);
- Decl_Item : Node_Id := Next (Parent (Tagged_Type));
-
- begin
- -- ??? The checks here for whether the type has been
- -- frozen prior to the new body are not complete. It's
- -- not simple to check frozenness at this point since
- -- the body has already caused the type to be prematurely
- -- frozen in Analyze_Declarations, but we're forced to
- -- recheck this here because of the odd rule interpretation
- -- that allows the overriding if the type wasn't frozen
- -- prior to the body. The freezing action should probably
- -- be delayed until after the spec is seen, but that's
- -- a tricky change to the delicate freezing code.
-
- -- Look at each declaration following the type up
- -- until the new subprogram body. If any of the
- -- declarations is a body then the type has been
- -- frozen already so the overriding primitive is
- -- illegal.
-
- while Present (Decl_Item)
- and then (Decl_Item /= Subp_Body)
- loop
- if Comes_From_Source (Decl_Item)
- and then (Nkind (Decl_Item) in N_Proper_Body
- or else Nkind (Decl_Item) in N_Body_Stub)
- then
- Error_Msg_N ("overriding of& is too late!", Subp);
- Error_Msg_N
- ("\spec should appear immediately after the type!",
- Subp);
- exit;
- end if;
-
- Next (Decl_Item);
- end loop;
-
- -- If the subprogram doesn't follow in the list of
- -- declarations including the type then the type
- -- has definitely been frozen already and the body
- -- is illegal.
-
- if No (Decl_Item) then
- Error_Msg_N ("overriding of& is too late!", Subp);
- Error_Msg_N
- ("\spec should appear immediately after the type!",
- Subp);
-
- elsif Is_Frozen (Subp) then
-
- -- The subprogram body declares a primitive operation.
- -- if the subprogram is already frozen, we must update
- -- its dispatching information explicitly here. The
- -- information is taken from the overridden subprogram.
- -- We must also generate a cross-reference entry because
- -- references to other primitives were already created
- -- when type was frozen.
-
- Body_Is_Last_Primitive := True;
-
- if Present (DTC_Entity (Old_Subp)) then
- Set_DTC_Entity (Subp, DTC_Entity (Old_Subp));
- Set_DT_Position (Subp, DT_Position (Old_Subp));
-
- if not Restriction_Active (No_Dispatching_Calls) then
- if Building_Static_DT (Tagged_Type) then
-
- -- If the static dispatch table has not been
- -- built then there is nothing else to do now;
- -- otherwise we notify that we cannot build the
- -- static dispatch table.
-
- if Has_Dispatch_Table (Tagged_Type) then
- Error_Msg_N
- ("overriding of& is too late for building" &
- " static dispatch tables!", Subp);
- Error_Msg_N
- ("\spec should appear immediately after" &
- " the type!", Subp);
- end if;
-
- else
- Register_Primitive (Sloc (Subp_Body),
- Prim => Subp,
- Ins_Nod => Subp_Body);
- end if;
-
- Generate_Reference (Tagged_Type, Subp, 'p', False);
- end if;
- end if;
- end if;
- end;
-
- else
- Error_Msg_N ("overriding of& is too late!", Subp);
- Error_Msg_N
- ("\subprogram spec should appear immediately after the type!",
- Subp);
- end if;
-
- -- If the type is not frozen yet and we are not in the overriding
- -- case it looks suspiciously like an attempt to define a primitive
- -- operation.
-
- elsif not Is_Frozen (Tagged_Type) then
- Error_Msg_N
- ("?not dispatching (must be defined in a package spec)", Subp);
- return;
-
- -- When the type is frozen, it is legitimate to define a new
- -- non-primitive operation.
-
- else
- return;
- end if;
-
- -- Now, we are sure that the scope is a package spec. If the subprogram
- -- is declared after the freezing point of the type that's an error
-
- elsif Is_Frozen (Tagged_Type) and then not Has_Dispatching_Parent then
- Error_Msg_N ("this primitive operation is declared too late", Subp);
- Error_Msg_NE
- ("?no primitive operations for& after this line",
- Freeze_Node (Tagged_Type),
- Tagged_Type);
- return;
- end if;
-
- Check_Controlling_Formals (Tagged_Type, Subp);
-
- -- Now it should be a correct primitive operation, put it in the list
-
- if Present (Old_Subp) then
-
- -- If the type has interfaces we complete this check after we
- -- set attribute Is_Dispatching_Operation
-
- Check_Subtype_Conformant (Subp, Old_Subp);
-
- if (Chars (Subp) = Name_Initialize
- or else Chars (Subp) = Name_Adjust
- or else Chars (Subp) = Name_Finalize)
- and then Is_Controlled (Tagged_Type)
- and then not Is_Visibly_Controlled (Tagged_Type)
- then
- Set_Is_Overriding_Operation (Subp, False);
- Error_Msg_NE
- ("operation does not override inherited&?", Subp, Subp);
- else
- Override_Dispatching_Operation (Tagged_Type, Old_Subp, Subp);
- Set_Is_Overriding_Operation (Subp);
-
- -- Ada 2005 (AI-251): In case of late overriding of a primitive
- -- that covers abstract interface subprograms we must register it
- -- in all the secondary dispatch tables associated with abstract
- -- interfaces.
-
- if Body_Is_Last_Primitive then
- declare
- Subp_Body : constant Node_Id := Unit_Declaration_Node (Subp);
- Elmt : Elmt_Id;
- Prim : Node_Id;
-
- begin
- Elmt := First_Elmt (Primitive_Operations (Tagged_Type));
- while Present (Elmt) loop
- Prim := Node (Elmt);
-
- if Present (Alias (Prim))
- and then Present (Interface_Alias (Prim))
- and then Alias (Prim) = Subp
- then
- Register_Primitive (Sloc (Prim),
- Prim => Prim,
- Ins_Nod => Subp_Body);
- end if;
-
- Next_Elmt (Elmt);
- end loop;
-
- -- Redisplay the contents of the updated dispatch table
-
- if Debug_Flag_ZZ then
- Write_Str ("Late overriding: ");
- Write_DT (Tagged_Type);
- end if;
- end;
- end if;
- end if;
-
- -- If no old subprogram, then we add this as a dispatching operation,
- -- but we avoid doing this if an error was posted, to prevent annoying
- -- cascaded errors.
-
- elsif not Error_Posted (Subp) then
- Add_Dispatching_Operation (Tagged_Type, Subp);
- end if;
-
- Set_Is_Dispatching_Operation (Subp, True);
-
- -- Ada 2005 (AI-251): If the type implements interfaces we must check
- -- subtype conformance against all the interfaces covered by this
- -- primitive.
-
- if Present (Old_Subp)
- and then Has_Interfaces (Tagged_Type)
- then
- declare
- Ifaces_List : Elist_Id;
- Iface_Elmt : Elmt_Id;
- Iface_Prim_Elmt : Elmt_Id;
- Iface_Prim : Entity_Id;
- Ret_Typ : Entity_Id;
-
- begin
- Collect_Interfaces (Tagged_Type, Ifaces_List);
-
- Iface_Elmt := First_Elmt (Ifaces_List);
- while Present (Iface_Elmt) loop
- if not Is_Ancestor (Node (Iface_Elmt), Tagged_Type) then
- Iface_Prim_Elmt :=
- First_Elmt (Primitive_Operations (Node (Iface_Elmt)));
- while Present (Iface_Prim_Elmt) loop
- Iface_Prim := Node (Iface_Prim_Elmt);
-
- if Is_Interface_Conformant
- (Tagged_Type, Iface_Prim, Subp)
- then
- -- Handle procedures, functions whose return type
- -- matches, or functions not returning interfaces
-
- if Ekind (Subp) = E_Procedure
- or else Etype (Iface_Prim) = Etype (Subp)
- or else not Is_Interface (Etype (Iface_Prim))
- then
- Check_Subtype_Conformant
- (New_Id => Subp,
- Old_Id => Iface_Prim,
- Err_Loc => Subp,
- Skip_Controlling_Formals => True);
-
- -- Handle functions returning interfaces
-
- elsif Implements_Interface
- (Etype (Subp), Etype (Iface_Prim))
- then
- -- Temporarily force both entities to return the
- -- same type. Required because Subtype_Conformant
- -- does not handle this case.
-
- Ret_Typ := Etype (Iface_Prim);
- Set_Etype (Iface_Prim, Etype (Subp));
-
- Check_Subtype_Conformant
- (New_Id => Subp,
- Old_Id => Iface_Prim,
- Err_Loc => Subp,
- Skip_Controlling_Formals => True);
-
- Set_Etype (Iface_Prim, Ret_Typ);
- end if;
- end if;
-
- Next_Elmt (Iface_Prim_Elmt);
- end loop;
- end if;
-
- Next_Elmt (Iface_Elmt);
- end loop;
- end;
- end if;
-
- if not Body_Is_Last_Primitive then
- Set_DT_Position (Subp, No_Uint);
-
- elsif Has_Controlled_Component (Tagged_Type)
- and then
- (Chars (Subp) = Name_Initialize
- or else Chars (Subp) = Name_Adjust
- or else Chars (Subp) = Name_Finalize)
- then
- declare
- F_Node : constant Node_Id := Freeze_Node (Tagged_Type);
- Decl : Node_Id;
- Old_P : Entity_Id;
- Old_Bod : Node_Id;
- Old_Spec : Entity_Id;
-
- C_Names : constant array (1 .. 3) of Name_Id :=
- (Name_Initialize,
- Name_Adjust,
- Name_Finalize);
-
- D_Names : constant array (1 .. 3) of TSS_Name_Type :=
- (TSS_Deep_Initialize,
- TSS_Deep_Adjust,
- TSS_Deep_Finalize);
-
- begin
- -- Remove previous controlled function, which was constructed
- -- and analyzed when the type was frozen. This requires
- -- removing the body of the redefined primitive, as well as
- -- its specification if needed (there is no spec created for
- -- Deep_Initialize, see exp_ch3.adb). We must also dismantle
- -- the exception information that may have been generated for
- -- it when front end zero-cost tables are enabled.
-
- for J in D_Names'Range loop
- Old_P := TSS (Tagged_Type, D_Names (J));
-
- if Present (Old_P)
- and then Chars (Subp) = C_Names (J)
- then
- Old_Bod := Unit_Declaration_Node (Old_P);
- Remove (Old_Bod);
- Set_Is_Eliminated (Old_P);
- Set_Scope (Old_P, Scope (Current_Scope));
-
- if Nkind (Old_Bod) = N_Subprogram_Body
- and then Present (Corresponding_Spec (Old_Bod))
- then
- Old_Spec := Corresponding_Spec (Old_Bod);
- Set_Has_Completion (Old_Spec, False);
- end if;
- end if;
- end loop;
-
- Build_Late_Proc (Tagged_Type, Chars (Subp));
-
- -- The new operation is added to the actions of the freeze
- -- node for the type, but this node has already been analyzed,
- -- so we must retrieve and analyze explicitly the new body.
-
- if Present (F_Node)
- and then Present (Actions (F_Node))
- then
- Decl := Last (Actions (F_Node));
- Analyze (Decl);
- end if;
- end;
- end if;
- end Check_Dispatching_Operation;
-
- ------------------------------------------
- -- Check_Operation_From_Incomplete_Type --
- ------------------------------------------
-
- procedure Check_Operation_From_Incomplete_Type
- (Subp : Entity_Id;
- Typ : Entity_Id)
- is
- Full : constant Entity_Id := Full_View (Typ);
- Parent_Typ : constant Entity_Id := Etype (Full);
- Old_Prim : constant Elist_Id := Primitive_Operations (Parent_Typ);
- New_Prim : constant Elist_Id := Primitive_Operations (Full);
- Op1, Op2 : Elmt_Id;
- Prev : Elmt_Id := No_Elmt;
-
- function Derives_From (Proc : Entity_Id) return Boolean;
- -- Check that Subp has the signature of an operation derived from Proc.
- -- Subp has an access parameter that designates Typ.
-
- ------------------
- -- Derives_From --
- ------------------
-
- function Derives_From (Proc : Entity_Id) return Boolean is
- F1, F2 : Entity_Id;
-
- begin
- if Chars (Proc) /= Chars (Subp) then
- return False;
- end if;
-
- F1 := First_Formal (Proc);
- F2 := First_Formal (Subp);
-
- while Present (F1) and then Present (F2) loop
-
- if Ekind (Etype (F1)) = E_Anonymous_Access_Type then
-
- if Ekind (Etype (F2)) /= E_Anonymous_Access_Type then
- return False;
-
- elsif Designated_Type (Etype (F1)) = Parent_Typ
- and then Designated_Type (Etype (F2)) /= Full
- then
- return False;
- end if;
-
- elsif Ekind (Etype (F2)) = E_Anonymous_Access_Type then
- return False;
-
- elsif Etype (F1) /= Etype (F2) then
- return False;
- end if;
-
- Next_Formal (F1);
- Next_Formal (F2);
- end loop;
-
- return No (F1) and then No (F2);
- end Derives_From;
-
- -- Start of processing for Check_Operation_From_Incomplete_Type
-
- begin
- -- The operation may override an inherited one, or may be a new one
- -- altogether. The inherited operation will have been hidden by the
- -- current one at the point of the type derivation, so it does not
- -- appear in the list of primitive operations of the type. We have to
- -- find the proper place of insertion in the list of primitive opera-
- -- tions by iterating over the list for the parent type.
-
- Op1 := First_Elmt (Old_Prim);
- Op2 := First_Elmt (New_Prim);
-
- while Present (Op1) and then Present (Op2) loop
-
- if Derives_From (Node (Op1)) then
-
- if No (Prev) then
-
- -- Avoid adding it to the list of primitives if already there!
-
- if Node (Op2) /= Subp then
- Prepend_Elmt (Subp, New_Prim);
- end if;
-
- else
- Insert_Elmt_After (Subp, Prev);
- end if;
-
- return;
- end if;
-
- Prev := Op2;
- Next_Elmt (Op1);
- Next_Elmt (Op2);
- end loop;
-
- -- Operation is a new primitive
-
- Append_Elmt (Subp, New_Prim);
- end Check_Operation_From_Incomplete_Type;
-
- ---------------------------------------
- -- Check_Operation_From_Private_View --
- ---------------------------------------
-
- procedure Check_Operation_From_Private_View (Subp, Old_Subp : Entity_Id) is
- Tagged_Type : Entity_Id;
-
- begin
- if Is_Dispatching_Operation (Alias (Subp)) then
- Set_Scope (Subp, Current_Scope);
- Tagged_Type := Find_Dispatching_Type (Subp);
-
- -- Add Old_Subp to primitive operations if not already present.
-
- if Present (Tagged_Type) and then Is_Tagged_Type (Tagged_Type) then
- Append_Unique_Elmt (Old_Subp, Primitive_Operations (Tagged_Type));
-
- -- If Old_Subp isn't already marked as dispatching then
- -- this is the case of an operation of an untagged private
- -- type fulfilled by a tagged type that overrides an
- -- inherited dispatching operation, so we set the necessary
- -- dispatching attributes here.
-
- if not Is_Dispatching_Operation (Old_Subp) then
-
- -- If the untagged type has no discriminants, and the full
- -- view is constrained, there will be a spurious mismatch
- -- of subtypes on the controlling arguments, because the tagged
- -- type is the internal base type introduced in the derivation.
- -- Use the original type to verify conformance, rather than the
- -- base type.
-
- if not Comes_From_Source (Tagged_Type)
- and then Has_Discriminants (Tagged_Type)
- then
- declare
- Formal : Entity_Id;
- begin
- Formal := First_Formal (Old_Subp);
- while Present (Formal) loop
- if Tagged_Type = Base_Type (Etype (Formal)) then
- Tagged_Type := Etype (Formal);
- end if;
-
- Next_Formal (Formal);
- end loop;
- end;
-
- if Tagged_Type = Base_Type (Etype (Old_Subp)) then
- Tagged_Type := Etype (Old_Subp);
- end if;
- end if;
-
- Check_Controlling_Formals (Tagged_Type, Old_Subp);
- Set_Is_Dispatching_Operation (Old_Subp, True);
- Set_DT_Position (Old_Subp, No_Uint);
- end if;
-
- -- If the old subprogram is an explicit renaming of some other
- -- entity, it is not overridden by the inherited subprogram.
- -- Otherwise, update its alias and other attributes.
-
- if Present (Alias (Old_Subp))
- and then Nkind (Unit_Declaration_Node (Old_Subp))
- /= N_Subprogram_Renaming_Declaration
- then
- Set_Alias (Old_Subp, Alias (Subp));
-
- -- The derived subprogram should inherit the abstractness
- -- of the parent subprogram (except in the case of a function
- -- returning the type). This sets the abstractness properly
- -- for cases where a private extension may have inherited
- -- an abstract operation, but the full type is derived from
- -- a descendant type and inherits a nonabstract version.
-
- if Etype (Subp) /= Tagged_Type then
- Set_Is_Abstract_Subprogram
- (Old_Subp, Is_Abstract_Subprogram (Alias (Subp)));
- end if;
- end if;
- end if;
- end if;
- end Check_Operation_From_Private_View;
-
- --------------------------
- -- Find_Controlling_Arg --
- --------------------------
-
- function Find_Controlling_Arg (N : Node_Id) return Node_Id is
- Orig_Node : constant Node_Id := Original_Node (N);
- Typ : Entity_Id;
-
- begin
- if Nkind (Orig_Node) = N_Qualified_Expression then
- return Find_Controlling_Arg (Expression (Orig_Node));
- end if;
-
- -- Dispatching on result case. If expansion is disabled, the node still
- -- has the structure of a function call. However, if the function name
- -- is an operator and the call was given in infix form, the original
- -- node has no controlling result and we must examine the current node.
-
- if Nkind (N) = N_Function_Call
- and then Present (Controlling_Argument (N))
- and then Has_Controlling_Result (Entity (Name (N)))
- then
- return Controlling_Argument (N);
-
- -- If expansion is enabled, the call may have been transformed into
- -- an indirect call, and we need to recover the original node.
-
- elsif Nkind (Orig_Node) = N_Function_Call
- and then Present (Controlling_Argument (Orig_Node))
- and then Has_Controlling_Result (Entity (Name (Orig_Node)))
- then
- return Controlling_Argument (Orig_Node);
-
- -- Normal case
-
- elsif Is_Controlling_Actual (N)
- or else
- (Nkind (Parent (N)) = N_Qualified_Expression
- and then Is_Controlling_Actual (Parent (N)))
- then
- Typ := Etype (N);
-
- if Is_Access_Type (Typ) then
- -- In the case of an Access attribute, use the type of
- -- the prefix, since in the case of an actual for an
- -- access parameter, the attribute's type may be of a
- -- specific designated type, even though the prefix
- -- type is class-wide.
-
- if Nkind (N) = N_Attribute_Reference then
- Typ := Etype (Prefix (N));
-
- -- An allocator is dispatching if the type of qualified
- -- expression is class_wide, in which case this is the
- -- controlling type.
-
- elsif Nkind (Orig_Node) = N_Allocator
- and then Nkind (Expression (Orig_Node)) = N_Qualified_Expression
- then
- Typ := Etype (Expression (Orig_Node));
-
- else
- Typ := Designated_Type (Typ);
- end if;
- end if;
-
- if Is_Class_Wide_Type (Typ)
- or else
- (Nkind (Parent (N)) = N_Qualified_Expression
- and then Is_Access_Type (Etype (N))
- and then Is_Class_Wide_Type (Designated_Type (Etype (N))))
- then
- return N;
- end if;
- end if;
-
- return Empty;
- end Find_Controlling_Arg;
-
- ---------------------------
- -- Find_Dispatching_Type --
- ---------------------------
-
- function Find_Dispatching_Type (Subp : Entity_Id) return Entity_Id is
- Formal : Entity_Id;
- Ctrl_Type : Entity_Id;
-
- begin
- if Present (DTC_Entity (Subp)) then
- return Scope (DTC_Entity (Subp));
-
- else
- Formal := First_Formal (Subp);
- while Present (Formal) loop
- Ctrl_Type := Check_Controlling_Type (Etype (Formal), Subp);
-
- if Present (Ctrl_Type) then
- return Ctrl_Type;
- end if;
-
- Next_Formal (Formal);
- end loop;
-
- -- The subprogram may also be dispatching on result
-
- if Present (Etype (Subp)) then
- Ctrl_Type := Check_Controlling_Type (Etype (Subp), Subp);
-
- if Present (Ctrl_Type) then
- return Ctrl_Type;
- end if;
- end if;
- end if;
-
- return Empty;
- end Find_Dispatching_Type;
-
- ---------------------------------------
- -- Find_Primitive_Covering_Interface --
- ---------------------------------------
-
- function Find_Primitive_Covering_Interface
- (Tagged_Type : Entity_Id;
- Iface_Prim : Entity_Id) return Entity_Id
- is
- E : Entity_Id;
-
- begin
- pragma Assert (Is_Interface (Find_Dispatching_Type (Iface_Prim))
- or else (Present (Alias (Iface_Prim))
- and then
- Is_Interface
- (Find_Dispatching_Type (Ultimate_Alias (Iface_Prim)))));
-
- E := Current_Entity (Iface_Prim);
- while Present (E) loop
- if Is_Subprogram (E)
- and then Is_Dispatching_Operation (E)
- and then Is_Interface_Conformant (Tagged_Type, Iface_Prim, E)
- then
- return E;
- end if;
-
- E := Homonym (E);
- end loop;
-
- return Empty;
- end Find_Primitive_Covering_Interface;
-
- ---------------------------
- -- Is_Dynamically_Tagged --
- ---------------------------
-
- function Is_Dynamically_Tagged (N : Node_Id) return Boolean is
- begin
- if Nkind (N) = N_Error then
- return False;
- else
- return Find_Controlling_Arg (N) /= Empty;
- end if;
- end Is_Dynamically_Tagged;
-
- --------------------------
- -- Is_Tag_Indeterminate --
- --------------------------
-
- function Is_Tag_Indeterminate (N : Node_Id) return Boolean is
- Nam : Entity_Id;
- Actual : Node_Id;
- Orig_Node : constant Node_Id := Original_Node (N);
-
- begin
- if Nkind (Orig_Node) = N_Function_Call
- and then Is_Entity_Name (Name (Orig_Node))
- then
- Nam := Entity (Name (Orig_Node));
-
- if not Has_Controlling_Result (Nam) then
- return False;
-
- -- An explicit dereference means that the call has already been
- -- expanded and there is no tag to propagate.
-
- elsif Nkind (N) = N_Explicit_Dereference then
- return False;
-
- -- If there are no actuals, the call is tag-indeterminate
-
- elsif No (Parameter_Associations (Orig_Node)) then
- return True;
-
- else
- Actual := First_Actual (Orig_Node);
- while Present (Actual) loop
- if Is_Controlling_Actual (Actual)
- and then not Is_Tag_Indeterminate (Actual)
- then
- return False; -- one operand is dispatching
- end if;
-
- Next_Actual (Actual);
- end loop;
-
- return True;
- end if;
-
- elsif Nkind (Orig_Node) = N_Qualified_Expression then
- return Is_Tag_Indeterminate (Expression (Orig_Node));
-
- -- Case of a call to the Input attribute (possibly rewritten), which is
- -- always tag-indeterminate except when its prefix is a Class attribute.
-
- elsif Nkind (Orig_Node) = N_Attribute_Reference
- and then
- Get_Attribute_Id (Attribute_Name (Orig_Node)) = Attribute_Input
- and then
- Nkind (Prefix (Orig_Node)) /= N_Attribute_Reference
- then
- return True;
-
- -- In Ada 2005 a function that returns an anonymous access type can
- -- dispatching, and the dereference of a call to such a function
- -- is also tag-indeterminate.
-
- elsif Nkind (Orig_Node) = N_Explicit_Dereference
- and then Ada_Version >= Ada_05
- then
- return Is_Tag_Indeterminate (Prefix (Orig_Node));
-
- else
- return False;
- end if;
- end Is_Tag_Indeterminate;
-
- ------------------------------------
- -- Override_Dispatching_Operation --
- ------------------------------------
-
- procedure Override_Dispatching_Operation
- (Tagged_Type : Entity_Id;
- Prev_Op : Entity_Id;
- New_Op : Entity_Id)
- is
- Elmt : Elmt_Id;
- Prim : Node_Id;
-
- begin
- -- Diagnose failure to match No_Return in parent (Ada-2005, AI-414, but
- -- we do it unconditionally in Ada 95 now, since this is our pragma!)
-
- if No_Return (Prev_Op) and then not No_Return (New_Op) then
- Error_Msg_N ("procedure & must have No_Return pragma", New_Op);
- Error_Msg_N ("\since overridden procedure has No_Return", New_Op);
- end if;
-
- -- If there is no previous operation to override, the type declaration
- -- was malformed, and an error must have been emitted already.
-
- Elmt := First_Elmt (Primitive_Operations (Tagged_Type));
- while Present (Elmt)
- and then Node (Elmt) /= Prev_Op
- loop
- Next_Elmt (Elmt);
- end loop;
-
- if No (Elmt) then
- return;
- end if;
-
- Replace_Elmt (Elmt, New_Op);
-
- if Ada_Version >= Ada_05
- and then Has_Interfaces (Tagged_Type)
- then
- -- Ada 2005 (AI-251): Update the attribute alias of all the aliased
- -- entities of the overridden primitive to reference New_Op, and also
- -- propagate the proper value of Is_Abstract_Subprogram. Verify
- -- that the new operation is subtype conformant with the interface
- -- operations that it implements (for operations inherited from the
- -- parent itself, this check is made when building the derived type).
-
- -- Note: This code is only executed in case of late overriding
-
- Elmt := First_Elmt (Primitive_Operations (Tagged_Type));
- while Present (Elmt) loop
- Prim := Node (Elmt);
-
- if Prim = New_Op then
- null;
-
- -- Note: The check on Is_Subprogram protects the frontend against
- -- reading attributes in entities that are not yet fully decorated
-
- elsif Is_Subprogram (Prim)
- and then Present (Interface_Alias (Prim))
- and then Alias (Prim) = Prev_Op
- and then Present (Etype (New_Op))
- then
- Set_Alias (Prim, New_Op);
- Check_Subtype_Conformant (New_Op, Prim);
- Set_Is_Abstract_Subprogram (Prim,
- Is_Abstract_Subprogram (New_Op));
-
- -- Ensure that this entity will be expanded to fill the
- -- corresponding entry in its dispatch table.
-
- if not Is_Abstract_Subprogram (Prim) then
- Set_Has_Delayed_Freeze (Prim);
- end if;
- end if;
-
- Next_Elmt (Elmt);
- end loop;
- end if;
-
- if (not Is_Package_Or_Generic_Package (Current_Scope))
- or else not In_Private_Part (Current_Scope)
- then
- -- Not a private primitive
-
- null;
-
- else pragma Assert (Is_Inherited_Operation (Prev_Op));
-
- -- Make the overriding operation into an alias of the implicit one.
- -- In this fashion a call from outside ends up calling the new body
- -- even if non-dispatching, and a call from inside calls the
- -- overriding operation because it hides the implicit one. To
- -- indicate that the body of Prev_Op is never called, set its
- -- dispatch table entity to Empty.
-
- Set_Alias (Prev_Op, New_Op);
- Set_DTC_Entity (Prev_Op, Empty);
- return;
- end if;
- end Override_Dispatching_Operation;
-
- -------------------
- -- Propagate_Tag --
- -------------------
-
- procedure Propagate_Tag (Control : Node_Id; Actual : Node_Id) is
- Call_Node : Node_Id;
- Arg : Node_Id;
-
- begin
- if Nkind (Actual) = N_Function_Call then
- Call_Node := Actual;
-
- elsif Nkind (Actual) = N_Identifier
- and then Nkind (Original_Node (Actual)) = N_Function_Call
- then
- -- Call rewritten as object declaration when stack-checking
- -- is enabled. Propagate tag to expression in declaration, which
- -- is original call.
-
- Call_Node := Expression (Parent (Entity (Actual)));
-
- -- Ada 2005: If this is a dereference of a call to a function with a
- -- dispatching access-result, the tag is propagated when the dereference
- -- itself is expanded (see exp_ch6.adb) and there is nothing else to do.
-
- elsif Nkind (Actual) = N_Explicit_Dereference
- and then Nkind (Original_Node (Prefix (Actual))) = N_Function_Call
- then
- return;
-
- -- Only other possibilities are parenthesized or qualified expression,
- -- or an expander-generated unchecked conversion of a function call to
- -- a stream Input attribute.
-
- else
- Call_Node := Expression (Actual);
- end if;
-
- -- Do not set the Controlling_Argument if already set. This happens
- -- in the special case of _Input (see Exp_Attr, case Input).
-
- if No (Controlling_Argument (Call_Node)) then
- Set_Controlling_Argument (Call_Node, Control);
- end if;
-
- Arg := First_Actual (Call_Node);
-
- while Present (Arg) loop
- if Is_Tag_Indeterminate (Arg) then
- Propagate_Tag (Control, Arg);
- end if;
-
- Next_Actual (Arg);
- end loop;
-
- -- Expansion of dispatching calls is suppressed when VM_Target, because
- -- the VM back-ends directly handle the generation of dispatching
- -- calls and would have to undo any expansion to an indirect call.
-
- if VM_Target = No_VM then
- Expand_Dispatching_Call (Call_Node);
-
- -- Expansion of a dispatching call results in an indirect call, which in
- -- turn causes current values to be killed (see Resolve_Call), so on VM
- -- targets we do the call here to ensure consistent warnings between VM
- -- and non-VM targets.
-
- else
- Kill_Current_Values;
- end if;
- end Propagate_Tag;
-
-end Sem_Disp;