OSDN Git Service

* gcc-interface/Makefile.in (gnatlib-shared-default): Append
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_aggr.adb
index 08e23ab..8cfbe3b 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2008, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT 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- --
@@ -28,12 +28,16 @@ with Checks;   use Checks;
 with Debug;    use Debug;
 with Einfo;    use Einfo;
 with Elists;   use Elists;
+with Errout;   use Errout;
 with Expander; use Expander;
 with Exp_Util; use Exp_Util;
 with Exp_Ch3;  use Exp_Ch3;
+with Exp_Ch6;  use Exp_Ch6;
 with Exp_Ch7;  use Exp_Ch7;
 with Exp_Ch9;  use Exp_Ch9;
+with Exp_Disp; use Exp_Disp;
 with Exp_Tss;  use Exp_Tss;
+with Fname;    use Fname;
 with Freeze;   use Freeze;
 with Itypes;   use Itypes;
 with Lib;      use Lib;
@@ -46,6 +50,8 @@ with Rident;   use Rident;
 with Rtsfind;  use Rtsfind;
 with Ttypes;   use Ttypes;
 with Sem;      use Sem;
+with Sem_Aggr; use Sem_Aggr;
+with Sem_Aux;  use Sem_Aux;
 with Sem_Ch3;  use Sem_Ch3;
 with Sem_Eval; use Sem_Eval;
 with Sem_Res;  use Sem_Res;
@@ -68,6 +74,14 @@ package body Exp_Aggr is
    type Case_Table_Type is array (Nat range <>) of Case_Bounds;
    --  Table type used by Check_Case_Choices procedure
 
+   function Has_Default_Init_Comps (N : Node_Id) return Boolean;
+   --  N is an aggregate (record or array). Checks the presence of default
+   --  initialization (<>) in any component (Ada 2005: AI-287).
+
+   function Is_Static_Dispatch_Table_Aggregate (N : Node_Id) return Boolean;
+   --  Returns true if N is an aggregate used to initialize the components
+   --  of an statically allocated dispatch table.
+
    function Must_Slide
      (Obj_Type : Entity_Id;
       Typ      : Entity_Id) return Boolean;
@@ -88,18 +102,26 @@ package body Exp_Aggr is
    --  statement of variant part will usually be small and probably in near
    --  sorted order.
 
-   function Has_Default_Init_Comps (N : Node_Id) return Boolean;
-   --  N is an aggregate (record or array). Checks the presence of default
-   --  initialization (<>) in any component (Ada 2005: AI-287)
-
-   function Is_Static_Dispatch_Table_Aggregate (N : Node_Id) return Boolean;
-   --  Returns true if N is an aggregate used to initialize the components
-   --  of an statically allocated dispatch table.
-
    ------------------------------------------------------
    -- Local subprograms for Record Aggregate Expansion --
    ------------------------------------------------------
 
+   function Build_Record_Aggr_Code
+     (N   : Node_Id;
+      Typ : Entity_Id;
+      Lhs : Node_Id) return List_Id;
+   --  N is an N_Aggregate or an N_Extension_Aggregate. Typ is the type of the
+   --  aggregate. Target is an expression containing the location on which the
+   --  component by component assignments will take place. Returns the list of
+   --  assignments plus all other adjustments needed for tagged and controlled
+   --  types.
+
+   procedure Convert_To_Assignments (N : Node_Id; Typ : Entity_Id);
+   --  N is an N_Aggregate or an N_Extension_Aggregate. Typ is the type of the
+   --  aggregate (which can only be a record type, this procedure is only used
+   --  for record types). Transform the given aggregate into a sequence of
+   --  assignments performed component by component.
+
    procedure Expand_Record_Aggregate
      (N           : Node_Id;
       Orig_Tag    : Node_Id := Empty;
@@ -117,37 +139,6 @@ package body Exp_Aggr is
    --    Parent_Expr is the ancestor part of the original extension
    --      aggregate
 
-   procedure Convert_To_Assignments (N : Node_Id; Typ : Entity_Id);
-   --  N is an N_Aggregate or an N_Extension_Aggregate. Typ is the type of the
-   --  aggregate (which can only be a record type, this procedure is only used
-   --  for record types). Transform the given aggregate into a sequence of
-   --  assignments performed component by component.
-
-   function Build_Record_Aggr_Code
-     (N                             : Node_Id;
-      Typ                           : Entity_Id;
-      Lhs                           : Node_Id;
-      Flist                         : Node_Id   := Empty;
-      Obj                           : Entity_Id := Empty;
-      Is_Limited_Ancestor_Expansion : Boolean   := False) return List_Id;
-   --  N is an N_Aggregate or an N_Extension_Aggregate. Typ is the type of the
-   --  aggregate. Target is an expression containing the location on which the
-   --  component by component assignments will take place. Returns the list of
-   --  assignments plus all other adjustments needed for tagged and controlled
-   --  types. Flist is an expression representing the finalization list on
-   --  which to attach the controlled components if any. Obj is present in the
-   --  object declaration and dynamic allocation cases, it contains an entity
-   --  that allows to know if the value being created needs to be attached to
-   --  the final list in case of pragma Finalize_Storage_Only.
-   --
-   --  ???
-   --  The meaning of the Obj formal is extremely unclear. *What* entity
-   --  should be passed? For the object declaration case we may guess that
-   --  this is the object being declared, but what about the allocator case?
-   --
-   --  Is_Limited_Ancestor_Expansion indicates that the function has been
-   --  called recursively to expand the limited ancestor to avoid copying it.
-
    function Has_Mutable_Components (Typ : Entity_Id) return Boolean;
    --  Return true if one of the component is of a discriminated type with
    --  defaults. An aggregate for a type with mutable components must be
@@ -169,12 +160,45 @@ package body Exp_Aggr is
    -- Local Subprograms for Array Aggregate Expansion --
    -----------------------------------------------------
 
-   function Aggr_Size_OK (Typ : Entity_Id) return Boolean;
-   --  Very large static aggregates present problems to the back-end, and
-   --  are transformed into assignments and loops. This function verifies
-   --  that the total number of components of an aggregate is acceptable
-   --  for transformation into a purely positional static form. It is called
-   --  prior to calling Flatten.
+   function Aggr_Size_OK (N : Node_Id; Typ : Entity_Id) return Boolean;
+   --  Very large static aggregates present problems to the back-end, and are
+   --  transformed into assignments and loops. This function verifies that the
+   --  total number of components of an aggregate is acceptable for rewriting
+   --  into a purely positional static form. Aggr_Size_OK must be called before
+   --  calling Flatten.
+   --
+   --  This function also detects and warns about one-component aggregates that
+   --  appear in a non-static context. Even if the component value is static,
+   --  such an aggregate must be expanded into an assignment.
+
+   function Backend_Processing_Possible (N : Node_Id) return Boolean;
+   --  This function checks if array aggregate N can be processed directly
+   --  by the backend. If this is the case True is returned.
+
+   function Build_Array_Aggr_Code
+     (N           : Node_Id;
+      Ctype       : Entity_Id;
+      Index       : Node_Id;
+      Into        : Node_Id;
+      Scalar_Comp : Boolean;
+      Indexes     : List_Id := No_List) return List_Id;
+   --  This recursive routine returns a list of statements containing the
+   --  loops and assignments that are needed for the expansion of the array
+   --  aggregate N.
+   --
+   --    N is the (sub-)aggregate node to be expanded into code. This node has
+   --    been fully analyzed, and its Etype is properly set.
+   --
+   --    Index is the index node corresponding to the array sub-aggregate N
+   --
+   --    Into is the target expression into which we are copying the aggregate.
+   --    Note that this node may not have been analyzed yet, and so the Etype
+   --    field may not be set.
+   --
+   --    Scalar_Comp is True if the component type of the aggregate is scalar
+   --
+   --    Indexes is the current list of expressions used to index the object we
+   --    are writing into.
 
    procedure Convert_Array_Aggr_In_Allocator
      (Decl   : Node_Id;
@@ -205,82 +229,46 @@ package body Exp_Aggr is
    --  Packed_Array_Aggregate_Handled, we set this parameter to True, since
    --  these are cases we handle in there.
 
+   --  It would seem worthwhile to have a higher default value for Max_Others_
+   --  replicate, but aggregates in the compiler make this impossible: the
+   --  compiler bootstrap fails if Max_Others_Replicate is greater than 25.
+   --  This is unexpected ???
+
    procedure Expand_Array_Aggregate (N : Node_Id);
    --  This is the top-level routine to perform array aggregate expansion.
    --  N is the N_Aggregate node to be expanded.
 
-   function Backend_Processing_Possible (N : Node_Id) return Boolean;
-   --  This function checks if array aggregate N can be processed directly
-   --  by Gigi. If this is the case True is returned.
-
-   function Build_Array_Aggr_Code
-     (N           : Node_Id;
-      Ctype       : Entity_Id;
-      Index       : Node_Id;
-      Into        : Node_Id;
-      Scalar_Comp : Boolean;
-      Indices     : List_Id := No_List;
-      Flist       : Node_Id := Empty) return List_Id;
-   --  This recursive routine returns a list of statements containing the
-   --  loops and assignments that are needed for the expansion of the array
-   --  aggregate N.
-   --
-   --    N is the (sub-)aggregate node to be expanded into code. This node
-   --    has been fully analyzed, and its Etype is properly set.
-   --
-   --    Index is the index node corresponding to the array sub-aggregate N.
-   --
-   --    Into is the target expression into which we are copying the aggregate.
-   --    Note that this node may not have been analyzed yet, and so the Etype
-   --    field may not be set.
-   --
-   --    Scalar_Comp is True if the component type of the aggregate is scalar.
-   --
-   --    Indices is the current list of expressions used to index the
-   --    object we are writing into.
-   --
-   --    Flist is an expression representing the finalization list on which
-   --    to attach the controlled components if any.
-
-   function Number_Of_Choices (N : Node_Id) return Nat;
-   --  Returns the number of discrete choices (not including the others choice
-   --  if present) contained in (sub-)aggregate N.
-
    function Late_Expansion
      (N      : Node_Id;
       Typ    : Entity_Id;
-      Target : Node_Id;
-      Flist  : Node_Id := Empty;
-      Obj    : Entity_Id := Empty) return List_Id;
-   --  N is a nested (record or array) aggregate that has been marked with
-   --  'Delay_Expansion'. Typ is the expected type of the aggregate and Target
-   --  is a (duplicable) expression that will hold the result of the aggregate
-   --  expansion. Flist is the finalization list to be used to attach
-   --  controlled components. 'Obj' when non empty, carries the original
-   --  object being initialized in order to know if it needs to be attached to
-   --  the previous parameter which may not be the case in the case where
-   --  Finalize_Storage_Only is set. Basically this procedure is used to
-   --  implement top-down expansions of nested aggregates. This is necessary
-   --  for avoiding temporaries at each level as well as for propagating the
-   --  right internal finalization list.
+      Target : Node_Id) return List_Id;
+   --  This routine implements top-down expansion of nested aggregates. In
+   --  doing so, it avoids the generation of temporaries at each level. N is
+   --  a nested record or array aggregate with the Expansion_Delayed flag.
+   --  Typ is the expected type of the aggregate. Target is a (duplicatable)
+   --  expression that will hold the result of the aggregate expansion.
 
    function Make_OK_Assignment_Statement
      (Sloc       : Source_Ptr;
       Name       : Node_Id;
       Expression : Node_Id) return Node_Id;
    --  This is like Make_Assignment_Statement, except that Assignment_OK
-   --  is set in the left operand. All assignments built by this unit
-   --  use this routine. This is needed to deal with assignments to
-   --  initialized constants that are done in place.
+   --  is set in the left operand. All assignments built by this unit use
+   --  this routine. This is needed to deal with assignments to initialized
+   --  constants that are done in place.
+
+   function Number_Of_Choices (N : Node_Id) return Nat;
+   --  Returns the number of discrete choices (not including the others choice
+   --  if present) contained in (sub-)aggregate N.
 
    function Packed_Array_Aggregate_Handled (N : Node_Id) return Boolean;
    --  Given an array aggregate, this function handles the case of a packed
    --  array aggregate with all constant values, where the aggregate can be
    --  evaluated at compile time. If this is possible, then N is rewritten
    --  to be its proper compile time value with all the components properly
-   --  assembled. The expression is analyzed and resolved and True is
-   --  returned. If this transformation is not possible, N is unchanged
-   --  and False is returned
+   --  assembled. The expression is analyzed and resolved and True is returned.
+   --  If this transformation is not possible, N is unchanged and False is
+   --  returned.
 
    function Safe_Slice_Assignment (N : Node_Id) return Boolean;
    --  If a slice assignment has an aggregate with a single others_choice,
@@ -291,7 +279,7 @@ package body Exp_Aggr is
    -- Aggr_Size_OK --
    ------------------
 
-   function Aggr_Size_OK (Typ : Entity_Id) return Boolean is
+   function Aggr_Size_OK (N : Node_Id; Typ : Entity_Id) return Boolean is
       Lo   : Node_Id;
       Hi   : Node_Id;
       Indx : Node_Id;
@@ -299,30 +287,28 @@ package body Exp_Aggr is
       Lov  : Uint;
       Hiv  : Uint;
 
-      --  The following constant determines the maximum size of an
-      --  array aggregate produced by converting named to positional
-      --  notation (e.g. from others clauses). This avoids running
-      --  away with attempts to convert huge aggregates, which hit
-      --  memory limits in the backend.
+      --  The following constant determines the maximum size of an array
+      --  aggregate produced by converting named to positional notation (e.g.
+      --  from others clauses). This avoids running away with attempts to
+      --  convert huge aggregates, which hit memory limits in the backend.
 
-      --  The normal limit is 5000, but we increase this limit to
-      --  2**24 (about 16 million) if Restrictions (No_Elaboration_Code)
-      --  or Restrictions (No_Implicit_Loops) is specified, since in
-      --  either case, we are at risk of declaring the program illegal
-      --  because of this limit.
+      --  The normal limit is 5000, but we increase this limit to 2**24 (about
+      --  16 million) if Restrictions (No_Elaboration_Code) or Restrictions
+      --  (No_Implicit_Loops) is specified, since in either case, we are at
+      --  risk of declaring the program illegal because of this limit.
 
       Max_Aggr_Size : constant Nat :=
                         5000 + (2 ** 24 - 5000) *
                           Boolean'Pos
                             (Restriction_Active (No_Elaboration_Code)
-                               or else
+                              or else
                              Restriction_Active (No_Implicit_Loops));
 
       function Component_Count (T : Entity_Id) return Int;
       --  The limit is applied to the total number of components that the
       --  aggregate will have, which is the number of static expressions
       --  that will appear in the flattened array. This requires a recursive
-      --  computation of the the number of scalar components of the structure.
+      --  computation of the number of scalar components of the structure.
 
       ---------------------
       -- Component_Count --
@@ -352,7 +338,7 @@ package body Exp_Aggr is
                Hi : constant Node_Id :=
                       Type_High_Bound (Etype (First_Index (T)));
 
-               Siz  : constant Int := Component_Count (Component_Type (T));
+               Siz : constant Int := Component_Count (Component_Type (T));
 
             begin
                if not Compile_Time_Known_Value (Lo)
@@ -399,6 +385,43 @@ package body Exp_Aggr is
             return True;
          end if;
 
+         --  One-component aggregates are suspicious, and if the context type
+         --  is an object declaration with non-static bounds it will trip gcc;
+         --  such an aggregate must be expanded into a single assignment.
+
+         if Hiv = Lov
+           and then Nkind (Parent (N)) = N_Object_Declaration
+         then
+            declare
+               Index_Type : constant Entity_Id :=
+                              Etype
+                                (First_Index
+                                   (Etype (Defining_Identifier (Parent (N)))));
+               Indx       : Node_Id;
+
+            begin
+               if not Compile_Time_Known_Value (Type_Low_Bound (Index_Type))
+                  or else not Compile_Time_Known_Value
+                                (Type_High_Bound (Index_Type))
+               then
+                  if Present (Component_Associations (N)) then
+                     Indx :=
+                       First (Choices (First (Component_Associations (N))));
+                     if Is_Entity_Name (Indx)
+                       and then not Is_Type (Entity (Indx))
+                     then
+                        Error_Msg_N
+                          ("single component aggregate in non-static context?",
+                            Indx);
+                        Error_Msg_N ("\maybe subtype name was meant?", Indx);
+                     end if;
+                  end if;
+
+                  return False;
+               end if;
+            end;
+         end if;
+
          declare
             Rng : constant Uint := Hiv - Lov + 1;
 
@@ -464,6 +487,10 @@ package body Exp_Aggr is
    --    9. There cannot be any discriminated record components, since the
    --       back end cannot handle this complex case.
 
+   --   10. No controlled actions need to be generated for components
+
+   --   11. For a VM back end, the array should have no aliased components
+
    function Backend_Processing_Possible (N : Node_Id) return Boolean is
       Typ : constant Entity_Id := Etype (N);
       --  Typ is the correct constrained array subtype of the aggregate
@@ -538,16 +565,16 @@ package body Exp_Aggr is
    --  Start of processing for Backend_Processing_Possible
 
    begin
-      --  Checks 2 (array must not be bit packed)
+      --  Checks 2 (array not bit packed) and 10 (no controlled actions)
 
-      if Is_Bit_Packed_Array (Typ) then
+      if Is_Bit_Packed_Array (Typ) or else Needs_Finalization (Typ) then
          return False;
       end if;
 
       --  If component is limited, aggregate must be expanded because each
       --  component assignment must be built in place.
 
-      if Is_Inherently_Limited_Type (Component_Type (Typ)) then
+      if Is_Immutably_Limited_Type (Component_Type (Typ)) then
          return False;
       end if;
 
@@ -578,7 +605,9 @@ package body Exp_Aggr is
       --    with tagged components, but not clear whether it's worthwhile ???;
       --    in the case of the JVM, object tags are handled implicitly)
 
-      if Is_Tagged_Type (Component_Type (Typ)) and then VM_Target = No_VM then
+      if Is_Tagged_Type (Component_Type (Typ))
+        and then Tagged_Type_Expansion
+      then
          return False;
       end if;
 
@@ -588,6 +617,16 @@ package body Exp_Aggr is
          return False;
       end if;
 
+      --  Checks 11: Array aggregates with aliased components are currently
+      --  not well supported by the VM backend; disable temporarily this
+      --  backend processing until it is definitely supported.
+
+      if VM_Target /= No_VM
+        and then Has_Aliased_Components (Base_Type (Typ))
+      then
+         return False;
+      end if;
+
       --  Backend processing is possible
 
       Set_Size_Known_At_Compile_Time (Etype (N), True);
@@ -640,8 +679,7 @@ package body Exp_Aggr is
       Index       : Node_Id;
       Into        : Node_Id;
       Scalar_Comp : Boolean;
-      Indices     : List_Id := No_List;
-      Flist       : Node_Id := Empty) return List_Id
+      Indexes     : List_Id := No_List) return List_Id
    is
       Loc          : constant Source_Ptr := Sloc (N);
       Index_Base   : constant Entity_Id  := Base_Type (Etype (Index));
@@ -667,7 +705,7 @@ package body Exp_Aggr is
       --  N to Build_Loop contains no sub-aggregates, then this function
       --  returns the assignment statement:
       --
-      --     Into (Indices, Ind) := Expr;
+      --     Into (Indexes, Ind) := Expr;
       --
       --  Otherwise we call Build_Code recursively
       --
@@ -680,7 +718,7 @@ package body Exp_Aggr is
       --  This routine returns the for loop statement
       --
       --     for J in Index_Base'(L) .. Index_Base'(H) loop
-      --        Into (Indices, J) := Expr;
+      --        Into (Indexes, J) := Expr;
       --     end loop;
       --
       --  Otherwise we call Build_Code recursively.
@@ -695,7 +733,7 @@ package body Exp_Aggr is
       --     J : Index_Base := L;
       --     while J < H loop
       --        J := Index_Base'Succ (J);
-      --        Into (Indices, J) := Expr;
+      --        Into (Indexes, J) := Expr;
       --     end loop;
       --
       --  Otherwise we call Build_Code recursively
@@ -878,10 +916,9 @@ package body Exp_Aggr is
 
       function Gen_Assign (Ind : Node_Id; Expr : Node_Id) return List_Id is
          L : constant List_Id := New_List;
-         F : Entity_Id;
          A : Node_Id;
 
-         New_Indices  : List_Id;
+         New_Indexes  : List_Id;
          Indexed_Comp : Node_Id;
          Expr_Q       : Node_Id;
          Comp_Type    : Entity_Id := Empty;
@@ -921,28 +958,13 @@ package body Exp_Aggr is
       --  Start of processing for Gen_Assign
 
       begin
-         if No (Indices) then
-            New_Indices := New_List;
+         if No (Indexes) then
+            New_Indexes := New_List;
          else
-            New_Indices := New_Copy_List_Tree (Indices);
+            New_Indexes := New_Copy_List_Tree (Indexes);
          end if;
 
-         Append_To (New_Indices, Ind);
-
-         if Present (Flist) then
-            F := New_Copy_Tree (Flist);
-
-         elsif Present (Etype (N)) and then Controlled_Type (Etype (N)) then
-            if Is_Entity_Name (Into)
-              and then Present (Scope (Entity (Into)))
-            then
-               F := Find_Final_List (Scope (Entity (Into)));
-            else
-               F := Find_Final_List (Current_Scope);
-            end if;
-         else
-            F := Empty;
-         end if;
+         Append_To (New_Indexes, Ind);
 
          if Present (Next_Index (Index)) then
             return
@@ -953,8 +975,7 @@ package body Exp_Aggr is
                    Index       => Next_Index (Index),
                    Into        => Into,
                    Scalar_Comp => Scalar_Comp,
-                   Indices     => New_Indices,
-                   Flist       => F));
+                   Indexes     => New_Indexes));
          end if;
 
          --  If we get here then we are at a bottom-level (sub-)aggregate
@@ -963,7 +984,7 @@ package body Exp_Aggr is
            Checks_Off
              (Make_Indexed_Component (Loc,
                 Prefix      => New_Copy_Tree (Into),
-                Expressions => New_Indices));
+                Expressions => New_Indexes));
 
          Set_Assignment_OK (Indexed_Comp);
 
@@ -984,7 +1005,7 @@ package body Exp_Aggr is
             Comp_Type := Component_Type (Etype (N));
             pragma Assert (Comp_Type = Ctype); --  AI-287
 
-         elsif Present (Next (First (New_Indices))) then
+         elsif Present (Next (First (New_Indexes))) then
 
             --  Ada 2005 (AI-287): Do nothing in case of default initialized
             --  component because we have received the component type in
@@ -1025,16 +1046,14 @@ package body Exp_Aggr is
          --  default initialized components (otherwise Expr_Q is not present).
 
          if Present (Expr_Q)
-           and then (Nkind (Expr_Q) = N_Aggregate
-                     or else Nkind (Expr_Q) = N_Extension_Aggregate)
+           and then Nkind_In (Expr_Q, N_Aggregate, N_Extension_Aggregate)
          then
-            --  At this stage the Expression may not have been
-            --  analyzed yet because the array aggregate code has not
-            --  been updated to use the Expansion_Delayed flag and
-            --  avoid analysis altogether to solve the same problem
-            --  (see Resolve_Aggr_Expr). So let us do the analysis of
-            --  non-array aggregates now in order to get the value of
-            --  Expansion_Delayed flag for the inner aggregate ???
+            --  At this stage the Expression may not have been analyzed yet
+            --  because the array aggregate code has not been updated to use
+            --  the Expansion_Delayed flag and avoid analysis altogether to
+            --  solve the same problem (see Resolve_Aggr_Expr). So let us do
+            --  the analysis of non-array aggregates now in order to get the
+            --  value of Expansion_Delayed flag for the inner aggregate ???
 
             if Present (Comp_Type) and then not Is_Array_Type (Comp_Type) then
                Analyze_And_Resolve (Expr_Q, Comp_Type);
@@ -1042,7 +1061,7 @@ package body Exp_Aggr is
 
             if Is_Delayed_Aggregate (Expr_Q) then
 
-               --  This is either a subaggregate of a multidimentional array,
+               --  This is either a subaggregate of a multidimensional array,
                --  or a component of an array type whose component type is
                --  also an array. In the latter case, the expression may have
                --  component associations that provide different bounds from
@@ -1062,8 +1081,7 @@ package body Exp_Aggr is
                else
                   return
                     Add_Loop_Actions (
-                      Late_Expansion (
-                        Expr_Q, Etype (Expr_Q), Indexed_Comp, F));
+                      Late_Expansion (Expr_Q, Etype (Expr_Q), Indexed_Comp));
                end if;
             end if;
          end if;
@@ -1096,13 +1114,11 @@ package body Exp_Aggr is
                      Expression => Make_Null (Loc)));
             end if;
 
-            if Controlled_Type (Ctype) then
-               Append_List_To (L,
+            if Needs_Finalization (Ctype) then
+               Append_To (L,
                  Make_Init_Call (
-                   Ref         => New_Copy_Tree (Indexed_Comp),
-                   Typ         => Ctype,
-                   Flist_Ref   => Find_Final_List (Current_Scope),
-                   With_Attach => Make_Integer_Literal (Loc, 1)));
+                   Obj_Ref => New_Copy_Tree (Indexed_Comp),
+                   Typ     => Ctype));
             end if;
 
          else
@@ -1118,7 +1134,7 @@ package body Exp_Aggr is
                 Name       => Indexed_Comp,
                 Expression => New_Copy_Tree (Expr));
 
-            if Present (Comp_Type) and then Controlled_Type (Comp_Type) then
+            if Present (Comp_Type) and then Needs_Finalization (Comp_Type) then
                Set_No_Ctrl_Actions (A);
 
                --  If this is an aggregate for an array of arrays, each
@@ -1145,29 +1161,34 @@ package body Exp_Aggr is
             Append_To (L, A);
 
             --  Adjust the tag if tagged (because of possible view
-            --  conversions), unless compiling for the Java VM where
+            --  conversions), unless compiling for a VM where
             --  tags are implicit.
 
             if Present (Comp_Type)
               and then Is_Tagged_Type (Comp_Type)
-              and then VM_Target = No_VM
+              and then Tagged_Type_Expansion
             then
-               A :=
-                 Make_OK_Assignment_Statement (Loc,
-                   Name =>
-                     Make_Selected_Component (Loc,
-                       Prefix =>  New_Copy_Tree (Indexed_Comp),
-                       Selector_Name =>
-                         New_Reference_To
-                           (First_Tag_Component (Comp_Type), Loc)),
-
-                   Expression =>
-                     Unchecked_Convert_To (RTE (RE_Tag),
-                       New_Reference_To
-                         (Node (First_Elmt (Access_Disp_Table (Comp_Type))),
-                          Loc)));
-
-               Append_To (L, A);
+               declare
+                  Full_Typ : constant Entity_Id := Underlying_Type (Comp_Type);
+
+               begin
+                  A :=
+                    Make_OK_Assignment_Statement (Loc,
+                      Name =>
+                        Make_Selected_Component (Loc,
+                          Prefix =>  New_Copy_Tree (Indexed_Comp),
+                          Selector_Name =>
+                            New_Reference_To
+                              (First_Tag_Component (Full_Typ), Loc)),
+
+                      Expression =>
+                        Unchecked_Convert_To (RTE (RE_Tag),
+                          New_Reference_To
+                            (Node (First_Elmt (Access_Disp_Table (Full_Typ))),
+                             Loc)));
+
+                  Append_To (L, A);
+               end;
             end if;
 
             --  Adjust and attach the component to the proper final list, which
@@ -1182,19 +1203,17 @@ package body Exp_Aggr is
             --  inner finalization actions).
 
             if Present (Comp_Type)
-              and then Controlled_Type (Comp_Type)
+              and then Needs_Finalization (Comp_Type)
               and then not Is_Limited_Type (Comp_Type)
-              and then
-                (not Is_Array_Type (Comp_Type)
-                   or else not Is_Controlled (Component_Type (Comp_Type))
-                   or else Nkind (Expr) /= N_Aggregate)
+              and then not
+                (Is_Array_Type (Comp_Type)
+                   and then Is_Controlled (Component_Type (Comp_Type))
+                   and then Nkind (Expr) = N_Aggregate)
             then
-               Append_List_To (L,
+               Append_To (L,
                  Make_Adjust_Call (
-                   Ref         => New_Copy_Tree (Indexed_Comp),
-                   Typ         => Comp_Type,
-                   Flist_Ref   => F,
-                   With_Attach => Make_Integer_Literal (Loc, 1)));
+                   Obj_Ref => New_Copy_Tree (Indexed_Comp),
+                   Typ     => Comp_Type));
             end if;
          end if;
 
@@ -1208,6 +1227,12 @@ package body Exp_Aggr is
       function Gen_Loop (L, H : Node_Id; Expr : Node_Id) return List_Id is
          L_J : Node_Id;
 
+         L_L : Node_Id;
+         --  Index_Base'(L)
+
+         L_H : Node_Id;
+         --  Index_Base'(H)
+
          L_Range : Node_Id;
          --  Index_Base'(L) .. Index_Base'(H)
 
@@ -1284,21 +1309,34 @@ package body Exp_Aggr is
 
          --  Otherwise construct the loop, starting with the loop index L_J
 
-         L_J := Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
+         L_J := Make_Temporary (Loc, 'J', L);
 
-         --  Construct "L .. H"
+         --  Construct "L .. H" in Index_Base. We use a qualified expression
+         --  for the bound to convert to the index base, but we don't need
+         --  to do that if we already have the base type at hand.
+
+         if Etype (L) = Index_Base then
+            L_L := L;
+         else
+            L_L :=
+              Make_Qualified_Expression (Loc,
+                Subtype_Mark => Index_Base_Name,
+                Expression   => L);
+         end if;
+
+         if Etype (H) = Index_Base then
+            L_H := H;
+         else
+            L_H :=
+              Make_Qualified_Expression (Loc,
+                Subtype_Mark => Index_Base_Name,
+                Expression   => H);
+         end if;
 
          L_Range :=
-           Make_Range
-             (Loc,
-              Low_Bound  => Make_Qualified_Expression
-                              (Loc,
-                               Subtype_Mark => Index_Base_Name,
-                               Expression   => L),
-              High_Bound => Make_Qualified_Expression
-                              (Loc,
-                               Subtype_Mark => Index_Base_Name,
-                               Expression => H));
+           Make_Range (Loc,
+             Low_Bound => L_L,
+             High_Bound => L_H);
 
          --  Construct "for L_J in Index_Base range L .. H"
 
@@ -1379,7 +1417,7 @@ package body Exp_Aggr is
 
          --  Build the decl of W_J
 
-         W_J    := Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
+         W_J    := Make_Temporary (Loc, 'J', L);
          W_Decl :=
            Make_Object_Declaration
              (Loc,
@@ -1521,6 +1559,16 @@ package body Exp_Aggr is
                  Make_Integer_Literal (Loc, Uint_0))));
       end if;
 
+      --  If the component type contains tasks, we need to build a Master
+      --  entity in the current scope, because it will be needed if build-
+      --  in-place functions are called in the expanded code.
+
+      if Nkind (Parent (N)) = N_Object_Declaration
+        and then Has_Task (Typ)
+      then
+         Build_Master_Entity (Defining_Identifier (Parent (N)));
+      end if;
+
       --  STEP 1: Process component associations
 
       --  For those associations that may generate a loop, initialize
@@ -1685,12 +1733,9 @@ package body Exp_Aggr is
    ----------------------------
 
    function Build_Record_Aggr_Code
-     (N                             : Node_Id;
-      Typ                           : Entity_Id;
-      Lhs                           : Node_Id;
-      Flist                         : Node_Id   := Empty;
-      Obj                           : Entity_Id := Empty;
-      Is_Limited_Ancestor_Expansion : Boolean   := False) return List_Id
+     (N   : Node_Id;
+      Typ : Entity_Id;
+      Lhs : Node_Id) return List_Id
    is
       Loc     : constant Source_Ptr := Sloc (N);
       L       : constant List_Id    := New_List;
@@ -1700,14 +1745,11 @@ package body Exp_Aggr is
       Instr     : Node_Id;
       Ref       : Node_Id;
       Target    : Entity_Id;
-      F         : Node_Id;
       Comp_Type : Entity_Id;
       Selector  : Entity_Id;
       Comp_Expr : Node_Id;
       Expr_Q    : Node_Id;
 
-      Internal_Final_List : Node_Id := Empty;
-
       --  If this is an internal aggregate, the External_Final_List is an
       --  expression for the controller record of the enclosing type.
 
@@ -1715,15 +1757,13 @@ package body Exp_Aggr is
       --  expression will appear in several calls to attach to the finali-
       --  zation list, and it must not be shared.
 
-      External_Final_List      : Node_Id;
       Ancestor_Is_Expression   : Boolean := False;
       Ancestor_Is_Subtype_Mark : Boolean := False;
 
       Init_Typ : Entity_Id := Empty;
-      Attach   : Node_Id;
 
-      Ctrl_Stuff_Done : Boolean := False;
-      --  True if Gen_Ctrl_Actions_For_Aggr has already been called; calls
+      Finalization_Done : Boolean := False;
+      --  True if Generate_Finalization_Actions has already been called; calls
       --  after the first do nothing.
 
       function Ancestor_Discriminant_Value (Disc : Entity_Id) return Node_Id;
@@ -1743,7 +1783,7 @@ package body Exp_Aggr is
       --  Return true if Agg_Bounds are equal or within Typ_Bounds. It is
       --  assumed that both bounds are integer ranges.
 
-      procedure Gen_Ctrl_Actions_For_Aggr;
+      procedure Generate_Finalization_Actions;
       --  Deal with the various controlled type data structure initializations
       --  (but only if it hasn't been done already).
 
@@ -1751,16 +1791,10 @@ package body Exp_Aggr is
       --  Returns the first discriminant association in the constraint
       --  associated with T, if any, otherwise returns Empty.
 
-      function Init_Controller
-        (Target  : Node_Id;
-         Typ     : Entity_Id;
-         F       : Node_Id;
-         Attach  : Node_Id;
-         Init_Pr : Boolean) return List_Id;
-      --  Returns the list of statements necessary to initialize the internal
-      --  controller of the (possible) ancestor typ into target and attach it
-      --  to finalization list F. Init_Pr conditions the call to the init proc
-      --  since it may already be done due to ancestor initialization.
+      procedure Init_Hidden_Discriminants (Typ : Entity_Id; List : List_Id);
+      --  If Typ is derived, and constrains discriminants of the parent type,
+      --  these discriminants are not components of the aggregate, and must be
+      --  initialized. The assignments are appended to List.
 
       function Is_Int_Range_Bounds (Bounds : Node_Id) return Boolean;
       --  Check whether Bounds is a range node and its lower and higher bounds
@@ -1817,7 +1851,9 @@ package body Exp_Aggr is
 
          Parent_Typ := Etype (Current_Typ);
          while Current_Typ /= Parent_Typ loop
-            if Has_Discriminants (Parent_Typ) then
+            if Has_Discriminants (Parent_Typ)
+              and then not Has_Unknown_Discriminants (Parent_Typ)
+            then
                Parent_Disc := First_Discriminant (Parent_Typ);
 
                --  We either get the association from the subtype indication
@@ -1949,10 +1985,23 @@ package body Exp_Aggr is
       --------------------------------
 
       function Get_Constraint_Association (T : Entity_Id) return Node_Id is
-         Typ_Def : constant Node_Id := Type_Definition (Parent (T));
-         Indic   : constant Node_Id := Subtype_Indication (Typ_Def);
+         Indic : Node_Id;
+         Typ   : Entity_Id;
 
       begin
+         Typ := T;
+
+         --  Handle private types in instances
+
+         if In_Instance
+           and then Is_Private_Type (Typ)
+           and then Present (Full_View (Typ))
+         then
+            Typ := Full_View (Typ);
+         end if;
+
+         Indic := Subtype_Indication (Type_Definition (Parent (Typ)));
+
          --  ??? Also need to cover case of a type mark denoting a subtype
          --  with constraint.
 
@@ -1965,102 +2014,55 @@ package body Exp_Aggr is
          return Empty;
       end Get_Constraint_Association;
 
-      ---------------------
-      -- Init_Controller --
-      ---------------------
+      -------------------------------
+      -- Init_Hidden_Discriminants --
+      -------------------------------
 
-      function Init_Controller
-        (Target  : Node_Id;
-         Typ     : Entity_Id;
-         F       : Node_Id;
-         Attach  : Node_Id;
-         Init_Pr : Boolean) return List_Id
-      is
-         L           : constant List_Id := New_List;
-         Ref         : Node_Id;
-         RC          : RE_Id;
-         Target_Type : Entity_Id;
+      procedure Init_Hidden_Discriminants (Typ : Entity_Id; List : List_Id) is
+         Btype       : Entity_Id;
+         Parent_Type : Entity_Id;
+         Disc        : Entity_Id;
+         Discr_Val   : Elmt_Id;
 
       begin
-         --  Generate:
-         --     init-proc (target._controller);
-         --     initialize (target._controller);
-         --     Attach_to_Final_List (target._controller, F);
-
-         Ref :=
-           Make_Selected_Component (Loc,
-             Prefix        => Convert_To (Typ, New_Copy_Tree (Target)),
-             Selector_Name => Make_Identifier (Loc, Name_uController));
-         Set_Assignment_OK (Ref);
-
-         --  Ada 2005 (AI-287): Give support to aggregates of limited types.
-         --  If the type is intrinsically limited the controller is limited as
-         --  well. If it is tagged and limited then so is the controller.
-         --  Otherwise an untagged type may have limited components without its
-         --  full view being limited, so the controller is not limited.
-
-         if Nkind (Target) = N_Identifier then
-            Target_Type := Etype (Target);
-
-         elsif Nkind (Target) = N_Selected_Component then
-            Target_Type := Etype (Selector_Name (Target));
-
-         elsif Nkind (Target) = N_Unchecked_Type_Conversion then
-            Target_Type := Etype (Target);
-
-         elsif Nkind (Target) = N_Unchecked_Expression
-           and then Nkind (Expression (Target)) = N_Indexed_Component
-         then
-            Target_Type := Etype (Prefix (Expression (Target)));
-
-         else
-            Target_Type := Etype (Target);
-         end if;
-
-         --  If the target has not been analyzed yet, as will happen with
-         --  delayed expansion, use the given type (either the aggregate type
-         --  or an ancestor) to determine limitedness.
-
-         if No (Target_Type) then
-            Target_Type := Typ;
-         end if;
+         Btype := Base_Type (Typ);
+         while Is_Derived_Type (Btype)
+           and then Present (Stored_Constraint (Btype))
+         loop
+            Parent_Type := Etype (Btype);
 
-         if (Is_Tagged_Type (Target_Type))
-           and then Is_Limited_Type (Target_Type)
-         then
-            RC := RE_Limited_Record_Controller;
+            Disc := First_Discriminant (Parent_Type);
+            Discr_Val := First_Elmt (Stored_Constraint (Base_Type (Typ)));
+            while Present (Discr_Val) loop
 
-         elsif Is_Inherently_Limited_Type (Target_Type) then
-            RC := RE_Limited_Record_Controller;
+               --  Only those discriminants of the parent that are not
+               --  renamed by discriminants of the derived type need to
+               --  be added explicitly.
 
-         else
-            RC := RE_Record_Controller;
-         end if;
+               if not Is_Entity_Name (Node (Discr_Val))
+                 or else Ekind (Entity (Node (Discr_Val))) /= E_Discriminant
+               then
+                  Comp_Expr :=
+                    Make_Selected_Component (Loc,
+                      Prefix        => New_Copy_Tree (Target),
+                      Selector_Name => New_Occurrence_Of (Disc, Loc));
 
-         if Init_Pr then
-            Append_List_To (L,
-              Build_Initialization_Call (Loc,
-                Id_Ref       => Ref,
-                Typ          => RTE (RC),
-                In_Init_Proc => Within_Init_Proc));
-         end if;
+                  Instr :=
+                    Make_OK_Assignment_Statement (Loc,
+                      Name       => Comp_Expr,
+                      Expression => New_Copy_Tree (Node (Discr_Val)));
 
-         Append_To (L,
-           Make_Procedure_Call_Statement (Loc,
-             Name =>
-               New_Reference_To (
-                 Find_Prim_Op (RTE (RC), Name_Initialize), Loc),
-             Parameter_Associations =>
-               New_List (New_Copy_Tree (Ref))));
+                  Set_No_Ctrl_Actions (Instr);
+                  Append_To (List, Instr);
+               end if;
 
-         Append_To (L,
-           Make_Attach_Call (
-             Obj_Ref     => New_Copy_Tree (Ref),
-             Flist_Ref   => F,
-             With_Attach => Attach));
+               Next_Discriminant (Disc);
+               Next_Elmt (Discr_Val);
+            end loop;
 
-         return L;
-      end Init_Controller;
+            Btype := Base_Type (Parent_Type);
+         end loop;
+      end Init_Hidden_Discriminants;
 
       -------------------------
       -- Is_Int_Range_Bounds --
@@ -2073,261 +2075,71 @@ package body Exp_Aggr is
            and then Nkind (High_Bound (Bounds)) = N_Integer_Literal;
       end Is_Int_Range_Bounds;
 
-      -------------------------------
-      -- Gen_Ctrl_Actions_For_Aggr --
-      -------------------------------
-
-      procedure Gen_Ctrl_Actions_For_Aggr is
-         Alloc : Node_Id := Empty;
+      -----------------------------------
+      -- Generate_Finalization_Actions --
+      -----------------------------------
 
+      procedure Generate_Finalization_Actions is
       begin
          --  Do the work only the first time this is called
 
-         if Ctrl_Stuff_Done then
+         if Finalization_Done then
             return;
          end if;
 
-         Ctrl_Stuff_Done := True;
-
-         if Present (Obj)
-           and then Finalize_Storage_Only (Typ)
-           and then
-             (Is_Library_Level_Entity (Obj)
-                or else Entity (Constant_Value (RTE (RE_Garbage_Collected))) =
-                                                          Standard_True)
-
-            --  why not Is_True (Expr_Value (RTE (RE_Garbaage_Collected) ???
-         then
-            Attach := Make_Integer_Literal (Loc, 0);
-
-         elsif Nkind (Parent (N)) = N_Qualified_Expression
-           and then Nkind (Parent (Parent (N))) = N_Allocator
-         then
-            Alloc  := Parent (Parent (N));
-            Attach := Make_Integer_Literal (Loc, 2);
-
-         else
-            Attach := Make_Integer_Literal (Loc, 1);
-         end if;
+         Finalization_Done := True;
 
          --  Determine the external finalization list. It is either the
          --  finalization list of the outer-scope or the one coming from
-         --  an outer aggregate.  When the target is not a temporary, the
+         --  an outer aggregate. When the target is not a temporary, the
          --  proper scope is the scope of the target rather than the
          --  potentially transient current scope.
 
-         if Controlled_Type (Typ) then
-
-            --  The current aggregate belongs to an allocator which creates
-            --  an object through an anonymous access type or acts as the root
-            --  of a coextension chain.
-
-            if Present (Alloc)
-              and then
-                (Is_Coextension_Root (Alloc)
-                   or else Ekind (Etype (Alloc)) = E_Anonymous_Access_Type)
-            then
-               if No (Associated_Final_Chain (Etype (Alloc))) then
-                  Build_Final_List (Alloc, Etype (Alloc));
-               end if;
-
-               External_Final_List :=
-                 Make_Selected_Component (Loc,
-                   Prefix =>
-                     New_Reference_To (
-                       Associated_Final_Chain (Etype (Alloc)), Loc),
-                   Selector_Name =>
-                     Make_Identifier (Loc, Name_F));
-
-            elsif Present (Flist) then
-               External_Final_List := New_Copy_Tree (Flist);
-
-            elsif Is_Entity_Name (Target)
-              and then Present (Scope (Entity (Target)))
-            then
-               External_Final_List :=
-                 Find_Final_List (Scope (Entity (Target)));
-
-            else
-               External_Final_List := Find_Final_List (Current_Scope);
-            end if;
-         else
-            External_Final_List := Empty;
-         end if;
-
-         --  Initialize and attach the outer object in the is_controlled case
-
-         if Is_Controlled (Typ) then
-            if Ancestor_Is_Subtype_Mark then
-               Ref := Convert_To (Init_Typ, New_Copy_Tree (Target));
-               Set_Assignment_OK (Ref);
-               Append_To (L,
-                 Make_Procedure_Call_Statement (Loc,
-                   Name =>
-                     New_Reference_To
-                       (Find_Prim_Op (Init_Typ, Name_Initialize), Loc),
-                   Parameter_Associations => New_List (New_Copy_Tree (Ref))));
-            end if;
-
-            if not Has_Controlled_Component (Typ) then
-               Ref := New_Copy_Tree (Target);
-               Set_Assignment_OK (Ref);
-
-               --  This is an aggregate of a coextension. Do not produce a
-               --  finalization call, but rather attach the reference of the
-               --  aggregate to its coextension chain.
-
-               if Present (Alloc)
-                 and then Is_Dynamic_Coextension (Alloc)
-               then
-                  if No (Coextensions (Alloc)) then
-                     Set_Coextensions (Alloc, New_Elmt_List);
-                  end if;
-
-                  Append_Elmt (Ref, Coextensions (Alloc));
-               else
-                  Append_To (L,
-                    Make_Attach_Call (
-                      Obj_Ref     => Ref,
-                      Flist_Ref   => New_Copy_Tree (External_Final_List),
-                      With_Attach => Attach));
-               end if;
-            end if;
-         end if;
-
-         --  In the Has_Controlled component case, all the intermediate
-         --  controllers must be initialized.
-
-         if Has_Controlled_Component (Typ)
-           and not Is_Limited_Ancestor_Expansion
+         if Is_Controlled (Typ)
+           and then Ancestor_Is_Subtype_Mark
          then
-            declare
-               Inner_Typ : Entity_Id;
-               Outer_Typ : Entity_Id;
-               At_Root   : Boolean;
-
-            begin
-               --  Find outer type with a controller
-
-               Outer_Typ := Base_Type (Typ);
-               while Outer_Typ /= Init_Typ
-                 and then not Has_New_Controlled_Component (Outer_Typ)
-               loop
-                  Outer_Typ := Etype (Outer_Typ);
-               end loop;
-
-               --  Attach it to the outer record controller to the external
-               --  final list.
-
-               if Outer_Typ = Init_Typ then
-                  Append_List_To (L,
-                    Init_Controller (
-                      Target  => Target,
-                      Typ     => Outer_Typ,
-                      F       => External_Final_List,
-                      Attach  => Attach,
-                      Init_Pr => False));
-
-                  At_Root   := True;
-                  Inner_Typ := Init_Typ;
-
-               else
-                  Append_List_To (L,
-                    Init_Controller (
-                      Target  => Target,
-                      Typ     => Outer_Typ,
-                      F       => External_Final_List,
-                      Attach  => Attach,
-                      Init_Pr => True));
-
-                  Inner_Typ := Etype (Outer_Typ);
-                  At_Root   :=
-                    not Is_Tagged_Type (Typ) or else Inner_Typ = Outer_Typ;
-               end if;
-
-               --  The outer object has to be attached as well
-
-               if Is_Controlled (Typ) then
-                  Ref := New_Copy_Tree (Target);
-                  Set_Assignment_OK (Ref);
-                  Append_To (L,
-                    Make_Attach_Call (
-                      Obj_Ref     => Ref,
-                      Flist_Ref   => New_Copy_Tree (External_Final_List),
-                      With_Attach => New_Copy_Tree (Attach)));
-               end if;
-
-               --  Initialize the internal controllers for tagged types with
-               --  more than one controller.
-
-               while not At_Root and then Inner_Typ /= Init_Typ loop
-                  if Has_New_Controlled_Component (Inner_Typ) then
-                     F :=
-                       Make_Selected_Component (Loc,
-                         Prefix =>
-                           Convert_To (Outer_Typ, New_Copy_Tree (Target)),
-                         Selector_Name =>
-                           Make_Identifier (Loc, Name_uController));
-                     F :=
-                       Make_Selected_Component (Loc,
-                         Prefix => F,
-                         Selector_Name => Make_Identifier (Loc, Name_F));
-
-                     Append_List_To (L,
-                       Init_Controller (
-                         Target  => Target,
-                         Typ     => Inner_Typ,
-                         F       => F,
-                         Attach  => Make_Integer_Literal (Loc, 1),
-                         Init_Pr => True));
-                     Outer_Typ := Inner_Typ;
-                  end if;
-
-                  --  Stop at the root
-
-                  At_Root := Inner_Typ = Etype (Inner_Typ);
-                  Inner_Typ := Etype (Inner_Typ);
-               end loop;
-
-               --  If not done yet attach the controller of the ancestor part
-
-               if Outer_Typ /= Init_Typ
-                 and then Inner_Typ = Init_Typ
-                 and then Has_Controlled_Component (Init_Typ)
-               then
-                  F :=
-                    Make_Selected_Component (Loc,
-                      Prefix => Convert_To (Outer_Typ, New_Copy_Tree (Target)),
-                      Selector_Name =>
-                        Make_Identifier (Loc, Name_uController));
-                  F :=
-                    Make_Selected_Component (Loc,
-                      Prefix => F,
-                      Selector_Name => Make_Identifier (Loc, Name_F));
-
-                  Attach := Make_Integer_Literal (Loc, 1);
-                  Append_List_To (L,
-                    Init_Controller (
-                      Target  => Target,
-                      Typ     => Init_Typ,
-                      F       => F,
-                      Attach  => Attach,
-                      Init_Pr => False));
-
-                     --  Note: Init_Pr is False because the ancestor part has
-                     --  already been initialized either way (by default, if
-                     --  given by a type name, otherwise from the expression).
-
-               end if;
-            end;
+            Ref := Convert_To (Init_Typ, New_Copy_Tree (Target));
+            Set_Assignment_OK (Ref);
+
+            Append_To (L,
+              Make_Procedure_Call_Statement (Loc,
+                Name =>
+                  New_Reference_To
+                    (Find_Prim_Op (Init_Typ, Name_Initialize), Loc),
+                Parameter_Associations => New_List (New_Copy_Tree (Ref))));
          end if;
-      end Gen_Ctrl_Actions_For_Aggr;
+      end Generate_Finalization_Actions;
+
+      function Rewrite_Discriminant (Expr : Node_Id) return Traverse_Result;
+      --  If default expression of a component mentions a discriminant of the
+      --  type, it must be rewritten as the discriminant of the target object.
 
       function Replace_Type (Expr : Node_Id) return Traverse_Result;
       --  If the aggregate contains a self-reference, traverse each expression
       --  to replace a possible self-reference with a reference to the proper
       --  component of the target of the assignment.
 
+      --------------------------
+      -- Rewrite_Discriminant --
+      --------------------------
+
+      function Rewrite_Discriminant (Expr : Node_Id) return Traverse_Result is
+      begin
+         if Is_Entity_Name (Expr)
+           and then Present (Entity (Expr))
+           and then Ekind (Entity (Expr)) = E_In_Parameter
+           and then Present (Discriminal_Link (Entity (Expr)))
+           and then Scope (Discriminal_Link (Entity (Expr)))
+                      = Base_Type (Etype (N))
+         then
+            Rewrite (Expr,
+              Make_Selected_Component (Loc,
+                Prefix        => New_Copy_Tree (Lhs),
+                Selector_Name => Make_Identifier (Loc, Chars (Expr))));
+         end if;
+         return OK;
+      end Rewrite_Discriminant;
+
       ------------------
       -- Replace_Type --
       ------------------
@@ -2356,7 +2168,7 @@ package body Exp_Aggr is
                Rewrite (Expr,
                  Make_Attribute_Reference (Loc,
                    Attribute_Name => Name_Unrestricted_Access,
-                   Prefix         => New_Copy_Tree (Prefix (Lhs))));
+                   Prefix         => New_Copy_Tree (Lhs)));
                Set_Analyzed (Parent (Expr), False);
 
             else
@@ -2374,6 +2186,9 @@ package body Exp_Aggr is
       procedure Replace_Self_Reference is
         new Traverse_Proc (Replace_Type);
 
+      procedure Replace_Discriminants is
+        new Traverse_Proc (Rewrite_Discriminant);
+
    --  Start of processing for Build_Record_Aggr_Code
 
    begin
@@ -2386,7 +2201,7 @@ package body Exp_Aggr is
       --  are visible. We know already that the types are compatible.
 
       if Present (Etype (Lhs))
-        and then Is_Interface (Etype (Lhs))
+        and then Is_Class_Wide_Type (Etype (Lhs))
       then
          Target := Unchecked_Convert_To (Typ, Lhs);
       else
@@ -2398,21 +2213,23 @@ package body Exp_Aggr is
 
       if Nkind (N) = N_Extension_Aggregate then
          declare
-            A      : constant Node_Id := Ancestor_Part (N);
-            Assign : List_Id;
+            Ancestor : constant Node_Id := Ancestor_Part (N);
+            Assign   : List_Id;
 
          begin
             --  If the ancestor part is a subtype mark "T", we generate
 
-            --     init-proc (T(tmp));  if T is constrained and
-            --     init-proc (S(tmp));  where S applies an appropriate
-            --                          constraint if T is unconstrained
+            --     init-proc (T (tmp));  if T is constrained and
+            --     init-proc (S (tmp));  where S applies an appropriate
+            --                           constraint if T is unconstrained
 
-            if Is_Entity_Name (A) and then Is_Type (Entity (A)) then
+            if Is_Entity_Name (Ancestor)
+              and then Is_Type (Entity (Ancestor))
+            then
                Ancestor_Is_Subtype_Mark := True;
 
-               if Is_Constrained (Entity (A)) then
-                  Init_Typ := Entity (A);
+               if Is_Constrained (Entity (Ancestor)) then
+                  Init_Typ := Entity (Ancestor);
 
                --  For an ancestor part given by an unconstrained type mark,
                --  create a subtype constrained by appropriate corresponding
@@ -2421,9 +2238,9 @@ package body Exp_Aggr is
                --  be used to generate the correct default value for the
                --  ancestor part.
 
-               elsif Has_Discriminants (Entity (A)) then
+               elsif Has_Discriminants (Entity (Ancestor)) then
                   declare
-                     Anc_Typ    : constant Entity_Id := Entity (A);
+                     Anc_Typ    : constant Entity_Id := Entity (Ancestor);
                      Anc_Constr : constant List_Id   := New_List;
                      Discrim    : Entity_Id;
                      Disc_Value : Node_Id;
@@ -2464,41 +2281,50 @@ package body Exp_Aggr is
                Ref := Convert_To (Init_Typ, New_Copy_Tree (Target));
                Set_Assignment_OK (Ref);
 
-               if Has_Default_Init_Comps (N)
-                 or else Has_Task (Base_Type (Init_Typ))
-               then
+               if not Is_Interface (Init_Typ) then
                   Append_List_To (L,
                     Build_Initialization_Call (Loc,
-                      Id_Ref       => Ref,
-                      Typ          => Init_Typ,
-                      In_Init_Proc => Within_Init_Proc,
-                      With_Default_Init => True));
-               else
-                  Append_List_To (L,
-                    Build_Initialization_Call (Loc,
-                      Id_Ref       => Ref,
-                      Typ          => Init_Typ,
-                      In_Init_Proc => Within_Init_Proc));
+                      Id_Ref            => Ref,
+                      Typ               => Init_Typ,
+                      In_Init_Proc      => Within_Init_Proc,
+                      With_Default_Init => Has_Default_Init_Comps (N)
+                                             or else
+                                           Has_Task (Base_Type (Init_Typ))));
+
+                  if Is_Constrained (Entity (Ancestor))
+                    and then Has_Discriminants (Entity (Ancestor))
+                  then
+                     Check_Ancestor_Discriminants (Entity (Ancestor));
+                  end if;
                end if;
 
-               if Is_Constrained (Entity (A))
-                 and then Has_Discriminants (Entity (A))
-               then
-                  Check_Ancestor_Discriminants (Entity (A));
-               end if;
+            --  Handle calls to C++ constructors
+
+            elsif Is_CPP_Constructor_Call (Ancestor) then
+               Init_Typ := Etype (Ancestor);
+               Ref := Convert_To (Init_Typ, New_Copy_Tree (Target));
+               Set_Assignment_OK (Ref);
+
+               Append_List_To (L,
+                 Build_Initialization_Call (Loc,
+                   Id_Ref            => Ref,
+                   Typ               => Init_Typ,
+                   In_Init_Proc      => Within_Init_Proc,
+                   With_Default_Init => Has_Default_Init_Comps (N),
+                   Constructor_Ref   => Ancestor));
 
             --  Ada 2005 (AI-287): If the ancestor part is an aggregate of
             --  limited type, a recursive call expands the ancestor. Note that
             --  in the limited case, the ancestor part must be either a
             --  function call (possibly qualified, or wrapped in an unchecked
             --  conversion) or aggregate (definitely qualified).
+            --  The ancestor part can also be a function call (that may be
+            --  transformed into an explicit dereference) or a qualification
+            --  of one such.
 
-            elsif Is_Limited_Type (Etype (A))
-              and then Nkind (Unqualify (A)) /= N_Function_Call --  aggregate?
-              and then
-                (Nkind (Unqualify (A)) /= N_Unchecked_Type_Conversion
-                   or else
-                 Nkind (Expression (Unqualify (A))) /= N_Function_Call)
+            elsif Is_Limited_Type (Etype (Ancestor))
+              and then Nkind_In (Unqualify (Ancestor), N_Aggregate,
+                                                    N_Extension_Aggregate)
             then
                Ancestor_Is_Expression := True;
 
@@ -2506,20 +2332,17 @@ package body Exp_Aggr is
                --  controlled subcomponents of the ancestor part will be
                --  attached to it.
 
-               Gen_Ctrl_Actions_For_Aggr;
+               Generate_Finalization_Actions;
 
                Append_List_To (L,
-                  Build_Record_Aggr_Code (
-                    N                             => Unqualify (A),
-                    Typ                           => Etype (Unqualify (A)),
-                    Lhs                           => Target,
-                    Flist                         => Flist,
-                    Obj                           => Obj,
-                    Is_Limited_Ancestor_Expansion => True));
+                  Build_Record_Aggr_Code
+                    (N   => Unqualify (Ancestor),
+                     Typ => Etype (Unqualify (Ancestor)),
+                     Lhs => Target));
 
             --  If the ancestor part is an expression "E", we generate
 
-            --     T(tmp) := E;
+            --     T (tmp) := E;
 
             --  In Ada 2005, this includes the case of a (possibly qualified)
             --  limited function call. The assignment will turn into a
@@ -2528,16 +2351,16 @@ package body Exp_Aggr is
 
             else
                Ancestor_Is_Expression := True;
-               Init_Typ := Etype (A);
+               Init_Typ := Etype (Ancestor);
 
                --  If the ancestor part is an aggregate, force its full
                --  expansion, which was delayed.
 
-               if Nkind (Unqualify (A)) = N_Aggregate
-                 or else Nkind (Unqualify (A)) = N_Extension_Aggregate
+               if Nkind_In (Unqualify (Ancestor), N_Aggregate,
+                                               N_Extension_Aggregate)
                then
-                  Set_Analyzed (A, False);
-                  Set_Analyzed (Expression (A), False);
+                  Set_Analyzed (Ancestor, False);
+                  Set_Analyzed (Expression (Ancestor), False);
                end if;
 
                Ref := Convert_To (Init_Typ, New_Copy_Tree (Target));
@@ -2550,14 +2373,14 @@ package body Exp_Aggr is
                Assign := New_List (
                  Make_OK_Assignment_Statement (Loc,
                    Name       => Ref,
-                   Expression => A));
+                   Expression => Ancestor));
                Set_No_Ctrl_Actions (First (Assign));
 
                --  Assign the tag now to make sure that the dispatching call in
                --  the subsequent deep_adjust works properly (unless VM_Target,
                --  where tags are implicit).
 
-               if VM_Target = No_VM then
+               if Tagged_Type_Expansion then
                   Instr :=
                     Make_OK_Assignment_Statement (Loc,
                       Name =>
@@ -2590,16 +2413,13 @@ package body Exp_Aggr is
 
                --  Call Adjust manually
 
-               if Controlled_Type (Etype (A))
-                 and then not Is_Limited_Type (Etype (A))
+               if Needs_Finalization (Etype (Ancestor))
+                 and then not Is_Limited_Type (Etype (Ancestor))
                then
-                  Append_List_To (Assign,
+                  Append_To (Assign,
                     Make_Adjust_Call (
-                      Ref         => New_Copy_Tree (Ref),
-                      Typ         => Etype (A),
-                      Flist_Ref   => New_Reference_To (
-                        RTE (RE_Global_Final_List), Loc),
-                      With_Attach => Make_Integer_Literal (Loc, 0)));
+                      Obj_Ref => New_Copy_Tree (Ref),
+                      Typ     => Etype (Ancestor)));
                end if;
 
                Append_To (L,
@@ -2611,6 +2431,17 @@ package body Exp_Aggr is
             end if;
          end;
 
+         --  Generate assignments of hidden assignments. If the base type is an
+         --  unchecked union, the discriminants are unknown to the back-end and
+         --  absent from a value of the type, so assignments for them are not
+         --  emitted.
+
+         if Has_Discriminants (Typ)
+           and then not Is_Unchecked_Union (Base_Type (Typ))
+         then
+            Init_Hidden_Discriminants (Typ, L);
+         end if;
+
       --  Normal case (not an extension aggregate)
 
       else
@@ -2622,59 +2453,7 @@ package body Exp_Aggr is
          if Has_Discriminants (Typ)
            and then not Is_Unchecked_Union (Base_Type (Typ))
          then
-            --  If the type is derived, and constrains discriminants of the
-            --  parent type, these discriminants are not components of the
-            --  aggregate, and must be initialized explicitly. They are not
-            --  visible components of the object, but can become visible with
-            --  a view conversion to the ancestor.
-
-            declare
-               Btype      : Entity_Id;
-               Parent_Type : Entity_Id;
-               Disc        : Entity_Id;
-               Discr_Val   : Elmt_Id;
-
-            begin
-               Btype := Base_Type (Typ);
-               while Is_Derived_Type (Btype)
-                  and then Present (Stored_Constraint (Btype))
-               loop
-                  Parent_Type := Etype (Btype);
-
-                  Disc := First_Discriminant (Parent_Type);
-                  Discr_Val :=
-                    First_Elmt (Stored_Constraint (Base_Type (Typ)));
-                  while Present (Discr_Val) loop
-
-                     --  Only those discriminants of the parent that are not
-                     --  renamed by discriminants of the derived type need to
-                     --  be added explicitly.
-
-                     if not Is_Entity_Name (Node (Discr_Val))
-                       or else
-                         Ekind (Entity (Node (Discr_Val))) /= E_Discriminant
-                     then
-                        Comp_Expr :=
-                          Make_Selected_Component (Loc,
-                            Prefix        => New_Copy_Tree (Target),
-                            Selector_Name => New_Occurrence_Of (Disc, Loc));
-
-                        Instr :=
-                          Make_OK_Assignment_Statement (Loc,
-                            Name       => Comp_Expr,
-                            Expression => New_Copy_Tree (Node (Discr_Val)));
-
-                        Set_No_Ctrl_Actions (Instr);
-                        Append_To (L, Instr);
-                     end if;
-
-                     Next_Discriminant (Disc);
-                     Next_Elmt (Discr_Val);
-                  end loop;
-
-                  Btype := Base_Type (Parent_Type);
-               end loop;
-            end;
+            Init_Hidden_Discriminants (Typ, L);
 
             --  Generate discriminant init values for the visible discriminants
 
@@ -2701,13 +2480,74 @@ package body Exp_Aggr is
                       Name       => Comp_Expr,
                       Expression => New_Copy_Tree (Discriminant_Value));
 
-                  Set_No_Ctrl_Actions (Instr);
-                  Append_To (L, Instr);
+                  Set_No_Ctrl_Actions (Instr);
+                  Append_To (L, Instr);
+
+                  Next_Stored_Discriminant (Discriminant);
+               end loop;
+            end;
+         end if;
+      end if;
+
+      --  For CPP types we generate an implicit call to the C++ default
+      --  constructor to ensure the proper initialization of the _Tag
+      --  component.
+
+      if Is_CPP_Class (Root_Type (Typ))
+        and then CPP_Num_Prims (Typ) > 0
+      then
+         Invoke_Constructor : declare
+            CPP_Parent : constant Entity_Id :=
+                           Enclosing_CPP_Parent (Typ);
+
+            procedure Invoke_IC_Proc (T : Entity_Id);
+            --  Recursive routine used to climb to parents. Required because
+            --  parents must be initialized before descendants to ensure
+            --  propagation of inherited C++ slots.
+
+            --------------------
+            -- Invoke_IC_Proc --
+            --------------------
+
+            procedure Invoke_IC_Proc (T : Entity_Id) is
+            begin
+               --  Avoid generating extra calls. Initialization required
+               --  only for types defined from the level of derivation of
+               --  type of the constructor and the type of the aggregate.
+
+               if T = CPP_Parent then
+                  return;
+               end if;
+
+               Invoke_IC_Proc (Etype (T));
+
+               --  Generate call to the IC routine
+
+               if Present (CPP_Init_Proc (T)) then
+                  Append_To (L,
+                    Make_Procedure_Call_Statement (Loc,
+                      New_Reference_To (CPP_Init_Proc (T), Loc)));
+               end if;
+            end Invoke_IC_Proc;
+
+         --  Start of processing for Invoke_Constructor
+
+         begin
+            --  Implicit invocation of the C++ constructor
+
+            if Nkind (N) = N_Aggregate then
+               Append_To (L,
+                 Make_Procedure_Call_Statement (Loc,
+                   Name =>
+                     New_Reference_To
+                       (Base_Init_Proc (CPP_Parent), Loc),
+                   Parameter_Associations => New_List (
+                     Unchecked_Convert_To (CPP_Parent,
+                       New_Copy_Tree (Lhs)))));
+            end if;
 
-                  Next_Stored_Discriminant (Discriminant);
-               end loop;
-            end;
-         end if;
+            Invoke_IC_Proc (Typ);
+         end Invoke_Constructor;
       end if;
 
       --  Generate the assignments, component by component
@@ -2720,14 +2560,28 @@ package body Exp_Aggr is
       while Present (Comp) loop
          Selector := Entity (First (Choices (Comp)));
 
+         --  C++ constructors
+
+         if Is_CPP_Constructor_Call (Expression (Comp)) then
+            Append_List_To (L,
+              Build_Initialization_Call (Loc,
+                Id_Ref            => Make_Selected_Component (Loc,
+                                       Prefix        => New_Copy_Tree (Target),
+                                       Selector_Name =>
+                                         New_Occurrence_Of (Selector, Loc)),
+                Typ               => Etype (Selector),
+                Enclos_Type       => Typ,
+                With_Default_Init => True,
+                Constructor_Ref   => Expression (Comp)));
+
          --  Ada 2005 (AI-287): For each default-initialized component generate
          --  a call to the corresponding IP subprogram if available.
 
-         if Box_Present (Comp)
+         elsif Box_Present (Comp)
            and then Has_Non_Null_Base_Init_Proc (Etype (Selector))
          then
             if Ekind (Selector) /= E_Discriminant then
-               Gen_Ctrl_Actions_For_Aggr;
+               Generate_Finalization_Actions;
             end if;
 
             --  Ada 2005 (AI-287): If the component type has tasks then
@@ -2737,8 +2591,8 @@ package body Exp_Aggr is
 
             declare
                Ctype            : constant Entity_Id := Etype (Selector);
-               Inside_Allocator : Boolean   := False;
-               P                : Node_Id   := Parent (N);
+               Inside_Allocator : Boolean            := False;
+               P                : Node_Id            := Parent (N);
 
             begin
                if Is_Task_Type (Ctype) or else Has_Task (Ctype) then
@@ -2759,20 +2613,17 @@ package body Exp_Aggr is
 
             Append_List_To (L,
               Build_Initialization_Call (Loc,
-                Id_Ref => Make_Selected_Component (Loc,
-                            Prefix => New_Copy_Tree (Target),
-                            Selector_Name => New_Occurrence_Of (Selector,
-                                                                   Loc)),
-                Typ    => Etype (Selector),
-                Enclos_Type => Typ,
+                Id_Ref            => Make_Selected_Component (Loc,
+                                       Prefix        => New_Copy_Tree (Target),
+                                       Selector_Name =>
+                                         New_Occurrence_Of (Selector, Loc)),
+                Typ               => Etype (Selector),
+                Enclos_Type       => Typ,
                 With_Default_Init => True));
 
-            goto Next_Comp;
-         end if;
-
          --  Prepare for component assignment
 
-         if Ekind (Selector) /= E_Discriminant
+         elsif Ekind (Selector) /= E_Discriminant
            or else Nkind (N) = N_Extension_Aggregate
          then
             --  All the discriminants have now been assigned
@@ -2781,10 +2632,10 @@ package body Exp_Aggr is
             --  controllers. Their position may depend on the discriminants.
 
             if Ekind (Selector) /= E_Discriminant then
-               Gen_Ctrl_Actions_For_Aggr;
+               Generate_Finalization_Actions;
             end if;
 
-            Comp_Type := Etype (Selector);
+            Comp_Type := Underlying_Type (Etype (Selector));
             Comp_Expr :=
               Make_Selected_Component (Loc,
                 Prefix        => New_Copy_Tree (Target),
@@ -2796,31 +2647,6 @@ package body Exp_Aggr is
                Expr_Q := Expression (Comp);
             end if;
 
-            --  The controller is the one of the parent type defining the
-            --  component (in case of inherited components).
-
-            if Controlled_Type (Comp_Type) then
-               Internal_Final_List :=
-                 Make_Selected_Component (Loc,
-                   Prefix => Convert_To (
-                     Scope (Original_Record_Component (Selector)),
-                     New_Copy_Tree (Target)),
-                   Selector_Name =>
-                     Make_Identifier (Loc, Name_uController));
-
-               Internal_Final_List :=
-                 Make_Selected_Component (Loc,
-                   Prefix => Internal_Final_List,
-                   Selector_Name => Make_Identifier (Loc, Name_F));
-
-               --  The internal final list can be part of a constant object
-
-               Set_Assignment_OK (Internal_Final_List);
-
-            else
-               Internal_Final_List := Empty;
-            end if;
-
             --  Now either create the assignment or generate the code for the
             --  inner aggregate top-down.
 
@@ -2862,35 +2688,31 @@ package body Exp_Aggr is
                   --  the corresponding aggregate.
 
                   declare
-                     SubE : constant Entity_Id :=
-                              Make_Defining_Identifier (Loc,
-                                New_Internal_Name ('T'));
+                     SubE : constant Entity_Id := Make_Temporary (Loc, 'T');
 
                      SubD : constant Node_Id :=
                               Make_Subtype_Declaration (Loc,
-                                Defining_Identifier =>
-                                  SubE,
+                                Defining_Identifier => SubE,
                                 Subtype_Indication  =>
                                   Make_Subtype_Indication (Loc,
-                                    Subtype_Mark => New_Reference_To (
-                                      Etype (Comp_Type), Loc),
+                                    Subtype_Mark =>
+                                      New_Reference_To
+                                        (Etype (Comp_Type), Loc),
                                     Constraint =>
-                                      Make_Index_Or_Discriminant_Constraint (
-                                        Loc, Constraints => New_List (
-                                          New_Copy_Tree (Aggregate_Bounds (
-                                            Expr_Q))))));
+                                      Make_Index_Or_Discriminant_Constraint
+                                        (Loc,
+                                         Constraints => New_List (
+                                          New_Copy_Tree
+                                            (Aggregate_Bounds (Expr_Q))))));
 
                      --  Create a temporary array of the above subtype which
                      --  will be used to capture the aggregate assignments.
 
-                     TmpE : constant Entity_Id :=
-                              Make_Defining_Identifier (Loc,
-                                New_Internal_Name ('A'));
+                     TmpE : constant Entity_Id := Make_Temporary (Loc, 'A', N);
 
                      TmpD : constant Node_Id :=
                               Make_Object_Declaration (Loc,
-                                Defining_Identifier =>
-                                  TmpE,
+                                Defining_Identifier => TmpE,
                                 Object_Definition   =>
                                   New_Reference_To (SubE, Loc));
 
@@ -2903,7 +2725,7 @@ package body Exp_Aggr is
 
                      Append_List_To (L,
                        Late_Expansion (Expr_Q, Comp_Type,
-                         New_Reference_To (TmpE, Loc), Internal_Final_List));
+                         New_Reference_To (TmpE, Loc)));
 
                      --  Slide
 
@@ -2911,32 +2733,26 @@ package body Exp_Aggr is
                        Make_Assignment_Statement (Loc,
                          Name       => New_Copy_Tree (Comp_Expr),
                          Expression => New_Reference_To (TmpE, Loc)));
-
-                     --  Do not pass the original aggregate to Gigi as is,
-                     --  since it will potentially clobber the front or the end
-                     --  of the array. Setting the expression to empty is safe
-                     --  since all aggregates are expanded into assignments.
-
-                     if Present (Obj) then
-                        Set_Expression (Parent (Obj), Empty);
-                     end if;
                   end;
 
                --  Normal case (sliding not required)
 
                else
                   Append_List_To (L,
-                    Late_Expansion (Expr_Q, Comp_Type, Comp_Expr,
-                      Internal_Final_List));
+                    Late_Expansion (Expr_Q, Comp_Type, Comp_Expr));
                end if;
 
             --  Expr_Q is not delayed aggregate
 
             else
+               if Has_Discriminants (Typ) then
+                  Replace_Discriminants (Expr_Q);
+               end if;
+
                Instr :=
                  Make_OK_Assignment_Statement (Loc,
                    Name       => Comp_Expr,
-                   Expression => Expression (Comp));
+                   Expression => Expr_Q);
 
                Set_No_Ctrl_Actions (Instr);
                Append_To (L, Instr);
@@ -2947,7 +2763,9 @@ package body Exp_Aggr is
 
                --    tmp.comp._tag := comp_typ'tag;
 
-               if Is_Tagged_Type (Comp_Type) and then VM_Target = No_VM then
+               if Is_Tagged_Type (Comp_Type)
+                 and then Tagged_Type_Expansion
+               then
                   Instr :=
                     Make_OK_Assignment_Statement (Loc,
                       Name =>
@@ -2966,21 +2784,16 @@ package body Exp_Aggr is
                   Append_To (L, Instr);
                end if;
 
-               --  Adjust and Attach the component to the proper controller
+               --  Generate:
+               --    Adjust (tmp.comp);
 
-               --     Adjust (tmp.comp);
-               --     Attach_To_Final_List (tmp.comp,
-               --       comp_typ (tmp)._record_controller.f)
-
-               if Controlled_Type (Comp_Type)
+               if Needs_Finalization (Comp_Type)
                  and then not Is_Limited_Type (Comp_Type)
                then
-                  Append_List_To (L,
+                  Append_To (L,
                     Make_Adjust_Call (
-                      Ref         => New_Copy_Tree (Comp_Expr),
-                      Typ         => Comp_Type,
-                      Flist_Ref   => Internal_Final_List,
-                      With_Attach => Make_Integer_Literal (Loc, 1)));
+                      Obj_Ref => New_Copy_Tree (Comp_Expr),
+                      Typ     => Comp_Type));
                end if;
             end if;
 
@@ -3052,8 +2865,6 @@ package body Exp_Aggr is
             end;
          end if;
 
-         <<Next_Comp>>
-
          Next (Comp);
       end loop;
 
@@ -3065,7 +2876,14 @@ package body Exp_Aggr is
       if Ancestor_Is_Expression then
          null;
 
-      elsif Is_Tagged_Type (Typ) and then VM_Target = No_VM then
+      --  For CPP types we generated a call to the C++ default constructor
+      --  before the components have been initialized to ensure the proper
+      --  initialization of the _Tag component (see above).
+
+      elsif Is_CPP_Class (Typ) then
+         null;
+
+      elsif Is_Tagged_Type (Typ) and then Tagged_Type_Expansion then
          Instr :=
            Make_OK_Assignment_Statement (Loc,
              Name =>
@@ -3098,7 +2916,7 @@ package body Exp_Aggr is
       --  If the controllers have not been initialized yet (by lack of non-
       --  discriminant components), let's do it now.
 
-      Gen_Ctrl_Actions_For_Aggr;
+      Generate_Finalization_Actions;
 
       return L;
    end Build_Record_Aggr_Code;
@@ -3121,34 +2939,7 @@ package body Exp_Aggr is
                  Make_Explicit_Dereference (Loc,
                    New_Reference_To (Temp, Loc)));
 
-      Access_Type : constant Entity_Id := Etype (Temp);
-      Flist       : Entity_Id;
-
    begin
-      --  If the allocator is for an access discriminant, there is no
-      --  finalization list for the anonymous access type, and the eventual
-      --  finalization of the object is handled through the coextension
-      --  mechanism. If the enclosing object is not dynamically allocated,
-      --  the access discriminant is itself placed on the stack. Otherwise,
-      --  some other finalization list is used (see exp_ch4.adb).
-
-      --  Decl has been inserted in the code ahead of the allocator, using
-      --  Insert_Actions. We use Insert_Actions below as well, to ensure that
-      --  subsequent insertions are done in the proper order. Using (for
-      --  example) Insert_Actions_After to place the expanded aggregate
-      --  immediately after Decl may lead to out-of-order references if the
-      --  allocator has generated a finalization list, as when the designated
-      --  object is controlled and there is an open transient scope.
-
-      if Ekind (Access_Type) = E_Anonymous_Access_Type
-        and then Nkind (Associated_Node_For_Itype (Access_Type)) =
-                                              N_Discriminant_Specification
-      then
-         Flist := Empty;
-      else
-         Flist := Find_Final_List (Access_Type);
-      end if;
-
       if Is_Array_Type (Typ) then
          Convert_Array_Aggr_In_Allocator (Decl, Aggr, Occ);
 
@@ -3158,14 +2949,7 @@ package body Exp_Aggr is
             Init_Stmts : List_Id;
 
          begin
-            Init_Stmts :=
-              Late_Expansion
-                (Aggr, Typ, Occ,
-                 Flist,
-                 Associated_Final_Chain (Base_Type (Access_Type)));
-
-            --  ??? Dubious actual for Obj: expect 'the original object being
-            --  initialized'
+            Init_Stmts := Late_Expansion (Aggr, Typ, Occ);
 
             if Has_Task (Typ) then
                Build_Task_Allocate_Block_With_Init_Stmts (L, Aggr, Init_Stmts);
@@ -3176,14 +2960,7 @@ package body Exp_Aggr is
          end;
 
       else
-         Insert_Actions (Alloc,
-           Late_Expansion
-             (Aggr, Typ, Occ, Flist,
-              Associated_Final_Chain (Base_Type (Access_Type))));
-
-         --  ??? Dubious actual for Obj: expect 'the original object being
-         --  initialized'
-
+         Insert_Actions (Alloc, Late_Expansion (Aggr, Typ, Occ));
       end if;
    end Convert_Aggr_In_Allocator;
 
@@ -3201,10 +2978,7 @@ package body Exp_Aggr is
          Aggr := Expression (Aggr);
       end if;
 
-      Insert_Actions_After (N,
-        Late_Expansion
-          (Aggr, Typ, Occ,
-           Find_Final_List (Typ, New_Copy_Tree (Occ))));
+      Insert_Actions_After (N, Late_Expansion (Aggr, Typ, Occ));
    end Convert_Aggr_In_Assignment;
 
    ---------------------------------
@@ -3323,7 +3097,7 @@ package body Exp_Aggr is
               Is_Controlled (Typ) or else Has_Controlled_Component (Typ));
       end if;
 
-      Insert_Actions_After (N, Late_Expansion (Aggr, Typ, Occ, Obj => Obj));
+      Insert_Actions_After (N, Late_Expansion (Aggr, Typ, Occ));
       Set_No_Initialization (N);
       Initialize_Discriminants (N, Typ);
    end Convert_Aggr_In_Object_Decl;
@@ -3362,6 +3136,7 @@ package body Exp_Aggr is
 
    procedure Convert_To_Assignments (N : Node_Id; Typ : Entity_Id) is
       Loc  : constant Source_Ptr := Sloc (N);
+      T    : Entity_Id;
       Temp : Entity_Id;
 
       Instr       : Node_Id;
@@ -3435,10 +3210,10 @@ package body Exp_Aggr is
          --  in place within the caller's scope).
 
          or else
-           (Is_Inherently_Limited_Type (Typ)
+           (Is_Immutably_Limited_Type (Typ)
              and then
                (Nkind (Parent (Parent_Node)) = N_Extended_Return_Statement
-                  or else Nkind (Parent_Node) = N_Simple_Return_Statement))
+                 or else Nkind (Parent_Node) = N_Simple_Return_Statement))
       then
          Set_Expansion_Delayed (N);
          return;
@@ -3450,34 +3225,45 @@ package body Exp_Aggr is
                  Is_Controlled (Typ) or else Has_Controlled_Component (Typ));
       end if;
 
-      --  If the aggregate is non-limited, create a temporary. If it is
-      --  limited and the context is an assignment, this is a subaggregate
-      --  for an enclosing aggregate being expanded. It must be built in place,
-      --  so use the target of the current assignment.
+      --  If the aggregate is non-limited, create a temporary. If it is limited
+      --  and the context is an assignment, this is a subaggregate for an
+      --  enclosing aggregate being expanded. It must be built in place, so use
+      --  the target of the current assignment.
 
       if Is_Limited_Type (Typ)
         and then Nkind (Parent (N)) = N_Assignment_Statement
       then
          Target_Expr := New_Copy_Tree (Name (Parent (N)));
-         Insert_Actions
-           (Parent (N), Build_Record_Aggr_Code (N, Typ, Target_Expr));
+         Insert_Actions (Parent (N),
+           Build_Record_Aggr_Code (N, Typ, Target_Expr));
          Rewrite (Parent (N), Make_Null_Statement (Loc));
 
       else
-         Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
+         Temp := Make_Temporary (Loc, 'A', N);
+
+         --  If the type inherits unknown discriminants, use the view with
+         --  known discriminants if available.
+
+         if Has_Unknown_Discriminants (Typ)
+            and then Present (Underlying_Record_View (Typ))
+         then
+            T := Underlying_Record_View (Typ);
+         else
+            T := Typ;
+         end if;
 
          Instr :=
            Make_Object_Declaration (Loc,
              Defining_Identifier => Temp,
-             Object_Definition   => New_Occurrence_Of (Typ, Loc));
+             Object_Definition   => New_Occurrence_Of (T, Loc));
 
          Set_No_Initialization (Instr);
          Insert_Action (N, Instr);
-         Initialize_Discriminants (Instr, Typ);
+         Initialize_Discriminants (Instr, T);
          Target_Expr := New_Occurrence_Of (Temp, Loc);
-         Insert_Actions (N, Build_Record_Aggr_Code (N, Typ, Target_Expr));
+         Insert_Actions (N, Build_Record_Aggr_Code (N, T, Target_Expr));
          Rewrite (N, New_Occurrence_Of (Temp, Loc));
-         Analyze_And_Resolve (N, Typ);
+         Analyze_And_Resolve (N, T);
       end if;
    end Convert_To_Assignments;
 
@@ -3508,8 +3294,8 @@ package body Exp_Aggr is
       --  total number of components is safe enough to expand.
 
       function Is_Flat (N : Node_Id; Dims : Int) return Boolean;
-      --  Return True iff the array N is flat (which is not rivial in the case
-      --  of multidimensionsl aggregates).
+      --  Return True iff the array N is flat (which is not trivial in the case
+      --  of multidimensional aggregates).
 
       -----------------------------
       -- Check_Static_Components --
@@ -3544,12 +3330,20 @@ package body Exp_Aggr is
          then
             Expr := First (Component_Associations (N));
             while Present (Expr) loop
-               if Nkind (Expression (Expr)) = N_Integer_Literal then
+               if Nkind_In (Expression (Expr), N_Integer_Literal,
+                                               N_Real_Literal)
+               then
+                  null;
+
+               elsif Is_Entity_Name (Expression (Expr))
+                 and then Present (Entity (Expression (Expr)))
+                 and then Ekind (Entity (Expression (Expr))) =
+                   E_Enumeration_Literal
+               then
                   null;
 
                elsif Nkind (Expression (Expr)) /= N_Aggregate
-                 or else
-                   not Compile_Time_Known_Aggregate (Expression (Expr))
+                 or else not Compile_Time_Known_Aggregate (Expression (Expr))
                  or else Expansion_Delayed (Expression (Expr))
                then
                   Static_Components := False;
@@ -3577,6 +3371,8 @@ package body Exp_Aggr is
          Lov : Uint;
          Hiv : Uint;
 
+         Others_Present : Boolean := False;
+
       begin
          if Nkind (Original_Node (N)) = N_String_Literal then
             return True;
@@ -3591,8 +3387,53 @@ package body Exp_Aggr is
          Lov := Expr_Value (Lo);
          Hiv := Expr_Value (Hi);
 
+         --  Check if there is an others choice
+
+         if Present (Component_Associations (N)) then
+            declare
+               Assoc   : Node_Id;
+               Choice  : Node_Id;
+
+            begin
+               Assoc := First (Component_Associations (N));
+               while Present (Assoc) loop
+
+                  --  If this is a box association, flattening is in general
+                  --  not possible because at this point we cannot tell if the
+                  --  default is static or even exists.
+
+                  if Box_Present (Assoc) then
+                     return False;
+                  end if;
+
+                  Choice := First (Choices (Assoc));
+
+                  while Present (Choice) loop
+                     if Nkind (Choice) = N_Others_Choice then
+                        Others_Present := True;
+                     end if;
+
+                     Next (Choice);
+                  end loop;
+
+                  Next (Assoc);
+               end loop;
+            end;
+         end if;
+
+         --  If the low bound is not known at compile time and others is not
+         --  present we can proceed since the bounds can be obtained from the
+         --  aggregate.
+
+         --  Note: This case is required in VM platforms since their backends
+         --  normalize array indexes in the range 0 .. N-1. Hence, if we do
+         --  not flat an array whose bounds cannot be obtained from the type
+         --  of the index the backend has no way to properly generate the code.
+         --  See ACATS c460010 for an example.
+
          if Hiv < Lov
-           or else not Compile_Time_Known_Value (Blo)
+           or else (not Compile_Time_Known_Value (Blo)
+                     and then Others_Present)
          then
             return False;
          end if;
@@ -3611,10 +3452,11 @@ package body Exp_Aggr is
             Rep_Count : Nat;
             --  Used to validate Max_Others_Replicate limit
 
-            Elmt   : Node_Id;
-            Num    : Int := UI_To_Int (Lov);
-            Choice : Node_Id;
-            Lo, Hi : Node_Id;
+            Elmt         : Node_Id;
+            Num          : Int := UI_To_Int (Lov);
+            Choice_Index : Int;
+            Choice       : Node_Id;
+            Lo, Hi       : Node_Id;
 
          begin
             if Present (Expressions (N)) then
@@ -3623,7 +3465,7 @@ package body Exp_Aggr is
                   if Nkind (Elmt) = N_Aggregate
                     and then Present (Next_Index (Ix))
                     and then
-                         not Flatten (Elmt, Next_Index (Ix), Next_Index (Ixb))
+                      not Flatten (Elmt, Next_Index (Ix), Next_Index (Ixb))
                   then
                      return False;
                   end if;
@@ -3669,24 +3511,43 @@ package body Exp_Aggr is
                            --  Check for maximum others replication. Note that
                            --  we skip this test if either of the restrictions
                            --  No_Elaboration_Code or No_Implicit_Loops is
-                           --  active, or if this is a preelaborable unit.
+                           --  active, if this is a preelaborable unit or a
+                           --  predefined unit. This ensures that predefined
+                           --  units get the same level of constant folding in
+                           --  Ada 95 and Ada 2005, where their categorization
+                           --  has changed.
 
                            declare
                               P : constant Entity_Id :=
                                     Cunit_Entity (Current_Sem_Unit);
 
                            begin
+                              --  Check if duplication OK and if so continue
+                              --  processing.
+
                               if Restriction_Active (No_Elaboration_Code)
                                 or else Restriction_Active (No_Implicit_Loops)
                                 or else Is_Preelaborated (P)
                                 or else (Ekind (P) = E_Package_Body
                                           and then
                                             Is_Preelaborated (Spec_Entity (P)))
+                                or else
+                                  Is_Predefined_File_Name
+                                    (Unit_File_Name (Get_Source_Unit (P)))
                               then
                                  null;
 
+                              --  If duplication not OK, then we return False
+                              --  if the replication count is too high
+
                               elsif Rep_Count > Max_Others_Replicate then
                                  return False;
+
+                              --  Continue on if duplication not OK, but the
+                              --  replication count is not excessive.
+
+                              else
+                                 null;
                               end if;
                            end;
                         end if;
@@ -3694,9 +3555,9 @@ package body Exp_Aggr is
 
                      exit Component_Loop;
 
-                  --  Case of a subtype mark
+                  --  Case of a subtype mark, identifier or expanded name
 
-                  elsif Nkind (Choice) = N_Identifier
+                  elsif Is_Entity_Name (Choice)
                     and then Is_Type (Entity (Choice))
                   then
                      Lo := Type_Low_Bound  (Etype (Choice));
@@ -3721,13 +3582,22 @@ package body Exp_Aggr is
                         return False;
 
                      else
-                        Vals (UI_To_Int (Expr_Value (Choice))) :=
-                          New_Copy_Tree (Expression (Elmt));
-                        goto Continue;
+                        Choice_Index := UI_To_Int (Expr_Value (Choice));
+                        if Choice_Index in Vals'Range then
+                           Vals (Choice_Index) :=
+                             New_Copy_Tree (Expression (Elmt));
+                           goto Continue;
+
+                        else
+                           --  Choice is statically out-of-range, will be
+                           --  rewritten to raise Constraint_Error.
+
+                           return False;
+                        end if;
                      end if;
                   end if;
 
-                  --  Range cases merge with Lo,Hi said
+                  --  Range cases merge with Lo,Hi set
 
                   if not Compile_Time_Known_Value (Lo)
                        or else
@@ -3837,7 +3707,7 @@ package body Exp_Aggr is
       --  assignments to the target anyway, but it is conceivable that
       --  it will eventually be able to treat such aggregates statically???
 
-      if Aggr_Size_OK (Typ)
+      if Aggr_Size_OK (N, Typ)
         and then Flatten (N, First_Index (Typ), First_Index (Base_Type (Typ)))
       then
          if Static_Components then
@@ -3930,12 +3800,6 @@ package body Exp_Aggr is
       --  array sub-aggregate we start the computation from. Dim is the
       --  dimension corresponding to the sub-aggregate.
 
-      function Has_Address_Clause (D : Node_Id) return Boolean;
-      --  If the aggregate is the expression in an object declaration, it
-      --  cannot be expanded in place. This function does a lookahead in the
-      --  current declarative part to find an address clause for the object
-      --  being declared.
-
       function In_Place_Assign_OK return Boolean;
       --  Simple predicate to determine whether an aggregate assignment can
       --  be done in place, because none of the new values can depend on the
@@ -3947,25 +3811,26 @@ package body Exp_Aggr is
       --  Sub_Aggr is an array sub-aggregate. Dim is the dimension
       --  corresponding to the sub-aggregate.
 
+      function Safe_Left_Hand_Side (N : Node_Id) return Boolean;
+      --  In addition to Maybe_In_Place_OK, in order for an aggregate to be
+      --  built directly into the target of the assignment it must be free
+      --  of side-effects.
+
       ----------------------------
       -- Build_Constrained_Type --
       ----------------------------
 
       procedure Build_Constrained_Type (Positional : Boolean) is
          Loc      : constant Source_Ptr := Sloc (N);
-         Agg_Type : Entity_Id;
+         Agg_Type : constant Entity_Id  := Make_Temporary (Loc, 'A');
          Comp     : Node_Id;
          Decl     : Node_Id;
          Typ      : constant Entity_Id := Etype (N);
-         Indices  : constant List_Id   := New_List;
+         Indexes  : constant List_Id   := New_List;
          Num      : Int;
          Sub_Agg  : Node_Id;
 
       begin
-         Agg_Type :=
-           Make_Defining_Identifier (
-             Loc, New_Internal_Name ('A'));
-
          --  If the aggregate is purely positional, all its subaggregates
          --  have the same size. We collect the dimensions from the first
          --  subaggregate at each level.
@@ -3983,26 +3848,23 @@ package body Exp_Aggr is
                   Next (Comp);
                end loop;
 
-               Append (
+               Append_To (Indexes,
                  Make_Range (Loc,
-                   Low_Bound => Make_Integer_Literal (Loc, 1),
-                   High_Bound =>
-                          Make_Integer_Literal (Loc, Num)),
-                 Indices);
+                   Low_Bound =>  Make_Integer_Literal (Loc, 1),
+                   High_Bound => Make_Integer_Literal (Loc, Num)));
             end loop;
 
          else
             --  We know the aggregate type is unconstrained and the aggregate
             --  is not processable by the back end, therefore not necessarily
             --  positional. Retrieve each dimension bounds (computed earlier).
-            --  earlier.
 
             for D in 1 .. Number_Dimensions (Typ) loop
                Append (
                  Make_Range (Loc,
                     Low_Bound  => Aggr_Low  (D),
                     High_Bound => Aggr_High (D)),
-                 Indices);
+                 Indexes);
             end loop;
          end if;
 
@@ -4011,10 +3873,10 @@ package body Exp_Aggr is
                Defining_Identifier => Agg_Type,
                Type_Definition =>
                  Make_Constrained_Array_Definition (Loc,
-                   Discrete_Subtype_Definitions => Indices,
-                   Component_Definition =>
+                   Discrete_Subtype_Definitions => Indexes,
+                   Component_Definition         =>
                      Make_Component_Definition (Loc,
-                       Aliased_Present => False,
+                       Aliased_Present    => False,
                        Subtype_Indication =>
                          New_Occurrence_Of (Component_Type (Typ), Loc))));
 
@@ -4243,35 +4105,6 @@ package body Exp_Aggr is
       end Compute_Others_Present;
 
       ------------------------
-      -- Has_Address_Clause --
-      ------------------------
-
-      function Has_Address_Clause (D : Node_Id) return Boolean is
-         Id   : constant Entity_Id := Defining_Identifier (D);
-         Decl : Node_Id;
-
-      begin
-         Decl := Next (D);
-         while Present (Decl) loop
-            if Nkind (Decl) = N_At_Clause
-               and then Chars (Identifier (Decl)) = Chars (Id)
-            then
-               return True;
-
-            elsif Nkind (Decl) = N_Attribute_Definition_Clause
-               and then Chars (Decl) = Name_Address
-               and then Chars (Name (Decl)) = Chars (Id)
-            then
-               return True;
-            end if;
-
-            Next (Decl);
-         end loop;
-
-         return False;
-      end Has_Address_Clause;
-
-      ------------------------
       -- In_Place_Assign_OK --
       ------------------------
 
@@ -4283,10 +4116,6 @@ package body Exp_Aggr is
          Obj_Lo  : Node_Id;
          Obj_Hi  : Node_Id;
 
-         function Is_Others_Aggregate (Aggr : Node_Id) return Boolean;
-         --  Aggregates that consist of a single Others choice are safe
-         --  if the single expression is.
-
          function Safe_Aggregate (Aggr : Node_Id) return Boolean;
          --  Check recursively that each component of a (sub)aggregate does
          --  not depend on the variable being assigned to.
@@ -4295,18 +4124,6 @@ package body Exp_Aggr is
          --  Verify that an expression cannot depend on the variable being
          --  assigned to. Room for improvement here (but less than before).
 
-         -------------------------
-         -- Is_Others_Aggregate --
-         -------------------------
-
-         function Is_Others_Aggregate (Aggr : Node_Id) return Boolean is
-         begin
-            return No (Expressions (Aggr))
-              and then Nkind
-                (First (Choices (First (Component_Associations (Aggr)))))
-                  = N_Others_Choice;
-         end Is_Others_Aggregate;
-
          --------------------
          -- Safe_Aggregate --
          --------------------
@@ -4339,6 +4156,12 @@ package body Exp_Aggr is
                         return False;
                      end if;
 
+                  --  If association has a box, no way to determine yet
+                  --  whether default can be assigned in place.
+
+                  elsif Box_Present (Expr) then
+                     return False;
+
                   elsif not Safe_Component (Expression (Expr)) then
                      return False;
                   end if;
@@ -4451,6 +4274,7 @@ package body Exp_Aggr is
             end if;
 
             Aggr_In := First_Index (Etype (N));
+
             if Nkind (Parent (N)) = N_Assignment_Statement then
                Obj_In  := First_Index (Etype (Name (Parent (N))));
 
@@ -4710,7 +4534,71 @@ package body Exp_Aggr is
          end if;
       end Others_Check;
 
-      --  Remaining Expand_Array_Aggregate variables
+      -------------------------
+      -- Safe_Left_Hand_Side --
+      -------------------------
+
+      function Safe_Left_Hand_Side (N : Node_Id) return Boolean is
+         function Is_Safe_Index (Indx : Node_Id) return Boolean;
+         --  If the left-hand side includes an indexed component, check that
+         --  the indexes are free of side-effect.
+
+         -------------------
+         -- Is_Safe_Index --
+         -------------------
+
+         function Is_Safe_Index (Indx : Node_Id) return Boolean is
+         begin
+            if Is_Entity_Name (Indx) then
+               return True;
+
+            elsif Nkind (Indx) = N_Integer_Literal then
+               return True;
+
+            elsif Nkind (Indx) = N_Function_Call
+              and then Is_Entity_Name (Name (Indx))
+              and then
+                Has_Pragma_Pure_Function (Entity (Name (Indx)))
+            then
+               return True;
+
+            elsif Nkind (Indx) = N_Type_Conversion
+              and then Is_Safe_Index (Expression (Indx))
+            then
+               return True;
+
+            else
+               return False;
+            end if;
+         end Is_Safe_Index;
+
+      --  Start of processing for Safe_Left_Hand_Side
+
+      begin
+         if Is_Entity_Name (N) then
+            return True;
+
+         elsif Nkind_In (N, N_Explicit_Dereference, N_Selected_Component)
+           and then Safe_Left_Hand_Side (Prefix (N))
+         then
+            return True;
+
+         elsif Nkind (N) = N_Indexed_Component
+           and then Safe_Left_Hand_Side (Prefix (N))
+           and then
+             Is_Safe_Index (First (Expressions (N)))
+         then
+            return True;
+
+         elsif Nkind (N) = N_Unchecked_Type_Conversion then
+            return Safe_Left_Hand_Side (Expression (N));
+
+         else
+            return False;
+         end if;
+      end Safe_Left_Hand_Side;
+
+      --  Local variables
 
       Tmp : Entity_Id;
       --  Holds the temporary aggregate value
@@ -4731,10 +4619,25 @@ package body Exp_Aggr is
         or else Is_RTE (Ctyp, RE_Asm_Output_Operand)
       then
          return;
+
+      --  Do not expand an aggregate for an array type which contains tasks if
+      --  the aggregate is associated with an unexpanded return statement of a
+      --  build-in-place function. The aggregate is expanded when the related
+      --  return statement (rewritten into an extended return) is processed.
+      --  This delay ensures that any temporaries and initialization code
+      --  generated for the aggregate appear in the proper return block and
+      --  use the correct _chain and _master.
+
+      elsif Has_Task (Base_Type (Etype (N)))
+        and then Nkind (Parent (N)) = N_Simple_Return_Statement
+        and then Is_Build_In_Place_Function
+                   (Return_Applies_To (Return_Statement_Entity (Parent (N))))
+      then
+         return;
       end if;
 
       --  If the semantic analyzer has determined that aggregate N will raise
-      --  Constraint_Error at run-time, then the aggregate node has been
+      --  Constraint_Error at run time, then the aggregate node has been
       --  replaced with an N_Raise_Constraint_Error node and we should
       --  never get here.
 
@@ -4821,7 +4724,6 @@ package body Exp_Aggr is
         and then Static_Elaboration_Desired (Current_Scope)
       then
          Convert_To_Positional (N, Max_Others_Replicate => 100);
-
       else
          Convert_To_Positional (N);
       end if;
@@ -4891,8 +4793,8 @@ package body Exp_Aggr is
 
       --  STEP 3
 
-      --  Delay expansion for nested aggregates it will be taken care of
-      --  when the parent aggregate is expanded
+      --  Delay expansion for nested aggregates: it will be taken care of
+      --  when the parent aggregate is expanded.
 
       Parent_Node := Parent (N);
       Parent_Kind := Nkind (Parent_Node);
@@ -4906,7 +4808,7 @@ package body Exp_Aggr is
         or else Parent_Kind = N_Extension_Aggregate
         or else Parent_Kind = N_Component_Association
         or else (Parent_Kind = N_Object_Declaration
-                  and then Controlled_Type (Typ))
+                  and then Needs_Finalization (Typ))
         or else (Parent_Kind = N_Assignment_Statement
                   and then Inside_Init_Proc)
       then
@@ -4954,21 +4856,23 @@ package body Exp_Aggr is
       else
          Maybe_In_Place_OK :=
           (Nkind (Parent (N)) = N_Assignment_Statement
-             and then Comes_From_Source (N)
-             and then In_Place_Assign_OK)
+            and then Comes_From_Source (N)
+            and then In_Place_Assign_OK)
 
           or else
             (Nkind (Parent (Parent (N))) = N_Allocator
               and then In_Place_Assign_OK);
       end if;
 
-      --  If  this is an array of tasks, it will be expanded into build-in-
-      --  -place assignments. Build an activation chain for the tasks now
+      --  If this is an array of tasks, it will be expanded into build-in-place
+      --  assignments. Build an activation chain for the tasks now.
 
       if Has_Task (Etype (N)) then
          Build_Activation_Chain_Entity (N);
       end if;
 
+      --  Should document these individual tests ???
+
       if not Has_Default_Init_Comps (N)
          and then Comes_From_Source (Parent (N))
          and then Nkind (Parent (N)) = N_Object_Declaration
@@ -4977,7 +4881,13 @@ package body Exp_Aggr is
          and then N = Expression (Parent (N))
          and then not Is_Bit_Packed_Array (Typ)
          and then not Has_Controlled_Component (Typ)
-         and then not Has_Address_Clause (Parent (N))
+
+      --  If the aggregate is the expression in an object declaration, it
+      --  cannot be expanded in place. Lookahead in the current declarative
+      --  part to find an address clause for the object being declared. If
+      --  one is present, we cannot build in place. Unclear comment???
+
+         and then not Has_Following_Address_Clause (Parent (N))
       then
          Tmp := Defining_Identifier (Parent (N));
          Set_No_Initialization (Parent (N));
@@ -5010,9 +4920,9 @@ package body Exp_Aggr is
       --  In the remaining cases the aggregate is the RHS of an assignment
 
       elsif Maybe_In_Place_OK
-        and then Is_Entity_Name (Name (Parent (N)))
+        and then Safe_Left_Hand_Side (Name (Parent (N)))
       then
-         Tmp := Entity (Name (Parent (N)));
+         Tmp := Name (Parent (N));
 
          if Etype (Tmp) /= Etype (N) then
             Apply_Length_Check (N, Etype (Tmp));
@@ -5026,16 +4936,6 @@ package body Exp_Aggr is
          end if;
 
       elsif Maybe_In_Place_OK
-        and then Nkind (Name (Parent (N))) = N_Explicit_Dereference
-        and then Is_Entity_Name (Prefix (Name (Parent (N))))
-      then
-         Tmp := Name (Parent (N));
-
-         if Etype (Tmp) /= Etype (N) then
-            Apply_Length_Check (N, Etype (Tmp));
-         end if;
-
-      elsif Maybe_In_Place_OK
         and then Nkind (Name (Parent (N))) = N_Slice
         and then Safe_Slice_Assignment (N)
       then
@@ -5049,7 +4949,7 @@ package body Exp_Aggr is
 
       else
          Maybe_In_Place_OK := False;
-         Tmp := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
+         Tmp := Make_Temporary (Loc, 'A', N);
          Tmp_Decl :=
            Make_Object_Declaration
              (Loc,
@@ -5058,8 +4958,8 @@ package body Exp_Aggr is
          Set_No_Initialization (Tmp_Decl, True);
 
          --  If we are within a loop, the temporary will be pushed on the
-         --  stack at each iteration. If the aggregate is the expression for
-         --  an allocator, it will be immediately copied to the heap and can
+         --  stack at each iteration. If the aggregate is the expression for an
+         --  allocator, it will be immediately copied to the heap and can
          --  be reclaimed at once. We create a transient scope around the
          --  aggregate for this purpose.
 
@@ -5072,9 +4972,9 @@ package body Exp_Aggr is
          Insert_Action (N, Tmp_Decl);
       end if;
 
-      --  Construct and insert the aggregate code. We can safely suppress
-      --  index checks because this code is guaranteed not to raise CE
-      --  on index checks. However we should *not* suppress all checks.
+      --  Construct and insert the aggregate code. We can safely suppress index
+      --  checks because this code is guaranteed not to raise CE on index
+      --  checks. However we should *not* suppress all checks.
 
       declare
          Target : Node_Id;
@@ -5172,21 +5072,22 @@ package body Exp_Aggr is
       --  of the following form (c1 and c2 are inherited components)
 
       --   (Exp with c3 => a, c4 => b)
-      --      ==> (c1 => Exp.c1, c2 => Exp.c2, c1 => a, c2 => b)
+      --      ==> (c1 => Exp.c1, c2 => Exp.c2, c3 => a, c4 => b)
 
       else
          Set_Etype (N, Typ);
 
-         if VM_Target = No_VM then
+         if Tagged_Type_Expansion then
             Expand_Record_Aggregate (N,
               Orig_Tag    =>
                 New_Occurrence_Of
                   (Node (First_Elmt (Access_Disp_Table (Typ))), Loc),
               Parent_Expr => A);
+
+         --  No tag is needed in the case of a VM
+
          else
-            --  No tag is needed in the case of a VM
-            Expand_Record_Aggregate (N,
-              Parent_Expr => A);
+            Expand_Record_Aggregate (N, Parent_Expr => A);
          end if;
       end if;
 
@@ -5214,6 +5115,14 @@ package body Exp_Aggr is
       --  and the aggregate can be constructed statically and handled by
       --  the back-end.
 
+      function Compile_Time_Known_Composite_Value (N : Node_Id) return Boolean;
+      --  Returns true if N is an expression of composite type which can be
+      --  fully evaluated at compile time without raising constraint error.
+      --  Such expressions can be passed as is to Gigi without any expansion.
+      --
+      --  This returns true for N_Aggregate with Compile_Time_Known_Aggregate
+      --  set and constants whose expression is such an aggregate, recursively.
+
       function Component_Not_OK_For_Backend return Boolean;
       --  Check for presence of component which makes it impossible for the
       --  backend to process the aggregate, thus requiring the use of a series
@@ -5234,6 +5143,55 @@ package body Exp_Aggr is
       --  semantics of Ada complicate the analysis and lead to anomalies in
       --  the gcc back-end if the aggregate is not expanded into assignments.
 
+      function Has_Visible_Private_Ancestor (Id : E) return Boolean;
+      --  If any ancestor of the current type is private, the aggregate
+      --  cannot be built in place. We canot rely on Has_Private_Ancestor,
+      --  because it will not be set when type and its parent are in the
+      --  same scope, and the parent component needs expansion.
+
+      function Top_Level_Aggregate (N : Node_Id) return Node_Id;
+      --  For nested aggregates return the ultimate enclosing aggregate; for
+      --  non-nested aggregates return N.
+
+      ----------------------------------------
+      -- Compile_Time_Known_Composite_Value --
+      ----------------------------------------
+
+      function Compile_Time_Known_Composite_Value
+        (N : Node_Id) return Boolean
+      is
+      begin
+         --  If we have an entity name, then see if it is the name of a
+         --  constant and if so, test the corresponding constant value.
+
+         if Is_Entity_Name (N) then
+            declare
+               E : constant Entity_Id := Entity (N);
+               V : Node_Id;
+            begin
+               if Ekind (E) /= E_Constant then
+                  return False;
+               else
+                  V := Constant_Value (E);
+                  return Present (V)
+                    and then Compile_Time_Known_Composite_Value (V);
+               end if;
+            end;
+
+         --  We have a value, see if it is compile time known
+
+         else
+            if Nkind (N) = N_Aggregate then
+               return Compile_Time_Known_Aggregate (N);
+            end if;
+
+            --  All other types of values are not known at compile time
+
+            return False;
+         end if;
+
+      end Compile_Time_Known_Composite_Value;
+
       ----------------------------------
       -- Component_Not_OK_For_Backend --
       ----------------------------------
@@ -5249,6 +5207,14 @@ package body Exp_Aggr is
 
          C := First (Comps);
          while Present (C) loop
+
+            --  If the component has box initialization, expansion is needed
+            --  and component is not ready for backend.
+
+            if Box_Present (C) then
+               return True;
+            end if;
+
             if Nkind (Expression (C)) = N_Qualified_Expression then
                Expr_Q := Expression (Expression (C));
             else
@@ -5268,7 +5234,7 @@ package body Exp_Aggr is
                          or else (Is_Entity_Name (Expr_Q)
                                     and then
                                       Ekind (Entity (Expr_Q)) in Formal_Kind))
-              and then VM_Target = No_VM
+              and then Tagged_Type_Expansion
             then
                Static_Components := False;
                return True;
@@ -5282,14 +5248,12 @@ package body Exp_Aggr is
                return True;
             end if;
 
-            if Is_Scalar_Type (Etype (Expr_Q)) then
+            if Is_Elementary_Type (Etype (Expr_Q)) then
                if not Compile_Time_Known_Value (Expr_Q) then
                   Static_Components := False;
                end if;
 
-            elsif Nkind (Expr_Q) /= N_Aggregate
-              or else not Compile_Time_Known_Aggregate (Expr_Q)
-            then
+            elsif not Compile_Time_Known_Composite_Value (Expr_Q) then
                Static_Components := False;
 
                if Is_Private_Type (Etype (Expr_Q))
@@ -5305,11 +5269,53 @@ package body Exp_Aggr is
          return False;
       end Component_Not_OK_For_Backend;
 
-      --  Remaining Expand_Record_Aggregate variables
+      -----------------------------------
+      --  Has_Visible_Private_Ancestor --
+      -----------------------------------
+
+      function Has_Visible_Private_Ancestor (Id : E) return Boolean is
+         R  : constant Entity_Id := Root_Type (Id);
+         T1 : Entity_Id := Id;
+
+      begin
+         loop
+            if Is_Private_Type (T1) then
+               return True;
+
+            elsif T1 = R then
+               return False;
+
+            else
+               T1 := Etype (T1);
+            end if;
+         end loop;
+      end Has_Visible_Private_Ancestor;
+
+      -------------------------
+      -- Top_Level_Aggregate --
+      -------------------------
+
+      function Top_Level_Aggregate (N : Node_Id) return Node_Id is
+         Aggr : Node_Id;
+
+      begin
+         Aggr := N;
+         while Present (Parent (Aggr))
+           and then Nkind_In (Parent (Aggr), N_Component_Association,
+                                             N_Aggregate)
+         loop
+            Aggr := Parent (Aggr);
+         end loop;
+
+         return Aggr;
+      end Top_Level_Aggregate;
+
+      --  Local variables
 
-      Tag_Value : Node_Id;
-      Comp      : Entity_Id;
-      New_Comp  : Node_Id;
+      Top_Level_Aggr : constant Node_Id := Top_Level_Aggregate (N);
+      Tag_Value      : Node_Id;
+      Comp           : Entity_Id;
+      New_Comp       : Node_Id;
 
    --  Start of processing for Expand_Record_Aggregate
 
@@ -5321,11 +5327,9 @@ package body Exp_Aggr is
       --  an atomic move for it.
 
       if Is_Atomic (Typ)
-        and then (Nkind (Parent (N)) = N_Object_Declaration
-                    or else Nkind (Parent (N)) = N_Assignment_Statement)
         and then Comes_From_Source (Parent (N))
+        and then Is_Atomic_Aggregate (N, Typ)
       then
-         Expand_Atomic_Aggregate (N, Typ);
          return;
 
       --  No special management required for aggregates used to initialize
@@ -5336,23 +5340,46 @@ package body Exp_Aggr is
       end if;
 
       --  Ada 2005 (AI-318-2): We need to convert to assignments if components
-      --  are build-in-place function calls. This test could be more specific,
-      --  but doing it for all inherently limited aggregates seems harmless.
-      --  The assignments will turn into build-in-place function calls (see
-      --  Make_Build_In_Place_Call_In_Assignment).
+      --  are build-in-place function calls. The assignments will each turn
+      --  into a build-in-place function call. If components are all static,
+      --  we can pass the aggregate to the backend regardless of limitedness.
 
-      if Ada_Version >= Ada_05 and then Is_Inherently_Limited_Type (Typ) then
-         Convert_To_Assignments (N, Typ);
+      --  Extension aggregates, aggregates in extended return statements, and
+      --  aggregates for C++ imported types must be expanded.
+
+      if Ada_Version >= Ada_2005 and then Is_Immutably_Limited_Type (Typ) then
+         if not Nkind_In (Parent (N), N_Object_Declaration,
+                                      N_Component_Association)
+         then
+            Convert_To_Assignments (N, Typ);
+
+         elsif Nkind (N) = N_Extension_Aggregate
+           or else Convention (Typ) = Convention_CPP
+         then
+            Convert_To_Assignments (N, Typ);
+
+         elsif not Size_Known_At_Compile_Time (Typ)
+           or else Component_Not_OK_For_Backend
+           or else not Static_Components
+         then
+            Convert_To_Assignments (N, Typ);
+
+         else
+            Set_Compile_Time_Known_Aggregate (N);
+            Set_Expansion_Delayed (N, False);
+         end if;
 
-      --  Gigi doesn't handle properly temporaries of variable size
-      --  so we generate it in the front-end
+      --  Gigi doesn't properly handle temporaries of variable size so we
+      --  generate it in the front-end
 
-      elsif not Size_Known_At_Compile_Time (Typ) then
+      elsif not Size_Known_At_Compile_Time (Typ)
+        and then Tagged_Type_Expansion
+      then
          Convert_To_Assignments (N, Typ);
 
-      --  Temporaries for controlled aggregates need to be attached to a
-      --  final chain in order to be properly finalized, so it has to
-      --  be created in the front-end
+      --  Temporaries for controlled aggregates need to be attached to a final
+      --  chain in order to be properly finalized, so it has to be created in
+      --  the front-end
 
       elsif Is_Controlled (Typ)
         or else Has_Controlled_Component (Base_Type (Typ))
@@ -5370,10 +5397,10 @@ package body Exp_Aggr is
       elsif Component_Not_OK_For_Backend then
          Convert_To_Assignments (N, Typ);
 
-      --  If an ancestor is private, some components are not inherited and
-      --  we cannot expand into a record aggregate
+      --  If an ancestor is private, some components are not inherited and we
+      --  cannot expand into a record aggregate.
 
-      elsif Has_Private_Ancestor (Typ) then
+      elsif Has_Visible_Private_Ancestor (Typ) then
          Convert_To_Assignments (N, Typ);
 
       --  ??? The following was done to compile fxacc00.ads in the ACVCs. Gigi
@@ -5391,9 +5418,16 @@ package body Exp_Aggr is
       --  If some components are mutable, the size of the aggregate component
       --  may be distinct from the default size of the type component, so
       --  we need to expand to insure that the back-end copies the proper
-      --  size of the data.
-
-      elsif Has_Mutable_Components (Typ) then
+      --  size of the data. However, if the aggregate is the initial value of
+      --  a constant, the target is immutable and might be built statically
+      --  if components are appropriate.
+
+      elsif Has_Mutable_Components (Typ)
+        and then
+          (Nkind (Parent (Top_Level_Aggr)) /= N_Object_Declaration
+            or else not Constant_Present (Parent (Top_Level_Aggr))
+            or else not Static_Components)
+      then
          Convert_To_Assignments (N, Typ);
 
       --  If the type involved has any non-bit aligned components, then we are
@@ -5425,7 +5459,7 @@ package body Exp_Aggr is
 
          elsif Is_Derived_Type (Typ) then
 
-            --  For untagged types,  non-stored discriminants are replaced
+            --  For untagged types, non-stored discriminants are replaced
             --  with stored discriminants, which are the ones that gigi uses
             --  to describe the type and its components.
 
@@ -5529,9 +5563,7 @@ package body Exp_Aggr is
 
                   Decl :=
                     Make_Subtype_Declaration (Loc,
-                      Defining_Identifier =>
-                         Make_Defining_Identifier (Loc,
-                            New_Internal_Name ('T')),
+                      Defining_Identifier => Make_Temporary (Loc, 'T'),
                       Subtype_Indication =>
                         Make_Subtype_Indication (Loc,
                           Subtype_Mark =>
@@ -5561,16 +5593,16 @@ package body Exp_Aggr is
 
          if Is_Tagged_Type (Typ) then
 
-            --  The tagged case, _parent and _tag component must be created
+            --  In the tagged case, _parent and _tag component must be created
 
-            --  Reset null_present unconditionally. tagged records always have
-            --  at least one field (the tag or the parent)
+            --  Reset Null_Present unconditionally. Tagged records always have
+            --  at least one field (the tag or the parent).
 
             Set_Null_Record_Present (N, False);
 
             --  When the current aggregate comes from the expansion of an
             --  extension aggregate, the parent expr is replaced by an
-            --  aggregate formed by selected components of this expr
+            --  aggregate formed by selected components of this expr.
 
             if Present (Parent_Expr)
               and then Is_Empty_List (Comps)
@@ -5610,11 +5642,11 @@ package body Exp_Aggr is
 
             --  Compute the value for the Tag now, if the type is a root it
             --  will be included in the aggregate right away, otherwise it will
-            --  be propagated to the parent aggregate
+            --  be propagated to the parent aggregate.
 
             if Present (Orig_Tag) then
                Tag_Value := Orig_Tag;
-            elsif VM_Target /= No_VM then
+            elsif not Tagged_Type_Expansion then
                Tag_Value := Empty;
             else
                Tag_Value :=
@@ -5671,14 +5703,21 @@ package body Exp_Aggr is
 
                   --  Expand recursively the parent propagating the right Tag
 
-                  Expand_Record_Aggregate (
-                    Parent_Aggr, Tag_Value, Parent_Expr);
+                  Expand_Record_Aggregate
+                    (Parent_Aggr, Tag_Value, Parent_Expr);
+
+                  --  The ancestor part may be a nested aggregate that has
+                  --  delayed expansion: recheck now.
+
+                  if Component_Not_OK_For_Backend then
+                     Convert_To_Assignments (N, Typ);
+                  end if;
                end;
 
             --  For a root type, the tag component is added (unless compiling
             --  for the VMs, where tags are implicit).
 
-            elsif VM_Target = No_VM then
+            elsif Tagged_Type_Expansion then
                declare
                   Tag_Name  : constant Node_Id :=
                                 New_Occurrence_Of
@@ -5709,8 +5748,7 @@ package body Exp_Aggr is
       C     : Node_Id;
       Expr  : Node_Id;
    begin
-      pragma Assert (Nkind (N) = N_Aggregate
-         or else Nkind (N) = N_Extension_Aggregate);
+      pragma Assert (Nkind_In (N, N_Aggregate, N_Extension_Aggregate));
 
       if No (Comps) then
          return False;
@@ -5738,8 +5776,8 @@ package body Exp_Aggr is
          Expr := Expression (C);
 
          if Present (Expr)
-           and then (Nkind (Expr) = N_Aggregate
-                     or else Nkind (Expr) = N_Extension_Aggregate)
+           and then
+             Nkind_In (Expr, N_Aggregate, N_Extension_Aggregate)
            and then Has_Default_Init_Comps (Expr)
          then
             return True;
@@ -5781,7 +5819,7 @@ package body Exp_Aggr is
 
    begin
       return Static_Dispatch_Tables
-        and then VM_Target = No_VM
+        and then Tagged_Type_Expansion
         and then RTU_Loaded (Ada_Tags)
 
          --  Avoid circularity when rebuilding the compiler
@@ -5812,13 +5850,11 @@ package body Exp_Aggr is
    function Late_Expansion
      (N      : Node_Id;
       Typ    : Entity_Id;
-      Target : Node_Id;
-      Flist  : Node_Id   := Empty;
-      Obj    : Entity_Id := Empty) return List_Id
+      Target : Node_Id) return List_Id
    is
    begin
       if Is_Record_Type (Etype (N)) then
-         return Build_Record_Aggr_Code (N, Typ, Target, Flist, Obj);
+         return Build_Record_Aggr_Code (N, Typ, Target);
 
       else pragma Assert (Is_Array_Type (Etype (N)));
          return
@@ -5828,8 +5864,7 @@ package body Exp_Aggr is
               Index       => First_Index (Typ),
               Into        => Target,
               Scalar_Comp => Is_Scalar_Type (Component_Type (Typ)),
-              Indices     => No_List,
-              Flist       => Flist);
+              Indexes     => No_List);
       end if;
    end Late_Expansion;
 
@@ -6008,7 +6043,7 @@ package body Exp_Aggr is
 
          if Present (Component_Associations (N)) then
             Convert_To_Positional
-             (N, Max_Others_Replicate => 64, Handle_Bit_Packed => True);
+              (N, Max_Others_Replicate => 64, Handle_Bit_Packed => True);
             return Nkind (N) /= N_Aggregate;
          end if;
 
@@ -6221,9 +6256,8 @@ package body Exp_Aggr is
         and then Nkind (First (Choices (First (Component_Associations (N)))))
                    = N_Others_Choice
       then
-         Expr :=
-           Expression (First (Component_Associations (N)));
-         L_J := Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
+         Expr := Expression (First (Component_Associations (N)));
+         L_J := Make_Temporary (Loc, 'J');
 
          L_Iter :=
            Make_Iteration_Scheme (Loc,
@@ -6355,8 +6389,8 @@ package body Exp_Aggr is
                return False;
 
             else
-               --  The aggregate is static if all components are literals, or
-               --  else all its components are static aggregates for the
+               --  The aggregate is static if all components are literals,
+               --  or else all its components are static aggregates for the
                --  component type. We also limit the size of a static aggregate
                --  to prevent runaway static expressions.
 
@@ -6372,8 +6406,9 @@ package body Exp_Aggr is
 
                elsif Nkind (Expression (Expr)) /= N_Integer_Literal then
                   return False;
+               end if;
 
-               elsif not Aggr_Size_OK (Typ) then
+               if not Aggr_Size_OK (N, Typ) then
                   return False;
                end if;
 
@@ -6386,7 +6421,13 @@ package body Exp_Aggr is
                loop
                   Append_To
                     (Expressions (Agg), New_Copy (Expression (Expr)));
-                  Set_Etype (Last (Expressions (Agg)), Component_Type (Typ));
+
+                  --  The copied expression must be analyzed and resolved.
+                  --  Besides setting the type, this ensures that static
+                  --  expressions are appropriately marked as such.
+
+                  Analyze_And_Resolve
+                    (Last (Expressions (Agg)), Component_Type (Typ));
                end loop;
 
                Set_Aggregate_Bounds (Agg, Bounds);
@@ -6403,4 +6444,5 @@ package body Exp_Aggr is
          return False;
       end if;
    end Static_Array_Aggregate;
+
 end Exp_Aggr;