diff mbox

[Ada] Wrong Finalize_Address leads to Segmentation_Fault

Message ID 20150130112041.GA20755@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 30, 2015, 11:20 a.m. UTC
This patch reimplements a key aspect of heap-allocated controlled objects.
Primitive Finalize_Address is now associated with the finalization master of
an access-to-controlled type when the designated type is frozen and not at the
point of object allocation.

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

--  types.ads

with Ada.Finalization; use Ada.Finalization;

package Types is
   type Ctrl is new Controlled with record
      Id : Natural := 0;
   end record;

   procedure Finalize (Obj : in out Ctrl);
   procedure Initialize (Obj : in out Ctrl);

   type Root is abstract tagged limited null record;
   type Any_Root_Ptr is access all Root'Class;

   function Make_Any_Root_Ptr (Is_Child_1 : Boolean) return Any_Root_Ptr;

   type Child_1 is new Root with record
      Comp_1 : Ctrl;
      Comp_2 : Ctrl;
   end record;
   type Any_Child_1_Ptr is access all Child_1'Class;
   type     Child_1_Ptr is access all Child_1;

   function Make_Child_1     return Child_1;
   function Make_Child_1_Ptr return Child_1_Ptr;

   type Child_2 is new Root with record
      Comp_1 : Ctrl;
   end record;
   type Any_Child_2_Ptr is access all Child_2'Class;
   type     Child_2_Ptr is access all Child_2;

   function Make_Child_2     return Child_2;
   function Make_Child_2_Ptr return Child_2_Ptr;
end Types;

--  types.adb

with Ada.Text_IO; use Ada.Text_IO;

package body Types is
   Id_Gen : Natural := 0;

   procedure Finalize (Obj : in out Ctrl) is
   begin
      Put_Line ("  fin:" & Obj.Id'Img);
      Obj.Id := 0;
   end Finalize;

   procedure Initialize (Obj : in out Ctrl) is
   begin
      Id_Gen := Id_Gen + 1;
      Obj.Id := Id_Gen;
      Put_Line ("  ini:" & Obj.Id'Img);
   end Initialize;

   function Make_Child_1 return Child_1 is
   begin
      return Obj : Child_1;
   end Make_Child_1;

   function Make_Child_1_Ptr return Child_1_Ptr is
      Result : constant Any_Child_1_Ptr := new Child_1'(Make_Child_1);
   begin
      return Child_1_Ptr (Result);
   end Make_Child_1_Ptr;

   function Make_Child_2 return Child_2 is
   begin
      return Obj : Child_2;
   end Make_Child_2;

   function Make_Child_2_Ptr return Child_2_Ptr is
      Result : constant Any_Child_2_Ptr := new Child_2'(Make_Child_2);
   begin
      return Child_2_Ptr (Result);
   end Make_Child_2_Ptr;

   function Make_Any_Root_Ptr (Is_Child_1 : Boolean) return Any_Root_Ptr is
   begin
      if Is_Child_1 then
         return Any_Root_Ptr (Make_Child_1_Ptr);
      else
         return Any_Root_Ptr (Make_Child_2_Ptr);
      end if;
   end Make_Any_Root_Ptr;
end Types;

--  main.adb

with Types; use Types;

procedure Main is
   Obj : Any_Root_Ptr;

begin
   Obj := Make_Any_Root_Ptr (True);
   Obj := Make_Any_Root_Ptr (False);
end Main;

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

$ gnatmake -q main.adb
$ ./main
  ini: 1
  ini: 2
  ini: 3
  fin: 3
  fin: 2
  fin: 1

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

2015-01-30  Hristian Kirtchev  <kirtchev@adacore.com>

	* einfo.adb Update the usage of attributes Entry_Bodies_Array,
	Lit_Indexes, Scale_Value, Storage_Size_Variable,
	String_Literal_Low_Bound along associated routines and
	Write_FieldX_Name.
	(Pending_Access_Types): New routine.
	(Set_Pending_Access_Types): New routine.
	(Write_Field15_Name): Add an entry for Pending_Access_Types.
	* einfo.ads Add new attribute Pending_Access_Types along
	with usage in nodes.  Update the usage of attributes
	Entry_Bodies_Array, Lit_Indexes, Scale_Value,
	Storage_Size_Variable, String_Literal_Low_Bound.
	(Pending_Access_Types): New routine along with pragma Inline.
	(Set_Pending_Access_Types): New routine along with pragma Inline.
	* exp_ch3.adb (Expand_Freeze_Array_Type): Add new local variable
	Ins_Node. Determine the insertion node for anonynous access type
	that acts as a component type of an array. Update the call to
	Build_Finalization_Master.
	(Expand_Freeze_Record_Type): Update
	the calls to Build_Finalization_Master.
	(Freeze_Type): Remove
	local variable RACW_Seen. Factor out the code that deals with
	remote access-to-class-wide types. Create a finalization master
	when the designated type contains a private component. Fully
	initialize all pending access types.
	(Process_RACW_Types): New routine.
	(Process_Pending_Access_Types): New routine.
	* exp_ch4.adb (Expand_Allocator_Expression): Allocation no longer
	needs to set primitive Finalize_Address.
	(Expand_N_Allocator): Allocation no longer sets primitive
	Finalize_Address.
	* exp_ch6.adb (Add_Finalization_Master_Actual_To_Build_In_Place_Call):
	Update the call to Build_Finalization_Master.
	(Make_Build_In_Place_Call_In_Allocator): Allocation no longer
	needs to set primitive Finalize_Address.
	* exp_ch7.adb (Add_Pending_Access_Type): New routine.
	(Build_Finalization_Master): New parameter profile. Associate
	primitive Finalize_Address with the finalization master if the
	designated type has been frozen, otherwise treat the access
	type as pending. Simplify the insertion of the master and
	related initialization code.
	(Make_Finalize_Address_Body): Allow Finalize_Address for class-wide
	abstract types.
	(Make_Set_Finalize_Address_Call): Remove forlam parameter Typ.
	Simplify the implementation.
	* exp_ch7.ads (Build_Finalization_Master): New parameter profile
	along with comment on usage.
	(Make_Set_Finalize_Address_Call): Remove formal parameter Typ. Update
	the comment on usage.
	* exp_util.adb (Build_Allocate_Deallocate_Proc): Use routine
	Finalize_Address to retrieve the primitive.
	(Finalize_Address): New routine.
	(Find_Finalize_Address): Removed.
	* exp_util.ads (Finalize_Address): New routine.
	* freeze.adb (Freeze_All): Remove the generation of finalization
	masters.
	* sem_ch3.adb (Analyze_Full_Type_Declaration): Propagate any
	pending access types from the partial to the full view.
diff mbox

Patch

Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb	(revision 220273)
+++ sem_ch3.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -2792,6 +2792,14 @@ 
          Generate_Definition (Def_Id);
       end if;
 
+      --  Propagate any pending access types whose finalization masters need to
+      --  be fully initialized from the partial to the full view. Guard against
+      --  an illegal full view that remains unanalyzed.
+
+      if Is_Type (Def_Id) and then Is_Incomplete_Or_Private_Type (Prev) then
+         Set_Pending_Access_Types (Def_Id, Pending_Access_Types (Prev));
+      end if;
+
       if Chars (Scope (Def_Id)) = Name_System
         and then Chars (Def_Id) = Name_Address
         and then Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (N)))
Index: exp_ch7.adb
===================================================================
--- exp_ch7.adb	(revision 220273)
+++ exp_ch7.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -764,14 +764,42 @@ 
    -------------------------------
 
    procedure Build_Finalization_Master
-     (Typ        : Entity_Id;
-      Ins_Node   : Node_Id := Empty;
-      Encl_Scope : Entity_Id := Empty)
+     (Typ            : Entity_Id;
+      For_Anonymous  : Boolean   := False;
+      For_Private    : Boolean   := False;
+      Context_Scope  : Entity_Id := Empty;
+      Insertion_Node : Node_Id   := Empty)
    is
+      procedure Add_Pending_Access_Type
+        (Typ     : Entity_Id;
+         Ptr_Typ : Entity_Id);
+      --  Add access type Ptr_Typ to the pending access type list for type Typ
+
       function In_Deallocation_Instance (E : Entity_Id) return Boolean;
       --  Determine whether entity E is inside a wrapper package created for
       --  an instance of Ada.Unchecked_Deallocation.
 
+      -----------------------------
+      -- Add_Pending_Access_Type --
+      -----------------------------
+
+      procedure Add_Pending_Access_Type
+        (Typ     : Entity_Id;
+         Ptr_Typ : Entity_Id)
+      is
+         List : Elist_Id;
+
+      begin
+         if Present (Pending_Access_Types (Typ)) then
+            List := Pending_Access_Types (Typ);
+         else
+            List := New_Elmt_List;
+            Set_Pending_Access_Types (Typ, List);
+         end if;
+
+         Prepend_Elmt (Ptr_Typ, List);
+      end Add_Pending_Access_Type;
+
       ------------------------------
       -- In_Deallocation_Instance --
       ------------------------------
@@ -799,7 +827,7 @@ 
 
       --  Local variables
 
-      Desig_Typ : constant Entity_Id := Directly_Designated_Type (Typ);
+      Desig_Typ : constant Entity_Id := Designated_Type (Typ);
 
       Ptr_Typ : constant Entity_Id := Root_Type_Of_Full_View (Base_Type (Typ));
       --  A finalization master created for a named access type is associated
@@ -855,7 +883,7 @@ 
       --  requires a finalization master.
 
       elsif Ekind (Ptr_Typ) = E_Anonymous_Access_Type
-        and then No (Ins_Node)
+        and then not For_Anonymous
       then
          return;
 
@@ -874,25 +902,21 @@ 
       elsif VM_Target /= No_VM and then not Is_Controlled (Desig_Typ) then
          return;
 
-      --  Do not create finalization masters in SPARK mode because they result
-      --  in unwanted expansion.
+      --  Do not create finalization masters in GNATprove mode because this
+      --  unwanted extra expansion. A compilation in this mode keeps the tree
+      --  as close as possible to the original sources.
 
-      --  More detail would be useful here ???
-
       elsif GNATprove_Mode then
          return;
       end if;
 
       declare
+         Actions    : constant List_Id    := New_List;
          Loc        : constant Source_Ptr := Sloc (Ptr_Typ);
-         Actions    : constant List_Id := New_List;
          Fin_Mas_Id : Entity_Id;
          Pool_Id    : Entity_Id;
 
       begin
-         --  Generate:
-         --    Fnn : aliased Finalization_Master;
-
          --  Source access types use fixed master names since the master is
          --  inserted in the same source unit only once. The only exception to
          --  this are instances using the same access type as generic actual.
@@ -910,6 +934,11 @@ 
             Fin_Mas_Id := Make_Temporary (Loc, 'F');
          end if;
 
+         Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
+
+         --  Generate:
+         --    <Ptr_Typ>FM : aliased Finalization_Master;
+
          Append_To (Actions,
            Make_Object_Declaration (Loc,
              Defining_Identifier => Fin_Mas_Id,
@@ -917,19 +946,18 @@ 
              Object_Definition   =>
                New_Occurrence_Of (RTE (RE_Finalization_Master), Loc)));
 
-         --  Storage pool selection and attribute decoration of the generated
-         --  master. Since .NET/JVM compilers do not support pools, this step
-         --  is skipped.
+         --  Set the associated pool and primitive Finalize_Address of the new
+         --  finalization master. This step is skipped on .NET/JVM because the
+         --  target does not support storage pools or address arithmetic.
 
          if VM_Target = No_VM then
 
-            --  If the access type has a user-defined pool, use it as the base
-            --  storage medium for the finalization pool.
+            --  The access type has a user-defined storage pool, use it
 
             if Present (Associated_Storage_Pool (Ptr_Typ)) then
                Pool_Id := Associated_Storage_Pool (Ptr_Typ);
 
-            --  The default choice is the global pool
+            --  Otherwise the default choice is the global storage pool
 
             else
                Pool_Id := RTE (RE_Global_Pool_Object);
@@ -937,7 +965,7 @@ 
             end if;
 
             --  Generate:
-            --    Set_Base_Pool (Fnn, Pool_Id'Unchecked_Access);
+            --    Set_Base_Pool (<Ptr_Typ>FM, Pool_Id'Unchecked_Access);
 
             Append_To (Actions,
               Make_Procedure_Call_Statement (Loc,
@@ -948,67 +976,90 @@ 
                   Make_Attribute_Reference (Loc,
                     Prefix         => New_Occurrence_Of (Pool_Id, Loc),
                     Attribute_Name => Name_Unrestricted_Access))));
-         end if;
 
-         Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
+            --  Finalize_Address is not generated in CodePeer mode because the
+            --  body contains address arithmetic. Skip this step.
 
-         --  A finalization master created for an anonymous access type must be
-         --  inserted before a context-dependent node.
+            if CodePeer_Mode then
+               null;
 
-         if Present (Ins_Node) then
-            Push_Scope (Encl_Scope);
+            --  Associate the Finalize_Address primitive of the designated type
+            --  with the finalization master of the access type. The designated
+            --  type must be forzen as Finalize_Address is generated when the
+            --  freeze node is expanded.
 
-            --  Treat use clauses as declarations and insert directly in front
-            --  of them.
+            elsif Is_Frozen (Desig_Typ)
+              and then Present (Finalize_Address (Desig_Typ))
 
-            if Nkind_In (Ins_Node, N_Use_Package_Clause,
-                                   N_Use_Type_Clause)
+              --  The finalization master of an anonymous access type may need
+              --  to be inserted in a specific place in the tree. For instance:
+
+              --    type Comp_Typ;
+
+              --    <finalization master of "access Comp_Typ">
+
+              --    type Rec_Typ is record
+              --       Comp : access Comp_Typ;
+              --    end record;
+
+              --    <freeze node for Comp_Typ>
+              --    <freeze node for Rec_Typ>
+
+              --  Due to this oddity, the anonymous access type is stored for
+              --  later processing (see below).
+
+              and then Ekind (Ptr_Typ) /= E_Anonymous_Access_Type
             then
-               Insert_List_Before_And_Analyze (Ins_Node, Actions);
+               --  Generate:
+               --    Set_Finalize_Address
+               --      (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
+
+               Append_To (Actions,
+                 Make_Set_Finalize_Address_Call
+                   (Loc     => Loc,
+                    Ptr_Typ => Ptr_Typ));
+
+            --  Otherwise the designated type is either anonymous access or a
+            --  Taft-amendment type and has not been frozen. Store the access
+            --  type for later processing (see Freeze_Type).
+
             else
-               Insert_Actions (Ins_Node, Actions);
+               Add_Pending_Access_Type (Desig_Typ, Ptr_Typ);
             end if;
+         end if;
 
-            Pop_Scope;
+         --  A finalization master created for an anonymous access type or an
+         --  access designating a type with private components must be inserted
+         --  before a context-dependent node.
 
-         elsif Ekind (Desig_Typ) = E_Incomplete_Type
-           and then Has_Completion_In_Body (Desig_Typ)
-         then
-            Insert_Actions (Parent (Ptr_Typ), Actions);
+         if For_Anonymous or For_Private then
 
-         --  If the designated type is not yet frozen, then append the actions
-         --  to that type's freeze actions. The actions need to be appended to
-         --  whichever type is frozen later, similarly to what Freeze_Type does
-         --  for appending the storage pool declaration for an access type.
-         --  Otherwise, the call to Set_Storage_Pool_Ptr might reference the
-         --  pool object before it's declared. However, it's not clear that
-         --  this is exactly the right test to accomplish that here. ???
+            --  At this point both the scope of the context and the insertion
+            --  mode must be known.
 
-         elsif Present (Freeze_Node (Desig_Typ))
-           and then not Analyzed (Freeze_Node (Desig_Typ))
-         then
-            Append_Freeze_Actions (Desig_Typ, Actions);
+            pragma Assert (Present (Context_Scope));
+            pragma Assert (Present (Insertion_Node));
 
-         elsif Present (Freeze_Node (Ptr_Typ))
-           and then not Analyzed (Freeze_Node (Ptr_Typ))
-         then
-            Append_Freeze_Actions (Ptr_Typ, Actions);
+            Push_Scope (Context_Scope);
 
-         --  If there's a pool created locally for the access type, then we
-         --  need to ensure that the master gets created after the pool object,
-         --  because otherwise we can have a forward reference, so we force the
-         --  master actions to be inserted and analyzed after the pool entity.
-         --  Note that both the access type and its designated type may have
-         --  already been frozen and had their freezing actions analyzed at
-         --  this point. (This seems a little unclean.???)
+            --  Treat use clauses as declarations and insert directly in front
+            --  of them.
 
-         elsif VM_Target = No_VM
-           and then Scope (Pool_Id) = Scope (Ptr_Typ)
-         then
-            Insert_List_After_And_Analyze (Parent (Pool_Id), Actions);
+            if Nkind_In (Insertion_Node, N_Use_Package_Clause,
+                                         N_Use_Type_Clause)
+            then
+               Insert_List_Before_And_Analyze (Insertion_Node, Actions);
+            else
+               Insert_Actions (Insertion_Node, Actions);
+            end if;
 
+            Pop_Scope;
+
+         --  Otherwise the finalization master and its initialization become a
+         --  part of the freeze node.
+
          else
-            Insert_Actions (Parent (Ptr_Typ), Actions);
+            Append_Freeze_Actions (Ptr_Typ, Actions);
          end if;
       end;
    end Build_Finalization_Master;
@@ -7397,7 +7448,6 @@ 
       --  do not need the Finalize_Address primitive.
 
       elsif not Needs_Finalization (Typ)
-        or else Is_Abstract_Type (Typ)
         or else Present (TSS (Typ, TSS_Finalize_Address))
         or else
           (Is_Class_Wide_Type (Typ)
@@ -7801,85 +7851,32 @@ 
 
    function Make_Set_Finalize_Address_Call
      (Loc     : Source_Ptr;
-      Typ     : Entity_Id;
       Ptr_Typ : Entity_Id) return Node_Id
    is
-      Desig_Typ   : constant Entity_Id :=
-                      Available_View (Designated_Type (Ptr_Typ));
-      Fin_Mas_Id  : constant Entity_Id := Finalization_Master (Ptr_Typ);
-      Fin_Mas_Ref : Node_Id;
-      Utyp        : Entity_Id;
+      Desig_Typ : constant Entity_Id :=
+                    Available_View (Designated_Type (Ptr_Typ));
+      Fin_Addr  : constant Entity_Id := Finalize_Address (Desig_Typ);
+      Fin_Mas   : constant Entity_Id := Finalization_Master (Ptr_Typ);
 
    begin
-      --  If the context is a class-wide allocator, we use the class-wide type
-      --  to obtain the proper Finalize_Address routine.
+      --  Both the finalization master and primitive Finalize_Address must be
+      --  available.
 
-      if Is_Class_Wide_Type (Desig_Typ) then
-         Utyp := Desig_Typ;
+      pragma Assert (Present (Fin_Addr) and Present (Fin_Mas));
 
-      else
-         Utyp := Typ;
-
-         if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
-            Utyp := Full_View (Utyp);
-         end if;
-
-         if Is_Concurrent_Type (Utyp) then
-            Utyp := Corresponding_Record_Type (Utyp);
-         end if;
-      end if;
-
-      Utyp := Underlying_Type (Base_Type (Utyp));
-
-      --  Deal with untagged derivation of private views. If the parent is
-      --  now known to be protected, the finalization routine is the one
-      --  defined on the corresponding record of the ancestor (corresponding
-      --  records do not automatically inherit operations, but maybe they
-      --  should???)
-
-      if Is_Untagged_Derivation (Typ) then
-         if Is_Protected_Type (Typ) then
-            Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
-         else
-            Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
-
-            if Is_Protected_Type (Utyp) then
-               Utyp := Corresponding_Record_Type (Utyp);
-            end if;
-         end if;
-      end if;
-
-      --  If the underlying_type is a subtype, we are dealing with the
-      --  completion of a private type. We need to access the base type and
-      --  generate a conversion to it.
-
-      if Utyp /= Base_Type (Utyp) then
-         pragma Assert (Is_Private_Type (Typ));
-
-         Utyp := Base_Type (Utyp);
-      end if;
-
-      Fin_Mas_Ref := New_Occurrence_Of (Fin_Mas_Id, Loc);
-
-      --  If the call is from a build-in-place function, the Master parameter
-      --  is actually a pointer. Dereference it for the call.
-
-      if Is_Access_Type (Etype (Fin_Mas_Id)) then
-         Fin_Mas_Ref := Make_Explicit_Dereference (Loc, Fin_Mas_Ref);
-      end if;
-
       --  Generate:
-      --    Set_Finalize_Address (<Ptr_Typ>FM, <Utyp>FD'Unrestricted_Access);
+      --    Set_Finalize_Address
+      --      (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
 
       return
         Make_Procedure_Call_Statement (Loc,
           Name                   =>
             New_Occurrence_Of (RTE (RE_Set_Finalize_Address), Loc),
           Parameter_Associations => New_List (
-            Fin_Mas_Ref,
+            New_Occurrence_Of (Fin_Mas, Loc),
+
             Make_Attribute_Reference (Loc,
-              Prefix         =>
-                New_Occurrence_Of (TSS (Utyp, TSS_Finalize_Address), Loc),
+              Prefix         => New_Occurrence_Of (Fin_Addr, Loc),
               Attribute_Name => Name_Unrestricted_Access)));
    end Make_Set_Finalize_Address_Call;
 
Index: exp_ch7.ads
===================================================================
--- exp_ch7.ads	(revision 220273)
+++ exp_ch7.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -98,17 +98,20 @@ 
    --  exception will be saved to a global location.
 
    procedure Build_Finalization_Master
-     (Typ        : Entity_Id;
-      Ins_Node   : Node_Id := Empty;
-      Encl_Scope : Entity_Id := Empty);
+     (Typ            : Entity_Id;
+      For_Anonymous  : Boolean   := False;
+      For_Private    : Boolean   := False;
+      Context_Scope  : Entity_Id := Empty;
+      Insertion_Node : Node_Id   := Empty);
    --  Build a finalization master for an access type. The designated type may
-   --  not necessarely be controlled or need finalization actions. The routine
-   --  creates a wrapper around a user-defined storage pool or the general
-   --  storage pool for access types. Ins_Nod and Encl_Scope are used in
-   --  conjunction with anonymous access types. Ins_Node designates the
-   --  insertion point before which the collection should be added. Encl_Scope
-   --  is the scope of the context, either the enclosing record or the scope
-   --  of the related function.
+   --  not necessarely be controlled or need finalization actions depending on
+   --  the context. Flag For_Anonymous must be set when creating a master for
+   --  an anonymous access type. Flag For_Private must be set when the
+   --  designated type contains a private component. Parameters Context_Scope
+   --  and Insertion_Node must be used in conjunction with flags For_Anonymous
+   --  and For_Private. Context_Scope is the scope of the context where the
+   --  finalization master must be analyzed. Insertion_Node is the insertion
+   --  point before which the master is inserted.
 
    procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id);
    --  Build one controlling procedure when a late body overrides one of
@@ -222,15 +225,13 @@ 
 
    function Make_Set_Finalize_Address_Call
      (Loc     : Source_Ptr;
-      Typ     : Entity_Id;
       Ptr_Typ : Entity_Id) return Node_Id;
+   --  Associate the Finalize_Address primitive of the designated type with the
+   --  finalization master of access type Ptr_Typ. The returned call is:
    --  Generate the following call:
    --
-   --    Set_Finalize_Address (<Ptr_Typ>FM, <Typ>FD'Unrestricted_Access);
-   --
-   --  where Finalize_Address is the corresponding TSS primitive of type Typ
-   --  and Ptr_Typ is the access type of the related allocation. Loc is the
-   --  source location of the related allocator.
+   --    Set_Finalize_Address
+   --      (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
 
    --------------------------------------------
    -- Task and Protected Object finalization --
Index: exp_util.adb
===================================================================
--- exp_util.adb	(revision 220273)
+++ exp_util.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -412,9 +412,6 @@ 
       Proc_To_Call : Node_Id := Empty;
       Ptr_Typ      : Entity_Id;
 
-      function Find_Finalize_Address (Typ : Entity_Id) return Entity_Id;
-      --  Locate TSS primitive Finalize_Address in type Typ
-
       function Find_Object (E : Node_Id) return Node_Id;
       --  Given an arbitrary expression of an allocator, try to find an object
       --  reference in it, otherwise return the original expression.
@@ -423,82 +420,6 @@ 
       --  Determine whether subprogram Subp denotes a custom allocate or
       --  deallocate.
 
-      ---------------------------
-      -- Find_Finalize_Address --
-      ---------------------------
-
-      function Find_Finalize_Address (Typ : Entity_Id) return Entity_Id is
-         Utyp : Entity_Id := Typ;
-
-      begin
-         --  Handle protected class-wide or task class-wide types
-
-         if Is_Class_Wide_Type (Utyp) then
-            if Is_Concurrent_Type (Root_Type (Utyp)) then
-               Utyp := Root_Type (Utyp);
-
-            elsif Is_Private_Type (Root_Type (Utyp))
-              and then Present (Full_View (Root_Type (Utyp)))
-              and then Is_Concurrent_Type (Full_View (Root_Type (Utyp)))
-            then
-               Utyp := Full_View (Root_Type (Utyp));
-            end if;
-         end if;
-
-         --  Handle private types
-
-         if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
-            Utyp := Full_View (Utyp);
-         end if;
-
-         --  Handle protected and task types
-
-         if Is_Concurrent_Type (Utyp)
-           and then Present (Corresponding_Record_Type (Utyp))
-         then
-            Utyp := Corresponding_Record_Type (Utyp);
-         end if;
-
-         Utyp := Underlying_Type (Base_Type (Utyp));
-
-         --  Deal with untagged derivation of private views. If the parent is
-         --  now known to be protected, the finalization routine is the one
-         --  defined on the corresponding record of the ancestor (corresponding
-         --  records do not automatically inherit operations, but maybe they
-         --  should???)
-
-         if Is_Untagged_Derivation (Typ) then
-            if Is_Protected_Type (Typ) then
-               Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
-            else
-               Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
-
-               if Is_Protected_Type (Utyp) then
-                  Utyp := Corresponding_Record_Type (Utyp);
-               end if;
-            end if;
-         end if;
-
-         --  If the underlying_type is a subtype, we are dealing with the
-         --  completion of a private type. We need to access the base type and
-         --  generate a conversion to it.
-
-         if Utyp /= Base_Type (Utyp) then
-            pragma Assert (Is_Private_Type (Typ));
-
-            Utyp := Base_Type (Utyp);
-         end if;
-
-         --  When dealing with an internally built full view for a type with
-         --  unknown discriminants, use the original record type.
-
-         if Is_Underlying_Record_View (Utyp) then
-            Utyp := Etype (Utyp);
-         end if;
-
-         return TSS (Utyp, TSS_Finalize_Address);
-      end Find_Finalize_Address;
-
       -----------------
       -- Find_Object --
       -----------------
@@ -764,7 +685,7 @@ 
             --  since it contains an Unchecked_Conversion.
 
             if Needs_Finalization (Desig_Typ) and then not CodePeer_Mode then
-               Fin_Addr_Id := Find_Finalize_Address (Desig_Typ);
+               Fin_Addr_Id := Finalize_Address (Desig_Typ);
                pragma Assert (Present (Fin_Addr_Id));
 
                Append_To (Actuals,
@@ -2443,6 +2364,82 @@ 
       end if;
    end Expand_Subtype_From_Expr;
 
+   ----------------------
+   -- Finalize_Address --
+   ----------------------
+
+   function Finalize_Address (Typ : Entity_Id) return Entity_Id is
+      Utyp : Entity_Id := Typ;
+
+   begin
+      --  Handle protected class-wide or task class-wide types
+
+      if Is_Class_Wide_Type (Utyp) then
+         if Is_Concurrent_Type (Root_Type (Utyp)) then
+            Utyp := Root_Type (Utyp);
+
+         elsif Is_Private_Type (Root_Type (Utyp))
+           and then Present (Full_View (Root_Type (Utyp)))
+           and then Is_Concurrent_Type (Full_View (Root_Type (Utyp)))
+         then
+            Utyp := Full_View (Root_Type (Utyp));
+         end if;
+      end if;
+
+      --  Handle private types
+
+      if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
+         Utyp := Full_View (Utyp);
+      end if;
+
+      --  Handle protected and task types
+
+      if Is_Concurrent_Type (Utyp)
+        and then Present (Corresponding_Record_Type (Utyp))
+      then
+         Utyp := Corresponding_Record_Type (Utyp);
+      end if;
+
+      Utyp := Underlying_Type (Base_Type (Utyp));
+
+      --  Deal with untagged derivation of private views. If the parent is
+      --  now known to be protected, the finalization routine is the one
+      --  defined on the corresponding record of the ancestor (corresponding
+      --  records do not automatically inherit operations, but maybe they
+      --  should???)
+
+      if Is_Untagged_Derivation (Typ) then
+         if Is_Protected_Type (Typ) then
+            Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
+         else
+            Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
+
+            if Is_Protected_Type (Utyp) then
+               Utyp := Corresponding_Record_Type (Utyp);
+            end if;
+         end if;
+      end if;
+
+      --  If the underlying_type is a subtype, we are dealing with the
+      --  completion of a private type. We need to access the base type and
+      --  generate a conversion to it.
+
+      if Utyp /= Base_Type (Utyp) then
+         pragma Assert (Is_Private_Type (Typ));
+
+         Utyp := Base_Type (Utyp);
+      end if;
+
+      --  When dealing with an internally built full view for a type with
+      --  unknown discriminants, use the original record type.
+
+      if Is_Underlying_Record_View (Utyp) then
+         Utyp := Etype (Utyp);
+      end if;
+
+      return TSS (Utyp, TSS_Finalize_Address);
+   end Finalize_Address;
+
    ------------------------
    -- Find_Interface_ADT --
    ------------------------
Index: exp_util.ads
===================================================================
--- exp_util.ads	(revision 220273)
+++ exp_util.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -450,6 +450,9 @@ 
    --  declarations and/or allocations when the type is indefinite (including
    --  class-wide).
 
+   function Finalize_Address (Typ : Entity_Id) return Entity_Id;
+   --  Locate TSS primitive Finalize_Address in type Typ
+
    function Find_Interface_ADT
      (T     : Entity_Id;
       Iface : Entity_Id) return Elmt_Id;
Index: einfo.adb
===================================================================
--- einfo.adb	(revision 220273)
+++ einfo.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -121,15 +121,11 @@ 
    --    Discriminant_Number             Uint15
    --    DT_Position                     Uint15
    --    DT_Entry_Count                  Uint15
-   --    Entry_Bodies_Array              Node15
    --    Entry_Parameters_Type           Node15
    --    Extra_Formal                    Node15
-   --    Lit_Indexes                     Node15
+   --    Pending_Access_Types            Elist15
    --    Related_Instance                Node15
    --    Status_Flag_Or_Transient_Decl   Node15
-   --    Scale_Value                     Uint15
-   --    Storage_Size_Variable           Node15
-   --    String_Literal_Low_Bound        Node15
 
    --    Access_Disp_Table               Elist16
    --    Body_References                 Elist16
@@ -138,6 +134,7 @@ 
    --    Entry_Formal                    Node16
    --    First_Private_Entity            Node16
    --    Lit_Strings                     Node16
+   --    Scale_Value                     Uint16
    --    String_Literal_Length           Uint16
    --    Unset_Reference                 Node16
 
@@ -159,14 +156,17 @@ 
    --    Delta_Value                     Ureal18
    --    Enclosing_Scope                 Node18
    --    Equivalent_Type                 Node18
+   --    Lit_Indexes                     Node18
    --    Private_Dependents              Elist18
    --    Renamed_Entity                  Node18
    --    Renamed_Object                  Node18
+   --    String_Literal_Low_Bound        Node18
 
    --    Body_Entity                     Node19
    --    Corresponding_Discriminant      Node19
    --    Default_Aspect_Component_Value  Node19
    --    Default_Aspect_Value            Node19
+   --    Entry_Bodies_Array              Node19
    --    Extra_Accessibility_Of_Result   Node19
    --    Parent_Subtype                  Node19
    --    Size_Check_Code                 Node19
@@ -226,10 +226,9 @@ 
 
    --    Dispatch_Table_Wrappers         Elist26
    --    Last_Assignment                 Node26
-   --    Original_Access_Type            Node26
    --    Overridden_Operation            Node26
    --    Package_Instantiation           Node26
-   --    Relative_Deadline_Variable      Node26
+   --    Storage_Size_Variable           Node26
 
    --    Current_Use_Clause              Node27
    --    Related_Type                    Node27
@@ -238,6 +237,8 @@ 
    --    Extra_Formals                   Node28
    --    Finalizer                       Node28
    --    Initialization_Statements       Node28
+   --    Original_Access_Type            Node28
+   --    Relative_Deadline_Variable      Node28
    --    Underlying_Record_View          Node28
 
    --    BIP_Initialization_Call         Node29
@@ -1093,7 +1094,7 @@ 
 
    function Entry_Bodies_Array (Id : E) return E is
    begin
-      return Node15 (Id);
+      return Node19 (Id);
    end Entry_Bodies_Array;
 
    function Entry_Cancel_Parameter (Id : E) return E is
@@ -2505,7 +2506,7 @@ 
    function Lit_Indexes (Id : E) return E is
    begin
       pragma Assert (Is_Enumeration_Type (Id));
-      return Node15 (Id);
+      return Node18 (Id);
    end Lit_Indexes;
 
    function Lit_Strings (Id : E) return E is
@@ -2689,7 +2690,7 @@ 
    function Original_Access_Type (Id : E) return E is
    begin
       pragma Assert (Ekind (Id) = E_Access_Subprogram_Type);
-      return Node26 (Id);
+      return Node28 (Id);
    end Original_Access_Type;
 
    function Original_Array_Type (Id : E) return E is
@@ -2738,6 +2739,12 @@ 
       return Elist9 (Id);
    end Part_Of_Constituents;
 
+   function Pending_Access_Types (Id : E) return L is
+   begin
+      pragma Assert (Is_Type (Id));
+      return Elist15 (Id);
+   end Pending_Access_Types;
+
    function Postcondition_Proc (Id : E) return E is
    begin
       pragma Assert (Ekind (Id) = E_Procedure);
@@ -2853,7 +2860,7 @@ 
    function Relative_Deadline_Variable (Id : E) return E is
    begin
       pragma Assert (Is_Task_Type (Id));
-      return Node26 (Implementation_Base_Type (Id));
+      return Node28 (Implementation_Base_Type (Id));
    end Relative_Deadline_Variable;
 
    function Renamed_Entity (Id : E) return N is
@@ -2929,7 +2936,7 @@ 
 
    function Scale_Value (Id : E) return U is
    begin
-      return Uint15 (Id);
+      return Uint16 (Id);
    end Scale_Value;
 
    function Scope_Depth_Value (Id : E) return U is
@@ -3063,7 +3070,7 @@ 
    function Storage_Size_Variable (Id : E) return E is
    begin
       pragma Assert (Is_Access_Type (Id) or else Is_Task_Type (Id));
-      return Node15 (Implementation_Base_Type (Id));
+      return Node26 (Implementation_Base_Type (Id));
    end Storage_Size_Variable;
 
    function Static_Elaboration_Desired (Id : E) return B is
@@ -3103,7 +3110,7 @@ 
 
    function String_Literal_Low_Bound (Id : E) return N is
    begin
-      return Node15 (Id);
+      return Node18 (Id);
    end String_Literal_Low_Bound;
 
    function Subprograms_For_Type (Id : E) return E is
@@ -3920,7 +3927,7 @@ 
 
    procedure Set_Entry_Bodies_Array (Id : E; V : E) is
    begin
-      Set_Node15 (Id, V);
+      Set_Node19 (Id, V);
    end Set_Entry_Bodies_Array;
 
    procedure Set_Entry_Cancel_Parameter (Id : E; V : E) is
@@ -5386,7 +5393,7 @@ 
    procedure Set_Lit_Indexes (Id : E; V : E) is
    begin
       pragma Assert (Is_Enumeration_Type (Id) and then Root_Type (Id) = Id);
-      Set_Node15 (Id, V);
+      Set_Node18 (Id, V);
    end Set_Lit_Indexes;
 
    procedure Set_Lit_Strings (Id : E; V : E) is
@@ -5576,7 +5583,7 @@ 
    procedure Set_Original_Access_Type (Id : E; V : E) is
    begin
       pragma Assert (Ekind (Id) = E_Access_Subprogram_Type);
-      Set_Node26 (Id, V);
+      Set_Node28 (Id, V);
    end Set_Original_Access_Type;
 
    procedure Set_Original_Array_Type (Id : E; V : E) is
@@ -5625,6 +5632,12 @@ 
       Set_Elist9 (Id, V);
    end Set_Part_Of_Constituents;
 
+   procedure Set_Pending_Access_Types (Id : E; V : L) is
+   begin
+      pragma Assert (Is_Type (Id));
+      Set_Elist15 (Id, V);
+   end Set_Pending_Access_Types;
+
    procedure Set_Postcondition_Proc (Id : E; V : E) is
    begin
       pragma Assert (Ekind (Id) = E_Procedure);
@@ -5748,7 +5761,7 @@ 
    procedure Set_Relative_Deadline_Variable (Id : E; V : E) is
    begin
       pragma Assert (Is_Task_Type (Id) and then Is_Base_Type (Id));
-      Set_Node26 (Id, V);
+      Set_Node28 (Id, V);
    end Set_Relative_Deadline_Variable;
 
    procedure Set_Renamed_Entity (Id : E; V : N) is
@@ -5827,7 +5840,7 @@ 
 
    procedure Set_Scale_Value (Id : E; V : U) is
    begin
-      Set_Uint15 (Id, V);
+      Set_Uint16 (Id, V);
    end Set_Scale_Value;
 
    procedure Set_Scope_Depth_Value (Id : E; V : U) is
@@ -5972,7 +5985,7 @@ 
    begin
       pragma Assert (Is_Access_Type (Id) or else Is_Task_Type (Id));
       pragma Assert (Id = Base_Type (Id));
-      Set_Node15 (Id, V);
+      Set_Node26 (Id, V);
    end Set_Storage_Size_Variable;
 
    procedure Set_Static_Elaboration_Desired (Id : E; V : B) is
@@ -6015,7 +6028,7 @@ 
    procedure Set_String_Literal_Low_Bound (Id : E; V : N) is
    begin
       pragma Assert (Ekind (Id) = E_String_Literal_Subtype);
-      Set_Node15 (Id, V);
+      Set_Node18 (Id, V);
    end Set_String_Literal_Low_Bound;
 
    procedure Set_Subprograms_For_Type (Id : E; V : E) is
@@ -9092,36 +9105,23 @@ 
               E_Procedure                                  =>
             Write_Str ("DT_Position");
 
-         when E_Protected_Type                             =>
-            Write_Str ("Entry_Bodies_Array");
-
          when Entry_Kind                                   =>
             Write_Str ("Entry_Parameters_Type");
 
          when Formal_Kind                                  =>
             Write_Str ("Extra_Formal");
 
-         when Enumeration_Kind                             =>
-            Write_Str ("Lit_Indexes");
+         when Type_Kind                                    =>
+            Write_Str ("Pending_Access_Types");
 
          when E_Package                                    |
               E_Package_Body                               =>
             Write_Str ("Related_Instance");
 
-         when Decimal_Fixed_Point_Kind                     =>
-            Write_Str ("Scale_Value");
-
          when E_Constant                                   |
               E_Variable                                   =>
             Write_Str ("Status_Flag_Or_Transient_Decl");
 
-         when Access_Kind                                  |
-              Task_Kind                                    =>
-            Write_Str ("Storage_Size_Variable");
-
-         when E_String_Literal_Subtype                     =>
-            Write_Str ("String_Literal_Low_Bound");
-
          when others                                       =>
             Write_Str ("Field15??");
       end case;
@@ -9160,6 +9160,9 @@ 
          when Enumeration_Kind                             =>
             Write_Str ("Lit_Strings");
 
+         when Decimal_Fixed_Point_Kind                     =>
+            Write_Str ("Scale_Value");
+
          when E_String_Literal_Subtype                     =>
             Write_Str ("String_Literal_Length");
 
@@ -9282,6 +9285,9 @@ 
          when Fixed_Point_Kind                             =>
             Write_Str ("Delta_Value");
 
+         when Enumeration_Kind                             =>
+            Write_Str ("Lit_Indexes");
+
          when Incomplete_Or_Private_Kind                   |
               E_Record_Subtype                             =>
             Write_Str ("Private_Dependents");
@@ -9296,6 +9302,9 @@ 
               E_Generic_Package                            =>
             Write_Str ("Renamed_Entity");
 
+         when E_String_Literal_Subtype                     =>
+            Write_Str ("String_Literal_Low_Bound");
+
          when others                                       =>
             Write_Str ("Field18??");
       end case;
@@ -9321,6 +9330,14 @@ 
          when E_Array_Type                                 =>
             Write_Str ("Default_Component_Value");
 
+         when E_Protected_Type                             =>
+            Write_Str ("Entry_Bodies_Array");
+
+         when E_Function                                   |
+              E_Operator                                   |
+              E_Subprogram_Type                            =>
+            Write_Str ("Extra_Accessibility_Of_Result");
+
          when E_Record_Type                                =>
             Write_Str ("Parent_Subtype");
 
@@ -9335,9 +9352,6 @@ 
          when Private_Kind                                 =>
             Write_Str ("Underlying_Full_View");
 
-         when E_Function | E_Operator | E_Subprogram_Type =>
-            Write_Str ("Extra_Accessibility_Of_Result");
-
          when others                                       =>
             Write_Str ("Field19??");
       end case;
@@ -9648,8 +9662,9 @@ 
               E_Variable                                   =>
             Write_Str ("Last_Assignment");
 
-         when E_Access_Subprogram_Type                     =>
-            Write_Str ("Original_Access_Type");
+         when E_Procedure                                  |
+              E_Function                                   =>
+            Write_Str ("Overridden_Operation");
 
          when E_Generic_Package                            |
               E_Package                                    =>
@@ -9659,13 +9674,10 @@ 
               E_Constant                                   =>
             Write_Str ("Related_Type");
 
-         when Task_Kind                                    =>
-            Write_Str ("Relative_Deadline_Variable");
+         when Access_Kind                                  |
+              Task_Kind                                    =>
+            Write_Str ("Storage_Size_Variable");
 
-         when E_Procedure                                  |
-              E_Function                                   =>
-            Write_Str ("Overridden_Operation");
-
          when others                                       =>
             Write_Str ("Field26??");
       end case;
@@ -9719,6 +9731,12 @@ 
               E_Variable                                   =>
             Write_Str ("Initialization_Statements");
 
+         when E_Access_Subprogram_Type                     =>
+            Write_Str ("Original_Access_Type");
+
+         when Task_Kind                                    =>
+            Write_Str ("Relative_Deadline_Variable");
+
          when E_Record_Type =>
             Write_Str ("Underlying_Record_View");
 
@@ -9867,6 +9885,7 @@ 
       case Ekind (Id) is
          when Subprogram_Kind                              =>
             Write_Str ("Import_Pragma");
+
          when others                                       =>
             Write_Str ("Field35??");
       end case;
Index: einfo.ads
===================================================================
--- einfo.ads	(revision 220273)
+++ einfo.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -1036,7 +1036,7 @@ 
 --       at least one accept for this entry in the task body. Used to
 --       generate warnings for missing accepts.
 
---    Entry_Bodies_Array (Node15)
+--    Entry_Bodies_Array (Node19)
 --       Defined in protected types for which Has_Entries is true.
 --       This is the defining identifier for the array of entry body
 --       action procedures and barrier functions used by the runtime to
@@ -3178,7 +3178,7 @@ 
 --       field may be set as a result of a linker section pragma applied to the
 --       type of the object.
 
---    Lit_Indexes (Node15)
+--    Lit_Indexes (Node18)
 --       Defined in enumeration types and subtypes. Non-empty only for the
 --       case of an enumeration root type, where it contains the entity for
 --       the generated indexes entity. See unit Exp_Imgv for full details of
@@ -3495,7 +3495,7 @@ 
 --       Optimize_Alignment (Off) mode applies to the type/object, then neither
 --       of the flags Optimize_Alignment_Space/Optimize_Alignment_Time is set.
 
---    Original_Access_Type (Node26)
+--    Original_Access_Type (Node28)
 --       Defined in E_Access_Subprogram_Type entities. Set only if the access
 --       type was generated by the expander as part of processing an access
 --       to protected subprogram type. Points to the access to protected
@@ -3578,6 +3578,14 @@ 
 --       Present in abstract state entities. Contains all constituents that are
 --       subject to indicator Part_Of (both aspect and option variants).
 
+--    Pending_Access_Types (Elist15)
+--       Defined in all types. Set for incomplete, private, Taft-amendment
+--       types, and their corresponding full views. This list contains all
+--       access types, both named and anonymous, declared between the partial
+--       and the full view. The list is used by the finalization machinery to
+--       ensure that the finalization masters of all pending access types are
+--       fully initialized when the full view is frozen.
+
 --    Postcondition_Proc (Node8)
 --       Defined only in procedure entities, saves the entity of the generated
 --       postcondition proc if one is present, otherwise is set to Empty. Used
@@ -3735,7 +3743,7 @@ 
 --       associated dispatch table to point to entities containing primary or
 --       secondary tags. Not set in the _tag component of record types.
 
---    Relative_Deadline_Variable (Node26) [implementation base type only]
+--    Relative_Deadline_Variable (Node28) [implementation base type only]
 --       Defined in task type entities. This flag is set if a valid and
 --       effective pragma Relative_Deadline applies to the base type. Points
 --       to the entity for a variable that is created to hold the value given
@@ -3852,7 +3860,7 @@ 
 --       node (with a constraint), or a Range node, but not a simple
 --       subtype reference (a subtype is converted into a range).
 
---    Scale_Value (Uint15)
+--    Scale_Value (Uint16)
 --       Defined in decimal fixed-point types and subtypes. Contains the scale
 --       for the type (i.e. the value of type'Scale = the number of decimal
 --       digits after the decimal point).
@@ -4043,7 +4051,7 @@ 
 --       This attribute uses the same field as Overridden_Operation, which is
 --       irrelevant in init_procs.
 
---    Storage_Size_Variable (Node15) [implementation base type only]
+--    Storage_Size_Variable (Node26) [implementation base type only]
 --       Defined in access types and task type entities. This flag is set
 --       if a valid and effective pragma Storage_Size applies to the base
 --       type. Points to the entity for a variable that is created to
@@ -4073,7 +4081,7 @@ 
 --       to string literals in the program). Contains the length of the string
 --       literal.
 
---    String_Literal_Low_Bound (Node15)
+--    String_Literal_Low_Bound (Node18)
 --       Defined in string literal subtypes (which are created to correspond
 --       to string literals in the program). Contains an expression whose
 --       value represents the low bound of the literal. This is a copy of
@@ -5280,6 +5288,7 @@ 
    --    Esize                               (Uint12)
    --    RM_Size                             (Uint13)
    --    Alignment                           (Uint14)
+   --    Pending_Access_Types                (Elist15)
    --    Related_Expression                  (Node24)
    --    Current_Use_Clause                  (Node27)
    --    Subprograms_For_Type                (Node29)
@@ -5396,17 +5405,17 @@ 
    --    Directly_Designated_Type            (Node20)
    --    Interface_Name                      (Node21)   (JGNAT usage only)
    --    Needs_No_Actuals                    (Flag22)
-   --    Original_Access_Type                (Node26)
+   --    Original_Access_Type                (Node28)
    --    Can_Use_Internal_Rep                (Flag229)
    --    (plus type attributes)
 
    --  E_Access_Type
    --  E_Access_Subtype
-   --    Storage_Size_Variable               (Node15)   (base type only)
    --    Master_Id                           (Node17)
    --    Directly_Designated_Type            (Node20)
    --    Associated_Storage_Pool             (Node22)   (base type only)
    --    Finalization_Master                 (Node23)   (base type only)
+   --    Storage_Size_Variable               (Node26)   (base type only)
    --    Has_Pragma_Controlled               (Flag27)   (base type only)
    --    Has_Storage_Size_Clause             (Flag23)   (base type only)
    --    Is_Access_Constant                  (Flag69)
@@ -5426,15 +5435,15 @@ 
 
    --  E_Anonymous_Access_Subprogram_Type
    --  E_Anonymous_Access_Protected_Subprogram_Type
-   --    Storage_Size_Variable               (Node15)   ??? is this needed ???
    --    Directly_Designated_Type            (Node20)
+   --    Storage_Size_Variable               (Node26)   ??? is this needed ???
    --    Can_Use_Internal_Rep                (Flag229)
    --    (plus type attributes)
 
    --  E_Anonymous_Access_Type
-   --    Storage_Size_Variable               (Node15)   ??? is this needed ???
    --    Directly_Designated_Type            (Node20)
    --    Finalization_Master                 (Node23)
+   --    Storage_Size_Variable               (Node26)   ??? is this needed ???
    --    (plus type attributes)
 
    --  E_Array_Type
@@ -5558,7 +5567,7 @@ 
 
    --  E_Decimal_Fixed_Point_Type
    --  E_Decimal_Fixed_Subtype
-   --    Scale_Value                         (Uint15)
+   --    Scale_Value                         (Uint16)
    --    Digits_Value                        (Uint17)
    --    Scalar_Range                        (Node20)
    --    Delta_Value                         (Ureal18)
@@ -5631,9 +5640,9 @@ 
 
    --  E_Enumeration_Type
    --  E_Enumeration_Subtype
-   --    Lit_Indexes                         (Node15)   (root type only)
    --    Lit_Strings                         (Node16)   (root type only)
    --    First_Literal                       (Node17)
+   --    Lit_Indexes                         (Node18)   (root type only)
    --    Default_Aspect_Value                (Node19)   (base type only)
    --    Scalar_Range                        (Node20)
    --    Enum_Pos_To_Rep                     (Node23)   (type only)
@@ -5768,11 +5777,11 @@ 
    --    Scope_Depth                         (synth)
 
    --  E_General_Access_Type
-   --    Storage_Size_Variable               (Node15)   (base type only)
    --    Master_Id                           (Node17)
    --    Directly_Designated_Type            (Node20)
    --    Associated_Storage_Pool             (Node22)   (root type only)
    --    Finalization_Master                 (Node23)   (root type only)
+   --    Storage_Size_Variable               (Node26)   (base type only)
    --    (plus type attributes)
 
    --  E_Generic_In_Parameter
@@ -6072,10 +6081,10 @@ 
    --  E_Protected_Type
    --  E_Protected_Subtype
    --    Direct_Primitive_Operations         (Elist10)
-   --    Entry_Bodies_Array                  (Node15)
    --    First_Private_Entity                (Node16)
    --    First_Entity                        (Node17)
    --    Corresponding_Record_Type           (Node18)
+   --    Entry_Bodies_Array                  (Node19)
    --    Last_Entity                         (Node20)
    --    Discriminant_Constraint             (Elist21)
    --    Scope_Depth_Value                   (Uint22)
@@ -6170,9 +6179,9 @@ 
    --    (plus type attributes)
 
    --  E_String_Literal_Subtype
-   --    String_Literal_Low_Bound            (Node15)
    --    String_Literal_Length               (Uint16)
    --    First_Index                         (Node17)   (always Empty)
+   --    String_Literal_Low_Bound            (Node18)
    --    Packed_Array_Impl_Type              (Node23)
    --    (plus type attributes)
 
@@ -6205,7 +6214,6 @@ 
    --  E_Task_Type
    --  E_Task_Subtype
    --    Direct_Primitive_Operations         (Elist10)
-   --    Storage_Size_Variable               (Node15)   (base type only)
    --    First_Private_Entity                (Node16)
    --    First_Entity                        (Node17)
    --    Corresponding_Record_Type           (Node18)
@@ -6215,6 +6223,8 @@ 
    --    Scope_Depth                         (synth)
    --    Stored_Constraint                   (Elist23)
    --    Task_Body_Procedure                 (Node25)
+   --    Storage_Size_Variable               (Node26)   (base type only)
+   --    Relative_Deadline_Variable          (Node28)   (base type only)
    --    Delay_Cleanups                      (Flag114)
    --    Has_Master_Entity                   (Flag21)
    --    Has_Storage_Size_Clause             (Flag23)   (base type only)
@@ -6222,7 +6232,6 @@ 
    --    Sec_Stack_Needed_For_Return         (Flag167)  ???
    --    Has_Entries                         (synth)
    --    Number_Entries                      (synth)
-   --    Relative_Deadline_Variable          (Node26)   (base type only)
    --    (plus type attributes)
 
    --  E_Variable
@@ -6868,6 +6877,7 @@ 
    function Packed_Array_Impl_Type              (Id : E) return E;
    function Parent_Subtype                      (Id : E) return E;
    function Part_Of_Constituents                (Id : E) return L;
+   function Pending_Access_Types                (Id : E) return L;
    function Postcondition_Proc                  (Id : E) return E;
    function Prival                              (Id : E) return E;
    function Prival_Link                         (Id : E) return E;
@@ -7514,6 +7524,7 @@ 
    procedure Set_Packed_Array_Impl_Type          (Id : E; V : E);
    procedure Set_Parent_Subtype                  (Id : E; V : E);
    procedure Set_Part_Of_Constituents            (Id : E; V : L);
+   procedure Set_Pending_Access_Types            (Id : E; V : L);
    procedure Set_Postcondition_Proc              (Id : E; V : E);
    procedure Set_Prival                          (Id : E; V : E);
    procedure Set_Prival_Link                     (Id : E; V : E);
@@ -8312,6 +8323,7 @@ 
    pragma Inline (Parameter_Mode);
    pragma Inline (Parent_Subtype);
    pragma Inline (Part_Of_Constituents);
+   pragma Inline (Pending_Access_Types);
    pragma Inline (Postcondition_Proc);
    pragma Inline (Prival);
    pragma Inline (Prival_Link);
@@ -8757,6 +8769,7 @@ 
    pragma Inline (Set_Packed_Array_Impl_Type);
    pragma Inline (Set_Parent_Subtype);
    pragma Inline (Set_Part_Of_Constituents);
+   pragma Inline (Set_Pending_Access_Types);
    pragma Inline (Set_Postcondition_Proc);
    pragma Inline (Set_Prival);
    pragma Inline (Set_Prival_Link);
Index: freeze.adb
===================================================================
--- freeze.adb	(revision 220273)
+++ freeze.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -1796,25 +1796,6 @@ 
                   Next_Entity (Ent);
                end loop;
             end;
-
-         --  We add finalization masters to access types whose designated types
-         --  require finalization. This is normally done when freezing the
-         --  type, but this misses recursive type definitions where the later
-         --  members of the recursion introduce controlled components (such as
-         --  can happen when incomplete types are involved), as well cases
-         --  where a component type is private and the controlled full type
-         --  occurs after the access type is frozen. Cases that don't need a
-         --  finalization master are generic formal types (the actual type will
-         --  have it) and types derived from them,  and types with Java and CIL
-         --  conventions, since those are used for API bindings.
-         --  (Are there any other cases that should be excluded here???)
-
-         elsif Is_Access_Type (E)
-           and then Comes_From_Source (E)
-           and then not Is_Generic_Type (Root_Type (E))
-           and then Needs_Finalization (Designated_Type (E))
-         then
-            Build_Finalization_Master (E);
          end if;
 
          Next_Entity (E);
Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb	(revision 220273)
+++ exp_ch4.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -1278,30 +1278,6 @@ 
                           Prefix => New_Occurrence_Of (Temp, Loc))),
                     Typ     => T));
             end if;
-
-            --  Generate:
-            --    Set_Finalize_Address (<PtrT>FM, <T>FD'Unrestricted_Access);
-
-            --  Do not generate this call in the following cases:
-
-            --    * .NET/JVM - these targets do not support address arithmetic
-            --    and unchecked conversion, key elements of Finalize_Address.
-
-            --    * CodePeer mode - TSS primitive Finalize_Address is not
-            --    created in this mode.
-
-            if VM_Target = No_VM
-              and then not CodePeer_Mode
-              and then Present (Finalization_Master (PtrT))
-              and then Present (Temp_Decl)
-              and then Nkind (Expression (Temp_Decl)) = N_Allocator
-            then
-               Insert_Action (N,
-                 Make_Set_Finalize_Address_Call
-                   (Loc     => Loc,
-                    Typ     => T,
-                    Ptr_Typ => PtrT));
-            end if;
          end if;
 
          Rewrite (N, New_Occurrence_Of (Temp, Loc));
@@ -4868,40 +4844,22 @@ 
                       (Obj_Ref => New_Copy_Tree (Init_Arg1),
                        Typ     => T));
 
-                  if Present (Finalization_Master (PtrT)) then
+                  --  Special processing for .NET/JVM, the allocated object is
+                  --  attached to the finalization master. Generate:
 
-                     --  Special processing for .NET/JVM, the allocated object
-                     --  is attached to the finalization master. Generate:
+                  --    Attach (<PtrT>FM, Root_Controlled_Ptr (Init_Arg1));
 
-                     --    Attach (<PtrT>FM, Root_Controlled_Ptr (Init_Arg1));
+                  --  Types derived from [Limited_]Controlled are the only ones
+                  --  considered since they have fields Prev and Next.
 
-                     --  Types derived from [Limited_]Controlled are the only
-                     --  ones considered since they have fields Prev and Next.
-
-                     if VM_Target /= No_VM then
-                        if Is_Controlled (T) then
-                           Insert_Action (N,
-                             Make_Attach_Call
-                               (Obj_Ref => New_Copy_Tree (Init_Arg1),
-                                Ptr_Typ => PtrT));
-                        end if;
-
-                     --  Default case, generate:
-
-                     --    Set_Finalize_Address
-                     --      (<PtrT>FM, <T>FD'Unrestricted_Access);
-
-                     --  Do not generate this call in CodePeer mode, as TSS
-                     --  primitive Finalize_Address is not created in this
-                     --  mode.
-
-                     elsif not CodePeer_Mode then
-                        Insert_Action (N,
-                          Make_Set_Finalize_Address_Call
-                            (Loc     => Loc,
-                             Typ     => T,
-                             Ptr_Typ => PtrT));
-                     end if;
+                  if VM_Target /= No_VM
+                    and then Is_Controlled (T)
+                    and then Present (Finalization_Master (PtrT))
+                  then
+                     Insert_Action (N,
+                       Make_Attach_Call
+                         (Obj_Ref => New_Copy_Tree (Init_Arg1),
+                          Ptr_Typ => PtrT));
                   end if;
                end if;
 
Index: exp_ch6.adb
===================================================================
--- exp_ch6.adb	(revision 220273)
+++ exp_ch6.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -415,9 +415,10 @@ 
                  and then No (Finalization_Master (Ptr_Typ))
                then
                   Build_Finalization_Master
-                    (Typ        => Ptr_Typ,
-                     Ins_Node   => Associated_Node_For_Itype (Ptr_Typ),
-                     Encl_Scope => Scope (Ptr_Typ));
+                    (Typ            => Ptr_Typ,
+                     For_Anonymous  => True,
+                     Context_Scope  => Scope (Ptr_Typ),
+                     Insertion_Node => Associated_Node_For_Itype (Ptr_Typ));
                end if;
 
                --  Access-to-controlled types should always have a master
@@ -8357,33 +8358,6 @@ 
       Add_Access_Actual_To_Build_In_Place_Call
         (Func_Call, Function_Id, Return_Obj_Actual);
 
-      --  If the build-in-place function call returns a controlled object,
-      --  the finalization master will require a reference to routine
-      --  Finalize_Address of the designated type. Setting this attribute
-      --  is done in the same manner to expansion of allocators.
-
-      if Needs_Finalization (Result_Subt) then
-
-         --  Controlled types with supressed finalization do not need to
-         --  associate the address of their Finalize_Address primitives with
-         --  a master since they do not need a master to begin with.
-
-         if Is_Library_Level_Entity (Acc_Type)
-           and then Finalize_Storage_Only (Result_Subt)
-         then
-            null;
-
-         --  Do not generate the call to Set_Finalize_Address in CodePeer mode
-         --  because Finalize_Address is never built.
-
-         elsif not CodePeer_Mode then
-            Insert_Action (Allocator,
-              Make_Set_Finalize_Address_Call (Loc,
-                Typ     => Etype (Function_Id),
-                Ptr_Typ => Acc_Type));
-         end if;
-      end if;
-
       --  Finally, replace the allocator node with a reference to the temp
 
       Rewrite (Allocator, New_Occurrence_Of (Return_Obj_Access, Loc));
Index: exp_ch3.adb
===================================================================
--- exp_ch3.adb	(revision 220273)
+++ exp_ch3.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, 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- --
@@ -2395,16 +2395,14 @@ 
                      declare
                         Parent_IP : constant Name_Id :=
                                       Make_Init_Proc_Name (Etype (Rec_Ent));
-                        Stmt      : Node_Id;
-                        IP_Call   : Node_Id;
+                        Stmt      : Node_Id := First (Stmts);
+                        IP_Call   : Node_Id := Empty;
                         IP_Stmts  : List_Id;
 
                      begin
                         --  Look for a call to the parent IP at the beginning
                         --  of Stmts associated with the record extension
 
-                        Stmt := First (Stmts);
-                        IP_Call := Empty;
                         while Present (Stmt) loop
                            if Nkind (Stmt) = N_Procedure_Call_Statement
                              and then Chars (Name (Stmt)) = Parent_IP
@@ -6318,8 +6316,9 @@ 
 
    procedure Expand_Freeze_Array_Type (N : Node_Id) is
       Typ      : constant Entity_Id := Entity (N);
+      Base     : constant Entity_Id := Base_Type (Typ);
       Comp_Typ : constant Entity_Id := Component_Type (Typ);
-      Base     : constant Entity_Id := Base_Type (Typ);
+      Ins_Node : Node_Id;
 
    begin
       if not Is_Bit_Packed_Array (Typ) then
@@ -6386,10 +6385,22 @@ 
             if Ekind (Comp_Typ) = E_Anonymous_Access_Type
               and then Needs_Finalization (Designated_Type (Comp_Typ))
             then
+               --  The finalization master is inserted before the declaration
+               --  of the array type. The only exception to this is when the
+               --  array type is an itype, in which case the master appears
+               --  before the related context.
+
+               if Is_Itype (Typ) then
+                  Ins_Node := Associated_Node_For_Itype (Typ);
+               else
+                  Ins_Node := Parent (Typ);
+               end if;
+
                Build_Finalization_Master
-                 (Typ        => Comp_Typ,
-                  Ins_Node   => Parent (Typ),
-                  Encl_Scope => Scope (Typ));
+                 (Typ            => Comp_Typ,
+                  For_Anonymous  => True,
+                  Context_Scope  => Scope (Typ),
+                  Insertion_Node => Ins_Node);
             end if;
          end if;
 
@@ -7342,9 +7353,10 @@ 
                           (Root_Type (Comp_Typ), RTE (RE_Global_Pool_Object));
 
                         Build_Finalization_Master
-                          (Typ        => Root_Type (Comp_Typ),
-                           Ins_Node   => Ins_Node,
-                           Encl_Scope => Encl_Scope);
+                          (Typ            => Root_Type (Comp_Typ),
+                           For_Anonymous  => True,
+                           Context_Scope  => Encl_Scope,
+                           Insertion_Node => Ins_Node);
 
                         Fin_Mas_Id := Finalization_Master (Comp_Typ);
 
@@ -7387,9 +7399,10 @@ 
 
                   else
                      Build_Finalization_Master
-                       (Typ        => Comp_Typ,
-                        Ins_Node   => Ins_Node,
-                        Encl_Scope => Encl_Scope);
+                       (Typ            => Comp_Typ,
+                        For_Anonymous  => True,
+                        Context_Scope  => Encl_Scope,
+                        Insertion_Node => Ins_Node);
                   end if;
                end if;
 
@@ -7466,9 +7479,97 @@ 
       --  Save the current Ghost mode in effect in case the type being frozen
       --  sets a different mode.
 
+      procedure Process_RACW_Types (Typ : Entity_Id);
+      --  Validate and generate stubs for all RACW types associated with type
+      --  Typ.
+
+      procedure Process_Pending_Access_Types (Typ : Entity_Id);
+      --  Associate type Typ's Finalize_Address primitive with the finalization
+      --  masters of pending access-to-Typ types.
+
       procedure Restore_Globals;
       --  Restore the values of all saved global variables
 
+      ------------------------
+      -- Process_RACW_Types --
+      ------------------------
+
+      procedure Process_RACW_Types (Typ : Entity_Id) is
+         List : constant Elist_Id := Access_Types_To_Process (N);
+         E    : Elmt_Id;
+         Seen : Boolean := False;
+
+      begin
+         if Present (List) then
+            E := First_Elmt (List);
+            while Present (E) loop
+               if Is_Remote_Access_To_Class_Wide_Type (Node (E)) then
+                  Validate_RACW_Primitives (Node (E));
+                  Seen := True;
+               end if;
+
+               Next_Elmt (E);
+            end loop;
+         end if;
+
+         --  If there are RACWs designating this type, make stubs now
+
+         if Seen then
+            Remote_Types_Tagged_Full_View_Encountered (Typ);
+         end if;
+      end Process_RACW_Types;
+
+      ----------------------------------
+      -- Process_Pending_Access_Types --
+      ----------------------------------
+
+      procedure Process_Pending_Access_Types (Typ : Entity_Id) is
+         E : Elmt_Id;
+
+      begin
+         --  Finalize_Address is not generated in CodePeer mode because the
+         --  body contains address arithmetic. This processing is disabled.
+
+         if CodePeer_Mode then
+            null;
+
+         --  Certain itypes are generated for contexts that cannot allocate
+         --  objects and should not set primitive Finalize_Address.
+
+         elsif Is_Itype (Typ)
+           and then Nkind (Associated_Node_For_Itype (Typ)) =
+                      N_Explicit_Dereference
+         then
+            null;
+
+         --  When an access type is declared after the incomplete view of a
+         --  Taft-amendment type, the access type is considered pending in
+         --  case the full view of the Taft-amendment type is controlled. If
+         --  this is indeed the case, associate the Finalize_Address routine
+         --  of the full view with the finalization masters of all pending
+         --  access types. This scenario applies to anonymous access types as
+         --  well.
+
+         elsif Needs_Finalization (Typ)
+           and then Present (Pending_Access_Types (Typ))
+         then
+            E := First_Elmt (Pending_Access_Types (Typ));
+            while Present (E) loop
+
+               --  Generate:
+               --    Set_Finalize_Address
+               --      (Ptr_Typ, <Typ>FD'Unrestricted_Access);
+
+               Append_Freeze_Action (Typ,
+                 Make_Set_Finalize_Address_Call
+                   (Loc     => Sloc (N),
+                    Ptr_Typ => Node (E)));
+
+               Next_Elmt (E);
+            end loop;
+         end if;
+      end Process_Pending_Access_Types;
+
       ---------------------
       -- Restore_Globals --
       ---------------------
@@ -7480,9 +7581,8 @@ 
 
       --  Local variables
 
-      Def_Id    : constant Entity_Id := Entity (N);
-      RACW_Seen : Boolean := False;
-      Result    : Boolean := False;
+      Def_Id : constant Entity_Id := Entity (N);
+      Result : Boolean := False;
 
    --  Start of processing for Freeze_Type
 
@@ -7493,30 +7593,11 @@ 
 
       Set_Ghost_Mode_For_Freeze (Def_Id, N);
 
-      --  Process associated access types needing special processing
+      --  Process any remote access-to-class-wide types designating the type
+      --  being frozen.
 
-      if Present (Access_Types_To_Process (N)) then
-         declare
-            E : Elmt_Id := First_Elmt (Access_Types_To_Process (N));
+      Process_RACW_Types (Def_Id);
 
-         begin
-            while Present (E) loop
-               if Is_Remote_Access_To_Class_Wide_Type (Node (E)) then
-                  Validate_RACW_Primitives (Node (E));
-                  RACW_Seen := True;
-               end if;
-
-               E := Next_Elmt (E);
-            end loop;
-         end;
-
-         --  If there are RACWs designating this type, make stubs now
-
-         if RACW_Seen then
-            Remote_Types_Tagged_Full_View_Encountered (Def_Id);
-         end if;
-      end if;
-
       --  Freeze processing for record types
 
       if Is_Record_Type (Def_Id) then
@@ -7760,18 +7841,26 @@ 
             then
                null;
 
-            --  Assume that incomplete and private types are always completed
-            --  by a controlled full view.
+            --  Create a finalization master for an access-to-controlled type
+            --  or an access-to-incomplete type. It is assumed that the full
+            --  view will be controlled.
 
             elsif Needs_Finalization (Desig_Type)
-              or else
-                (Is_Incomplete_Or_Private_Type (Desig_Type)
-                  and then No (Full_View (Desig_Type)))
-              or else
-                (Is_Array_Type (Desig_Type)
-                  and then Needs_Finalization (Component_Type (Desig_Type)))
+              or else (Is_Incomplete_Type (Desig_Type)
+                         and then No (Full_View (Desig_Type)))
             then
                Build_Finalization_Master (Def_Id);
+
+            --  Create a finalization master when the designated type contains
+            --  a private component. It is assumed that the full view will be
+            --  controlled.
+
+            elsif Has_Private_Component (Desig_Type) then
+               Build_Finalization_Master
+                 (Typ            => Def_Id,
+                  For_Private    => True,
+                  Context_Scope  => Scope (Def_Id),
+                  Insertion_Node => Declaration_Node (Desig_Type));
             end if;
          end;
 
@@ -7810,6 +7899,11 @@ 
 
       end if;
 
+      --  Complete the initialization of all pending access types' finalization
+      --  masters now that the designated type has been is frozen and primitive
+      --  Finalize_Address generated.
+
+      Process_Pending_Access_Types (Def_Id);
       Freeze_Stream_Operations (N, Def_Id);
 
       Restore_Globals;