[Ada] Better handling of controlled objects in conditional expressions
Arnaud Charlet
charlet@adacore.com
Mon Oct 14 13:19:00 GMT 2013
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 <schonberg@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.
-------------- next part --------------
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
More information about the Gcc-patches
mailing list