public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-2121] [Ada] Implement new legality checks specified by AI12-0412
@ 2021-07-07 16:26 Pierre-Marie de Rodat
0 siblings, 0 replies; only message in thread
From: Pierre-Marie de Rodat @ 2021-07-07 16:26 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:14212dc422ed09f8324bbfd1dec662cbb2fdbe0e
commit r12-2121-g14212dc422ed09f8324bbfd1dec662cbb2fdbe0e
Author: Gary Dismukes <dismukes@adacore.com>
Date: Mon May 17 03:35:25 2021 -0400
[Ada] Implement new legality checks specified by AI12-0412
gcc/ada/
* freeze.adb (Check_Inherited_Conditions): Setting of Ekind,
LSP_Subprogram, and Is_Wrapper needs to happen for null
procedures as well as other wrapper cases, so the code is moved
from the else part in front of the if statement. (Fixes a
latent bug encountered while working on this set of changes.)
* sem_attr.adb (Resolve_Attribute): Report an error for the case
of an Access attribute applied to a primitive of an abstract
type when the primitive has any nonstatic Pre'Class or
Post'Class expressions.
* sem_ch8.adb (Analyze_Subprogram_Renaming): Report an error for
the case of a actual subprogram associated with a nonabstract
formal subprogram when the actual is a primitive of an abstract
type and the primitive has any nonstatic Pre'Class or Post'Class
expressions.
* sem_disp.adb (Check_Dispatching_Context): Remove special
testing for null procedures, and replace it with a relaxed test
that avoids getting an error about illegal calls to abstract
subprograms in cases where RM 6.1.1(7/5) applies in
Pre/Post'Class aspects. Also, remove special test for
Postcondition, which seems to be unnecessary, update associated
comments, and fix a typo in one comment.
(Check_Dispatching_Call): Remove an unneeded return statement,
and report an error for the case of a nondispatching call to a
nonabstract subprogram of an abstract type where the subprogram
has nonstatic Pre/Post'Class aspects.
* sem_util.ads
(Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post): New function.
(In_Pre_Post_Condition): Add a flag formal Class_Wide_Only,
defaulted to False, for indicating whether the function should
only test for the node being within class-wide pre- and
postconditions.
* sem_util.adb
(Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post): New function
to determine whether a subprogram is a primitive of an abstract
type where the primitive has class-wide Pre/Post'Class aspects
specified with nonstatic expressions.
(In_Pre_Post_Condition): Extend testing to account for the new
formal Class_Wide_Only.
Diff:
---
gcc/ada/freeze.adb | 12 +++++-----
gcc/ada/sem_attr.adb | 19 +++++++++++++++
gcc/ada/sem_ch8.adb | 28 +++++++++++++++++-----
gcc/ada/sem_disp.adb | 67 +++++++++++++++++++++++++++++++++-------------------
gcc/ada/sem_util.adb | 67 +++++++++++++++++++++++++++++++++++++++++++++-------
gcc/ada/sem_util.ads | 12 ++++++++--
6 files changed, 159 insertions(+), 46 deletions(-)
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index fa16887c0d7..37964337c3a 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -1671,6 +1671,12 @@ package body Freeze is
-- type declaration that generates inherited operation. For
-- a null procedure, the declaration implies a null body.
+ -- Before insertion, do some minimal decoration of fields
+
+ Mutate_Ekind (New_Id, Ekind (Par_Prim));
+ Set_LSP_Subprogram (New_Id, Par_Prim);
+ Set_Is_Wrapper (New_Id);
+
if Nkind (New_Spec) = N_Procedure_Specification
and then Null_Present (New_Spec)
then
@@ -1684,12 +1690,6 @@ package body Freeze is
Build_Class_Wide_Clone_Call
(Loc, Decls, Par_Prim, New_Spec);
- -- Adding minimum decoration
-
- Mutate_Ekind (New_Id, Ekind (Par_Prim));
- Set_LSP_Subprogram (New_Id, Par_Prim);
- Set_Is_Wrapper (New_Id);
-
Insert_List_After_And_Analyze
(Par_R, New_List (New_Decl, New_Body));
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index e0b2072307f..d1a91d8864e 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -11499,6 +11499,25 @@ package body Sem_Attr is
Error_Msg_F ("context requires a non-protected subprogram", P);
end if;
+ -- AI12-0412: The rule in RM 6.1.1(18.2/5) disallows applying
+ -- attribute Access to a primitive of an abstract type when the
+ -- primitive has any Pre'Class or Post'Class aspects specified
+ -- with nonstatic expressions.
+
+ if Attr_Id = Attribute_Access
+ and then Ekind (Btyp) in E_Access_Subprogram_Type
+ | E_Anonymous_Access_Subprogram_Type
+ and then Is_Entity_Name (P)
+ and then Is_Dispatching_Operation (Entity (P))
+ and then
+ Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Entity (P))
+ then
+ Error_Msg_N
+ ("attribute not allowed for primitive of abstract type with "
+ & "nonstatic class-wide pre/postconditions",
+ N);
+ end if;
+
-- The context cannot be a pool-specific type, but this is a
-- legality rule, not a resolution rule, so it must be checked
-- separately, after possibly disambiguation (see AI-245).
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index f056a189b2d..78d2426610c 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -3790,15 +3790,31 @@ package body Sem_Ch8 is
Set_Has_Delayed_Freeze (New_S, False);
Freeze_Before (N, New_S);
- -- An abstract subprogram is only allowed as an actual in the case
- -- where the formal subprogram is also abstract.
-
if (Ekind (Old_S) = E_Procedure or else Ekind (Old_S) = E_Function)
- and then Is_Abstract_Subprogram (Old_S)
and then not Is_Abstract_Subprogram (Formal_Spec)
then
- Error_Msg_N
- ("abstract subprogram not allowed as generic actual", Nam);
+ -- An abstract subprogram is only allowed as an actual in the
+ -- case where the formal subprogram is also abstract.
+
+ if Is_Abstract_Subprogram (Old_S) then
+ Error_Msg_N
+ ("abstract subprogram not allowed as generic actual", Nam);
+ end if;
+
+ -- AI12-0412: A primitive of an abstract type with Pre'Class
+ -- or Post'Class aspects specified with nonstatic expressions
+ -- is not allowed as actual for a nonabstract formal subprogram
+ -- (see RM 6.1.1(18.2/5).
+
+ if Is_Dispatching_Operation (Old_S)
+ and then
+ Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post (Old_S)
+ then
+ Error_Msg_N
+ ("primitive of abstract type with nonstatic class-wide "
+ & "pre/postconditions not allowed as actual",
+ Nam);
+ end if;
end if;
end if;
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 06c4b07c0c7..064e2b5da14 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -612,29 +612,32 @@ 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;
@@ -663,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
@@ -970,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);
@@ -985,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
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 799f720e673..12e5aa89775 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -13295,6 +13295,44 @@ package body Sem_Util is
and then Nkind (Node (First_Elmt (Constits))) = N_Null;
end Has_Null_Refinement;
+ ------------------------------------------
+ -- Has_Nonstatic_Class_Wide_Pre_Or_Post --
+ ------------------------------------------
+
+ function Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post
+ (Subp : Entity_Id) return Boolean
+ is
+ Disp_Type : constant Entity_Id := Find_Dispatching_Type (Subp);
+ Prag : Node_Id;
+ Pragma_Arg : Node_Id;
+
+ begin
+ if Present (Disp_Type)
+ and then Is_Abstract_Type (Disp_Type)
+ and then Present (Contract (Subp))
+ then
+ Prag := Pre_Post_Conditions (Contract (Subp));
+
+ while Present (Prag) loop
+ if Pragma_Name (Prag) in Name_Precondition | Name_Postcondition
+ and then Class_Present (Prag)
+ then
+ Pragma_Arg :=
+ Nlists.First
+ (Pragma_Argument_Associations (Prag));
+
+ if not Is_Static_Expression (Expression (Pragma_Arg)) then
+ return True;
+ end if;
+ end if;
+
+ Prag := Next_Pragma (Prag);
+ end loop;
+ end if;
+
+ return False;
+ end Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post;
+
-------------------------------
-- Has_Overriding_Initialize --
-------------------------------
@@ -14431,7 +14469,9 @@ package body Sem_Util is
-- In_Pre_Post_Condition --
---------------------------
- function In_Pre_Post_Condition (N : Node_Id) return Boolean is
+ function In_Pre_Post_Condition
+ (N : Node_Id; Class_Wide_Only : Boolean := False) return Boolean
+ is
Par : Node_Id;
Prag : Node_Id := Empty;
Prag_Id : Pragma_Id;
@@ -14457,13 +14497,24 @@ package body Sem_Util is
if Present (Prag) then
Prag_Id := Get_Pragma_Id (Prag);
- return
- Prag_Id = Pragma_Post
- or else Prag_Id = Pragma_Post_Class
- or else Prag_Id = Pragma_Postcondition
- or else Prag_Id = Pragma_Pre
- or else Prag_Id = Pragma_Pre_Class
- or else Prag_Id = Pragma_Precondition;
+ if Class_Wide_Only then
+ return
+ Prag_Id = Pragma_Post_Class
+ or else Prag_Id = Pragma_Pre_Class
+ or else (Class_Present (Prag)
+ and then (Prag_Id = Pragma_Post
+ or else Prag_Id = Pragma_Postcondition
+ or else Prag_Id = Pragma_Pre
+ or else Prag_Id = Pragma_Precondition));
+ else
+ return
+ Prag_Id = Pragma_Post
+ or else Prag_Id = Pragma_Post_Class
+ or else Prag_Id = Pragma_Postcondition
+ or else Prag_Id = Pragma_Pre
+ or else Prag_Id = Pragma_Pre_Class
+ or else Prag_Id = Pragma_Precondition;
+ end if;
-- Otherwise the node is not enclosed by a pre/postcondition pragma
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index bacf8b42459..fb8309f4a2b 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -1516,6 +1516,12 @@ package Sem_Util is
-- integer for use in compile-time checking. Note: Level is restricted to
-- be non-dynamic.
+ function Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post
+ (Subp : Entity_Id) return Boolean;
+ -- Return True if Subp is a primitive of an abstract type, where the
+ -- primitive has a class-wide pre- or postcondition whose expression
+ -- is nonstatic.
+
function Has_Overriding_Initialize (T : Entity_Id) return Boolean;
-- Predicate to determine whether a controlled type has a user-defined
-- Initialize primitive (and, in Ada 2012, whether that primitive is
@@ -1634,9 +1640,11 @@ package Sem_Util is
function In_Pragma_Expression (N : Node_Id; Nam : Name_Id) return Boolean;
-- Returns true if the expression N occurs within a pragma with name Nam
- function In_Pre_Post_Condition (N : Node_Id) return Boolean;
+ function In_Pre_Post_Condition
+ (N : Node_Id; Class_Wide_Only : Boolean := False) return Boolean;
-- Returns True if node N appears within a pre/postcondition pragma. Note
- -- the pragma Check equivalents are NOT considered.
+ -- the pragma Check equivalents are NOT considered. If Class_Wide_Only is
+ -- True, then tests for N appearing within a class-wide pre/postcondition.
function In_Quantified_Expression (N : Node_Id) return Boolean;
-- Returns true if the expression N occurs within a quantified expression
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-07-07 16:26 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-07 16:26 [gcc r12-2121] [Ada] Implement new legality checks specified by AI12-0412 Pierre-Marie de Rodat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).