aboutsummaryrefslogtreecommitdiff
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.adb207
1 files changed, 146 insertions, 61 deletions
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 36efa42..064e2b5 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2021, 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- --
@@ -23,37 +23,40 @@
-- --
------------------------------------------------------------------------------
-with Aspects; use Aspects;
-with Atree; use Atree;
-with Debug; use Debug;
-with Elists; use Elists;
-with Einfo; use Einfo;
-with Exp_Disp; use Exp_Disp;
-with Exp_Util; use Exp_Util;
-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_Aux; use Sem_Aux;
-with Sem_Ch3; use Sem_Ch3;
-with Sem_Ch6; use Sem_Ch6;
-with Sem_Ch8; use Sem_Ch8;
-with Sem_Eval; use Sem_Eval;
-with Sem_Type; use Sem_Type;
-with Sem_Util; use Sem_Util;
-with Snames; use Snames;
-with Sinfo; use Sinfo;
-with Tbuild; use Tbuild;
-with Uintp; use Uintp;
-with Warnsw; use Warnsw;
+with Aspects; use Aspects;
+with Atree; use Atree;
+with Debug; use Debug;
+with Elists; use Elists;
+with Einfo; use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils; use Einfo.Utils;
+with Exp_Disp; use Exp_Disp;
+with Exp_Util; use Exp_Util;
+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_Aux; use Sem_Aux;
+with Sem_Ch6; use Sem_Ch6;
+with Sem_Ch8; use Sem_Ch8;
+with Sem_Eval; use Sem_Eval;
+with Sem_Type; use Sem_Type;
+with Sem_Util; use Sem_Util;
+with Snames; use Snames;
+with Sinfo; use Sinfo;
+with Sinfo.Nodes; use Sinfo.Nodes;
+with Sinfo.Utils; use Sinfo.Utils;
+with Tbuild; use Tbuild;
+with Uintp; use Uintp;
+with Warnsw; use Warnsw;
package body Sem_Disp is
@@ -517,6 +520,12 @@ package body Sem_Disp is
procedure Abstract_Context_Error;
-- Error for abstract call dispatching on result is not dispatching
+ function Has_Controlling_Current_Instance_Actual_In_DIC
+ (Call : Node_Id) return Boolean;
+ -- Return True if the subprogram call Call has a controlling actual
+ -- given directly by a current instance referenced within a DIC
+ -- aspect.
+
----------------------------
-- Abstract_Context_Error --
----------------------------
@@ -536,6 +545,44 @@ package body Sem_Disp is
end if;
end Abstract_Context_Error;
+ ----------------------------------------
+ -- Has_Current_Instance_Actual_In_DIC --
+ ----------------------------------------
+
+ function Has_Controlling_Current_Instance_Actual_In_DIC
+ (Call : Node_Id) return Boolean
+ is
+ A : Node_Id;
+ F : Entity_Id;
+ begin
+ F := First_Formal (Subp_Entity);
+ A := First_Actual (Call);
+
+ while Present (F) loop
+
+ -- Return True if the actual denotes a current instance (which
+ -- will be represented by an in-mode formal of the enclosing
+ -- DIC_Procedure) passed to a controlling formal. We don't have
+ -- to worry about controlling access formals here, because its
+ -- illegal to apply Access (etc.) attributes to a current
+ -- instance within an aspect (by AI12-0068).
+
+ if Is_Controlling_Formal (F)
+ and then Nkind (A) = N_Identifier
+ and then Ekind (Entity (A)) = E_In_Parameter
+ and then Is_Subprogram (Scope (Entity (A)))
+ and then Is_DIC_Procedure (Scope (Entity (A)))
+ then
+ return True;
+ end if;
+
+ Next_Formal (F);
+ Next_Actual (A);
+ end loop;
+
+ return False;
+ end Has_Controlling_Current_Instance_Actual_In_DIC;
+
-- Local variables
Scop : constant Entity_Id := Current_Scope_No_Loops;
@@ -565,29 +612,46 @@ package body Sem_Disp is
Set_Entity (Name (N), Alias (Subp));
return;
- -- An obscure special case: a null procedure may have a class-
- -- wide pre/postcondition that includes a call to an abstract
- -- subp. Calls within the expression may not have been rewritten
- -- as dispatching calls yet, because the null body appears in
- -- the current declarative part. The expression will be properly
- -- rewritten/reanalyzed when the postcondition procedure is built.
-
- -- Similarly, if this is a pre/postcondition for an abstract
- -- subprogram, it may call another abstract function which is
- -- a primitive of an abstract type. The call is non-dispatching
- -- but will be legal in overridings of the operation. However,
- -- if the call is tag-indeterminate we want to continue with
- -- with the error checking below, as this case is illegal even
- -- for abstract subprograms (see AI12-0170).
-
- elsif (Is_Subprogram (Scop)
- or else Chars (Scop) = Name_Postcondition)
+ -- If this is a pre/postcondition for an abstract subprogram,
+ -- it may call another abstract function that is a primitive
+ -- of an abstract type. The call is nondispatching but will be
+ -- legal in overridings of the operation. However, if the call
+ -- is tag-indeterminate we want to continue with with the error
+ -- checking below, as this case is illegal even for abstract
+ -- subprograms (see AI12-0170).
+
+ -- Similarly, as per AI12-0412, a nonabstract subprogram may
+ -- have a class-wide pre/postcondition that includes a call to
+ -- an abstract primitive of the subprogram's controlling type.
+ -- Certain operations (nondispatching calls, 'Access, use as
+ -- a generic actual) applied to such a nonabstract subprogram
+ -- are illegal in the case where the type is abstract (see
+ -- RM 6.1.1(18.2/5)).
+
+ elsif Is_Subprogram (Scop)
+ and then not Is_Tag_Indeterminate (N)
+ and then In_Pre_Post_Condition (Call, Class_Wide_Only => True)
+
+ -- The tagged type associated with the called subprogram must be
+ -- the same as that of the subprogram with a class-wide aspect.
+
+ and then Is_Dispatching_Operation (Scop)
and then
- ((Is_Abstract_Subprogram (Scop)
- and then not Is_Tag_Indeterminate (N))
- or else
- (Nkind (Parent (Scop)) = N_Procedure_Specification
- and then Null_Present (Parent (Scop))))
+ Find_Dispatching_Type (Subp) = Find_Dispatching_Type (Scop)
+ then
+ null;
+
+ -- Similarly to the dispensation for postconditions, a call to
+ -- an abstract function within a Default_Initial_Condition aspect
+ -- can be legal when passed a current instance of the type. Such
+ -- a call will be effectively mapped to a call to a primitive of
+ -- a descendant type (see AI12-0397, as well as AI12-0170), so
+ -- doesn't need to be dispatching. We test for being within a DIC
+ -- procedure, since that's where the call will be analyzed.
+
+ elsif Is_Subprogram (Scop)
+ and then Is_DIC_Procedure (Scop)
+ and then Has_Controlling_Current_Instance_Actual_In_DIC (Call)
then
null;
@@ -602,7 +666,7 @@ package body Sem_Disp is
-- provides a tag to make the call dispatching. This requires
-- the call to be the actual in an enclosing call, and that
-- actual must be controlling. If the call is an operand of
- -- equality, the other operand must not ve abstract.
+ -- equality, the other operand must not be abstract.
if not Is_Tagged_Type (Typ)
and then not
@@ -909,7 +973,6 @@ package body Sem_Disp is
end loop;
Check_Dispatching_Context (N);
- return;
elsif Nkind (Parent (N)) in N_Subexpr then
Check_Dispatching_Context (N);
@@ -924,6 +987,23 @@ package body Sem_Disp is
return;
end if;
+ -- If this is a nondispatching call to a nonabstract subprogram
+ -- and the subprogram has any Pre'Class or Post'Class aspects with
+ -- nonstatic values, then report an error. This is specified by
+ -- RM 6.1.1(18.2/5) (by AI12-0412).
+
+ if No (Control)
+ and then not Is_Abstract_Subprogram (Subp_Entity)
+ and then
+ Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Subp_Entity)
+ then
+ Error_Msg_N
+ ("nondispatching call to nonabstract subprogram of "
+ & "abstract type with nonstatic class-wide "
+ & "pre/postconditions",
+ N);
+ end if;
+
else
-- If dispatching on result, the enclosing call, if any, will
-- determine the controlling argument. Otherwise this is the
@@ -1147,7 +1227,7 @@ package body Sem_Disp is
-- primitives.
-- 3. Subprograms associated with stream attributes (built by
- -- New_Stream_Subprogram)
+ -- New_Stream_Subprogram) or with the Put_Image attribute.
-- 4. Wrappers built for inherited operations with inherited class-
-- wide conditions, where the conditions include calls to other
@@ -1176,8 +1256,11 @@ package body Sem_Disp is
or else Get_TSS_Name (Subp) = TSS_Stream_Read
or else Get_TSS_Name (Subp) = TSS_Stream_Write
+ or else Get_TSS_Name (Subp) = TSS_Put_Image
- or else Present (Contract (Overridden_Operation (Subp)))
+ or else
+ (Is_Wrapper (Subp)
+ and then Present (LSP_Subprogram (Subp)))
or else GNATprove_Mode);
@@ -2137,6 +2220,8 @@ package body Sem_Disp is
while Present (Elmt) loop
if Node (Elmt) = Orig_Prim then
Set_Overridden_Operation (S, Prim);
+ Set_Is_Ada_2022_Only (S,
+ Is_Ada_2022_Only (Prim));
Set_Alias (Prim, Orig_Prim);
return Prim;
end if;
@@ -2582,8 +2667,7 @@ package body Sem_Disp is
procedure Override_Dispatching_Operation
(Tagged_Type : Entity_Id;
Prev_Op : Entity_Id;
- New_Op : Entity_Id;
- Is_Wrapper : Boolean := False)
+ New_Op : Entity_Id)
is
Elmt : Elmt_Id;
Prim : Node_Id;
@@ -2660,7 +2744,7 @@ package body Sem_Disp is
-- wrappers of controlling functions since (at this stage)
-- they are not yet decorated.
- if not Is_Wrapper then
+ if not Is_Wrapper (New_Op) then
Check_Subtype_Conformant (New_Op, Prim);
Set_Is_Abstract_Subprogram (Prim,
@@ -2699,6 +2783,7 @@ package body Sem_Disp is
Set_Alias (Prev_Op, New_Op);
Set_DTC_Entity (Prev_Op, Empty);
Set_Has_Controlling_Result (New_Op, Has_Controlling_Result (Prev_Op));
+ Set_Is_Ada_2022_Only (New_Op, Is_Ada_2022_Only (Prev_Op));
end if;
end Override_Dispatching_Operation;