public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [COMMITTED] ada: Further cleanup in finalization machinery
@ 2023-12-19 14:29 Marc Poulhiès
  0 siblings, 0 replies; 5+ messages in thread
From: Marc Poulhiès @ 2023-12-19 14:29 UTC (permalink / raw)
  To: gcc-patches; +Cc: Eric Botcazou

From: Eric Botcazou <ebotcazou@adacore.com>

This streamlines the submachinery that makes it so that the finalization of
temporaries created for EWAs and conditional expressions is deferred to the
enclosing context.

The original implementation was using a deep tree traversal for EWAs, which
was later restricted to immediate subexpressions; this further flattens it
to the traversal of the immediate list of actions of the EWA in keeping with
the implementation for conditional expressions.

This should not change anything because the enclosing context found by the
machinery is the same, whatever the starting position in a nest of EWAs or
conditional expressions.

gcc/ada/

	* exp_ch4.adb (Process_If_Case_Statements): Rename into...
	(Process_Transients_In_Expression): ...this and beef up comment.
	(Expand_N_Case_Expression): Call Process_Transients_In_Expression
	unconditionally on the list of actions of each alternative.
	(Expand_N_Expression_With_Actions): Do not deal with actions in
	nested subexpressions, but call Process_Transients_In_Expression
	on the list of actions only.
	(Expand_N_If_Expression): Adjust to above renaming.  Add missing
	calls to Process_Transients_In_Expression in the case when an EWA
	is not used because of Minimize_Expression_With_Actions.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_ch4.adb | 154 +++++++++++++++++++-------------------------
 1 file changed, 66 insertions(+), 88 deletions(-)

diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 99be96d3ab7..8f4cf0808dc 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -241,11 +241,6 @@ package body Exp_Ch4 is
    --  and X is a simple entity, and op is a comparison operator, optimizes it
    --  into a comparison of X'First and X'Last.
 
-   procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id);
-   --  Inspect and process statement list Stmt of if or case expression N for
-   --  transient objects. If such objects are found, the routine generates code
-   --  to clean them up when the context of the expression is evaluated.
-
    procedure Process_Transient_In_Expression
      (Obj_Decl : Node_Id;
       Expr     : Node_Id;
@@ -255,9 +250,25 @@ package body Exp_Ch4 is
    --  object when the enclosing context is elaborated or evaluated. Obj_Decl
    --  denotes the declaration of the transient object, which is usually the
    --  result of a controlled function call. Expr denotes the expression with
-   --  actions, if expression, or case expression node. Stmts denotes the
-   --  statement list which contains Decl, either at the top level or within a
-   --  nested construct.
+   --  actions, if expression, or case expression node. Stmts denotes one of
+   --  the actions list of Expr, which contains Decl.
+
+   procedure Process_Transients_In_Expression
+     (Expr  : Node_Id;
+      Stmts : List_Id);
+   --  Subsidiary routine to the expansion of expression_with_actions, if and
+   --  case expressions. Inspect and process actions list Stmts of expression
+   --  Expr for transient objects. If such objects are found, the routine will
+   --  generate code to finalize them when the enclosing context is elaborated
+   --  or evaluated.
+
+   --  This specific processing is required for these expressions because the
+   --  management of transient objects for expressions implemented in Exp_Ch7
+   --  cannot deal with nested lists of actions whose effects may outlive the
+   --  lists and affect the result of the parent expressions. In these cases,
+   --  the lifetime of temporaries created in these lists must be extended to
+   --  match that of the enclosing context of the parent expressions and, in
+   --  particular, their finalization must be deferred to this context.
 
    procedure Rewrite_Comparison (N : Node_Id);
    --  If N is the node for a comparison whose outcome can be determined at
@@ -5411,14 +5422,10 @@ package body Exp_Ch4 is
                  Statements       => Stmts));
 
             --  Finalize any transient objects on exit from the alternative.
-            --  This needs to be done only when the case expression is _not_
-            --  later converted into an expression with actions, which already
-            --  contains this form of processing, and after Stmts is attached
+            --  Note that this needs to be done only after Stmts is attached
             --  to the Alternatives list above (for Safe_To_Capture_Value).
 
-            if Optimize_Return_Stmt or else not Is_Copy_Type (Typ) then
-               Process_If_Case_Statements (N, Stmts);
-            end if;
+            Process_Transients_In_Expression (N, Stmts);
          end;
 
          Next (Alt);
@@ -5482,12 +5489,6 @@ package body Exp_Ch4 is
       procedure Force_Boolean_Evaluation (Expr : Node_Id);
       --  Force the evaluation of Boolean expression Expr
 
-      function Process_Action (Act : Node_Id) return Traverse_Result;
-      --  Inspect and process a single action of an expression_with_actions for
-      --  transient objects. If such objects are found, the routine generates
-      --  code to clean them up when the context of the expression is evaluated
-      --  or elaborated.
-
       ------------------------------
       -- Force_Boolean_Evaluation --
       ------------------------------
@@ -5520,42 +5521,6 @@ package body Exp_Ch4 is
          Analyze (Expression (N));
       end Force_Boolean_Evaluation;
 
-      --------------------
-      -- Process_Action --
-      --------------------
-
-      function Process_Action (Act : Node_Id) return Traverse_Result is
-      begin
-         if Nkind (Act) = N_Object_Declaration
-           and then Is_Finalizable_Transient (Act, N)
-         then
-            Process_Transient_In_Expression (Act, N, Acts);
-            return Skip;
-
-         --  Avoid processing temporary function results multiple times when
-         --  dealing with nested expression_with_actions or nested blocks.
-         --  Similarly, do not process temporary function results in loops.
-         --  This is done by Expand_N_Loop_Statement and Build_Finalizer.
-         --  Note that we used to wrongly return Abandon instead of Skip here:
-         --  this is wrong since it means that we were ignoring lots of
-         --  relevant subsequent statements.
-
-         elsif Nkind (Act) in N_Expression_With_Actions
-                            | N_Block_Statement
-                            | N_Loop_Statement
-         then
-            return Skip;
-         end if;
-
-         return OK;
-      end Process_Action;
-
-      procedure Process_Single_Action is new Traverse_Proc (Process_Action);
-
-      --  Local variables
-
-      Act : Node_Id;
-
    --  Start of processing for Expand_N_Expression_With_Actions
 
    begin
@@ -5616,14 +5581,9 @@ package body Exp_Ch4 is
          Force_Evaluation (Expression (N));
       end if;
 
-      --  Process all transient objects found within the actions of the EWA
-      --  node.
+      --  Process transient objects found within the actions of the EWA node
 
-      Act := First (Acts);
-      while Present (Act) loop
-         Process_Single_Action (Act);
-         Next (Act);
-      end loop;
+      Process_Transients_In_Expression (N, Acts);
 
       --  Deal with case where there are no actions. In this case we simply
       --  rewrite the node with its expression since we don't need the actions
@@ -5802,8 +5762,8 @@ package body Exp_Ch4 is
          --  of actions. These temporaries need to be finalized after the if
          --  expression is evaluated.
 
-         Process_If_Case_Statements (N, Then_Actions (N));
-         Process_If_Case_Statements (N, Else_Actions (N));
+         Process_Transients_In_Expression (N, Then_Actions (N));
+         Process_Transients_In_Expression (N, Else_Actions (N));
 
          New_If :=
            Make_Implicit_If_Statement (N,
@@ -5843,8 +5803,8 @@ package body Exp_Ch4 is
          --  of actions. These temporaries need to be finalized after the if
          --  expression is evaluated.
 
-         Process_If_Case_Statements (N, Then_Actions (N));
-         Process_If_Case_Statements (N, Else_Actions (N));
+         Process_Transients_In_Expression (N, Then_Actions (N));
+         Process_Transients_In_Expression (N, Else_Actions (N));
 
          declare
             Cnn     : constant Entity_Id := Make_Temporary (Loc, 'C', N);
@@ -6186,13 +6146,20 @@ package body Exp_Ch4 is
         or else Present (Else_Actions (N))
         or else Force_Expand
       then
-
          --  We now wrap the actions into the appropriate expression
 
          if Minimize_Expression_With_Actions
            and then (Is_Elementary_Type (Underlying_Type (Typ))
                       or else Is_Constrained (Underlying_Type (Typ)))
          then
+            --  When the "then" or "else" expressions involve controlled
+            --  function calls, generated temporaries are chained on the
+            --  corresponding list of actions. These temporaries need to
+            --  be finalized after the if expression is evaluated.
+
+            Process_Transients_In_Expression (N, Then_Actions (N));
+            Process_Transients_In_Expression (N, Else_Actions (N));
+
             --  If we can't use N_Expression_With_Actions nodes, then we insert
             --  the following sequence of actions (using Insert_Actions):
 
@@ -6239,6 +6206,10 @@ package body Exp_Ch4 is
          --  Regular path using Expression_With_Actions
 
          else
+            --  We do not need to call Process_Transients_In_Expression on
+            --  the list of actions in this case, because the expansion of
+            --  Expression_With_Actions will do it.
+
             if Present (Then_Actions (N)) then
                Rewrite (Thenx,
                  Make_Expression_With_Actions (Sloc (Thenx),
@@ -14938,26 +14909,6 @@ package body Exp_Ch4 is
       Analyze_And_Resolve (N, Typ, Suppress => Overflow_Check);
    end Optimize_Length_Comparison;
 
-   --------------------------------
-   -- Process_If_Case_Statements --
-   --------------------------------
-
-   procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id) is
-      Decl : Node_Id;
-
-   begin
-      Decl := First (Stmts);
-      while Present (Decl) loop
-         if Nkind (Decl) = N_Object_Declaration
-           and then Is_Finalizable_Transient (Decl, N)
-         then
-            Process_Transient_In_Expression (Decl, N, Stmts);
-         end if;
-
-         Next (Decl);
-      end loop;
-   end Process_If_Case_Statements;
-
    -------------------------------------
    -- Process_Transient_In_Expression --
    -------------------------------------
@@ -15116,6 +15067,33 @@ package body Exp_Ch4 is
       end if;
    end Process_Transient_In_Expression;
 
+   --------------------------------------
+   -- Process_Transients_In_Expression --
+   --------------------------------------
+
+   procedure Process_Transients_In_Expression
+     (Expr : Node_Id;
+      Stmts : List_Id)
+   is
+      Decl : Node_Id;
+
+   begin
+      pragma Assert (Nkind (Expr) in N_Case_Expression
+                                   | N_Expression_With_Actions
+                                   | N_If_Expression);
+
+      Decl := First (Stmts);
+      while Present (Decl) loop
+         if Nkind (Decl) = N_Object_Declaration
+           and then Is_Finalizable_Transient (Decl, Expr)
+         then
+            Process_Transient_In_Expression (Decl, Expr, Stmts);
+         end if;
+
+         Next (Decl);
+      end loop;
+   end Process_Transients_In_Expression;
+
    ------------------------
    -- Rewrite_Comparison --
    ------------------------
-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] ada: Further cleanup in finalization machinery
@ 2023-12-19 14:30 Marc Poulhiès
  0 siblings, 0 replies; 5+ messages in thread
From: Marc Poulhiès @ 2023-12-19 14:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: Eric Botcazou

From: Eric Botcazou <ebotcazou@adacore.com>

This removes the setting of the Is_Ignored_Transient flag on the temporaries
needing finalization created by Expand_Ctrl_Function_Call when invoked from
within the dependent expressions of conditional expressions.

This flag tells the general finalization machinery to disregard the object.
But temporaries needing finalization present in action lists of dependent
expressions are picked up by Process_Transients_In_Expression, which deals
with their finalization and sets the Is_Finalized_Transient flag on them.

Now this latter flag has exactly the same effect as Is_Ignored_Transient
as far as the general finalization machinery is concerned, so setting the
flag is unnecessary.  In the end, the flag can be decoupled entirely from
transient objects and renamed into Is_Ignored_For_Finalization.

This also moves around the declaration of a local variable and turns a
library-level procedure into a nested procedure.

gcc/ada/

	* einfo.ads (Is_Ignored_Transient): Rename into...
	(Is_Ignored_For_Finalization): ...this.
	* gen_il-fields.ads (Opt_Field_Enum): Adjust to above renaming.
	* gen_il-gen-gen_entities.adb (Object_Kind): Likewise.
	* exp_aggr.adb (Expand_Array_Aggregate): Likewise.
	* exp_ch7.adb (Build_Finalizer.Process_Declarations): Likewise.
	* exp_util.adb (Requires_Cleanup_Actions): Likewise.
	* exp_ch4.adb (Expand_N_If_Expression): Move down declaration of
	variable Optimize_Return_Stmt.
	(Process_Transient_In_Expression): Turn procedure into a child of...
	(Process_Transients_In_Expression): ...this procedure.
	* exp_ch6.adb (Expand_Ctrl_Function_Call): Remove obsolete setting
	of Is_Ignored_Transient flag on the temporary if within a dependent
	expression of a conditional expression.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/einfo.ads                   |  16 +-
 gcc/ada/exp_aggr.adb                |   2 +-
 gcc/ada/exp_ch4.adb                 | 278 ++++++++++++++--------------
 gcc/ada/exp_ch6.adb                 |  43 -----
 gcc/ada/exp_ch7.adb                 |  14 +-
 gcc/ada/exp_util.adb                |  12 +-
 gcc/ada/gen_il-fields.ads           |   2 +-
 gcc/ada/gen_il-gen-gen_entities.adb |   2 +-
 8 files changed, 158 insertions(+), 211 deletions(-)

diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 9165fb7485d..1dd55494a53 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -2727,6 +2727,11 @@ package Einfo is
 --       instantiation of a child unit, and whose entities are not visible
 --       during analysis of the instance.
 
+--    Is_Ignored_For_Finalization
+--       Defined in constants and variables. Set when an object must be ignored
+--       by the general finalization mechanism because its cleanup actions are
+--       already accounted for.
+
 --    Is_Ignored_Ghost_Entity
 --       Applies to all entities. Set for abstract states, [generic] packages,
 --       [generic] subprograms, components, discriminants, formal parameters,
@@ -2734,13 +2739,6 @@ package Einfo is
 --       pragma Ghost or inherit "ghostness" from an enclosing construct, and
 --       subject to Assertion_Policy Ghost => Ignore.
 
---    Is_Ignored_Transient
---       Defined in constants, loop parameters of generalized iterators, and
---       variables. Set when a transient object must be processed by one of
---       the transient finalization mechanisms. Once marked, a transient is
---       intentionally ignored by the general finalization mechanism because
---       its clean up actions are context specific.
-
 --    Is_Immediately_Visible
 --       Defined in all entities. Set if entity is immediately visible, i.e.
 --       is defined in some currently open scope (RM 8.3(4)).
@@ -5325,7 +5323,7 @@ package Einfo is
    --    Is_Elaboration_Warnings_OK_Id         (constants only)
    --    Is_Eliminated
    --    Is_Finalized_Transient
-   --    Is_Ignored_Transient
+   --    Is_Ignored_For_Finalization
    --    Is_Independent
    --    Is_Return_Object
    --    Is_True_Constant
@@ -6213,7 +6211,7 @@ package Einfo is
    --    Is_Elaboration_Warnings_OK_Id
    --    Is_Eliminated
    --    Is_Finalized_Transient
-   --    Is_Ignored_Transient
+   --    Is_Ignored_For_Finalization
    --    Is_Independent
    --    Is_Return_Object
    --    Is_Safe_To_Reevaluate
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 2d02bad0c4c..d61fbbc8c73 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6317,7 +6317,7 @@ package body Exp_Aggr is
            and then No_Ctrl_Actions (Parent_Node)
          then
             Mutate_Ekind (Tmp, E_Variable);
-            Set_Is_Ignored_Transient (Tmp);
+            Set_Is_Ignored_For_Finalization (Tmp);
          end if;
 
          Insert_Action (N, Tmp_Decl);
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 527ca16aac4..037c8b528bd 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -241,18 +241,6 @@ package body Exp_Ch4 is
    --  and X is a simple entity, and op is a comparison operator, optimizes it
    --  into a comparison of X'First and X'Last.
 
-   procedure Process_Transient_In_Expression
-     (Obj_Decl : Node_Id;
-      Expr     : Node_Id;
-      Stmts    : List_Id);
-   --  Subsidiary routine to the expansion of expression_with_actions, if and
-   --  case expressions. Generate all necessary code to finalize a transient
-   --  object when the enclosing context is elaborated or evaluated. Obj_Decl
-   --  denotes the declaration of the transient object, which is usually the
-   --  result of a controlled function call. Expr denotes the expression with
-   --  actions, if expression, or case expression node. Stmts denotes one of
-   --  the actions list of Expr, which contains Decl.
-
    procedure Process_Transients_In_Expression
      (Expr  : Node_Id;
       Stmts : List_Id);
@@ -5643,10 +5631,6 @@ package body Exp_Ch4 is
            UI_Max (Hi1, Hi2) - UI_Min (Lo1, Lo2) < Too_Large_Length_For_Array;
       end OK_For_Single_Subtype;
 
-      Optimize_Return_Stmt : Boolean := False;
-      --  Flag set when the if expression can be optimized in the context of
-      --  a simple return statement.
-
       --  Local variables
 
       Actions : List_Id;
@@ -5655,6 +5639,10 @@ package body Exp_Ch4 is
       New_If  : Node_Id;
       New_N   : Node_Id;
 
+      Optimize_Return_Stmt : Boolean := False;
+      --  Flag set when the if expression can be optimized in the context of
+      --  a simple return statement.
+
    --  Start of processing for Expand_N_If_Expression
 
    begin
@@ -14917,174 +14905,178 @@ package body Exp_Ch4 is
       Analyze_And_Resolve (N, Typ, Suppress => Overflow_Check);
    end Optimize_Length_Comparison;
 
-   -------------------------------------
-   -- Process_Transient_In_Expression --
-   -------------------------------------
+   --------------------------------------
+   -- Process_Transients_In_Expression --
+   --------------------------------------
 
-   procedure Process_Transient_In_Expression
-     (Obj_Decl : Node_Id;
-      Expr     : Node_Id;
-      Stmts    : List_Id)
+   procedure Process_Transients_In_Expression
+     (Expr : Node_Id;
+      Stmts : List_Id)
    is
-      Loc    : constant Source_Ptr := Sloc (Obj_Decl);
-      Obj_Id : constant Entity_Id  := Defining_Identifier (Obj_Decl);
+      procedure Process_Transient_In_Expression (Obj_Decl : Node_Id);
+      --  Process the object whose declaration Obj_Decl is present in Stmts
 
-      Hook_Context : constant Node_Id := Find_Hook_Context (Expr);
-      --  The node on which to insert the hook as an action. This is usually
-      --  the innermost enclosing non-transient construct.
+      -------------------------------------
+      -- Process_Transient_In_Expression --
+      -------------------------------------
 
-      Fin_Call    : Node_Id;
-      Hook_Assign : Node_Id;
-      Hook_Clear  : Node_Id;
-      Hook_Decl   : Node_Id;
-      Hook_Insert : Node_Id;
-      Ptr_Decl    : Node_Id;
+      procedure Process_Transient_In_Expression (Obj_Decl : Node_Id) is
+         Loc    : constant Source_Ptr := Sloc (Obj_Decl);
+         Obj_Id : constant Entity_Id  := Defining_Identifier (Obj_Decl);
 
-      Fin_Context : Node_Id;
-      --  The node after which to insert the finalization actions of the
-      --  transient object.
+         Hook_Context : constant Node_Id := Find_Hook_Context (Expr);
+         --  The node on which to insert the hook as an action. This is usually
+         --  the innermost enclosing non-transient construct.
 
-   begin
-      pragma Assert (Nkind (Expr) in N_Case_Expression
-                                   | N_Expression_With_Actions
-                                   | N_If_Expression);
+         Fin_Call    : Node_Id;
+         Hook_Assign : Node_Id;
+         Hook_Clear  : Node_Id;
+         Hook_Decl   : Node_Id;
+         Hook_Insert : Node_Id;
+         Ptr_Decl    : Node_Id;
 
-      --  When the context is a Boolean evaluation, all three nodes capture the
-      --  result of their computation in a local temporary:
+         Fin_Context : Node_Id;
+         --  The node after which to insert the finalization actions of the
+         --  transient object.
 
-      --    do
-      --       Trans_Id : Ctrl_Typ := ...;
-      --       Result : constant Boolean := ... Trans_Id ...;
-      --       <finalize Trans_Id>
-      --    in Result end;
+      begin
+         pragma Assert (Nkind (Expr) in N_Case_Expression
+                                      | N_Expression_With_Actions
+                                      | N_If_Expression);
 
-      --  As a result, the finalization of any transient objects can take place
-      --  just after the result is captured, except for the case of conditional
-      --  expressions in a simple return statement because the return statement
-      --  will be distributed into the conditional expressions (see the special
-      --  handling of simple return statements a few lines below).
+         --  When the context is a Boolean evaluation, all three nodes capture
+         --  the result of their computation in a local temporary:
 
-      --  ??? could this be extended to elementary types?
+         --    do
+         --       Trans_Id : Ctrl_Typ := ...;
+         --       Result : constant Boolean := ... Trans_Id ...;
+         --       <finalize Trans_Id>
+         --    in Result end;
 
-      if Is_Boolean_Type (Etype (Expr))
-        and then (Nkind (Expr) = N_Expression_With_Actions
-                   or else Nkind (Parent (Expr)) /= N_Simple_Return_Statement)
-      then
-         Fin_Context := Last (Stmts);
+         --  As a result, the finalization of any transient objects can take
+         --  place just after the result is captured, except for the case of
+         --  conditional expressions in a simple return statement because the
+         --  return statement will be distributed into dependent expressions
+         --  (see the special handling of simple return statements below).
 
-      --  Otherwise the immediate context may not be safe enough to carry
-      --  out transient object finalization due to aliasing and nesting of
-      --  constructs. Insert calls to [Deep_]Finalize after the innermost
-      --  enclosing non-transient construct.
+         --  ??? could this be extended to elementary types?
 
-      else
-         Fin_Context := Hook_Context;
-      end if;
+         if Is_Boolean_Type (Etype (Expr))
+           and then
+             (Nkind (Expr) = N_Expression_With_Actions
+               or else Nkind (Parent (Expr)) /= N_Simple_Return_Statement)
+         then
+            Fin_Context := Last (Stmts);
 
-      --  Mark the transient object as successfully processed to avoid double
-      --  finalization.
+         --  Otherwise the immediate context may not be safe enough to carry
+         --  out transient object finalization due to aliasing and nesting of
+         --  constructs. Insert calls to [Deep_]Finalize after the innermost
+         --  enclosing non-transient construct.
 
-      Set_Is_Finalized_Transient (Obj_Id);
+         else
+            Fin_Context := Hook_Context;
+         end if;
 
-      --  Construct all the pieces necessary to hook and finalize a transient
-      --  object.
+         --  Mark the transient object as successfully processed to avoid
+         --  double finalization.
 
-      Build_Transient_Object_Statements
-        (Obj_Decl     => Obj_Decl,
-         Fin_Call     => Fin_Call,
-         Hook_Assign  => Hook_Assign,
-         Hook_Clear   => Hook_Clear,
-         Hook_Decl    => Hook_Decl,
-         Ptr_Decl     => Ptr_Decl,
-         Finalize_Obj => False);
+         Set_Is_Finalized_Transient (Obj_Id);
 
-      --  Add the access type which provides a reference to the transient
-      --  object. Generate:
+         --  Construct all the pieces necessary to hook and finalize a
+         --  transient object.
 
-      --    type Ptr_Typ is access all Desig_Typ;
+         Build_Transient_Object_Statements
+           (Obj_Decl     => Obj_Decl,
+            Fin_Call     => Fin_Call,
+            Hook_Assign  => Hook_Assign,
+            Hook_Clear   => Hook_Clear,
+            Hook_Decl    => Hook_Decl,
+            Ptr_Decl     => Ptr_Decl,
+            Finalize_Obj => False);
 
-      Insert_Action (Hook_Context, Ptr_Decl);
+         --  Add the access type which provides a reference to the transient
+         --  object. Generate:
 
-      --  Add the temporary which acts as a hook to the transient object.
-      --  Generate:
+         --    type Ptr_Typ is access all Desig_Typ;
 
-      --    Hook : Ptr_Id := null;
+         Insert_Action (Hook_Context, Ptr_Decl);
 
-      Insert_Action (Hook_Context, Hook_Decl);
+         --  Add the temporary which acts as a hook to the transient object.
+         --  Generate:
 
-      --  When the transient object is initialized by an aggregate, the hook
-      --  must capture the object after the last aggregate assignment takes
-      --  place. Only then is the object considered initialized. Generate:
+         --    Hook : Ptr_Id := null;
 
-      --    Hook := Ptr_Typ (Obj_Id);
-      --      <or>
-      --    Hook := Obj_Id'Unrestricted_Access;
+         Insert_Action (Hook_Context, Hook_Decl);
 
-      if Ekind (Obj_Id) in E_Constant | E_Variable
-        and then Present (Last_Aggregate_Assignment (Obj_Id))
-      then
-         Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
+         --  When the transient object is initialized by an aggregate, the hook
+         --  must capture the object after the last aggregate assignment takes
+         --  place. Only then is the object considered initialized. Generate:
 
-      --  Otherwise the hook seizes the related object immediately
+         --    Hook := Ptr_Typ (Obj_Id);
+         --      <or>
+         --    Hook := Obj_Id'Unrestricted_Access;
 
-      else
-         Hook_Insert := Obj_Decl;
-      end if;
+         if Ekind (Obj_Id) in E_Constant | E_Variable
+           and then Present (Last_Aggregate_Assignment (Obj_Id))
+         then
+            Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
 
-      Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
+         --  Otherwise the hook seizes the related object immediately
 
-      --  When the node is part of a return statement, there is no need to
-      --  insert a finalization call, as the general finalization mechanism
-      --  (see Build_Finalizer) would take care of the transient object on
-      --  subprogram exit. Note that it would also be impossible to insert the
-      --  finalization code after the return statement as this will render it
-      --  unreachable.
+         else
+            Hook_Insert := Obj_Decl;
+         end if;
 
-      if Nkind (Fin_Context) = N_Simple_Return_Statement then
-         null;
+         Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
 
-      --  Finalize the hook after the context has been evaluated. Generate:
+         --  When the node is part of a return statement, there is no need to
+         --  insert a finalization call, as the general finalization mechanism
+         --  (see Build_Finalizer) would take care of the transient object on
+         --  subprogram exit. Note that it would also be impossible to insert
+         --  the finalization code after the return statement as this will
+         --  render it unreachable.
 
-      --    if Hook /= null then
-      --       [Deep_]Finalize (Hook.all);
-      --       Hook := null;
-      --    end if;
+         if Nkind (Fin_Context) = N_Simple_Return_Statement then
+            null;
 
-      --  Note that the value returned by Find_Hook_Context may be an operator
-      --  node, which is not a list member. We must locate the proper node in
-      --  in the tree after which to insert the finalization code.
+         --  Finalize the hook after the context has been evaluated. Generate:
 
-      else
-         while not Is_List_Member (Fin_Context) loop
-            Fin_Context := Parent (Fin_Context);
-         end loop;
+         --    if Hook /= null then
+         --       [Deep_]Finalize (Hook.all);
+         --       Hook := null;
+         --    end if;
 
-         pragma Assert (Present (Fin_Context));
+         --  But the node returned by Find_Hook_Context may be an operator,
+         --  which is not a list member. We must locate the proper node
+         --  in the tree after which to insert the finalization code.
 
-         Insert_Action_After (Fin_Context,
-           Make_Implicit_If_Statement (Obj_Decl,
-             Condition =>
-               Make_Op_Ne (Loc,
-                 Left_Opnd  =>
-                   New_Occurrence_Of (Defining_Entity (Hook_Decl), Loc),
-                 Right_Opnd => Make_Null (Loc)),
+         else
+            while not Is_List_Member (Fin_Context) loop
+               Fin_Context := Parent (Fin_Context);
+            end loop;
 
-             Then_Statements => New_List (
-               Fin_Call,
-               Hook_Clear)));
-      end if;
-   end Process_Transient_In_Expression;
+            pragma Assert (Present (Fin_Context));
 
-   --------------------------------------
-   -- Process_Transients_In_Expression --
-   --------------------------------------
+            Insert_Action_After (Fin_Context,
+              Make_Implicit_If_Statement (Obj_Decl,
+                Condition =>
+                  Make_Op_Ne (Loc,
+                    Left_Opnd  =>
+                      New_Occurrence_Of (Defining_Entity (Hook_Decl), Loc),
+                   Right_Opnd => Make_Null (Loc)),
+
+                Then_Statements => New_List (
+                 Fin_Call,
+                  Hook_Clear)));
+         end if;
+      end Process_Transient_In_Expression;
+
+      --  Local variables
 
-   procedure Process_Transients_In_Expression
-     (Expr : Node_Id;
-      Stmts : List_Id)
-   is
       Decl : Node_Id;
 
+   --  Start of processing for Process_Transients_In_Expression
+
    begin
       pragma Assert (Nkind (Expr) in N_Case_Expression
                                    | N_Expression_With_Actions
@@ -15095,7 +15087,7 @@ package body Exp_Ch4 is
          if Nkind (Decl) = N_Object_Declaration
            and then Is_Finalizable_Transient (Decl, Expr)
          then
-            Process_Transient_In_Expression (Decl, Expr, Stmts);
+            Process_Transient_In_Expression (Decl);
          end if;
 
          Next (Decl);
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index a2b5cdcfa8e..195e34a3479 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -5441,29 +5441,6 @@ package body Exp_Ch6 is
    is
       Par : constant Node_Id := Parent (N);
 
-      function Is_Element_Reference (N : Node_Id) return Boolean;
-      --  Determine whether node N denotes a reference to an Ada 2012 container
-      --  element.
-
-      --------------------------
-      -- Is_Element_Reference --
-      --------------------------
-
-      function Is_Element_Reference (N : Node_Id) return Boolean is
-         Ref : constant Node_Id := Original_Node (N);
-
-      begin
-         --  Analysis marks an element reference by setting the generalized
-         --  indexing attribute of an indexed component before the component
-         --  is rewritten into a function call.
-
-         return
-           Nkind (Ref) = N_Indexed_Component
-             and then Present (Generalized_Indexing (Ref));
-      end Is_Element_Reference;
-
-   --  Start of processing for Expand_Ctrl_Function_Call
-
    begin
       --  Optimization: if the returned value is returned again, then no need
       --  to copy/readjust/finalize, we can just pass the value through (see
@@ -5505,26 +5482,6 @@ package body Exp_Ch6 is
       if Nkind (Par) /= N_Reference then
          Remove_Side_Effects (N);
       end if;
-
-      --  The side effect removal of the function call produced a temporary.
-      --  When the context is a case expression, if expression, or expression
-      --  with actions, the lifetime of the temporary must be extended to match
-      --  that of the context. Otherwise the function result will be finalized
-      --  too early and affect the result of the expression. To prevent this
-      --  unwanted effect, the temporary should not be considered for clean up
-      --  actions by the general finalization machinery.
-
-      --  Exception to this rule are references to Ada 2012 container elements.
-      --  Such references must be finalized at the end of each iteration of the
-      --  related quantified expression, otherwise the container will remain
-      --  busy.
-
-      if Nkind (N) = N_Explicit_Dereference
-        and then Within_Case_Or_If_Expression (N)
-        and then not Is_Element_Reference (N)
-      then
-         Set_Is_Ignored_Transient (Entity (Prefix (N)));
-      end if;
    end Expand_Ctrl_Function_Call;
 
    ----------------------------------------
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index f5d9b0fe802..a95beec956b 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -1265,7 +1265,7 @@ package body Exp_Ch7 is
 
          --  Associate the Finalize_Address primitive of the designated type
          --  with the finalization master of the access type. The designated
-         --  type must be forzen as Finalize_Address is generated when the
+         --  type must be frozen, as Finalize_Address is generated when the
          --  freeze node is expanded.
 
          elsif Is_Frozen (Desig_Typ)
@@ -2257,19 +2257,19 @@ package body Exp_Ch7 is
                if For_Package and then Finalize_Storage_Only (Obj_Typ) then
                   null;
 
-               --  Finalization of transient objects are treated separately in
+               --  Finalization of transient objects is treated separately in
                --  order to handle sensitive cases. These include:
 
                --    * Conditional expressions
                --    * Expressions with actions
                --    * Transient scopes
 
-               --  If one of those contexts has marked the transient object as
-               --  ignored, do not generate finalization actions for it.
+               elsif Is_Finalized_Transient (Obj_Id) then
+                  null;
 
-               elsif Is_Finalized_Transient (Obj_Id)
-                 or else Is_Ignored_Transient (Obj_Id)
-               then
+               --  Finalization of specific objects is also treated separately
+
+               elsif Is_Ignored_For_Finalization (Obj_Id) then
                   null;
 
                --  Ignored Ghost objects do not need any cleanup actions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 17fde44d7ab..b9346a9f405 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -13020,19 +13020,19 @@ package body Exp_Util is
             if Lib_Level and then Finalize_Storage_Only (Obj_Typ) then
                null;
 
-            --  Finalization of transient objects are treated separately in
+            --  Finalization of transient objects is treated separately in
             --  order to handle sensitive cases. These include:
 
             --    * Conditional expressions
             --    * Expressions with actions
             --    * Transient scopes
 
-            --  If one of those contexts has marked the transient object as
-            --  ignored, do not generate finalization actions for it.
+            elsif Is_Finalized_Transient (Obj_Id) then
+               null;
 
-            elsif Is_Finalized_Transient (Obj_Id)
-              or else Is_Ignored_Transient (Obj_Id)
-            then
+            --  Finalization of specific objects is also treated separately
+
+            elsif Is_Ignored_For_Finalization (Obj_Id) then
                null;
 
             --  Ignored Ghost objects do not need any cleanup actions because
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 632ce489b08..8a62eac889d 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -721,8 +721,8 @@ package Gen_IL.Fields is
       Is_Hidden,
       Is_Hidden_Non_Overridden_Subpgm,
       Is_Hidden_Open_Scope,
+      Is_Ignored_For_Finalization,
       Is_Ignored_Ghost_Entity,
-      Is_Ignored_Transient,
       Is_Immediately_Visible,
       Is_Implementation_Defined,
       Is_Imported,
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb
index 3e6ed9633bd..b7e7865a0ba 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -337,7 +337,7 @@ begin -- Gen_IL.Gen.Gen_Entities
         Sm (Esize, Uint),
         Sm (Interface_Name, Node_Id),
         Sm (Is_Finalized_Transient, Flag),
-        Sm (Is_Ignored_Transient, Flag),
+        Sm (Is_Ignored_For_Finalization, Flag),
         Sm (Linker_Section_Pragma, Node_Id),
         Sm (Related_Expression, Node_Id),
         Sm (Status_Flag_Or_Transient_Decl, Node_Id)));
-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] ada: Further cleanup in finalization machinery
@ 2023-11-28  9:39 Marc Poulhiès
  0 siblings, 0 replies; 5+ messages in thread
From: Marc Poulhiès @ 2023-11-28  9:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: Eric Botcazou

From: Eric Botcazou <ebotcazou@adacore.com>

When transient scopes are being materialized, they can give rise to a block
created around the construct being wrapped or not, depending on the kind of
construct.  In both cases finalization actions for the transient objects of
the scope are generated the same way, with normal finalization done manually
immediately after the construct and exceptional finalization deferred to the
enclosing scope by means of a hooking mechanism.

Now when the block is generated, it becomes this enclosing scope, so the
normal finalization that comes with it would also be done immediately after
the construct, even without normal finalization generated manually.

Therefore this change gets rid of the manual finalization as well as of the
hooking in the cases where the block is generated, leading to a significant
streamlining of the expanded code in these cases.  This requires fixing a
small inaccuracy of the Within_Case_Or_If_Expression predicate, which must
only be concerned with the dependent expressions, since those are the only
ones to be treated specially by the finalization machinery.

It also contains a small cleanup for the description of the transient scope
management present at the beginning of the exp_ch7.adb file.

gcc/ada/

	* exp_ch7.ads (Expand_Cleanup_Actions): Move declaration to the
	Finalization Management section.
	* exp_ch7.adb (Transient Scope Management): Move description down to
	after that of the general finalization and make a few changes.
	(Insert_Actions_In_Scope_Around): Call Process_Transients_In_Scope
	only if cleanups are being handled.
	(Process_Transients_In_Scope): Remove redundant test on Clean.
	* exp_util.ads (Within_Case_Or_If_Expression): Adjust description.
	* exp_util.adb (Within_Case_Or_If_Expression): Only return true if
	within the dependent expressions of the conditional expressions.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_ch7.adb  | 149 +++++++++++++++++++++++++------------------
 gcc/ada/exp_ch7.ads  |  12 ++--
 gcc/ada/exp_util.adb |  16 ++++-
 gcc/ada/exp_util.ads |   7 +-
 4 files changed, 110 insertions(+), 74 deletions(-)

diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index f8c12b73e9b..f5d9b0fe802 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -70,59 +70,6 @@ with Uintp;          use Uintp;
 
 package body Exp_Ch7 is
 
-   --------------------------------
-   -- Transient Scope Management --
-   --------------------------------
-
-   --  A transient scope is needed when certain temporary objects are created
-   --  by the compiler. These temporary objects are allocated on the secondary
-   --  stack and/or need finalization, and the transient scope is responsible
-   --  for finalizing the objects and reclaiming the memory of the secondary
-   --  stack at the appropriate time. They are generally objects allocated to
-   --  store the result of a function returning an unconstrained or controlled
-   --  value. Expressions needing to be wrapped in a transient scope may appear
-   --  in three different contexts which lead to different kinds of transient
-   --  scope expansion:
-
-   --   1. In a simple statement (procedure call, assignment, ...). In this
-   --      case the instruction is wrapped into a transient block. See
-   --      Wrap_Transient_Statement for details.
-
-   --   2. In an expression of a control structure (test in a IF statement,
-   --      expression in a CASE statement, ...). See Wrap_Transient_Expression
-   --      for details.
-
-   --   3. In a expression of an object_declaration. No wrapping is possible
-   --      here, so the finalization actions, if any, are done right after the
-   --      declaration and the secondary stack deallocation is done in the
-   --      proper enclosing scope. See Wrap_Transient_Declaration for details.
-
-   --------------------------------------------------
-   -- Transient Blocks and Finalization Management --
-   --------------------------------------------------
-
-   procedure Insert_Actions_In_Scope_Around
-     (N         : Node_Id;
-      Clean     : Boolean;
-      Manage_SS : Boolean);
-   --  Insert the before-actions kept in the scope stack before N, and the
-   --  after-actions after N, which must be a member of a list. If flag Clean
-   --  is set, insert any cleanup actions. If flag Manage_SS is set, insert
-   --  calls to mark and release the secondary stack.
-
-   function Make_Transient_Block
-     (Loc    : Source_Ptr;
-      Action : Node_Id;
-      Par    : Node_Id) return Node_Id;
-   --  Action is a single statement or object declaration. Par is the proper
-   --  parent of the generated block. Create a transient block whose name is
-   --  the current scope and the only handled statement is Action. If Action
-   --  involves controlled objects or secondary stack usage, the corresponding
-   --  cleanup actions are performed at the end of the block.
-
-   procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
-   --  Shared processing for Store_xxx_Actions_In_Scope
-
    -----------------------------
    -- Finalization Management --
    -----------------------------
@@ -292,6 +239,84 @@ package body Exp_Ch7 is
    --  Build the deep Initialize/Adjust/Finalize for a record Typ with
    --  Has_Component_Component set and store them using the TSS mechanism.
 
+   --------------------------------
+   -- Transient Scope Management --
+   --------------------------------
+
+   --  A transient scope is needed when certain temporary objects are created
+   --  by the compiler. These temporary objects are allocated on the secondary
+   --  stack and/or need finalization, and the transient scope is responsible
+   --  for finalizing the objects and reclaiming the memory of the secondary
+   --  stack at the appropriate time. They are generally objects allocated to
+   --  store the result of a function returning an unconstrained or controlled
+   --  value. Expressions needing to be wrapped in a transient scope may appear
+   --  in three different contexts, which lead to different kinds of transient
+   --  scope expansion:
+
+   --   1. In a simple statement (procedure call, assignment, ...). In this
+   --      case the statement is wrapped into a transient block, which takes
+   --      care of the finalization actions as well as the secondary stack
+   --      deallocation, See Wrap_Transient_Statement for details.
+
+   --   2. In an expression of a control structure (test in a If statement,
+   --      expression in a Case statement, ...). In this case the expression
+   --      is replaced by a temporary and the enclosing statement is wrapped
+   --      into a transient block, which takes care of the finalization actions
+   --      and the secondary stack deallocation. See Wrap_Transient_Expression
+   --      for details.
+
+   --   3. In an expression of an object declaration. No wrapping is possible
+   --      here, so the finalization actions performed on the normal path, if
+   --      any, are done right after the declaration, and those performed on
+   --      the exceptional path, as well as the secondary stack deallocation,
+   --      are deferred to the enclosing scope. See Wrap_Transient_Declaration
+   --      for details.
+
+   --  A transient scope is created by calling Establish_Transient_Scope on the
+   --  node that needs to be serviced by it (the serviced node can subsequently
+   --  be retrieved by invoking Node_To_Be_Wrapped when the current scope is a
+   --  transient scope). Once this has been done, the normal processing of the
+   --  Insert_Actions procedures is blocked and the procedures are redirected
+   --  to the Store_xxx_Actions_In_Scope procedures and Store_Actions_In_Scope
+   --  is ultimately invoked to store the pending actions.
+
+   --  A transient scope is finalized by calling one of the Wrap_Transient_xxx
+   --  procedures depending on the context as explained above. They ultimately
+   --  invoke Insert_Actions_In_Scope_Around as per the following picture:
+
+   --            Wrap_Transient_Expression          Wrap_Transient_Statement
+   --                                  |              |
+   --                                  V              V
+   --                                Make_Transient_Block
+   --                                        |
+   --   Wrap_Transient_Declaration           |
+   --                          |             |
+   --                          V             V
+   --                       Insert_Actions_In_Scope_Around
+
+   procedure Insert_Actions_In_Scope_Around
+     (N         : Node_Id;
+      Clean     : Boolean;
+      Manage_SS : Boolean);
+   --  Insert the before-actions kept in the scope stack before N, and the
+   --  after-actions after N, which must be a member of a list. If Clean is
+   --  true, insert any cleanup actions kept in the scope stack and generate
+   --  required finalization actions for the before-actions and after-actions.
+   --  If Manage_SS is true, insert calls to mark/release the secondary stack.
+
+   function Make_Transient_Block
+     (Loc    : Source_Ptr;
+      Action : Node_Id;
+      Par    : Node_Id) return Node_Id;
+   --  Action is a single statement or object declaration. Par is the proper
+   --  parent of the generated block. Create a transient block whose name is
+   --  the current scope and the only handled statement is Action. If Action
+   --  involves controlled objects or secondary stack usage, the corresponding
+   --  cleanup actions are performed at the end of the block.
+
+   procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
+   --  Shared processing for Store_xxx_Actions_In_Scope
+
    -------------------------------------------
    -- Unnesting procedures for CCG and LLVM --
    -------------------------------------------
@@ -5641,9 +5666,7 @@ package body Exp_Ch7 is
             Blk_Ins   := Last_Object;
          end if;
 
-         if Clean then
-            Insert_List_After_And_Analyze (Blk_Ins, Act_Cleanup);
-         end if;
+         Insert_List_After_And_Analyze (Blk_Ins, Act_Cleanup);
 
          --  Examine all objects in the list First_Object .. Last_Object
 
@@ -5824,13 +5847,15 @@ package body Exp_Ch7 is
            (Last_Obj, Build_SS_Release_Call (Loc, Mark_Id));
       end if;
 
-      --  Check for transient objects associated with Target and generate the
-      --  appropriate finalization actions for them.
+      --  If we are handling cleanups, check for transient objects associated
+      --  with Target and generate the required finalization actions for them.
 
-      Process_Transients_In_Scope
-        (First_Object => First_Obj,
-         Last_Object  => Last_Obj,
-         Related_Node => Target);
+      if Clean then
+         Process_Transients_In_Scope
+           (First_Object => First_Obj,
+            Last_Object  => Last_Obj,
+            Related_Node => Target);
+      end if;
 
       --  Reset the action lists
 
diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads
index a131e55f5c3..105aa7e3d2f 100644
--- a/gcc/ada/exp_ch7.ads
+++ b/gcc/ada/exp_ch7.ads
@@ -176,6 +176,12 @@ package Exp_Ch7 is
    --  triggered by an abort, E_Id denotes the defining identifier of a local
    --  exception occurrence, Raised_Id is the entity of a local boolean flag.
 
+   procedure Expand_Cleanup_Actions (N : Node_Id);
+   --  Expand the necessary stuff into a scope to enable finalization of local
+   --  objects and deallocation of transient data when exiting the scope. N is
+   --  one of N_Block_Statement, N_Subprogram_Body, N_Task_Body, N_Entry_Body,
+   --  or N_Extended_Return_Statement.
+
    function Make_Adjust_Call
      (Obj_Ref   : Node_Id;
       Typ       : Entity_Id;
@@ -275,12 +281,6 @@ package Exp_Ch7 is
    -- Transient Scope Management --
    --------------------------------
 
-   procedure Expand_Cleanup_Actions (N : Node_Id);
-   --  Expand the necessary stuff into a scope to enable finalization of local
-   --  objects and deallocation of transient data when exiting the scope. N is
-   --  one of N_Block_Statement, N_Subprogram_Body, N_Task_Body, N_Entry_Body,
-   --  or N_Extended_Return_Statement.
-
    procedure Establish_Transient_Scope
      (N                : Node_Id;
       Manage_Sec_Stack : Boolean);
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 3952a161bd7..3dc34fcb493 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -14401,6 +14401,7 @@ package body Exp_Util is
    ----------------------------------
 
    function Within_Case_Or_If_Expression (N : Node_Id) return Boolean is
+      Nod : Node_Id;
       Par : Node_Id;
 
    begin
@@ -14408,9 +14409,17 @@ package body Exp_Util is
       --  can be expanded into Expression_With_Actions, hence the test of the
       --  original node.
 
-      Par := Parent (N);
+      Nod := N;
+      Par := Parent (Nod);
+
       while Present (Par) loop
-         if Nkind (Original_Node (Par)) in N_Case_Expression | N_If_Expression
+         if Nkind (Original_Node (Par)) = N_Case_Expression
+           and then Nod /= Expression (Original_Node (Par))
+         then
+            return True;
+
+         elsif Nkind (Original_Node (Par)) = N_If_Expression
+           and then Nod /= First (Expressions (Original_Node (Par)))
          then
             return True;
 
@@ -14430,7 +14439,8 @@ package body Exp_Util is
             return False;
          end if;
 
-         Par := Parent (Par);
+         Nod := Par;
+         Par := Parent (Nod);
       end loop;
 
       return False;
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index 932bf3fdcbc..eb737d67769 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -1255,9 +1255,10 @@ package Exp_Util is
    --  extension to verify legality rules on inherited conditions.
 
    function Within_Case_Or_If_Expression (N : Node_Id) return Boolean;
-   --  Determine whether arbitrary node N is immediately within a case or an if
-   --  expression. The criterion is whether temporaries created by the actions
-   --  attached to N need to outlive an enclosing case or if expression.
+   --  Determine whether arbitrary node N is immediately within a dependent
+   --  expression of a case or an if expression. The criterion is whether
+   --  temporaries created by the actions attached to N need to outlive an
+   --  enclosing case or if expression.
 
 private
    pragma Inline (Duplicate_Subexpr);
-- 
2.42.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] ada: Further cleanup in finalization machinery
@ 2023-11-21 10:00 Marc Poulhiès
  0 siblings, 0 replies; 5+ messages in thread
From: Marc Poulhiès @ 2023-11-21 10:00 UTC (permalink / raw)
  To: gcc-patches; +Cc: Eric Botcazou

From: Eric Botcazou <ebotcazou@adacore.com>

The bodies of generic units are instantiated separately by GNAT at the end
of the processing of the compilation unit.  This requires the deferral of
the generation of cleanups and finalization actions in enclosing scopes,
except for instantiations in generic units where they are not generated.

The criterion used to detect this latter case is Inside_A_Generic, but this
global variable is not properly updated during the instantiation of generic
bodies, leading to problems with nested instantiations, so it is changed to
Expander_Active instead.  As a matter of fact, the exact same idiom is used
a few lines above to clear the Needs_Body variable.

gcc/ada/

	* sem_ch12.adb (Analyze_Package_Instantiation): Test Expander_Active
	to detect generic contexts for the generation of cleanup actions.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/sem_ch12.adb | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 31fcbedf774..7c645c490ae 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -4824,10 +4824,7 @@ package body Sem_Ch12 is
                      --  Cleanup actions are not generated within generic units
                      --  or in the formal part of generic units.
 
-                     if Inside_A_Generic
-                       or else Is_Generic_Unit (S)
-                       or else Ekind (S) = E_Void
-                     then
+                     if not Expander_Active then
                         exit;
 
                      --  For package scopes, cleanup actions are generated only
-- 
2.42.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [COMMITTED] ada: Further cleanup in finalization machinery
@ 2023-11-21 10:00 Marc Poulhiès
  0 siblings, 0 replies; 5+ messages in thread
From: Marc Poulhiès @ 2023-11-21 10:00 UTC (permalink / raw)
  To: gcc-patches; +Cc: Eric Botcazou

From: Eric Botcazou <ebotcazou@adacore.com>

This removes the specific treatment of transient scopes in initialization
procedures, which is obsolete.

gcc/ada/

	* exp_aggr.adb (Convert_To_Assignments): Do not treat initialization
	procedures specially when it comes to creating a transient scope.
	* exp_ch7.adb (Build_Finalizer.Process_Declarations): Likewise.
	* exp_util.adb (Requires_Cleanup_Actions): Likewise.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_aggr.adb | 10 ++--------
 gcc/ada/exp_ch7.adb  | 29 -----------------------------
 gcc/ada/exp_util.adb |  9 ---------
 3 files changed, 2 insertions(+), 46 deletions(-)

diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index a6a54e892e2..691430a3e52 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -4294,15 +4294,9 @@ package body Exp_Aggr is
          return;
       end if;
 
-      --  Otherwise, if a transient scope is required, create it now. If we
-      --  are within an initialization procedure do not create such, because
-      --  the target of the assignment must not be declared within a local
-      --  block, and because cleanup will take place on return from the
-      --  initialization procedure.
+      --  Otherwise, if a transient scope is required, create it now
 
-      --  Should the condition be more restrictive ???
-
-      if Requires_Transient_Scope (Typ) and then not Inside_Init_Proc then
+      if Requires_Transient_Scope (Typ) then
          Establish_Transient_Scope (N, Manage_Sec_Stack => False);
       end if;
 
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 2e3da4cfaed..ef3b5c95d64 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -2479,35 +2479,6 @@ package body Exp_Ch7 is
               and then Present (Library_Unit (Decl))
             then
                Process_Package_Body (Proper_Body (Unit (Library_Unit (Decl))));
-
-            --  Handle a rare case caused by a controlled transient object
-            --  created as part of a record init proc. The variable is wrapped
-            --  in a block, but the block is not associated with a transient
-            --  scope.
-
-            elsif Nkind (Decl) = N_Block_Statement
-              and then Inside_Init_Proc
-            then
-               Old_Counter_Val := Counter_Val;
-
-               if Present (Handled_Statement_Sequence (Decl)) then
-                  Process_Declarations
-                    (Statements (Handled_Statement_Sequence (Decl)),
-                     Preprocess);
-               end if;
-
-               Process_Declarations (Declarations (Decl), Preprocess);
-
-               --  Either the declaration or statement list of the block has a
-               --  controlled object.
-
-               if Preprocess
-                 and then Top_Level
-                 and then No (Last_Top_Level_Ctrl_Construct)
-                 and then Counter_Val > Old_Counter_Val
-               then
-                  Last_Top_Level_Ctrl_Construct := Decl;
-               end if;
             end if;
 
             Prev_Non_Pragma (Decl);
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 3b34e4659f1..3952a161bd7 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -13233,15 +13233,6 @@ package body Exp_Util is
             then
                return True;
             end if;
-
-        --  Handle a rare case caused by a controlled transient object created
-        --  as part of a record init proc. The variable is wrapped in a block,
-        --  but the block is not associated with a transient scope.
-
-         elsif Nkind (Decl) = N_Block_Statement and then Inside_Init_Proc then
-            if Requires_Cleanup_Actions (Decl, Lib_Level) then
-               return True;
-            end if;
          end if;
 
          Next (Decl);
-- 
2.42.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-12-19 14:30 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-19 14:29 [COMMITTED] ada: Further cleanup in finalization machinery Marc Poulhiès
  -- strict thread matches above, loose matches on Subject: below --
2023-12-19 14:30 Marc Poulhiès
2023-11-28  9:39 Marc Poulhiès
2023-11-21 10:00 Marc Poulhiès
2023-11-21 10:00 Marc Poulhiès

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).