]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
exp_ch7.adb (Build_Array_Deep_Procs, [...]): Rename Is_Return_By_Reference_Type to...
authorBob Duff <duff@adacore.com>
Tue, 31 Oct 2006 17:57:36 +0000 (18:57 +0100)
committerArnaud Charlet <charlet@gcc.gnu.org>
Tue, 31 Oct 2006 17:57:36 +0000 (18:57 +0100)
2006-10-31  Bob Duff  <duff@adacore.com>
    Ed Schonberg  <schonberg@adacore.com>
    Robert Dewar  <dewar@adacore.com>

* exp_ch7.adb (Build_Array_Deep_Procs, Build_Record_Deep_Procs,
Make_Deep_Record_Body): Rename Is_Return_By_Reference_Type to be
Is_Inherently_Limited_Type, because return-by-reference has no meaning
in Ada 2005.
(Find_Node_To_Be_Wrapped): Use new method of determining the result
type of the function containing a return statement, because the
Return_Type field was removed. We now use the Return_Applies_To field.

        * exp_util.ads, exp_util.adb: Use new subtype N_Membership_Test
(Build_Task_Image_Decl): If procedure is not called from an
initialization procedure, indicate that function that builds task name
uses the sec. stack. Otherwise the enclosing initialization procedure
will carry the indication.
(Insert_Actions): Remove N_Return_Object_Declaration. We now use
N_Object_Declaration instead.
(Kill_Dead_Code): New interface to implement -gnatwt warning for
conditional dead code killed, and change implementation accordingly.
(Insert_Actions): Add N_Return_Object_Declaration case.
Correct comment to mention N_Extension_Aggregate node.
(Set_Current_Value_Condition): Call Safe_To_Capture_Value to avoid bad
attempts to save information for global variables which cannot be
safely tracked.
(Get_Current_Value_Condition): Handle conditions the other way round
(constant on left). Also handle right operand of AND and AND THEN
(Set_Current_Value_Condition): Corresponding changes
(Append_Freeze_Action): Remove unnecessary initialization of Fnode.
(Get_Current_Value_Condition): Handle simple boolean operands
(Get_Current_Value_Condition): Handle left operand of AND or AND THEN
(Get_Current_Value_Condition): If the variable reference is within an
if-statement, does not appear in the list of then_statments, and does
not come from source, treat it as being at unknown location.
(Get_Current_Value_Condition): Enhance to allow while statements to be
processed as well as if statements.
(New_Class_Wide_Subtype): The entity for a class-wide subtype does not
come from source.
(OK_To_Do_Constant_Replacement): Allow constant replacement within body
of loop. This is safe now that we fixed Kill_Current_Values.
(OK_To_Do_Constant_Replacement): Check whether current scope is
Standard, before examining outer scopes.

From-SVN: r118269

gcc/ada/exp_ch7.adb
gcc/ada/exp_util.adb
gcc/ada/exp_util.ads

index 2535bb2c70c219da67455af21bf068b6e8b886b6..0a4a52714e59d2579979e34f7ef0eb117dd62e50 100644 (file)
@@ -380,7 +380,7 @@ package body Exp_Ch7 is
           Typ   => Typ,
           Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
 
-      if not Is_Return_By_Reference_Type (Typ) then
+      if not Is_Inherently_Limited_Type (Typ) then
          Set_TSS (Typ,
            Make_Deep_Proc (
              Prim  => Adjust_Case,
@@ -475,7 +475,7 @@ package body Exp_Ch7 is
           Typ   => Typ,
           Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
 
-      if not Is_Return_By_Reference_Type (Typ) then
+      if not Is_Inherently_Limited_Type (Typ) then
          Set_TSS (Typ,
            Make_Deep_Proc (
              Prim  => Adjust_Case,
@@ -1825,11 +1825,18 @@ package body Exp_Ch7 is
             --  itself needs wrapping at the outer-level
 
             when N_Return_Statement            =>
-               if Requires_Transient_Scope (Return_Type (The_Parent)) then
-                  return Empty;
-               else
-                  return The_Parent;
-               end if;
+               declare
+                  Applies_To : constant Entity_Id :=
+                                 Return_Applies_To
+                                   (Return_Statement_Entity (The_Parent));
+                  Return_Type : constant Entity_Id := Etype (Applies_To);
+               begin
+                  if Requires_Transient_Scope (Return_Type) then
+                     return Empty;
+                  else
+                     return The_Parent;
+                  end if;
+               end;
 
             --  If we leave a scope without having been able to find a node to
             --  wrap, something is going wrong but this can happen in error
@@ -2632,7 +2639,7 @@ package body Exp_Ch7 is
       Res            : constant List_Id := New_List;
 
    begin
-      if Is_Return_By_Reference_Type (Typ) then
+      if Is_Inherently_Limited_Type (Typ) then
          Controller_Typ := RTE (RE_Limited_Record_Controller);
       else
          Controller_Typ := RTE (RE_Record_Controller);
index 732e0626475b83aa7d0dbd4d73d022cc5c57a0b8..13878a3ef1928128f481dde486468f8ca3732f7e 100644 (file)
@@ -268,7 +268,7 @@ package body Exp_Util is
    --------------------------
 
    procedure Append_Freeze_Action (T : Entity_Id; N : Node_Id) is
-      Fnode : Node_Id := Freeze_Node (T);
+      Fnode : Node_Id;
 
    begin
       Ensure_Freeze_Node (T);
@@ -580,9 +580,10 @@ package body Exp_Util is
    ----------------------------
 
    function Build_Task_Image_Decls
-     (Loc    : Source_Ptr;
-      Id_Ref : Node_Id;
-      A_Type : Entity_Id) return List_Id
+     (Loc          : Source_Ptr;
+      Id_Ref       : Node_Id;
+      A_Type       : Entity_Id;
+      In_Init_Proc : Boolean := False) return List_Id
    is
       Decls  : constant List_Id   := New_List;
       T_Id   : Entity_Id := Empty;
@@ -651,6 +652,10 @@ package body Exp_Util is
          Append (Fun, Decls);
          Expr := Make_Function_Call (Loc,
            Name => New_Occurrence_Of (Defining_Entity (Fun), Loc));
+
+         if not In_Init_Proc then
+            Set_Uses_Sec_Stack (Defining_Entity (Fun));
+         end if;
       end if;
 
       Decl := Make_Object_Declaration (Loc,
@@ -688,8 +693,6 @@ package body Exp_Util is
       --  Calls to 'Image use the secondary stack, which must be cleaned
       --  up after the task name is built.
 
-      Set_Uses_Sec_Stack (Defining_Unit_Name (Spec));
-
       return Make_Subprogram_Body (Loc,
          Specification => Spec,
          Declarations => Decls,
@@ -1124,8 +1127,8 @@ package body Exp_Util is
    --  objects which are constrained by an initial expression. Basically it
    --  transforms an unconstrained subtype indication into a constrained one.
    --  The expression may also be transformed in certain cases in order to
-   --  avoid multiple evaulation. In the static allocation case, the general
-   --  scheme is :
+   --  avoid multiple evaluation. In the static allocation case, the general
+   --  scheme is:
 
    --     Val : T := Expr;
 
@@ -1833,6 +1836,11 @@ package body Exp_Util is
    -- Get_Current_Value_Condition --
    ---------------------------------
 
+   --  Note: the implementation of this procedure is very closely tied to the
+   --  implementation of Set_Current_Value_Condition. In the Get procedure, we
+   --  interpret Current_Value fields set by the Set procedure, so the two
+   --  procedures need to be closely coordinated.
+
    procedure Get_Current_Value_Condition
      (Var : Node_Id;
       Op  : out Node_Kind;
@@ -1841,6 +1849,134 @@ package body Exp_Util is
       Loc : constant Source_Ptr := Sloc (Var);
       Ent : constant Entity_Id  := Entity (Var);
 
+      procedure Process_Current_Value_Condition
+        (N : Node_Id;
+         S : Boolean);
+      --  N is an expression which holds either True (S = True) or False (S =
+      --  False) in the condition. This procedure digs out the expression and
+      --  if it refers to Ent, sets Op and Val appropriately.
+
+      -------------------------------------
+      -- Process_Current_Value_Condition --
+      -------------------------------------
+
+      procedure Process_Current_Value_Condition
+        (N : Node_Id;
+         S : Boolean)
+      is
+         Cond : Node_Id;
+         Sens : Boolean;
+
+      begin
+         Cond := N;
+         Sens := S;
+
+         --  Deal with NOT operators, inverting sense
+
+         while Nkind (Cond) = N_Op_Not loop
+            Cond := Right_Opnd (Cond);
+            Sens := not Sens;
+         end loop;
+
+         --  Deal with AND THEN and AND cases
+
+         if Nkind (Cond) = N_And_Then
+           or else Nkind (Cond) = N_Op_And
+         then
+            --  Don't ever try to invert a condition that is of the form
+            --  of an AND or AND THEN (since we are not doing sufficiently
+            --  general processing to allow this).
+
+            if Sens = False then
+               Op  := N_Empty;
+               Val := Empty;
+               return;
+            end if;
+
+            --  Recursively process AND and AND THEN branches
+
+            Process_Current_Value_Condition (Left_Opnd (Cond), True);
+
+            if Op /= N_Empty then
+               return;
+            end if;
+
+            Process_Current_Value_Condition (Right_Opnd (Cond), True);
+            return;
+
+         --  Case of relational operator
+
+         elsif Nkind (Cond) in N_Op_Compare then
+            Op := Nkind (Cond);
+
+            --  Invert sense of test if inverted test
+
+            if Sens = False then
+               case Op is
+                  when N_Op_Eq => Op := N_Op_Ne;
+                  when N_Op_Ne => Op := N_Op_Eq;
+                  when N_Op_Lt => Op := N_Op_Ge;
+                  when N_Op_Gt => Op := N_Op_Le;
+                  when N_Op_Le => Op := N_Op_Gt;
+                  when N_Op_Ge => Op := N_Op_Lt;
+                  when others  => raise Program_Error;
+               end case;
+            end if;
+
+            --  Case of entity op value
+
+            if Is_Entity_Name (Left_Opnd (Cond))
+              and then Ent = Entity (Left_Opnd (Cond))
+              and then Compile_Time_Known_Value (Right_Opnd (Cond))
+            then
+               Val := Right_Opnd (Cond);
+
+            --  Case of value op entity
+
+            elsif Is_Entity_Name (Right_Opnd (Cond))
+              and then Ent = Entity (Right_Opnd (Cond))
+              and then Compile_Time_Known_Value (Left_Opnd (Cond))
+            then
+               Val := Left_Opnd (Cond);
+
+               --  We are effectively swapping operands
+
+               case Op is
+                  when N_Op_Eq => null;
+                  when N_Op_Ne => null;
+                  when N_Op_Lt => Op := N_Op_Gt;
+                  when N_Op_Gt => Op := N_Op_Lt;
+                  when N_Op_Le => Op := N_Op_Ge;
+                  when N_Op_Ge => Op := N_Op_Le;
+                  when others  => raise Program_Error;
+               end case;
+
+            else
+               Op := N_Empty;
+            end if;
+
+            return;
+
+            --  Case of Boolean variable reference, return as though the
+            --  reference had said var = True.
+
+         else
+            if Is_Entity_Name (Cond)
+              and then Ent = Entity (Cond)
+            then
+               Val := New_Occurrence_Of (Standard_True, Sloc (Cond));
+
+               if Sens = False then
+                  Op := N_Op_Ne;
+               else
+                  Op := N_Op_Eq;
+               end if;
+            end if;
+         end if;
+      end Process_Current_Value_Condition;
+
+   --  Start of processing for Get_Current_Value_Condition
+
    begin
       Op  := N_Empty;
       Val := Empty;
@@ -1857,7 +1993,6 @@ package body Exp_Util is
          CV   : constant Node_Id := Current_Value (Ent);
          Sens : Boolean;
          Stm  : Node_Id;
-         Cond : Node_Id;
 
       begin
          --  If statement. Condition is known true in THEN section, known False
@@ -1909,7 +2044,17 @@ package body Exp_Util is
                then
                   Sens := True;
 
-                  --  Otherwise we must be in ELSIF or ELSE part
+               --  If the variable reference does not come from source, we
+               --  cannot reliably tell whether it appears in the else part.
+               --  In particular, if if appears in generated code for a node
+               --  that requires finalization, it may be attached to a list
+               --  that has not been yet inserted into the code. For now,
+               --  treat it as unknown.
+
+               elsif not Comes_From_Source (N) then
+                  return;
+
+               --  Otherwise we must be in ELSIF or ELSE part
 
                else
                   Sens := False;
@@ -1972,44 +2117,41 @@ package body Exp_Util is
                end if;
             end;
 
-            --  All other cases of Current_Value settings
+         --  Iteration scheme of while loop. The condition is known to be
+         --  true within the body of the loop.
 
-         else
-            return;
-         end if;
+         elsif Nkind (CV) = N_Iteration_Scheme then
+            declare
+               Loop_Stmt : constant Node_Id := Parent (CV);
 
-         --  If we fall through here, then we have a reportable condition, Sens
-         --  is True if the condition is true and False if it needs inverting.
+            begin
+               --  Before start of body of loop
 
-         --  Deal with NOT operators, inverting sense
+               if Loc < Sloc (Loop_Stmt) then
+                  return;
 
-         Cond := Condition (CV);
-         while Nkind (Cond) = N_Op_Not loop
-            Cond := Right_Opnd (Cond);
-            Sens := not Sens;
-         end loop;
+               --  After end of LOOP statement
 
-         --  Now we must have a relational operator
+               elsif Loc >= Sloc (End_Label (Loop_Stmt)) then
+                  return;
 
-         pragma Assert (Entity (Var) = Entity (Left_Opnd (Cond)));
-         Val := Right_Opnd (Cond);
-         Op  := Nkind (Cond);
+               --  We are within the body of the loop
 
-         if Sens = False then
-            case Op is
-            when N_Op_Eq => Op := N_Op_Ne;
-            when N_Op_Ne => Op := N_Op_Eq;
-            when N_Op_Lt => Op := N_Op_Ge;
-            when N_Op_Gt => Op := N_Op_Le;
-            when N_Op_Le => Op := N_Op_Gt;
-            when N_Op_Ge => Op := N_Op_Lt;
+               else
+                  Sens := True;
+               end if;
+            end;
 
-               --  No other entry should be possible
+         --  All other cases of Current_Value settings
 
-            when others =>
-               raise Program_Error;
-            end case;
+         else
+            return;
          end if;
+
+         --  If we fall through here, then we have a reportable condition, Sens
+         --  is True if the condition is true and False if it needs inverting.
+
+         Process_Current_Value_Condition (Condition (CV), Sens);
       end;
    end Get_Current_Value_Condition;
 
@@ -2183,7 +2325,7 @@ package body Exp_Util is
       --  Capture root of the transient scope
 
       if Scope_Is_Transient then
-         Wrapped_Node  := Node_To_Be_Wrapped;
+         Wrapped_Node := Node_To_Be_Wrapped;
       end if;
 
       loop
@@ -2362,8 +2504,9 @@ package body Exp_Util is
                   null;
 
                --  Do not insert if parent of P is an N_Component_Association
-               --  node (i.e. we are in the context of an N_Aggregate node.
-               --  In this case we want to insert before the entire aggregate.
+               --  node (i.e. we are in the context of an N_Aggregate or
+               --  N_Extension_Aggregate node. In this case we want to insert
+               --  before the entire aggregate.
 
                elsif Nkind (Parent (P)) = N_Component_Association then
                   null;
@@ -2397,7 +2540,7 @@ package body Exp_Util is
 
                --  Otherwise we can go ahead and do the insertion
 
-               elsif  P = Wrapped_Node then
+               elsif P = Wrapped_Node then
                   Store_Before_Actions_In_Scope (Ins_Actions);
                   return;
 
@@ -3230,18 +3373,22 @@ package body Exp_Util is
                and then not Is_Tagged_Type (Full_View (T))
                and then Is_Derived_Type (Full_View (T))
                and then Etype (Full_View (T)) /= T);
-
    end Is_Untagged_Derivation;
 
    --------------------
    -- Kill_Dead_Code --
    --------------------
 
-   procedure Kill_Dead_Code (N : Node_Id) is
+   procedure Kill_Dead_Code (N : Node_Id; Warn : Boolean := False) is
    begin
       if Present (N) then
          Remove_Warning_Messages (N);
 
+         if Warn then
+            Error_Msg_F
+              ("?this code can never be executed and has been deleted", N);
+         end if;
+
          --  Recurse into block statements and bodies to process declarations
          --  and statements
 
@@ -3249,8 +3396,10 @@ package body Exp_Util is
            or else Nkind (N) = N_Subprogram_Body
            or else Nkind (N) = N_Package_Body
          then
-            Kill_Dead_Code (Declarations (N));
-            Kill_Dead_Code (Statements (Handled_Statement_Sequence (N)));
+            Kill_Dead_Code
+              (Declarations (N), False);
+            Kill_Dead_Code
+              (Statements (Handled_Statement_Sequence (N)));
 
             if Nkind (N) = N_Subprogram_Body then
                Set_Is_Eliminated (Defining_Entity (N));
@@ -3309,15 +3458,17 @@ package body Exp_Util is
 
    --  Case where argument is a list of nodes to be killed
 
-   procedure Kill_Dead_Code (L : List_Id) is
+   procedure Kill_Dead_Code (L : List_Id; Warn : Boolean := False) is
       N : Node_Id;
-
+      W : Boolean;
    begin
+      W := Warn;
       if Is_Non_Empty_List (L) then
          loop
             N := Remove_Head (L);
             exit when No (N);
-            Kill_Dead_Code (N);
+            Kill_Dead_Code (N, W);
+            W := False;
          end loop;
       end if;
    end Kill_Dead_Code;
@@ -3829,6 +3980,7 @@ package body Exp_Util is
 
    begin
       Copy_Node (CW_Typ, Res);
+      Set_Comes_From_Source (Res, False);
       Set_Sloc (Res, Sloc (N));
       Set_Is_Itype (Res);
       Set_Associated_Node_For_Itype (Res, N);
@@ -3884,7 +4036,6 @@ package body Exp_Util is
       --  Otherwise check scopes
 
       else
-
          CS := Current_Scope;
 
          loop
@@ -3896,14 +4047,21 @@ package body Exp_Util is
             --  Packages do not affect the determination of safety
 
             elsif Ekind (CS) = E_Package then
-               CS := Scope (CS);
                exit when CS = Standard_Standard;
+               CS := Scope (CS);
 
             --  Blocks do not affect the determination of safety
 
             elsif Ekind (CS) = E_Block then
                CS := Scope (CS);
 
+            --  Loops do not affect the determination of safety. Note that we
+            --  kill all current values on entry to a loop, so we are just
+            --  talking about processing within a loop here.
+
+            elsif Ekind (CS) = E_Loop then
+               CS := Scope (CS);
+
             --  Otherwise, the reference is dubious, and we cannot be sure that
             --  it is safe to do the replacement.
 
@@ -4091,11 +4249,10 @@ package body Exp_Util is
             --  are side effect free. For this purpose binary operators
             --  include membership tests and short circuit forms
 
-            when N_Binary_Op |
-                 N_In        |
-                 N_Not_In    |
-                 N_And_Then  |
-                 N_Or_Else   =>
+            when N_Binary_Op       |
+                 N_Membership_Test |
+                 N_And_Then        |
+                 N_Or_Else         =>
                return Side_Effect_Free (Left_Opnd  (N))
                  and then Side_Effect_Free (Right_Opnd (N));
 
@@ -4687,9 +4844,113 @@ package body Exp_Util is
       else
          return False;
       end if;
-
    end Safe_Unchecked_Type_Conversion;
 
+   ---------------------------------
+   -- Set_Current_Value_Condition --
+   ---------------------------------
+
+   --  Note: the implementation of this procedure is very closely tied to the
+   --  implementation of Get_Current_Value_Condition. Here we set required
+   --  Current_Value fields, and in Get_Current_Value_Condition, we interpret
+   --  them, so they must have a consistent view.
+
+   procedure Set_Current_Value_Condition (Cnode : Node_Id) is
+
+      procedure Set_Entity_Current_Value (N : Node_Id);
+      --  If N is an entity reference, where the entity is of an appropriate
+      --  kind, then set the current value of this entity to Cnode, unless
+      --  there is already a definite value set there.
+
+      procedure Set_Expression_Current_Value (N : Node_Id);
+      --  If N is of an appropriate form, sets an appropriate entry in current
+      --  value fields of relevant entities. Multiple entities can be affected
+      --  in the case of an AND or AND THEN.
+
+      ------------------------------
+      -- Set_Entity_Current_Value --
+      ------------------------------
+
+      procedure Set_Entity_Current_Value (N : Node_Id) is
+      begin
+         if Is_Entity_Name (N) then
+            declare
+               Ent : constant Entity_Id := Entity (N);
+
+            begin
+               --  Don't capture if not safe to do so
+
+               if not Safe_To_Capture_Value (N, Ent, Cond => True) then
+                  return;
+               end if;
+
+               --  Here we have a case where the Current_Value field may
+               --  need to be set. We set it if it is not already set to a
+               --  compile time expression value.
+
+               --  Note that this represents a decision that one condition
+               --  blots out another previous one. That's certainly right
+               --  if they occur at the same level. If the second one is
+               --  nested, then the decision is neither right nor wrong (it
+               --  would be equally OK to leave the outer one in place, or
+               --  take the new inner one. Really we should record both, but
+               --  our data structures are not that elaborate.
+
+               if Nkind (Current_Value (Ent)) not in N_Subexpr then
+                  Set_Current_Value (Ent, Cnode);
+               end if;
+            end;
+         end if;
+      end Set_Entity_Current_Value;
+
+      ----------------------------------
+      -- Set_Expression_Current_Value --
+      ----------------------------------
+
+      procedure Set_Expression_Current_Value (N : Node_Id) is
+         Cond : Node_Id;
+
+      begin
+         Cond := N;
+
+         --  Loop to deal with (ignore for now) any NOT operators present. The
+         --  presence of NOT operators will be handled properly when we call
+         --  Get_Current_Value_Condition.
+
+         while Nkind (Cond) = N_Op_Not loop
+            Cond := Right_Opnd (Cond);
+         end loop;
+
+         --  For an AND or AND THEN, recursively process operands
+
+         if Nkind (Cond) = N_Op_And or else Nkind (Cond) = N_And_Then then
+            Set_Expression_Current_Value (Left_Opnd (Cond));
+            Set_Expression_Current_Value (Right_Opnd (Cond));
+            return;
+         end if;
+
+         --  Check possible relational operator
+
+         if Nkind (Cond) in N_Op_Compare then
+            if Compile_Time_Known_Value (Right_Opnd (Cond)) then
+               Set_Entity_Current_Value (Left_Opnd (Cond));
+            elsif Compile_Time_Known_Value (Left_Opnd (Cond)) then
+               Set_Entity_Current_Value (Right_Opnd (Cond));
+            end if;
+
+            --  Check possible boolean variable reference
+
+         else
+            Set_Entity_Current_Value (Cond);
+         end if;
+      end Set_Expression_Current_Value;
+
+   --  Start of processing for Set_Current_Value_Condition
+
+   begin
+      Set_Expression_Current_Value (Condition (Cnode));
+   end Set_Current_Value_Condition;
+
    --------------------------
    -- Set_Elaboration_Flag --
    --------------------------
index 3a272fa7ec071feaf2d9ef01d726b3b39a1860d3..cfff619aa85fc1b264d8aaf217dcb260f60931f8 100644 (file)
@@ -191,7 +191,7 @@ package Exp_Util is
    --  Add a new freeze action for the given type. The freeze action is
    --  attached to the freeze node for the type. Actions will be elaborated in
    --  the order in which they are added. Note that the added node is not
-   --  analyzed. The analyze call is found in Sem_Ch13.Expand_N_Freeze_Entity.
+   --  analyzed. The analyze call is found in Exp_Ch13.Expand_N_Freeze_Entity.
 
    procedure Append_Freeze_Actions (T : Entity_Id; L : List_Id);
    --  Adds the given list of freeze actions (declarations or statements) for
@@ -199,7 +199,7 @@ package Exp_Util is
    --  the type. Actions will be elaborated in the order in which they are
    --  added, and the actions within the list will be elaborated in list order.
    --  Note that the added nodes are not analyzed. The analyze call is found in
-   --  Sem_Ch13.Expand_N_Freeze_Entity.
+   --  Exp_Ch13.Expand_N_Freeze_Entity.
 
    function Build_Runtime_Call (Loc : Source_Ptr; RE : RE_Id) return Node_Id;
    --  Build an N_Procedure_Call_Statement calling the given runtime entity.
@@ -208,10 +208,10 @@ package Exp_Util is
    --  analyzed on return, the caller is responsible for analyzing it.
 
    function Build_Task_Image_Decls
-     (Loc    : Source_Ptr;
-      Id_Ref : Node_Id;
-      A_Type : Entity_Id)
-      return   List_Id;
+     (Loc          : Source_Ptr;
+      Id_Ref       : Node_Id;
+      A_Type       : Entity_Id;
+      In_Init_Proc : Boolean := False) return List_Id;
    --  Build declaration for a variable that holds an identifying string to be
    --  used as a task name. Id_Ref is an identifier if the task is a variable,
    --  and a selected or indexed component if the task is component of an
@@ -220,6 +220,11 @@ package Exp_Util is
    --  index values. For composite types, the result includes two declarations:
    --  one for a generated function that computes the image without using
    --  concatenation, and one for the variable that holds the result.
+   --  If In_Init_Proc is true, the call is part of the initialization of
+   --  a component of a composite type, and the enclosing initialization
+   --  procedure must be flagged as using the secondary stack. If In_Init_Proc
+   --  is false, the call is for a stand-alone object, and the generated
+   --  function itself must do its own cleanups.
 
    function Component_May_Be_Bit_Aligned (Comp : Entity_Id) return Boolean;
    --  This function is in charge of detecting record components that may cause
@@ -407,17 +412,14 @@ package Exp_Util is
    --  on return Cond is set to N_Empty, and Val is set to Empty.
    --
    --  The other case is when Current_Value points to an N_If_Statement or an
-   --  N_Elsif_Part (while statement). Such a setting only occurs if the
-   --  condition of an IF or ELSIF is of the form X op Y, where is the variable
-   --  in question, Y is a compile-time known value, and op is one of the six
-   --  possible relational operators.
-   --
-   --  In this case, Get_Current_Condition digs out the condition, and then
-   --  checks if the condition is known false, known true, or not known at all.
-   --  In the first two cases, Get_Current_Condition will return with Op set to
-   --  the appropriate conditional operator (inverted if the condition is known
-   --  false), and Val set to the constant value. If the condition is not
-   --  known, then Cond and Val are set for the empty case (N_Empty and Empty).
+   --  N_Elsif_Part or a N_Iteration_Scheme node (see description in Einfo for
+   --  exact details). In this case, Get_Current_Condition digs out the
+   --  condition, and then checks if the condition is known false, known true,
+   --  or not known at all. In the first two cases, Get_Current_Condition will
+   --  return with Op set to the appropriate conditional operator (inverted if
+   --  the condition is known false), and Val set to the constant value. If the
+   --  condition is not known, then Cond and Val are set for the empty case
+   --  (N_Empty and Empty).
    --
    --  The check for whether the condition is true/false unknown depends
    --  on the case:
@@ -465,7 +467,7 @@ package Exp_Util is
    --  routine with No_List as the argument.
 
    function Is_Predefined_Dispatching_Operation (E : Entity_Id) return Boolean;
-   --  Ada 2005 (AI-251): Determines if E is a predefined primitive operation.
+   --  Ada 2005 (AI-251): Determines if E is a predefined primitive operation
 
    function Is_Ref_To_Bit_Packed_Array (N : Node_Id) return Boolean;
    --  Determine whether the node P is a reference to a bit packed array, i.e.
@@ -505,14 +507,17 @@ package Exp_Util is
    --  Returns true if type T is not tagged and is a derived type,
    --  or is a private type whose completion is such a type.
 
-   procedure Kill_Dead_Code (N : Node_Id);
+   procedure Kill_Dead_Code (N : Node_Id; Warn : Boolean := False);
    --  N represents a node for a section of code that is known to be dead. The
    --  node is deleted, and any exception handler references and warning
-   --  messages relating to this code are removed.
+   --  messages relating to this code are removed. If Warn is True, a warning
+   --  will be output at the start of N indicating the deletion of the code.
 
-   procedure Kill_Dead_Code (L : List_Id);
+   procedure Kill_Dead_Code (L : List_Id; Warn : Boolean := False);
    --  Like the above procedure, but applies to every element in the given
    --  list. Each of the entries is removed from the list before killing it.
+   --  If Warn is True, a warning will be output at the start of N indicating
+   --  the deletion of the code.
 
    function Known_Non_Negative (Opnd : Node_Id) return Boolean;
    --  Given a node for a subexpression, determines if it represents a value
@@ -589,6 +594,13 @@ package Exp_Util is
    --  field may not be set, but in that case it must be the case that the
    --  Subtype_Mark field of the node is set/analyzed.
 
+   procedure Set_Current_Value_Condition (Cnode : Node_Id);
+   --  Cnode is N_If_Statement, N_Elsif_Part, or N_Iteration_Scheme (the latter
+   --  when a WHILE condition is present). This call checks whether Condition
+   --  (Cnode) has embedded expressions of a form that should result in setting
+   --  the Current_Value field of one or more entities, and if so sets these
+   --  fields to point to Cnode.
+
    procedure Set_Elaboration_Flag (N : Node_Id; Spec_Id : Entity_Id);
    --  N is the node for a subprogram or generic body, and Spec_Id is the
    --  entity for the corresponding spec. If an elaboration entity is defined,