A call to a function that returns a controlled object generates finalization actions that must be placed in the code immediately after use of the object. This patch fixes a bug in the handling of these actions when the context of the function call is a generated if-expression.
Executing: gnatmake -gnatE -q main main must yield: True --- with Ada.Text_IO; use Ada.Text_IO; with Pack; use Pack; procedure Main is function Factorial (Val : Natural) return Natural is begin if Val > 1 then return Factorial (Val - 1) * Val; else return 1; end if; end Factorial; begin if Is_Even (Factorial (2)) or Equal (Left => New_Ctrl, Right => New_Ctrl) then Put_Line ("True"); else Put_Line ("False"); end if; end Main; --- with Ada.Finalization; use Ada.Finalization; package Pack is type Ctrl is new Controlled with record Id : Natural := 123; end record; function Equal (Left : Ctrl; Right : Ctrl) return Boolean; function Is_Even (Val : Natural) return Boolean; function New_Ctrl return Ctrl; end Pack; --- package body Pack is function Equal (Left : Ctrl; Right : Ctrl) return Boolean is begin return Left.Id = Right.Id; end Equal; function Is_Even (Val : Natural) return Boolean is begin return Val / 2 = 0; end Is_Even; function New_Ctrl return Ctrl is Result : Ctrl; begin return Result; end New_Ctrl; end Pack; Tested on x86_64-pc-linux-gnu, committed on trunk 2013-10-14 Ed Schonberg <schonb...@adacore.com> * exp_ch4.adb (Process_Transient_Object): If a transient scope has already been created, use the corresponding Node_To_Be_Wrapped as the insertion point for the controlled actions.
Index: exp_ch4.adb =================================================================== --- exp_ch4.adb (revision 203521) +++ exp_ch4.adb (working copy) @@ -12159,11 +12159,22 @@ Top : Node_Id; begin + -- In most cases an expression that creates a controlled object + -- generates a transient scope around it. If this is the case then + -- other controlled values can reuse it. + + if Scope_Is_Transient then + return Node_To_Be_Wrapped; + + -- In some cases, such as return statements, no transient scope is + -- generated, in which case we have to look up in the tree to find + -- the proper list on which to place the transient. + -- When the node is inside a case/if expression, the lifetime of any -- temporary controlled object is extended. Find a suitable insertion -- node by locating the topmost case or if expressions. - if Within_Case_Or_If_Expression (N) then + elsif Within_Case_Or_If_Expression (N) then Par := N; Top := N; while Present (Par) loop