summaryrefslogtreecommitdiffstats
path: root/gcc/ada/sem_disp.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_disp.adb')
-rw-r--r--gcc/ada/sem_disp.adb170
1 files changed, 135 insertions, 35 deletions
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 31dae9026e9..53fc27b15a7 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -6,9 +6,9 @@
-- --
-- B o d y --
-- --
--- $Revision: 1.114 $
+-- $Revision$
-- --
--- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2002 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- --
@@ -31,13 +31,18 @@ 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 Hostparm; use Hostparm;
with Nlists; use Nlists;
+with Opt; use Opt;
with Output; use Output;
+with Sem; use Sem;
with Sem_Ch6; use Sem_Ch6;
with Sem_Eval; use Sem_Eval;
with Sem_Util; use Sem_Util;
+with Snames; use Snames;
with Sinfo; use Sinfo;
with Uintp; use Uintp;
@@ -267,29 +272,42 @@ package body Sem_Disp is
if Is_Abstract (Func)
and then No (Controlling_Argument (N))
then
- Par := Parent (N);
+ if Present (Alias (Func))
+ and then not Is_Abstract (Alias (Func))
+ and then No (DTC_Entity (Func))
+ then
+ -- private overriding of inherited abstract operation,
+ -- call is legal
- while Present (Par) loop
+ Set_Entity (Name (N), Alias (Func));
+ return;
- 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
- then
- return;
+ else
+ Par := Parent (N);
- elsif Nkind (Par) = N_Qualified_Expression
- or else Nkind (Par) = N_Unchecked_Type_Conversion
- then
- Par := Parent (Par);
+ while Present (Par) loop
- else
- Error_Msg_N
- ("call to abstract function must be dispatching", N);
- return;
- end if;
- end 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 (Func))
+ then
+ return;
+
+ elsif Nkind (Par) = N_Qualified_Expression
+ or else Nkind (Par) = N_Unchecked_Type_Conversion
+ then
+ Par := Parent (Par);
+
+ else
+ Error_Msg_N
+ ("call to abstract function must be dispatching", N);
+ return;
+ end if;
+ end loop;
+ end if;
end if;
end Check_Dispatching_Context;
@@ -403,7 +421,7 @@ package body Sem_Disp is
---------------------------------
procedure Check_Dispatching_Operation (Subp, Old_Subp : Entity_Id) is
- Tagged_Seen : Entity_Id;
+ Tagged_Type : Entity_Id;
Has_Dispatching_Parent : Boolean := False;
Body_Is_Last_Primitive : Boolean := False;
@@ -413,7 +431,7 @@ package body Sem_Disp is
end if;
Set_Is_Dispatching_Operation (Subp, False);
- Tagged_Seen := Find_Dispatching_Type (Subp);
+ Tagged_Type := Find_Dispatching_Type (Subp);
-- If Subp is derived from a dispatching operation then it should
-- always be treated as dispatching. In this case various checks
@@ -424,13 +442,13 @@ package body Sem_Disp is
Has_Dispatching_Parent := Present (Alias (Subp))
and then Is_Dispatching_Operation (Alias (Subp));
- if No (Tagged_Seen) then
+ if No (Tagged_Type) then
return;
-- The subprograms build internally after the freezing point (such as
-- the Init procedure) are not primitives
- elsif Is_Frozen (Tagged_Seen)
+ elsif Is_Frozen (Tagged_Type)
and then not Comes_From_Source (Subp)
and then not Has_Dispatching_Parent
then
@@ -451,7 +469,7 @@ package body Sem_Disp is
and then not Has_Dispatching_Parent
then
if not Comes_From_Source (Subp)
- or else (Present (Old_Subp) and then not Is_Frozen (Tagged_Seen))
+ or else (Present (Old_Subp) and then not Is_Frozen (Tagged_Type))
then
null;
@@ -471,7 +489,7 @@ package body Sem_Disp is
then
declare
Subp_Body : constant Node_Id := Unit_Declaration_Node (Subp);
- Decl_Item : Node_Id := Next (Parent (Tagged_Seen));
+ Decl_Item : Node_Id := Next (Parent (Tagged_Type));
begin
-- ??? The checks here for whether the type has been
@@ -548,7 +566,7 @@ package body Sem_Disp is
-- case it looks suspiciously like an attempt to define a primitive
-- operation.
- elsif not Is_Frozen (Tagged_Seen) then
+ elsif not Is_Frozen (Tagged_Type) then
Error_Msg_N
("?not dispatching (must be defined in a package spec)", Subp);
return;
@@ -563,33 +581,105 @@ package body Sem_Disp is
-- Now, we are sure that the scope is a package spec. If the subprogram
-- is declared after the freezing point ot the type that's an error
- elsif Is_Frozen (Tagged_Seen) and then not Has_Dispatching_Parent then
+ 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_Seen),
- Tagged_Seen);
+ Freeze_Node (Tagged_Type),
+ Tagged_Type);
return;
end if;
- Check_Controlling_Formals (Tagged_Seen, Subp);
+ Check_Controlling_Formals (Tagged_Type, Subp);
-- Now it should be a correct primitive operation, put it in the list
if Present (Old_Subp) then
Check_Subtype_Conformant (Subp, Old_Subp);
- Override_Dispatching_Operation (Tagged_Seen, Old_Subp, Subp);
+ Override_Dispatching_Operation (Tagged_Type, Old_Subp, Subp);
else
- Add_Dispatching_Operation (Tagged_Seen, Subp);
+ Add_Dispatching_Operation (Tagged_Type, Subp);
end if;
Set_Is_Dispatching_Operation (Subp, True);
if not Body_Is_Last_Primitive then
Set_DT_Position (Subp, No_Uint);
- end if;
+ 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 : 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 Name_Id :=
+ (Name_uDeep_Initialize,
+ Name_uDeep_Adjust,
+ Name_uDeep_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 zero-cost is 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);
+
+ if Exception_Mechanism = Front_End_ZCX then
+ Set_Has_Subprogram_Descriptor (Old_Spec, False);
+ Set_Handler_Records (Old_Spec, No_List);
+ Set_Is_Eliminated (Old_Spec);
+ end if;
+ 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 one 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;
------------------------------------------
@@ -777,6 +867,16 @@ package body Sem_Disp is
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;
OpenPOWER on IntegriCloud