diff mbox

[Ada] Missing finalization of a transient class-wide function result

Message ID 20140717062250.GA28260@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet July 17, 2014, 6:22 a.m. UTC
This patch corrects the transient object machinery to treat the renamed result
of a controlled function call as a finalizable transient when the context is an
expression with actions. If this was a different context, the lifetime of the
result would be considered extended and not finalized.

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

--  types.ads

with Ada.Finalization; use Ada.Finalization;

package Types is
   type Ctrl is new Limited_Controlled with record
      Val : Integer := 0;
   end record;

   function F1 (Obj : Ctrl) return Integer;
   function F2 (Val : Integer) return Ctrl'Class;
   procedure Finalize (Obj : in out Ctrl);

   procedure Test (Flag : Boolean; Obj : Ctrl);
end Types;

--  types.adb

with Ada.Text_IO; use Ada.Text_IO;

package body Types is
   procedure Finalize (Obj : in out Ctrl) is
   begin
      Put_Line ("fin" & Obj.Val'Img);
   end Finalize;

   function F1 (Obj : Ctrl) return Integer is
   begin
      return Obj.Val + 1;
   end F1;

   function F2 (Val : Integer) return Ctrl'Class is
   begin
      Put_Line ("ini" & Val'Img);
      return Ctrl'(Limited_Controlled with Val => Val);
   end F2;

   procedure Test (Flag : Boolean; Obj : Ctrl) is
   begin
      if Flag and then F2 (F1 (Obj)).Val = 42 then
         raise Program_Error;
      end if;
   end Test;
end Types;

--  main.adb

with Ada.Text_IO; use Ada.Text_IO;
with Types;       use Types;

procedure Main is
begin
   declare
      Obj : Ctrl;
   begin
      Obj.Val := 1;
      Test (True, Obj);
   exception
      when others =>
         Put_Line ("ERROR: unexpected exception 1");
   end;

   declare
      Obj : Ctrl;
   begin
      Obj.Val := 41;
      Test (True, Obj);
      Put_Line ("ERROR: exception not raised");
   exception
      when Program_Error =>
         null;
      when others =>
         Put_Line ("ERROR: unexpected exception 2");
   end;
end Main;

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

$ gnatmake -q main.adb
$ ./main
ini 2
fin 2
fin 1
ini 42
fin 42
fin 41

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

2014-07-17  Hristian Kirtchev  <kirtchev@adacore.com>

	* exp_util.adb (Is_Aliased): Transient objects
	within an expression with actions cannot be considered aliased.
diff mbox

Patch

Index: exp_util.adb
===================================================================
--- exp_util.adb	(revision 212719)
+++ exp_util.adb	(working copy)
@@ -4557,6 +4557,15 @@ 
       --  Start of processing for Is_Aliased
 
       begin
+         --  Aliasing in expression with actions does not matter because the
+         --  scope of the transient object is always limited by the scope of
+         --  the EWA. Such objects are always hooked and always finalized at
+         --  the end of the EWA's scope.
+
+         if Nkind (Rel_Node) = N_Expression_With_Actions then
+            return False;
+         end if;
+
          Stmt := First_Stmt;
          while Present (Stmt) loop
             if Nkind (Stmt) = N_Object_Declaration then
@@ -7343,7 +7352,7 @@ 
             elsif Is_Access_Type (Obj_Typ)
               and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
               and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
-                                                        N_Object_Declaration
+                                N_Object_Declaration
               and then Is_Finalizable_Transient
                          (Status_Flag_Or_Transient_Decl (Obj_Id), Decl)
             then