[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