]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Rework fix for wrong finalization of qualified aggregate in allocator
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 20 Nov 2023 07:58:52 +0000 (08:58 +0100)
committerMarc Poulhiès <poulhies@adacore.com>
Thu, 30 Nov 2023 10:12:49 +0000 (11:12 +0100)
The problem is that there is no easy method to insert an action after an
arbitrary node in the tree, so the original fix does not correctly work
when the allocator is nested in another expression.

Therefore this moves the burden of the insertion from Apply_Predicate_Check
to Expand_Allocator_Expression and restricts the new processing to the case
where it is really required.

gcc/ada/

* checks.ads (Apply_Predicate_Check): Add Deref boolean parameter.
* checks.adb (Apply_Predicate_Check): Revert latest change. Use
Loc local variable to hold the source location. Use a common code
path for the generic processing and make a dereference if Deref is
True.
* exp_ch4.adb (Expand_Allocator_Expression): Compute Aggr_In_Place
earlier. If it is true, do not call Apply_Predicate_Check on the
expression on entry but on the temporary on exit with a
dereference.
* sem_res.adb (Resolve_Actuals): Add explicit parameter
association in call to Apply_Predicate_Check.

gcc/ada/checks.adb
gcc/ada/checks.ads
gcc/ada/exp_ch4.adb
gcc/ada/sem_res.adb

index 14e82f2adc66a1561cbebd45e57ec40036006d6c..d59d44fd6ab969682081e1812a35ef983803c012 100644 (file)
@@ -2720,15 +2720,20 @@ package body Checks is
    ---------------------------
 
    procedure Apply_Predicate_Check
-     (N   : Node_Id;
-      Typ : Entity_Id;
-      Fun : Entity_Id := Empty)
+     (N     : Node_Id;
+      Typ   : Entity_Id;
+      Deref : Boolean := False;
+      Fun   : Entity_Id := Empty)
    is
-      Par : Node_Id;
-      S   : Entity_Id;
+      Loc            : constant Source_Ptr := Sloc (N);
+      Check_Disabled : constant Boolean :=
+        not Predicate_Enabled (Typ)
+          or else not Predicate_Check_In_Scope (N);
+
+      Expr : Node_Id;
+      Par  : Node_Id;
+      S    : Entity_Id;
 
-      Check_Disabled : constant Boolean := not Predicate_Enabled (Typ)
-        or else not Predicate_Check_In_Scope (N);
    begin
       S := Current_Scope;
       while Present (S) and then not Is_Subprogram (S) loop
@@ -2757,7 +2762,7 @@ package body Checks is
 
          if not Check_Disabled then
             Insert_Action (N,
-              Make_Raise_Storage_Error (Sloc (N),
+              Make_Raise_Storage_Error (Loc,
                 Reason => SE_Infinite_Recursion));
             return;
          end if;
@@ -2824,19 +2829,9 @@ package body Checks is
          Par := Parent (Par);
       end if;
 
-      --  For an entity of the type, generate a call to the predicate
-      --  function, unless its type is an actual subtype, which is not
-      --  visible outside of the enclosing subprogram.
-
-      if Is_Entity_Name (N)
-        and then not Is_Actual_Subtype (Typ)
-      then
-         Insert_Action (N,
-           Make_Predicate_Check
-             (Typ, New_Occurrence_Of (Entity (N), Sloc (N))));
-         return;
+      --  Try to avoid creating a temporary if the expression is an aggregate
 
-      elsif Nkind (N) in N_Aggregate | N_Extension_Aggregate then
+      if Nkind (N) in N_Aggregate | N_Extension_Aggregate then
 
          --  If the expression is an aggregate in an assignment, apply the
          --  check to the LHS after the assignment, rather than create a
@@ -2851,27 +2846,6 @@ package body Checks is
                 (Typ, Duplicate_Subexpr (Name (Par))));
             return;
 
-         --  Similarly, if the expression is a qualified aggregate in an
-         --  allocator, apply the check to the dereference of the access
-         --  value, rather than create a temporary. This is necessary for
-         --  inherently limited types, for which the temporary is illegal.
-
-         elsif Nkind (Par) = N_Allocator then
-            declare
-               Deref : constant Node_Id :=
-                         Make_Explicit_Dereference (Sloc (N),
-                           Prefix => Duplicate_Subexpr (Par));
-
-            begin
-               --  This is required by Predicate_Check_In_Scope ???
-
-               Preserve_Comes_From_Source (Deref, N);
-
-               Insert_Action_After (Parent (Par),
-                 Make_Predicate_Check (Typ, Deref));
-               return;
-            end;
-
          --  Similarly, if the expression is an aggregate in an object
          --  declaration, apply it to the object after the declaration.
 
@@ -2892,21 +2866,36 @@ package body Checks is
             then
                Insert_Action_After (Par,
                   Make_Predicate_Check (Typ,
-                    New_Occurrence_Of (Defining_Identifier (Par), Sloc (N))));
+                    New_Occurrence_Of (Defining_Identifier (Par), Loc)));
                return;
             end if;
 
          end if;
       end if;
 
-      --  If the expression is not an entity it may have side effects,
-      --  and the following call will create an object declaration for
-      --  it. We disable checks during its analysis, to prevent an
-      --  infinite recursion.
+      --  For an entity of the type, generate a call to the predicate
+      --  function, unless its type is an actual subtype, which is not
+      --  visible outside of the enclosing subprogram.
 
-      Insert_Action (N,
-        Make_Predicate_Check
-          (Typ, Duplicate_Subexpr (N)), Suppress => All_Checks);
+      if Is_Entity_Name (N) and then not Is_Actual_Subtype (Typ) then
+         Expr := New_Occurrence_Of (Entity (N), Loc);
+
+      --  If the expression is not an entity, it may have side effects
+
+      else
+         Expr := Duplicate_Subexpr (N);
+      end if;
+
+      --  Make the dereference if requested
+
+      if Deref then
+         Expr := Make_Explicit_Dereference (Loc, Prefix => Expr);
+      end if;
+
+      --  Disable checks to prevent an infinite recursion
+
+      Insert_Action
+        (N, Make_Predicate_Check (Typ, Expr), Suppress => All_Checks);
    end Apply_Predicate_Check;
 
    -----------------------
index 64f0809dbea47de1cee4f83807adb93c3f90c0bd..8fd380283cca9dcbba86a5163b37b73110f34378 100644 (file)
@@ -256,13 +256,14 @@ package Checks is
    --  results.
 
    procedure Apply_Predicate_Check
-     (N   : Node_Id;
-      Typ : Entity_Id;
-      Fun : Entity_Id := Empty);
+     (N     : Node_Id;
+      Typ   : Entity_Id;
+      Deref : Boolean := False;
+      Fun   : Entity_Id := Empty);
    --  N is an expression to which a predicate check may need to be applied for
-   --  Typ, if Typ has a predicate function. When N is an actual in a call, Fun
-   --  is the function being called, which is used to generate a better warning
-   --  if the call leads to an infinite recursion.
+   --  Typ if Typ has a predicate function, after dereference if Deref is True.
+   --  When N is an actual in a call, Fun is the function being called, which
+   --  is used to generate a warning if the call leads to infinite recursion.
 
    procedure Apply_Type_Conversion_Checks (N : Node_Id);
    --  N is an N_Type_Conversion node. A type conversion actually involves
index e708ed350d140e80a0beba17a0d70d6d1285dd7c..99be96d3ab767590ae5a4cf830a8638ca6c6af37 100644 (file)
@@ -563,8 +563,6 @@ package body Exp_Ch4 is
       DesigT         : constant Entity_Id  := Designated_Type (PtrT);
       Special_Return : constant Boolean    := For_Special_Return_Object (N);
 
-      --  Local variables
-
       Adj_Call      : Node_Id;
       Aggr_In_Place : Boolean;
       Node          : Node_Id;
@@ -577,8 +575,6 @@ package body Exp_Ch4 is
       TagR : Node_Id := Empty;
       --  Target reference for tag assignment
 
-   --  Start of processing for Expand_Allocator_Expression
-
    begin
       --  Handle call to C++ constructor
 
@@ -598,7 +594,15 @@ package body Exp_Ch4 is
 
       Apply_Constraint_Check (Exp, T, No_Sliding => True);
 
-      Apply_Predicate_Check (Exp, T);
+      Aggr_In_Place := Is_Delayed_Aggregate (Exp);
+
+      --  If the expression is an aggregate to be built in place, then we need
+      --  to delay applying predicate checks, because this would result in the
+      --  creation of a temporary, which is illegal for limited types,
+
+      if not Aggr_In_Place then
+         Apply_Predicate_Check (Exp, T);
+      end if;
 
       --  Check that any anonymous access discriminants are suitable
       --  for use in an allocator.
@@ -659,8 +663,6 @@ package body Exp_Ch4 is
          return;
       end if;
 
-      Aggr_In_Place := Is_Delayed_Aggregate (Exp);
-
       --  Case of tagged type or type requiring finalization
 
       if Is_Tagged_Type (T) or else Needs_Finalization (T) then
@@ -972,6 +974,10 @@ package body Exp_Ch4 is
          Rewrite (N, New_Occurrence_Of (Temp, Loc));
          Analyze_And_Resolve (N, PtrT);
 
+         if Aggr_In_Place then
+            Apply_Predicate_Check (N, T, Deref => True);
+         end if;
+
          --  Ada 2005 (AI-251): Displace the pointer to reference the record
          --  component containing the secondary dispatch table of the interface
          --  type.
@@ -1012,6 +1018,10 @@ package body Exp_Ch4 is
          Rewrite (N, New_Occurrence_Of (Temp, Loc));
          Analyze_And_Resolve (N, PtrT);
 
+         if Aggr_In_Place then
+            Apply_Predicate_Check (N, T, Deref => True);
+         end if;
+
       elsif Is_Access_Type (T) and then Can_Never_Be_Null (T) then
          Install_Null_Excluding_Check (Exp);
 
index 8e5d351141d2ee90fb536784e21a72990b481f8e..c684075219b14a4fee7a3bd2f3e9ca6e0bf787b7 100644 (file)
@@ -4735,7 +4735,7 @@ package body Sem_Res is
                --  leads to an infinite recursion.
 
                if Predicate_Tests_On_Arguments (Nam) then
-                  Apply_Predicate_Check (A, F_Typ, Nam);
+                  Apply_Predicate_Check (A, F_Typ, Fun => Nam);
                end if;
 
                --  Apply required constraint checks