]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[multiple changes]
authorArnaud Charlet <charlet@gcc.gnu.org>
Mon, 8 Jul 2013 07:52:49 +0000 (09:52 +0200)
committerArnaud Charlet <charlet@gcc.gnu.org>
Mon, 8 Jul 2013 07:52:49 +0000 (09:52 +0200)
2013-07-08  Hristian Kirtchev  <kirtchev@adacore.com>

* exp_ch4.adb (Create_Alternative): Removed.
(Expand_N_If_Expression): Remove constant
In_Case_Or_If_Expression. Add local variable
Ptr_Typ. Inspect the "then" and "else" action lists
for transient controlled objects and generate code to
finalize them. (Is_Controlled_Function_Call): Removed.
(Process_Action): Update the comment on usage. Update the call
to Process_Transient_Object. There is no need to continue the
traversal of the object itself.
(Process_Actions): New routine.
(Process_Transient_Object): Moved to the top level of Exp_Ch4. Add
a new formal and update the related comment on usage.
* exp_util.adb (Within_Case_Or_If_Expression): Start the search
from the parent of the node.

2013-07-08  Robert Dewar  <dewar@adacore.com>

* a-cusyqu.ads, a-cbprqu.ads, s-interr.ads, a-cuprqu.ads,
a-cbsyqu.ads: Minor reformatting (proper formatting of overriding).

From-SVN: r200759

gcc/ada/ChangeLog
gcc/ada/a-cbprqu.ads
gcc/ada/a-cbsyqu.ads
gcc/ada/a-cuprqu.ads
gcc/ada/a-cusyqu.ads
gcc/ada/exp_ch4.adb
gcc/ada/exp_util.adb
gcc/ada/s-interr.ads

index 9f72a459e925a062a588bf159686fffe83d39894..8d8c993ffbdb3321fa587c220dd2f98aecf4af80 100644 (file)
@@ -1,3 +1,25 @@
+2013-07-08  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * exp_ch4.adb (Create_Alternative): Removed.
+       (Expand_N_If_Expression): Remove constant
+       In_Case_Or_If_Expression. Add local variable
+       Ptr_Typ. Inspect the "then" and "else" action lists
+       for transient controlled objects and generate code to
+       finalize them.  (Is_Controlled_Function_Call): Removed.
+       (Process_Action): Update the comment on usage. Update the call
+       to Process_Transient_Object. There is no need to continue the
+       traversal of the object itself.
+       (Process_Actions): New routine.
+       (Process_Transient_Object): Moved to the top level of Exp_Ch4. Add
+       a new formal and update the related comment on usage.
+       * exp_util.adb (Within_Case_Or_If_Expression): Start the search
+       from the parent of the node.
+
+2013-07-08  Robert Dewar  <dewar@adacore.com>
+
+       * a-cusyqu.ads, a-cbprqu.ads, s-interr.ads, a-cuprqu.ads,
+       a-cbsyqu.ads: Minor reformatting (proper formatting of overriding).
+
 2013-07-08  Ed Schonberg  <schonberg@adacore.com>
 
        * sem_ch8.adb (Attribute_Renaming): Treat 'Img as an attribute
index aa184a1cc5aabb4ff76b78d4d2e0fb6b9a98ad94..fb44d02c1dd1b477d1872af5977c5ffd00f8f103 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---            Copyright (C) 2011, Free Software Foundation, Inc.            --
+--          Copyright (C) 2011-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- This specification is derived from the Ada Reference Manual for use with --
 -- GNAT. The copyright notice above, and the license provisions that follow --
@@ -101,13 +101,13 @@ package Ada.Containers.Bounded_Priority_Queues is
    protected type Queue
      (Capacity : Count_Type := Default_Capacity;
       Ceiling  : System.Any_Priority := Default_Ceiling)
-     with Priority => Ceiling is new Queue_Interfaces.Queue with
+   with
+     Priority => Ceiling
+   is new Queue_Interfaces.Queue with
 
-      overriding
-      entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
+      overriding entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
 
-      overriding
-      entry Dequeue (Element : out Queue_Interfaces.Element_Type);
+      overriding entry Dequeue (Element : out Queue_Interfaces.Element_Type);
 
       --  The priority queue operation Dequeue_Only_High_Priority had been a
       --  protected entry in early drafts of AI05-0159, but it was discovered
@@ -116,22 +116,17 @@ package Ada.Containers.Bounded_Priority_Queues is
       --  ARG meeting in Edinburgh (June 2011), with a different signature and
       --  semantics.
 
-      not overriding
       procedure Dequeue_Only_High_Priority
         (At_Least : Queue_Priority;
          Element  : in out Queue_Interfaces.Element_Type;
          Success  : out Boolean);
 
-      overriding
-      function Current_Use return Count_Type;
+      overriding function Current_Use return Count_Type;
 
-      overriding
-      function Peak_Use return Count_Type;
+      overriding function Peak_Use return Count_Type;
 
    private
-
       List : Implementation.List_Type (Capacity);
-
    end Queue;
 
 end Ada.Containers.Bounded_Priority_Queues;
index 0d6e3c39958442ee727ed6590fdca2e174e7c063..908463906ce678a96a1a2f0d8884ea5ef60c1e16 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---            Copyright (C) 2011, Free Software Foundation, Inc.            --
+--          Copyright (C) 2011-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- This specification is derived from the Ada Reference Manual for use with --
 -- GNAT. The copyright notice above, and the license provisions that follow --
@@ -83,24 +83,20 @@ package Ada.Containers.Bounded_Synchronized_Queues is
    protected type Queue
      (Capacity : Count_Type := Default_Capacity;
       Ceiling  : System.Any_Priority := Default_Ceiling)
-     with Priority => Ceiling is new Queue_Interfaces.Queue with
+   with
+     Priority => Ceiling
+   is new Queue_Interfaces.Queue with
 
-      overriding
-      entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
+      overriding entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
 
-      overriding
-      entry Dequeue (Element : out Queue_Interfaces.Element_Type);
+      overriding entry Dequeue (Element : out Queue_Interfaces.Element_Type);
 
-      overriding
-      function Current_Use return Count_Type;
+      overriding function Current_Use return Count_Type;
 
-      overriding
-      function Peak_Use return Count_Type;
+      overriding function Peak_Use return Count_Type;
 
    private
-
       List : Implementation.List_Type (Capacity);
-
    end Queue;
 
 end Ada.Containers.Bounded_Synchronized_Queues;
index 3709f42aa29ddbc95093fef63bf6fae9da5a852a..4e11d6eef057c75180502f32240d02934b7827b2 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---            Copyright (C) 2011, Free Software Foundation, Inc.            --
+--          Copyright (C) 2011-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- This specification is derived from the Ada Reference Manual for use with --
 -- GNAT. The copyright notice above, and the license provisions that follow --
@@ -94,19 +94,18 @@ package Ada.Containers.Unbounded_Priority_Queues is
          Max_Length  : Count_Type := 0;
       end record;
 
-      overriding
-      procedure Finalize (List : in out List_Type);
+      overriding procedure Finalize (List : in out List_Type);
 
    end Implementation;
 
    protected type Queue (Ceiling : System.Any_Priority := Default_Ceiling)
-     with Priority => Ceiling is new Queue_Interfaces.Queue with
+   with
+     Priority => Ceiling
+   is new Queue_Interfaces.Queue with
 
-      overriding
-      entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
+      overriding entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
 
-      overriding
-      entry Dequeue (Element : out Queue_Interfaces.Element_Type);
+      overriding entry Dequeue (Element : out Queue_Interfaces.Element_Type);
 
       --  The priority queue operation Dequeue_Only_High_Priority had been a
       --  protected entry in early drafts of AI05-0159, but it was discovered
@@ -115,22 +114,17 @@ package Ada.Containers.Unbounded_Priority_Queues is
       --  ARG meeting in Edinburgh (June 2011), with a different signature and
       --  semantics.
 
-      not overriding
       procedure Dequeue_Only_High_Priority
         (At_Least : Queue_Priority;
          Element  : in out Queue_Interfaces.Element_Type;
          Success  : out Boolean);
 
-      overriding
-      function Current_Use return Count_Type;
+      overriding function Current_Use return Count_Type;
 
-      overriding
-      function Peak_Use return Count_Type;
+      overriding function Peak_Use return Count_Type;
 
    private
-
       List : Implementation.List_Type;
-
    end Queue;
 
 end Ada.Containers.Unbounded_Priority_Queues;
index c4f9d7f7d590704cad5e45872f04bbda989bfe8f..c4f18020356696406db331f7d80e2a443080900e 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---            Copyright (C) 2011, Free Software Foundation, Inc.            --
+--          Copyright (C) 2011-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- This specification is derived from the Ada Reference Manual for use with --
 -- GNAT. The copyright notice above, and the license provisions that follow --
@@ -80,30 +80,26 @@ package Ada.Containers.Unbounded_Synchronized_Queues is
          Max_Length  : Count_Type := 0;
       end record;
 
-      overriding
-      procedure Finalize (List : in out List_Type);
+      overriding procedure Finalize (List : in out List_Type);
 
    end Implementation;
 
-   protected type Queue (Ceiling : System.Any_Priority := Default_Ceiling)
-     with Priority => Ceiling is new Queue_Interfaces.Queue with
+   protected type Queue
+     (Ceiling : System.Any_Priority := Default_Ceiling)
+   with
+     Priority => Ceiling
+   is new Queue_Interfaces.Queue with
 
-      overriding
-      entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
+      overriding entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
 
-      overriding
-      entry Dequeue (Element : out Queue_Interfaces.Element_Type);
+      overriding entry Dequeue (Element : out Queue_Interfaces.Element_Type);
 
-      overriding
-      function Current_Use return Count_Type;
+      overriding function Current_Use return Count_Type;
 
-      overriding
-      function Peak_Use return Count_Type;
+      overriding function Peak_Use return Count_Type;
 
    private
-
       List : Implementation.List_Type;
-
    end Queue;
 
 end Ada.Containers.Unbounded_Synchronized_Queues;
index f9c6fd81f7b12cae84bbcf26d3b729a2dded1745..26c517678f5de21c8d0ea3499f7f53ab494b58d4 100644 (file)
@@ -233,6 +233,16 @@ package body Exp_Ch4 is
    --  simple entity, and op is a comparison operator, optimizes it into a
    --  comparison of First and Last.
 
+   procedure Process_Transient_Object
+     (Decl     : Node_Id;
+      Rel_Node : Node_Id);
+   --  Subsidiary routine to the expansion of expression_with_actions and if
+   --  expressions. Generate all the necessary code to finalize a transient
+   --  controlled object when the enclosing context is elaborated or evaluated.
+   --  Decl denotes the declaration of the transient controlled object which is
+   --  usually the result of a controlled function call. Rel_Node denotes the
+   --  context, either an expression_with_actions or an if expression.
+
    procedure Rewrite_Comparison (N : Node_Id);
    --  If N is the node for a comparison whose outcome can be determined at
    --  compile time, then the node N can be rewritten with True or False. If
@@ -5052,306 +5062,23 @@ package body Exp_Ch4 is
    --------------------------------------
 
    procedure Expand_N_Expression_With_Actions (N : Node_Id) is
-      In_Case_Or_If_Expression : constant Boolean :=
-                                   Within_Case_Or_If_Expression (N);
-
       function Process_Action (Act : Node_Id) return Traverse_Result;
-      --  Inspect and process a single action of an expression_with_actions
+      --  Inspect and process a single action of an expression_with_actions for
+      --  transient controlled objects. If such objects are found, the routine
+      --  generates code to clean them up when the context of the expression is
+      --  evaluated or elaborated.
 
       --------------------
       -- Process_Action --
       --------------------
 
       function Process_Action (Act : Node_Id) return Traverse_Result is
-         procedure Process_Transient_Object (Obj_Decl : Node_Id);
-         --  Obj_Decl denotes the declaration of a transient controlled object.
-         --  Generate all necessary types and hooks to properly finalize the
-         --  result when the enclosing context is elaborated/evaluated.
-
-         ------------------------------
-         -- Process_Transient_Object --
-         ------------------------------
-
-         procedure Process_Transient_Object (Obj_Decl : Node_Id) is
-            function Find_Enclosing_Context return Node_Id;
-            --  Find the context where the expression_with_actions appears
-
-            ----------------------------
-            -- Find_Enclosing_Context --
-            ----------------------------
-
-            function Find_Enclosing_Context return Node_Id is
-               Par : Node_Id;
-               Top : Node_Id;
-
-            begin
-               --  The expression_with_actions is in a case/if expression and
-               --  the lifetime of any temporary controlled object is therefore
-               --  extended. Find a suitable insertion node by locating the top
-               --  most case or if expressions.
-
-               if In_Case_Or_If_Expression then
-                  Par := N;
-                  Top := N;
-                  while Present (Par) loop
-                     if Nkind_In (Original_Node (Par), N_Case_Expression,
-                                                       N_If_Expression)
-                     then
-                        Top := Par;
-
-                     --  Prevent the search from going too far
-
-                     elsif Is_Body_Or_Package_Declaration (Par) then
-                        exit;
-                     end if;
-
-                     Par := Parent (Par);
-                  end loop;
-
-                  --  The topmost case or if expression is now recovered, but
-                  --  it may still not be the correct place to add all the
-                  --  generated code. Climb to find a parent that is part of a
-                  --  declarative or statement list.
-
-                  Par := Top;
-                  while Present (Par) loop
-                     if Is_List_Member (Par)
-                       and then
-                         not Nkind_In (Par, N_Component_Association,
-                                            N_Discriminant_Association,
-                                            N_Parameter_Association,
-                                            N_Pragma_Argument_Association)
-                     then
-                        return Par;
-
-                     --  Prevent the search from going too far
-
-                     elsif Is_Body_Or_Package_Declaration (Par) then
-                        exit;
-                     end if;
-
-                     Par := Parent (Par);
-                  end loop;
-
-                  return Par;
-
-               --  Short circuit operators in complex expressions are converted
-               --  into expression_with_actions.
-
-               else
-                  --  Take care of the case where the expression_with_actions
-                  --  is buried deep inside an IF statement. The temporary
-                  --  function result must be finalized before the then, elsif
-                  --  or else statements are evaluated.
-
-                  --    if Something
-                  --      and then Ctrl_Func_Call
-                  --    then
-                  --       <result must be finalized at this point>
-                  --       <statements>
-                  --    end if;
-
-                  --  To achieve this, find the topmost logical operator. The
-                  --  generated actions are then inserted before/after it.
-
-                  Par := N;
-                  while Present (Par) loop
-
-                     --  Keep climbing past various operators
-
-                     if Nkind (Parent (Par)) in N_Op
-                       or else Nkind_In (Parent (Par), N_And_Then, N_Or_Else)
-                     then
-                        Par := Parent (Par);
-                     else
-                        exit;
-                     end if;
-                  end loop;
-
-                  Top := Par;
-
-                  --  The expression_with_actions might be located in a pragma
-                  --  in which case locate the pragma itself:
-
-                  --    pragma Precondition (... and then Ctrl_Func_Call ...);
-
-                  --  Similar case occurs when the expression_with_actions is
-                  --  related to an object declaration or assignment:
-
-                  --    Obj [: Some_Typ] := ... and then Ctrl_Func_Call ...;
-
-                  --  Another case to consider is an expression_with_actions as
-                  --  part of a return statement:
-
-                  --    return ... and then Ctrl_Func_Call ...;
-
-                  --  Yet another case: a formal in a procedure call statement:
-
-                  --    Proc (... and then Ctrl_Func_Call ...);
-
-                  while Present (Par) loop
-                     if Nkind_In (Par, N_Assignment_Statement,
-                                       N_Object_Declaration,
-                                       N_Pragma,
-                                       N_Procedure_Call_Statement,
-                                       N_Simple_Return_Statement)
-                     then
-                        return Par;
-
-                     --  Prevent the search from going too far
-
-                     elsif Is_Body_Or_Package_Declaration (Par) then
-                        exit;
-                     end if;
-
-                     Par := Parent (Par);
-                  end loop;
-
-                  --  Return the topmost short circuit operator
-
-                  return Top;
-               end if;
-            end Find_Enclosing_Context;
-
-            --  Local variables
-
-            Context   : constant Node_Id    := Find_Enclosing_Context;
-            Loc       : constant Source_Ptr := Sloc (Obj_Decl);
-            Obj_Id    : constant Entity_Id  := Defining_Identifier (Obj_Decl);
-            Obj_Typ   : constant Node_Id    := Etype (Obj_Id);
-            Desig_Typ : Entity_Id;
-            Expr      : Node_Id;
-            Fin_Call  : Node_Id;
-            Ptr_Id    : Entity_Id;
-            Temp_Id   : Entity_Id;
-
-         --  Start of processing for Process_Transient_Object
-
-         begin
-            --  Step 1: Create the access type which provides a reference to
-            --  the transient object.
-
-            if Is_Access_Type (Obj_Typ) then
-               Desig_Typ := Directly_Designated_Type (Obj_Typ);
-            else
-               Desig_Typ := Obj_Typ;
-            end if;
-
-            Desig_Typ := Base_Type (Desig_Typ);
-
-            --  Generate:
-            --    Ann : access [all] <Desig_Typ>;
-
-            Ptr_Id := Make_Temporary (Loc, 'A');
-
-            Insert_Action (Context,
-              Make_Full_Type_Declaration (Loc,
-                Defining_Identifier => Ptr_Id,
-                Type_Definition     =>
-                  Make_Access_To_Object_Definition (Loc,
-                    All_Present        =>
-                      Ekind (Obj_Typ) = E_General_Access_Type,
-                    Subtype_Indication => New_Reference_To (Desig_Typ, Loc))));
-
-            --  Step 2: Create a temporary which acts as a hook to the
-            --  transient object. Generate:
-
-            --    Temp : Ptr_Id := null;
-
-            Temp_Id := Make_Temporary (Loc, 'T');
-
-            Insert_Action (Context,
-              Make_Object_Declaration (Loc,
-                Defining_Identifier => Temp_Id,
-                Object_Definition   => New_Reference_To (Ptr_Id, Loc)));
-
-            --  Mark this temporary as created for the purposes of exporting
-            --  the transient declaration out of the Actions list. This signals
-            --  the machinery in Build_Finalizer to recognize this special
-            --  case.
-
-            Set_Status_Flag_Or_Transient_Decl (Temp_Id, Obj_Decl);
-
-            --  Step 3: Hook the transient object to the temporary
-
-            --  The use of unchecked conversion / unrestricted access is needed
-            --  to avoid an accessibility violation. Note that the finalization
-            --  code is structured in such a way that the "hook" is processed
-            --  only when it points to an existing object.
-
-            if Is_Access_Type (Obj_Typ) then
-               Expr :=
-                 Unchecked_Convert_To (Ptr_Id, New_Reference_To (Obj_Id, Loc));
-            else
-               Expr :=
-                 Make_Attribute_Reference (Loc,
-                   Prefix         => New_Reference_To (Obj_Id, Loc),
-                   Attribute_Name => Name_Unrestricted_Access);
-            end if;
-
-            --  Generate:
-            --    Temp := Ptr_Id (Obj_Id);
-            --      <or>
-            --    Temp := Obj_Id'Unrestricted_Access;
-
-            Insert_After_And_Analyze (Obj_Decl,
-              Make_Assignment_Statement (Loc,
-                Name       => New_Reference_To (Temp_Id, Loc),
-                Expression => Expr));
-
-            --  Step 4: Finalize the function result after the context has been
-            --  evaluated/elaborated. Generate:
-
-            --    if Temp /= null then
-            --       [Deep_]Finalize (Temp.all);
-            --       Temp := null;
-            --    end if;
-
-            --  When the expression_with_actions is part of a return statement,
-            --  there is no need to insert a finalization call, as the general
-            --  finalization mechanism (see Build_Finalizer) would take care of
-            --  the temporary function result on subprogram exit. Note that it
-            --  would also be impossible to insert the finalization code after
-            --  the return statement as this would make it unreachable.
-
-            if Nkind (Context) /= N_Simple_Return_Statement then
-               Fin_Call :=
-                 Make_Implicit_If_Statement (Obj_Decl,
-                   Condition =>
-                     Make_Op_Ne (Loc,
-                       Left_Opnd  => New_Reference_To (Temp_Id, Loc),
-                       Right_Opnd => Make_Null (Loc)),
-
-                   Then_Statements => New_List (
-                     Make_Final_Call
-                       (Obj_Ref =>
-                          Make_Explicit_Dereference (Loc,
-                            Prefix => New_Reference_To (Temp_Id, Loc)),
-                        Typ     => Desig_Typ),
-
-                     Make_Assignment_Statement (Loc,
-                       Name       => New_Reference_To (Temp_Id, Loc),
-                       Expression => Make_Null (Loc))));
-
-               --  Use the Actions list of logical operators when inserting the
-               --  finalization call. This ensures that all transient objects
-               --  are finalized after the operators are evaluated.
-
-               if Nkind_In (Context, N_And_Then, N_Or_Else) then
-                  Insert_Action (Context, Fin_Call);
-               else
-                  Insert_Action_After (Context, Fin_Call);
-               end if;
-            end if;
-         end Process_Transient_Object;
-
-      --  Start of processing for Process_Action
-
       begin
          if Nkind (Act) = N_Object_Declaration
            and then Is_Finalizable_Transient (Act, N)
          then
-            Process_Transient_Object (Act);
+            Process_Transient_Object (Act, N);
+            return Abandon;
 
          --  Avoid processing temporary function results multiple times when
          --  dealing with nested expression_with_actions.
@@ -5359,8 +5086,8 @@ package body Exp_Ch4 is
          elsif Nkind (Act) = N_Expression_With_Actions then
             return Abandon;
 
-         --  Do not process temporary function results in loops. This is
-         --  done by Expand_N_Loop_Statement and Build_Finalizer.
+         --  Do not process temporary function results in loops. This is done
+         --  by Expand_N_Loop_Statement and Build_Finalizer.
 
          elsif Nkind (Act) = N_Loop_Statement then
             return Abandon;
@@ -5393,67 +5120,31 @@ package body Exp_Ch4 is
    --  Deal with limited types and condition actions
 
    procedure Expand_N_If_Expression (N : Node_Id) is
-      function Create_Alternative
-        (Loc     : Source_Ptr;
-         Temp_Id : Entity_Id;
-         Flag_Id : Entity_Id;
-         Expr    : Node_Id) return List_Id;
-      --  Build the statements of a "then" or "else" dependent expression
-      --  alternative. Temp_Id is the if expression result, Flag_Id is a
-      --  finalization flag created to service expression Expr.
-
-      function Is_Controlled_Function_Call (Expr : Node_Id) return Boolean;
-      --  Determine if expression Expr is a rewritten controlled function call
+      procedure Process_Actions (Actions : List_Id);
+      --  Inspect and process a single action list of an if expression for
+      --  transient controlled objects. If such objects are found, the routine
+      --  generates code to clean them up when the context of the expression is
+      --  evaluated or elaborated.
 
-      ------------------------
-      -- Create_Alternative --
-      ------------------------
+      ---------------------
+      -- Process_Actions --
+      ---------------------
 
-      function Create_Alternative
-        (Loc     : Source_Ptr;
-         Temp_Id : Entity_Id;
-         Flag_Id : Entity_Id;
-         Expr    : Node_Id) return List_Id
-      is
-         Result : constant List_Id := New_List;
+      procedure Process_Actions (Actions : List_Id) is
+         Act : Node_Id;
 
       begin
-         --  Generate:
-         --    Fnn := True;
-
-         if Present (Flag_Id)
-           and then not Is_Controlled_Function_Call (Expr)
-         then
-            Append_To (Result,
-              Make_Assignment_Statement (Loc,
-                Name       => New_Reference_To (Flag_Id, Loc),
-                Expression => New_Reference_To (Standard_True, Loc)));
-         end if;
-
-         --  Generate:
-         --    Cnn := <expr>'Unrestricted_Access;
-
-         Append_To (Result,
-           Make_Assignment_Statement (Loc,
-             Name       => New_Reference_To (Temp_Id, Loc),
-             Expression =>
-               Make_Attribute_Reference (Loc,
-                 Prefix         => Relocate_Node (Expr),
-                 Attribute_Name => Name_Unrestricted_Access)));
-
-         return Result;
-      end Create_Alternative;
-
-      ---------------------------------
-      -- Is_Controlled_Function_Call --
-      ---------------------------------
+         Act := First (Actions);
+         while Present (Act) loop
+            if Nkind (Act) = N_Object_Declaration
+              and then Is_Finalizable_Transient (Act, N)
+            then
+               Process_Transient_Object (Act, N);
+            end if;
 
-      function Is_Controlled_Function_Call (Expr : Node_Id) return Boolean is
-      begin
-         return
-           Nkind (Original_Node (Expr)) = N_Function_Call
-             and then Needs_Finalization (Etype (Expr));
-      end Is_Controlled_Function_Call;
+            Next (Act);
+         end loop;
+      end Process_Actions;
 
       --  Local variables
 
@@ -5469,6 +5160,7 @@ package body Exp_Ch4 is
       Expr    : Node_Id;
       New_If  : Node_Id;
       New_N   : Node_Id;
+      Ptr_Typ : Entity_Id;
 
    --  Start of processing for Expand_N_If_Expression
 
@@ -5541,70 +5233,66 @@ package body Exp_Ch4 is
       if Is_By_Reference_Type (Typ)
         and then not Back_End_Handles_Limited_Types
       then
-         declare
-            Flag_Id : Entity_Id;
-            Ptr_Typ : Entity_Id;
+         --  When the "then" or "else" expressions involve controlled function
+         --  calls, generated temporaries are chained on the corresponding list
+         --  of actions. These temporaries need to be finalized after the if
+         --  expression is evaluated.
 
-         begin
-            Flag_Id := Empty;
-
-            --  At least one of the if expression dependent expressions uses a
-            --  controlled function to provide the result. Create a status flag
-            --  to signal the finalization machinery that Cnn needs special
-            --  handling.
+         Process_Actions (Then_Actions (N));
+         Process_Actions (Else_Actions (N));
 
-            if Is_Controlled_Function_Call (Thenx)
-                 or else
-               Is_Controlled_Function_Call (Elsex)
-            then
-               Flag_Id := Make_Temporary (Loc, 'F');
+         --  Generate:
+         --    type Ann is access all Typ;
 
-               Insert_Action (N,
-                 Make_Object_Declaration (Loc,
-                   Defining_Identifier => Flag_Id,
-                   Object_Definition   =>
-                     New_Reference_To (Standard_Boolean, Loc),
-                   Expression          =>
-                     New_Reference_To (Standard_False, Loc)));
-            end if;
+         Ptr_Typ := Make_Temporary (Loc, 'A');
 
-            --  Generate:
-            --    type Ann is access all Typ;
+         Insert_Action (N,
+           Make_Full_Type_Declaration (Loc,
+             Defining_Identifier => Ptr_Typ,
+             Type_Definition     =>
+               Make_Access_To_Object_Definition (Loc,
+                 All_Present        => True,
+                 Subtype_Indication => New_Reference_To (Typ, Loc))));
 
-            Ptr_Typ := Make_Temporary (Loc, 'A');
+         --  Generate:
+         --    Cnn : Ann;
 
-            Insert_Action (N,
-              Make_Full_Type_Declaration (Loc,
-                Defining_Identifier => Ptr_Typ,
-                Type_Definition     =>
-                  Make_Access_To_Object_Definition (Loc,
-                    All_Present        => True,
-                    Subtype_Indication => New_Reference_To (Typ, Loc))));
+         Cnn := Make_Temporary (Loc, 'C', N);
 
-            --  Generate:
-            --    Cnn : Ann;
+         Decl :=
+           Make_Object_Declaration (Loc,
+             Defining_Identifier => Cnn,
+             Object_Definition   => New_Occurrence_Of (Ptr_Typ, Loc));
 
-            Cnn := Make_Temporary (Loc, 'C', N);
-            Set_Ekind (Cnn, E_Variable);
-            Set_Status_Flag_Or_Transient_Decl (Cnn, Flag_Id);
+         --  Generate:
+         --    if Cond then
+         --       Cnn := <Thenx>'Unrestricted_Access;
+         --    else
+         --       Cnn := <Elsex>'Unrestricted_Access;
+         --    end if;
 
-            Decl :=
-               Make_Object_Declaration (Loc,
-                 Defining_Identifier => Cnn,
-                 Object_Definition   => New_Occurrence_Of (Ptr_Typ, Loc));
+         New_If :=
+           Make_Implicit_If_Statement (N,
+             Condition       => Relocate_Node (Cond),
+             Then_Statements => New_List (
+               Make_Assignment_Statement (Sloc (Thenx),
+                 Name       => New_Reference_To (Cnn, Sloc (Thenx)),
+                 Expression =>
+                   Make_Attribute_Reference (Loc,
+                     Prefix         => Relocate_Node (Thenx),
+                     Attribute_Name => Name_Unrestricted_Access))),
 
-            New_If :=
-              Make_Implicit_If_Statement (N,
-                Condition       => Relocate_Node (Cond),
-                Then_Statements =>
-                  Create_Alternative (Sloc (Thenx), Cnn, Flag_Id, Thenx),
-                Else_Statements =>
-                  Create_Alternative (Sloc (Elsex), Cnn, Flag_Id, Elsex));
+             Else_Statements => New_List (
+               Make_Assignment_Statement (Sloc (Elsex),
+                 Name       => New_Reference_To (Cnn, Sloc (Elsex)),
+                 Expression =>
+                   Make_Attribute_Reference (Loc,
+                     Prefix         => Relocate_Node (Elsex),
+                     Attribute_Name => Name_Unrestricted_Access))));
 
             New_N :=
               Make_Explicit_Dereference (Loc,
                 Prefix => New_Occurrence_Of (Cnn, Loc));
-         end;
 
       --  For other types, we only need to expand if there are other actions
       --  associated with either branch.
@@ -5615,26 +5303,28 @@ package body Exp_Ch4 is
 
          if Present (Then_Actions (N)) then
             Rewrite (Thenx,
-                     Make_Expression_With_Actions (Sloc (Thenx),
-                       Actions    => Then_Actions (N),
-                       Expression => Relocate_Node (Thenx)));
+              Make_Expression_With_Actions (Sloc (Thenx),
+                Actions    => Then_Actions (N),
+                Expression => Relocate_Node (Thenx)));
+
             Set_Then_Actions (N, No_List);
             Analyze_And_Resolve (Thenx, Typ);
          end if;
 
          if Present (Else_Actions (N)) then
             Rewrite (Elsex,
-                     Make_Expression_With_Actions (Sloc (Elsex),
-                       Actions    => Else_Actions (N),
-                       Expression => Relocate_Node (Elsex)));
+              Make_Expression_With_Actions (Sloc (Elsex),
+                Actions    => Else_Actions (N),
+                Expression => Relocate_Node (Elsex)));
+
             Set_Else_Actions (N, No_List);
             Analyze_And_Resolve (Elsex, Typ);
          end if;
 
          return;
 
-         --  If no actions then no expansion needed, gigi will handle it using
-         --  the same approach as a C conditional expression.
+      --  If no actions then no expansion needed, gigi will handle it using the
+      --  same approach as a C conditional expression.
 
       else
          return;
@@ -12387,6 +12077,282 @@ package body Exp_Ch4 is
       return;
    end Optimize_Length_Comparison;
 
+   ------------------------------
+   -- Process_Transient_Object --
+   ------------------------------
+
+   procedure Process_Transient_Object
+     (Decl     : Node_Id;
+      Rel_Node : Node_Id)
+   is
+      function Find_Enclosing_Context (N : Node_Id) return Node_Id;
+      --  Find the logical context where N appears. The context is chosen such
+      --  that it is possible to insert before and after it.
+
+      ----------------------------
+      -- Find_Enclosing_Context --
+      ----------------------------
+
+      function Find_Enclosing_Context (N : Node_Id) return Node_Id is
+         Par : Node_Id;
+         Top : Node_Id;
+
+      begin
+         --  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
+            Par := N;
+            Top := N;
+            while Present (Par) loop
+               if Nkind_In (Original_Node (Par), N_Case_Expression,
+                                                 N_If_Expression)
+               then
+                  Top := Par;
+
+               --  Prevent the search from going too far
+
+               elsif Is_Body_Or_Package_Declaration (Par) then
+                  exit;
+               end if;
+
+               Par := Parent (Par);
+            end loop;
+
+            --  The topmost case or if expression is now recovered, but it may
+            --  still not be the correct place to add generated code. Climb to
+            --  find a parent that is part of a declarative or statement list.
+
+            Par := Top;
+            while Present (Par) loop
+               if Is_List_Member (Par)
+                 and then not Nkind_In (Par, N_Component_Association,
+                                             N_Discriminant_Association,
+                                             N_Parameter_Association,
+                                             N_Pragma_Argument_Association)
+               then
+                  return Par;
+
+               --  Prevent the search from going too far
+
+               elsif Is_Body_Or_Package_Declaration (Par) then
+                  exit;
+               end if;
+
+               Par := Parent (Par);
+            end loop;
+
+            return Par;
+
+         --  Short circuit operators in complex expressions are converted into
+         --  expression_with_actions.
+
+         else
+            --  Handle the case where the node is buried deep inside an if
+            --  statement. The temporary controlled object must be finalized
+            --  before the then, elsif or else statements are evaluated.
+
+            --    if Something
+            --      and then Ctrl_Func_Call
+            --    then
+            --       <result must be finalized at this point>
+            --       <statements>
+            --    end if;
+
+            --  To achieve this, find the topmost logical operator. Generated
+            --  actions are then inserted before/after it.
+
+            Par := N;
+            while Present (Par) loop
+
+               --  Keep climbing past various operators
+
+               if Nkind (Parent (Par)) in N_Op
+                 or else Nkind_In (Parent (Par), N_And_Then, N_Or_Else)
+               then
+                  Par := Parent (Par);
+               else
+                  exit;
+               end if;
+            end loop;
+
+            Top := Par;
+
+            --  The node may be located in a pragma in which case return the
+            --  pragma itself:
+
+            --    pragma Precondition (... and then Ctrl_Func_Call ...);
+
+            --  Similar case occurs when the node is related to an object
+            --  declaration or assignment:
+
+            --    Obj [: Some_Typ] := ... and then Ctrl_Func_Call ...;
+
+            --  Another case to consider is when the node is part of a return
+            --  statement:
+
+            --    return ... and then Ctrl_Func_Call ...;
+
+            --  Another case is when the node acts as a formal in a procedure
+            --  call statement:
+
+            --    Proc (... and then Ctrl_Func_Call ...);
+
+            while Present (Par) loop
+               if Nkind_In (Par, N_Assignment_Statement,
+                                 N_Object_Declaration,
+                                 N_Pragma,
+                                 N_Procedure_Call_Statement,
+                                 N_Simple_Return_Statement)
+               then
+                  return Par;
+
+               --  Prevent the search from going too far
+
+               elsif Is_Body_Or_Package_Declaration (Par) then
+                  exit;
+               end if;
+
+               Par := Parent (Par);
+            end loop;
+
+            --  Return the topmost short circuit operator
+
+            return Top;
+         end if;
+      end Find_Enclosing_Context;
+
+      --  Local variables
+
+      Context   : constant Node_Id    := Find_Enclosing_Context (Rel_Node);
+      Loc       : constant Source_Ptr := Sloc (Decl);
+      Obj_Id    : constant Entity_Id  := Defining_Identifier (Decl);
+      Obj_Typ   : constant Node_Id    := Etype (Obj_Id);
+      Desig_Typ : Entity_Id;
+      Expr      : Node_Id;
+      Fin_Call  : Node_Id;
+      Ptr_Id    : Entity_Id;
+      Temp_Id   : Entity_Id;
+
+   --  Start of processing for Process_Transient_Object
+
+   begin
+      --  Step 1: Create the access type which provides a reference to the
+      --  transient controlled object.
+
+      if Is_Access_Type (Obj_Typ) then
+         Desig_Typ := Directly_Designated_Type (Obj_Typ);
+      else
+         Desig_Typ := Obj_Typ;
+      end if;
+
+      Desig_Typ := Base_Type (Desig_Typ);
+
+      --  Generate:
+      --    Ann : access [all] <Desig_Typ>;
+
+      Ptr_Id := Make_Temporary (Loc, 'A');
+
+      Insert_Action (Context,
+        Make_Full_Type_Declaration (Loc,
+          Defining_Identifier => Ptr_Id,
+          Type_Definition     =>
+            Make_Access_To_Object_Definition (Loc,
+              All_Present        => Ekind (Obj_Typ) = E_General_Access_Type,
+              Subtype_Indication => New_Reference_To (Desig_Typ, Loc))));
+
+      --  Step 2: Create a temporary which acts as a hook to the transient
+      --  controlled object. Generate:
+
+      --    Temp : Ptr_Id := null;
+
+      Temp_Id := Make_Temporary (Loc, 'T');
+
+      Insert_Action (Context,
+        Make_Object_Declaration (Loc,
+          Defining_Identifier => Temp_Id,
+          Object_Definition   => New_Reference_To (Ptr_Id, Loc)));
+
+      --  Mark the temporary as created for the purposes of exporting the
+      --  transient controlled object out of the expression_with_action or if
+      --  expression. This signals the machinery in Build_Finalizer to treat
+      --  this case specially.
+
+      Set_Status_Flag_Or_Transient_Decl (Temp_Id, Decl);
+
+      --  Step 3: Hook the transient object to the temporary
+
+      --  The use of unchecked conversion / unrestricted access is needed to
+      --  avoid an accessibility violation. Note that the finalization code is
+      --  structured in such a way that the "hook" is processed only when it
+      --  points to an existing object.
+
+      if Is_Access_Type (Obj_Typ) then
+         Expr := Unchecked_Convert_To (Ptr_Id, New_Reference_To (Obj_Id, Loc));
+      else
+         Expr :=
+           Make_Attribute_Reference (Loc,
+             Prefix         => New_Reference_To (Obj_Id, Loc),
+             Attribute_Name => Name_Unrestricted_Access);
+      end if;
+
+      --  Generate:
+      --    Temp := Ptr_Id (Obj_Id);
+      --      <or>
+      --    Temp := Obj_Id'Unrestricted_Access;
+
+      Insert_After_And_Analyze (Decl,
+        Make_Assignment_Statement (Loc,
+          Name       => New_Reference_To (Temp_Id, Loc),
+          Expression => Expr));
+
+      --  Step 4: Finalize the transient controlled object after the context
+      --  has been evaluated/elaborated. Generate:
+
+      --    if Temp /= null then
+      --       [Deep_]Finalize (Temp.all);
+      --       Temp := null;
+      --    end if;
+
+      --  When the node is part of a return statement, there is no need to
+      --  insert a finalization call, as the general finalization mechanism
+      --  (see Build_Finalizer) would take care of the transient controlled
+      --  object on subprogram exit. Note that it would also be impossible to
+      --  insert the finalization code after the return statement as this will
+      --  render it unreachable.
+
+      if Nkind (Context) /= N_Simple_Return_Statement then
+         Fin_Call :=
+           Make_Implicit_If_Statement (Decl,
+             Condition =>
+               Make_Op_Ne (Loc,
+                 Left_Opnd  => New_Reference_To (Temp_Id, Loc),
+                 Right_Opnd => Make_Null (Loc)),
+
+             Then_Statements => New_List (
+               Make_Final_Call
+                 (Obj_Ref =>
+                    Make_Explicit_Dereference (Loc,
+                      Prefix => New_Reference_To (Temp_Id, Loc)),
+                  Typ     => Desig_Typ),
+
+               Make_Assignment_Statement (Loc,
+                 Name       => New_Reference_To (Temp_Id, Loc),
+                 Expression => Make_Null (Loc))));
+
+         --  Use the Actions list of logical operators when inserting the
+         --  finalization call. This ensures that all transient controlled
+         --  objects are finalized after the operators are evaluated.
+
+         if Nkind_In (Context, N_And_Then, N_Or_Else) then
+            Insert_Action (Context, Fin_Call);
+         else
+            Insert_Action_After (Context, Fin_Call);
+         end if;
+      end if;
+   end Process_Transient_Object;
+
    ------------------------
    -- Rewrite_Comparison --
    ------------------------
index 0473bfafc1dc56977c3fb5c6ba61c38f207c7100..ca8bc9839ab4685b2dc374cbd18116711f0625cf 100644 (file)
@@ -8040,11 +8040,11 @@ package body Exp_Util is
       Par : Node_Id;
 
    begin
-      --  Locate an enclosing case or if expression. Note: these constructs can
-      --  get expanded into Expression_With_Actions, hence the need to test
-      --  using the original node.
+      --  Locate an enclosing case or if expression. Note that these constructs
+      --  can be expanded into Expression_With_Actions, hence the test of the
+      --  original node.
 
-      Par := N;
+      Par := Parent (N);
       while Present (Par) loop
          if Nkind_In (Original_Node (Par), N_Case_Expression,
                                            N_If_Expression)
index 1d936f5a5f0fb52f9b64def44eb69ff0a9652eae..a771db6f8a3a4444fb40bf980b149a9d8772e929 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                  S p e c                                 --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2013, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNARL is free software; you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -256,8 +256,7 @@ package System.Interrupts is
      (Object : access Static_Interrupt_Protection) return Boolean;
    --  Returns True
 
-   overriding
-   procedure Finalize (Object : in out Static_Interrupt_Protection);
+   overriding procedure Finalize (Object : in out Static_Interrupt_Protection);
    --  Restore previous handlers as required by C.3.1(12) then call
    --  Finalize (Protection).