This patch modifies the expansion of Expression_With_Actions in order to handle
the finalization of a function call nested deep within the condition of an if
statement.

------------
-- Source --
------------

--  main.adb

with Ada.Finalization; use Ada.Finalization;
with Ada.Text_IO;      use Ada.Text_IO;

procedure Main is
   type Ctrl is new Controlled with record
     Id : Natural := 0;
   end record;

   procedure Finalize (Obj : in out Ctrl) is
   begin
      Put_Line ("  finalize Id:" & Obj.Id'Img);
   end Finalize;

   function Make_Ctrl (Id : Natural) return Ctrl is
   begin
      return (Controlled with Id => Id);
   end Make_Ctrl;

   function Equal (Left : Ctrl; Right : Ctrl) return Boolean is
   begin
      return Left.Id = Right.Id;
   end Equal;

   procedure Test
     (Obj     : Ctrl;
      Id      : Natural;
      Check_1 : Integer;
      Check_2 : Integer)
   is
   begin
      Put_Line ("before if statement");
      if Check_1 > 1
        and then
          (Check_2 > 1
             or else Equal (Obj, Make_Ctrl (Id)))
      then
         Put_Line ("inside if statement");
      end if;
       Put_Line ("after if statement");
   end Test;

   Id  : constant Natural := 1234;
   Obj : constant Ctrl := (Controlled with Id => Id);
begin
   Test (Obj, Id, 2, 1);
end Main;

-------------------------------------
-- Compilation and expected output --
-------------------------------------

$ gnatmake -q -gnat05 main.adb
$ ./main
before if statement
  finalize Id: 1234
  finalize Id: 1234
inside if statement
after if statement
  finalize Id: 1234

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-09-01  Hristian Kirtchev  <kirtc...@adacore.com>

        * exp_ch4.adb (Find_Insertion_Node): New routine. Determines the proper
        insertion node in a tree of nested Expression_With_Actions nodes.
        (Process_Transient_Object): In the case where a complex if statement
        has been converted into nested Expression_With_Actions nodes, the
        "hook" object and the associated access type must be inserted before
        the top most Expression_With_Actions.

Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb (revision 178381)
+++ exp_ch4.adb (working copy)
@@ -4415,10 +4415,32 @@
       ------------------------------
 
       procedure Process_Transient_Object (Decl : Node_Id) is
-         Ins_Nod : constant Node_Id := Parent (N);
-         --  To avoid the insertion of generated code in the list of Actions,
-         --  Insert_Action must look at the parent field of the EWA.
 
+         function Find_Insertion_Node return Node_Id;
+         --  Complex if statements may be converted into nested EWAs. In this
+         --  case, any generated code must be inserted before the if statement
+         --  to ensure proper visibility of the "hook" objects. This routine
+         --  returns the top most short circuit operator or the parent of the
+         --  EWA if no nesting was detected.
+
+         -------------------------
+         -- Find_Insertion_Node --
+         -------------------------
+
+         function Find_Insertion_Node return Node_Id is
+            Par : Node_Id := N;
+
+         begin
+            --  Climb up the branches of a complex if statement
+
+            while Nkind_In (Parent (Par), N_And_Then, N_Op_Not, N_Or_Else) loop
+               Par := Parent (Par);
+            end loop;
+
+            return Par;
+         end Find_Insertion_Node;
+
+         Ins_Nod   : constant Node_Id    := Find_Insertion_Node;
          Loc       : constant Source_Ptr := Sloc (Decl);
          Obj_Id    : constant Entity_Id  := Defining_Identifier (Decl);
          Obj_Typ   : constant Entity_Id  := Etype (Obj_Id);

Reply via email to