diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 9165fb7485d..1dd55494a53 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -2727,6 +2727,11 @@ package Einfo is
 --       instantiation of a child unit, and whose entities are not visible
 --       during analysis of the instance.
 
+--    Is_Ignored_For_Finalization
+--       Defined in constants and variables. Set when an object must be ignored
+--       by the general finalization mechanism because its cleanup actions are
+--       already accounted for.
+
 --    Is_Ignored_Ghost_Entity
 --       Applies to all entities. Set for abstract states, [generic] packages,
 --       [generic] subprograms, components, discriminants, formal parameters,
@@ -2734,13 +2739,6 @@ package Einfo is
 --       pragma Ghost or inherit "ghostness" from an enclosing construct, and
 --       subject to Assertion_Policy Ghost => Ignore.
 
---    Is_Ignored_Transient
---       Defined in constants, loop parameters of generalized iterators, and
---       variables. Set when a transient object must be processed by one of
---       the transient finalization mechanisms. Once marked, a transient is
---       intentionally ignored by the general finalization mechanism because
---       its clean up actions are context specific.
-
 --    Is_Immediately_Visible
 --       Defined in all entities. Set if entity is immediately visible, i.e.
 --       is defined in some currently open scope (RM 8.3(4)).
@@ -5325,7 +5323,7 @@ package Einfo is
    --    Is_Elaboration_Warnings_OK_Id         (constants only)
    --    Is_Eliminated
    --    Is_Finalized_Transient
-   --    Is_Ignored_Transient
+   --    Is_Ignored_For_Finalization
    --    Is_Independent
    --    Is_Return_Object
    --    Is_True_Constant
@@ -6213,7 +6211,7 @@ package Einfo is
    --    Is_Elaboration_Warnings_OK_Id
    --    Is_Eliminated
    --    Is_Finalized_Transient
-   --    Is_Ignored_Transient
+   --    Is_Ignored_For_Finalization
    --    Is_Independent
    --    Is_Return_Object
    --    Is_Safe_To_Reevaluate
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 2d02bad0c4c..d61fbbc8c73 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6317,7 +6317,7 @@ package body Exp_Aggr is
            and then No_Ctrl_Actions (Parent_Node)
          then
             Mutate_Ekind (Tmp, E_Variable);
-            Set_Is_Ignored_Transient (Tmp);
+            Set_Is_Ignored_For_Finalization (Tmp);
          end if;
 
          Insert_Action (N, Tmp_Decl);
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 527ca16aac4..037c8b528bd 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -241,18 +241,6 @@ package body Exp_Ch4 is
    --  and X is a simple entity, and op is a comparison operator, optimizes it
    --  into a comparison of X'First and X'Last.
 
-   procedure Process_Transient_In_Expression
-     (Obj_Decl : Node_Id;
-      Expr     : Node_Id;
-      Stmts    : List_Id);
-   --  Subsidiary routine to the expansion of expression_with_actions, if and
-   --  case expressions. Generate all necessary code to finalize a transient
-   --  object when the enclosing context is elaborated or evaluated. Obj_Decl
-   --  denotes the declaration of the transient object, which is usually the
-   --  result of a controlled function call. Expr denotes the expression with
-   --  actions, if expression, or case expression node. Stmts denotes one of
-   --  the actions list of Expr, which contains Decl.
-
    procedure Process_Transients_In_Expression
      (Expr  : Node_Id;
       Stmts : List_Id);
@@ -5643,10 +5631,6 @@ package body Exp_Ch4 is
            UI_Max (Hi1, Hi2) - UI_Min (Lo1, Lo2) < Too_Large_Length_For_Array;
       end OK_For_Single_Subtype;
 
-      Optimize_Return_Stmt : Boolean := False;
-      --  Flag set when the if expression can be optimized in the context of
-      --  a simple return statement.
-
       --  Local variables
 
       Actions : List_Id;
@@ -5655,6 +5639,10 @@ package body Exp_Ch4 is
       New_If  : Node_Id;
       New_N   : Node_Id;
 
+      Optimize_Return_Stmt : Boolean := False;
+      --  Flag set when the if expression can be optimized in the context of
+      --  a simple return statement.
+
    --  Start of processing for Expand_N_If_Expression
 
    begin
@@ -14917,174 +14905,178 @@ package body Exp_Ch4 is
       Analyze_And_Resolve (N, Typ, Suppress => Overflow_Check);
    end Optimize_Length_Comparison;
 
-   -------------------------------------
-   -- Process_Transient_In_Expression --
-   -------------------------------------
+   --------------------------------------
+   -- Process_Transients_In_Expression --
+   --------------------------------------
 
-   procedure Process_Transient_In_Expression
-     (Obj_Decl : Node_Id;
-      Expr     : Node_Id;
-      Stmts    : List_Id)
+   procedure Process_Transients_In_Expression
+     (Expr : Node_Id;
+      Stmts : List_Id)
    is
-      Loc    : constant Source_Ptr := Sloc (Obj_Decl);
-      Obj_Id : constant Entity_Id  := Defining_Identifier (Obj_Decl);
+      procedure Process_Transient_In_Expression (Obj_Decl : Node_Id);
+      --  Process the object whose declaration Obj_Decl is present in Stmts
 
-      Hook_Context : constant Node_Id := Find_Hook_Context (Expr);
-      --  The node on which to insert the hook as an action. This is usually
-      --  the innermost enclosing non-transient construct.
+      -------------------------------------
+      -- Process_Transient_In_Expression --
+      -------------------------------------
 
-      Fin_Call    : Node_Id;
-      Hook_Assign : Node_Id;
-      Hook_Clear  : Node_Id;
-      Hook_Decl   : Node_Id;
-      Hook_Insert : Node_Id;
-      Ptr_Decl    : Node_Id;
+      procedure Process_Transient_In_Expression (Obj_Decl : Node_Id) is
+         Loc    : constant Source_Ptr := Sloc (Obj_Decl);
+         Obj_Id : constant Entity_Id  := Defining_Identifier (Obj_Decl);
 
-      Fin_Context : Node_Id;
-      --  The node after which to insert the finalization actions of the
-      --  transient object.
+         Hook_Context : constant Node_Id := Find_Hook_Context (Expr);
+         --  The node on which to insert the hook as an action. This is usually
+         --  the innermost enclosing non-transient construct.
 
-   begin
-      pragma Assert (Nkind (Expr) in N_Case_Expression
-                                   | N_Expression_With_Actions
-                                   | N_If_Expression);
+         Fin_Call    : Node_Id;
+         Hook_Assign : Node_Id;
+         Hook_Clear  : Node_Id;
+         Hook_Decl   : Node_Id;
+         Hook_Insert : Node_Id;
+         Ptr_Decl    : Node_Id;
 
-      --  When the context is a Boolean evaluation, all three nodes capture the
-      --  result of their computation in a local temporary:
+         Fin_Context : Node_Id;
+         --  The node after which to insert the finalization actions of the
+         --  transient object.
 
-      --    do
-      --       Trans_Id : Ctrl_Typ := ...;
-      --       Result : constant Boolean := ... Trans_Id ...;
-      --       <finalize Trans_Id>
-      --    in Result end;
+      begin
+         pragma Assert (Nkind (Expr) in N_Case_Expression
+                                      | N_Expression_With_Actions
+                                      | N_If_Expression);
 
-      --  As a result, the finalization of any transient objects can take place
-      --  just after the result is captured, except for the case of conditional
-      --  expressions in a simple return statement because the return statement
-      --  will be distributed into the conditional expressions (see the special
-      --  handling of simple return statements a few lines below).
+         --  When the context is a Boolean evaluation, all three nodes capture
+         --  the result of their computation in a local temporary:
 
-      --  ??? could this be extended to elementary types?
+         --    do
+         --       Trans_Id : Ctrl_Typ := ...;
+         --       Result : constant Boolean := ... Trans_Id ...;
+         --       <finalize Trans_Id>
+         --    in Result end;
 
-      if Is_Boolean_Type (Etype (Expr))
-        and then (Nkind (Expr) = N_Expression_With_Actions
-                   or else Nkind (Parent (Expr)) /= N_Simple_Return_Statement)
-      then
-         Fin_Context := Last (Stmts);
+         --  As a result, the finalization of any transient objects can take
+         --  place just after the result is captured, except for the case of
+         --  conditional expressions in a simple return statement because the
+         --  return statement will be distributed into dependent expressions
+         --  (see the special handling of simple return statements below).
 
-      --  Otherwise the immediate context may not be safe enough to carry
-      --  out transient object finalization due to aliasing and nesting of
-      --  constructs. Insert calls to [Deep_]Finalize after the innermost
-      --  enclosing non-transient construct.
+         --  ??? could this be extended to elementary types?
 
-      else
-         Fin_Context := Hook_Context;
-      end if;
+         if Is_Boolean_Type (Etype (Expr))
+           and then
+             (Nkind (Expr) = N_Expression_With_Actions
+               or else Nkind (Parent (Expr)) /= N_Simple_Return_Statement)
+         then
+            Fin_Context := Last (Stmts);
 
-      --  Mark the transient object as successfully processed to avoid double
-      --  finalization.
+         --  Otherwise the immediate context may not be safe enough to carry
+         --  out transient object finalization due to aliasing and nesting of
+         --  constructs. Insert calls to [Deep_]Finalize after the innermost
+         --  enclosing non-transient construct.
 
-      Set_Is_Finalized_Transient (Obj_Id);
+         else
+            Fin_Context := Hook_Context;
+         end if;
 
-      --  Construct all the pieces necessary to hook and finalize a transient
-      --  object.
+         --  Mark the transient object as successfully processed to avoid
+         --  double finalization.
 
-      Build_Transient_Object_Statements
-        (Obj_Decl     => Obj_Decl,
-         Fin_Call     => Fin_Call,
-         Hook_Assign  => Hook_Assign,
-         Hook_Clear   => Hook_Clear,
-         Hook_Decl    => Hook_Decl,
-         Ptr_Decl     => Ptr_Decl,
-         Finalize_Obj => False);
+         Set_Is_Finalized_Transient (Obj_Id);
 
-      --  Add the access type which provides a reference to the transient
-      --  object. Generate:
+         --  Construct all the pieces necessary to hook and finalize a
+         --  transient object.
 
-      --    type Ptr_Typ is access all Desig_Typ;
+         Build_Transient_Object_Statements
+           (Obj_Decl     => Obj_Decl,
+            Fin_Call     => Fin_Call,
+            Hook_Assign  => Hook_Assign,
+            Hook_Clear   => Hook_Clear,
+            Hook_Decl    => Hook_Decl,
+            Ptr_Decl     => Ptr_Decl,
+            Finalize_Obj => False);
 
-      Insert_Action (Hook_Context, Ptr_Decl);
+         --  Add the access type which provides a reference to the transient
+         --  object. Generate:
 
-      --  Add the temporary which acts as a hook to the transient object.
-      --  Generate:
+         --    type Ptr_Typ is access all Desig_Typ;
 
-      --    Hook : Ptr_Id := null;
+         Insert_Action (Hook_Context, Ptr_Decl);
 
-      Insert_Action (Hook_Context, Hook_Decl);
+         --  Add the temporary which acts as a hook to the transient object.
+         --  Generate:
 
-      --  When the transient object is initialized by an aggregate, the hook
-      --  must capture the object after the last aggregate assignment takes
-      --  place. Only then is the object considered initialized. Generate:
+         --    Hook : Ptr_Id := null;
 
-      --    Hook := Ptr_Typ (Obj_Id);
-      --      <or>
-      --    Hook := Obj_Id'Unrestricted_Access;
+         Insert_Action (Hook_Context, Hook_Decl);
 
-      if Ekind (Obj_Id) in E_Constant | E_Variable
-        and then Present (Last_Aggregate_Assignment (Obj_Id))
-      then
-         Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
+         --  When the transient object is initialized by an aggregate, the hook
+         --  must capture the object after the last aggregate assignment takes
+         --  place. Only then is the object considered initialized. Generate:
 
-      --  Otherwise the hook seizes the related object immediately
+         --    Hook := Ptr_Typ (Obj_Id);
+         --      <or>
+         --    Hook := Obj_Id'Unrestricted_Access;
 
-      else
-         Hook_Insert := Obj_Decl;
-      end if;
+         if Ekind (Obj_Id) in E_Constant | E_Variable
+           and then Present (Last_Aggregate_Assignment (Obj_Id))
+         then
+            Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
 
-      Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
+         --  Otherwise the hook seizes the related object immediately
 
-      --  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 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.
+         else
+            Hook_Insert := Obj_Decl;
+         end if;
 
-      if Nkind (Fin_Context) = N_Simple_Return_Statement then
-         null;
+         Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
 
-      --  Finalize the hook after the context has been evaluated. Generate:
+         --  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 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 Hook /= null then
-      --       [Deep_]Finalize (Hook.all);
-      --       Hook := null;
-      --    end if;
+         if Nkind (Fin_Context) = N_Simple_Return_Statement then
+            null;
 
-      --  Note that the value returned by Find_Hook_Context may be an operator
-      --  node, which is not a list member. We must locate the proper node in
-      --  in the tree after which to insert the finalization code.
+         --  Finalize the hook after the context has been evaluated. Generate:
 
-      else
-         while not Is_List_Member (Fin_Context) loop
-            Fin_Context := Parent (Fin_Context);
-         end loop;
+         --    if Hook /= null then
+         --       [Deep_]Finalize (Hook.all);
+         --       Hook := null;
+         --    end if;
 
-         pragma Assert (Present (Fin_Context));
+         --  But the node returned by Find_Hook_Context may be an operator,
+         --  which is not a list member. We must locate the proper node
+         --  in the tree after which to insert the finalization code.
 
-         Insert_Action_After (Fin_Context,
-           Make_Implicit_If_Statement (Obj_Decl,
-             Condition =>
-               Make_Op_Ne (Loc,
-                 Left_Opnd  =>
-                   New_Occurrence_Of (Defining_Entity (Hook_Decl), Loc),
-                 Right_Opnd => Make_Null (Loc)),
+         else
+            while not Is_List_Member (Fin_Context) loop
+               Fin_Context := Parent (Fin_Context);
+            end loop;
 
-             Then_Statements => New_List (
-               Fin_Call,
-               Hook_Clear)));
-      end if;
-   end Process_Transient_In_Expression;
+            pragma Assert (Present (Fin_Context));
 
-   --------------------------------------
-   -- Process_Transients_In_Expression --
-   --------------------------------------
+            Insert_Action_After (Fin_Context,
+              Make_Implicit_If_Statement (Obj_Decl,
+                Condition =>
+                  Make_Op_Ne (Loc,
+                    Left_Opnd  =>
+                      New_Occurrence_Of (Defining_Entity (Hook_Decl), Loc),
+                   Right_Opnd => Make_Null (Loc)),
+
+                Then_Statements => New_List (
+                 Fin_Call,
+                  Hook_Clear)));
+         end if;
+      end Process_Transient_In_Expression;
+
+      --  Local variables
 
-   procedure Process_Transients_In_Expression
-     (Expr : Node_Id;
-      Stmts : List_Id)
-   is
       Decl : Node_Id;
 
+   --  Start of processing for Process_Transients_In_Expression
+
    begin
       pragma Assert (Nkind (Expr) in N_Case_Expression
                                    | N_Expression_With_Actions
@@ -15095,7 +15087,7 @@ package body Exp_Ch4 is
          if Nkind (Decl) = N_Object_Declaration
            and then Is_Finalizable_Transient (Decl, Expr)
          then
-            Process_Transient_In_Expression (Decl, Expr, Stmts);
+            Process_Transient_In_Expression (Decl);
          end if;
 
          Next (Decl);
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index a2b5cdcfa8e..195e34a3479 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -5441,29 +5441,6 @@ package body Exp_Ch6 is
    is
       Par : constant Node_Id := Parent (N);
 
-      function Is_Element_Reference (N : Node_Id) return Boolean;
-      --  Determine whether node N denotes a reference to an Ada 2012 container
-      --  element.
-
-      --------------------------
-      -- Is_Element_Reference --
-      --------------------------
-
-      function Is_Element_Reference (N : Node_Id) return Boolean is
-         Ref : constant Node_Id := Original_Node (N);
-
-      begin
-         --  Analysis marks an element reference by setting the generalized
-         --  indexing attribute of an indexed component before the component
-         --  is rewritten into a function call.
-
-         return
-           Nkind (Ref) = N_Indexed_Component
-             and then Present (Generalized_Indexing (Ref));
-      end Is_Element_Reference;
-
-   --  Start of processing for Expand_Ctrl_Function_Call
-
    begin
       --  Optimization: if the returned value is returned again, then no need
       --  to copy/readjust/finalize, we can just pass the value through (see
@@ -5505,26 +5482,6 @@ package body Exp_Ch6 is
       if Nkind (Par) /= N_Reference then
          Remove_Side_Effects (N);
       end if;
-
-      --  The side effect removal of the function call produced a temporary.
-      --  When the context is a case expression, if expression, or expression
-      --  with actions, the lifetime of the temporary must be extended to match
-      --  that of the context. Otherwise the function result will be finalized
-      --  too early and affect the result of the expression. To prevent this
-      --  unwanted effect, the temporary should not be considered for clean up
-      --  actions by the general finalization machinery.
-
-      --  Exception to this rule are references to Ada 2012 container elements.
-      --  Such references must be finalized at the end of each iteration of the
-      --  related quantified expression, otherwise the container will remain
-      --  busy.
-
-      if Nkind (N) = N_Explicit_Dereference
-        and then Within_Case_Or_If_Expression (N)
-        and then not Is_Element_Reference (N)
-      then
-         Set_Is_Ignored_Transient (Entity (Prefix (N)));
-      end if;
    end Expand_Ctrl_Function_Call;
 
    ----------------------------------------
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index f5d9b0fe802..a95beec956b 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -1265,7 +1265,7 @@ package body Exp_Ch7 is
 
          --  Associate the Finalize_Address primitive of the designated type
          --  with the finalization master of the access type. The designated
-         --  type must be forzen as Finalize_Address is generated when the
+         --  type must be frozen, as Finalize_Address is generated when the
          --  freeze node is expanded.
 
          elsif Is_Frozen (Desig_Typ)
@@ -2257,19 +2257,19 @@ package body Exp_Ch7 is
                if For_Package and then Finalize_Storage_Only (Obj_Typ) then
                   null;
 
-               --  Finalization of transient objects are treated separately in
+               --  Finalization of transient objects is treated separately in
                --  order to handle sensitive cases. These include:
 
                --    * Conditional expressions
                --    * Expressions with actions
                --    * Transient scopes
 
-               --  If one of those contexts has marked the transient object as
-               --  ignored, do not generate finalization actions for it.
+               elsif Is_Finalized_Transient (Obj_Id) then
+                  null;
 
-               elsif Is_Finalized_Transient (Obj_Id)
-                 or else Is_Ignored_Transient (Obj_Id)
-               then
+               --  Finalization of specific objects is also treated separately
+
+               elsif Is_Ignored_For_Finalization (Obj_Id) then
                   null;
 
                --  Ignored Ghost objects do not need any cleanup actions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 17fde44d7ab..b9346a9f405 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -13020,19 +13020,19 @@ package body Exp_Util is
             if Lib_Level and then Finalize_Storage_Only (Obj_Typ) then
                null;
 
-            --  Finalization of transient objects are treated separately in
+            --  Finalization of transient objects is treated separately in
             --  order to handle sensitive cases. These include:
 
             --    * Conditional expressions
             --    * Expressions with actions
             --    * Transient scopes
 
-            --  If one of those contexts has marked the transient object as
-            --  ignored, do not generate finalization actions for it.
+            elsif Is_Finalized_Transient (Obj_Id) then
+               null;
 
-            elsif Is_Finalized_Transient (Obj_Id)
-              or else Is_Ignored_Transient (Obj_Id)
-            then
+            --  Finalization of specific objects is also treated separately
+
+            elsif Is_Ignored_For_Finalization (Obj_Id) then
                null;
 
             --  Ignored Ghost objects do not need any cleanup actions because
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 632ce489b08..8a62eac889d 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -721,8 +721,8 @@ package Gen_IL.Fields is
       Is_Hidden,
       Is_Hidden_Non_Overridden_Subpgm,
       Is_Hidden_Open_Scope,
+      Is_Ignored_For_Finalization,
       Is_Ignored_Ghost_Entity,
-      Is_Ignored_Transient,
       Is_Immediately_Visible,
       Is_Implementation_Defined,
       Is_Imported,
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb
index 3e6ed9633bd..b7e7865a0ba 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -337,7 +337,7 @@ begin -- Gen_IL.Gen.Gen_Entities
         Sm (Esize, Uint),
         Sm (Interface_Name, Node_Id),
         Sm (Is_Finalized_Transient, Flag),
-        Sm (Is_Ignored_Transient, Flag),
+        Sm (Is_Ignored_For_Finalization, Flag),
         Sm (Linker_Section_Pragma, Node_Id),
         Sm (Related_Expression, Node_Id),
         Sm (Status_Flag_Or_Transient_Decl, Node_Id)));
