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