OSDN Git Service

2007-04-20 Gary Dismukes <dismukes@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jun 2007 10:25:50 +0000 (10:25 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jun 2007 10:25:50 +0000 (10:25 +0000)
    Ed Schonberg  <schonberg@adacore.com>

* exp_ch6.ads, exp_ch6.adb (Expand_Call): When adding an extra
accessibility actual, check for the case of an aliased object that has
been rewritten as an Access attribute, and assign Prev to Prev_Orig so
we fall into processing for the attribute rather than the name of the
object.
(Expand_Inline_Call): If an actual is a literal, and the corresponding
formal has its address taken in the body, create a temporary to capture
value.  If the return type is a limited interface, do not treat the
return value as Controlled.
(Is_In_Place_Function):  If the return type is a limited interface,
treat as returning in place. The actual returned object may not always
be limited, but the caller has to assume that it is returned in place.
(Add_Final_List_Actual_To_Build_In_Place_Call): If the call is the
context of an allocator, use the correct finalization chain (that is,
the chain belonging to the access type, rather than the chain belonging
to the current scope).
(Add_Alloc_Form_Actual_To_Build_In_Place_Call): Test for a tagged
result type rather than a controlling result as a precondition for
adding an allocation form actual to a build-in-place call.
(Add_Final_List_Actual_To_Build_In_Place_Call): Ditto.
(Freeze_Subprogram): Code cleanup. Remove all the code that register the
primitive in the dispatch tables. This work is now done by Make_DT when
the type is frozen.
(Register_Predefined_DT_Entry): Removed.
(Add_Return): If end label is not present, use sloc of last statement
for generated return statement in procedure, for better gdb behavior
on expanded code.
(Add_Access_Actual_To_Build_In_Place_Call): Set parent fields of the
object address nodes to ensure proper processing by routines like
Insert_After*.
(Expand_Call): Fix generation of validity check for parameter
(Add_Alloc_Form_Actual_To_Build_In_Place_Call): Return without passing
the allocation form parameter if the result subtype is constrained,
except when the function has a controlling result.
(Add_Final_List_Actual_To_Build_In_Place_Call): Test Controlled_Type
rather than Is_Controlled and Has_Controlled_Component, since we want to
include class-wide result types in this treatment. Also test for a
controlling result, since that also requires passing a finalization
list.
(Make_Build_In_Place_Call_In_Allocator): Call Add_Alloc_Form_Actual_*
even when the result subtype is constrained, to handle calls involving
controlling results.
(Make_Build_In_Place_Call_In_Anonymous_Context): Add_Alloc_Form_Actual_*
is now called even when the result subtype is constrained, to handle
calls involving controlling results.
(Make_Build_In_Place_Call_In_Assignment): Remove test for Is_Constrained
on call to Add_Alloc_Form_Actual_To_Build_In_Place_Call (that procedure
now performs the test).
(Make_Build_In_Place_Call_In_Object_Declaration):
Add_Alloc_Form_Actual_* is now called even when the result subtype is
constrained, to handle calls involving controlling results.
(Add_Return): Accomodate rewritten pattern from local raise to goto
transformation, so that we still recognize an transfer statement
and do the right thing here in that case.
(Expand_N_Subprogram_Body): Add dummy Push/Pop_xxx_Label nodes at start
and end of subprogram code.
(Register_Interface_DT_Entry, Register_Predefined_DT_Entry): Add missing
support for primitives that are functions (without formals) with a
controlling result.
(Inherited_From_Formal): If the actual subtype has not generic parent
type, it is not an actual for a formal derived type, and there is no
operation to inherit from the formal.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125399 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/exp_ch6.adb
gcc/ada/exp_ch6.ads

index e1d245b..d3ee497 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2006, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2007, 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- --
@@ -44,9 +44,9 @@ with Exp_Tss;  use Exp_Tss;
 with Exp_Util; use Exp_Util;
 with Fname;    use Fname;
 with Freeze;   use Freeze;
-with Hostparm; use Hostparm;
 with Inline;   use Inline;
 with Lib;      use Lib;
+with Namet;    use Namet;
 with Nlists;   use Nlists;
 with Nmake;    use Nmake;
 with Opt;      use Opt;
@@ -67,8 +67,8 @@ with Sem_Util; use Sem_Util;
 with Sinfo;    use Sinfo;
 with Snames;   use Snames;
 with Stand;    use Stand;
+with Targparm; use Targparm;
 with Tbuild;   use Tbuild;
-with Ttypes;   use Ttypes;
 with Uintp;    use Uintp;
 with Validsw;  use Validsw;
 
@@ -110,10 +110,14 @@ package body Exp_Ch6 is
 
    procedure Add_Final_List_Actual_To_Build_In_Place_Call
      (Function_Call : Node_Id;
-      Function_Id   : Entity_Id);
+      Function_Id   : Entity_Id;
+      Acc_Type      : Entity_Id);
    --  Ada 2005 (AI-318-02): For a build-in-place call, if the result type has
-   --  controlled parts, add an actual parameter that is a pointer to caller's
-   --  finalization list.
+   --  controlled parts, add an actual parameter that is a pointer to
+   --  appropriate finalization list. The finalization list is that of the
+   --  current scope, except for "new Acc'(F(...))" in which case it's the
+   --  finalization list of the access type returned by the allocator. Acc_Type
+   --  is that type in the allocator case; Empty otherwise.
 
    procedure Add_Task_Actuals_To_Build_In_Place_Call
      (Function_Call : Node_Id;
@@ -230,6 +234,7 @@ package body Exp_Ch6 is
 
       if not Present (Return_Object) then
          Obj_Address := Make_Null (Loc);
+         Set_Parent (Obj_Address, Function_Call);
 
       --  If Return_Object is already an expression of an access type, then use
       --  it directly, since it must be an access value denoting the return
@@ -237,6 +242,7 @@ package body Exp_Ch6 is
 
       elsif Is_Access then
          Obj_Address := Return_Object;
+         Set_Parent (Obj_Address, Function_Call);
 
       --  Apply Unrestricted_Access to caller's return object
 
@@ -245,6 +251,9 @@ package body Exp_Ch6 is
             Make_Attribute_Reference (Loc,
               Prefix         => Return_Object,
               Attribute_Name => Name_Unrestricted_Access);
+
+         Set_Parent (Return_Object, Obj_Address);
+         Set_Parent (Obj_Address, Function_Call);
       end if;
 
       Analyze_And_Resolve (Obj_Address, Etype (Obj_Acc_Formal));
@@ -270,6 +279,19 @@ package body Exp_Ch6 is
       Alloc_Form_Formal : Node_Id;
 
    begin
+      --  The allocation form generally doesn't need to be passed in the case
+      --  of a constrained result subtype, since normally the caller performs
+      --  the allocation in that case. However this formal is still needed in
+      --  the case where the function has a tagged result, because generally
+      --  such functions can be called in a dispatching context and such calls
+      --  must be handled like calls to class-wide functions.
+
+      if Is_Constrained (Underlying_Type (Etype (Function_Id)))
+        and then not Is_Tagged_Type (Underlying_Type (Etype (Function_Id)))
+      then
+         return;
+      end if;
+
       --  Locate the implicit allocation form parameter in the called function.
       --  Maybe it would be better for each implicit formal of a build-in-place
       --  function to have a flag or a Uint attribute to identify it. ???
@@ -357,7 +379,8 @@ package body Exp_Ch6 is
 
    procedure Add_Final_List_Actual_To_Build_In_Place_Call
      (Function_Call : Node_Id;
-      Function_Id   : Entity_Id)
+      Function_Id   : Entity_Id;
+      Acc_Type      : Entity_Id)
    is
       Loc               : constant Source_Ptr := Sloc (Function_Call);
       Final_List        : Node_Id;
@@ -365,10 +388,17 @@ package body Exp_Ch6 is
       Final_List_Formal : Node_Id;
 
    begin
-      --  No such extra parameter is needed if there are no controlled parts
-
-      if not (Is_Controlled (Etype (Function_Id))
-              or else Has_Controlled_Component (Etype (Function_Id))) then
+      --  No such extra parameter is needed if there are no controlled parts.
+      --  The test for Controlled_Type accounts for class-wide results (which
+      --  potentially have controlled parts, even if the root type doesn't),
+      --  and the test for a tagged result type is needed because calls to
+      --  such a function can in general occur in dispatching contexts, which
+      --  must be treated the same as a call to class-wide functions. Both of
+      --  these situations require that a finalization list be passed.
+
+      if not Controlled_Type (Underlying_Type (Etype (Function_Id)))
+        and then not Is_Tagged_Type (Underlying_Type (Etype (Function_Id)))
+      then
          return;
       end if;
 
@@ -376,9 +406,21 @@ package body Exp_Ch6 is
 
       Final_List_Formal := Build_In_Place_Formal (Function_Id, BIP_Final_List);
 
-      --  Create the actual which is a pointer to the current finalization list
+      --  Create the actual which is a pointer to the appropriate finalization
+      --  list. Acc_Type is present if and only if this call is the
+      --  initialization of an allocator. Use the Current_Scope or the Acc_Type
+      --  as appropriate.
+
+      if Present (Acc_Type)
+        and then (Ekind (Acc_Type) = E_Anonymous_Access_Type
+                   or else
+                     Present (Associated_Final_Chain (Base_Type (Acc_Type))))
+      then
+         Final_List := Find_Final_List (Acc_Type);
+      else
+         Final_List := Find_Final_List (Current_Scope);
+      end if;
 
-      Final_List := Find_Final_List (Current_Scope);
       Final_List_Actual :=
         Make_Attribute_Reference (Loc,
           Prefix         => Final_List,
@@ -499,9 +541,9 @@ package body Exp_Ch6 is
            Chars (Extra_Formal) =
              New_External_Name (Chars (Func), BIP_Formal_Suffix (Kind));
          Next_Formal_With_Extras (Extra_Formal);
+         pragma Assert (Present (Extra_Formal));
       end loop;
 
-      pragma Assert (Present (Extra_Formal));
       return Extra_Formal;
    end Build_In_Place_Formal;
 
@@ -735,7 +777,7 @@ package body Exp_Ch6 is
       --  Push our current scope for analyzing the declarations and code that
       --  we will insert for the checking.
 
-      New_Scope (Spec);
+      Push_Scope (Spec);
 
       --  This loop builds temporary variables for each of the referenced
       --  globals, so that at the end of the loop the list Shad_List contains
@@ -1261,7 +1303,7 @@ package body Exp_Ch6 is
             return False;
 
          --  For users of Starlet, we assume that the specification of by-
-         --  reference mechanism is mandatory. This may lead to unligned
+         --  reference mechanism is mandatory. This may lead to unaligned
          --  objects but at least for DEC legacy code it is known to work.
          --  The warning will alert users of this code that a problem may
          --  be lurking.
@@ -1461,7 +1503,7 @@ package body Exp_Ch6 is
             elsif Is_Possibly_Unaligned_Slice (Actual) then
                Add_Call_By_Copy_Code;
 
-            --  Deal with access types where the actual subtpe and the
+            --  Deal with access types where the actual subtype and the
             --  formal subtype are not the same, requiring a check.
 
             --  It is necessary to exclude tagged types because of "downward
@@ -1750,6 +1792,13 @@ package body Exp_Ch6 is
             Gen_Par := Generic_Parent_Type (Parent (Par));
          end if;
 
+         --  If the actual has no generic parent type, the formal is not
+         --  a formal derived type, so nothing to inherit.
+
+         if No (Gen_Par) then
+            return Empty;
+         end if;
+
          --  If the generic parent type is still the generic type, this is a
          --  private formal, not a derived formal, and there are no operations
          --  inherited from the formal.
@@ -1835,8 +1884,12 @@ package body Exp_Ch6 is
          --  if we can tell that the first parameter cannot possibly be null.
          --  This helps optimization and also generation of warnings.
 
-         if not Restriction_Active (No_Exception_Handlers)
-           and then Is_RTE (Subp, RE_Raise_Exception)
+         --  We do not do this if Raise_Exception_Always does not exist, which
+         --  can happen in configurable run time profiles which provide only a
+         --  Raise_Exception, which is in fact an unconditional raise anyway.
+
+         if Is_RTE (Subp, RE_Raise_Exception)
+           and then RTE_Available (RE_Raise_Exception_Always)
          then
             declare
                FA : constant Node_Id := Original_Node (First_Actual (N));
@@ -1850,7 +1903,7 @@ package body Exp_Ch6 is
                  and then Attribute_Name (FA) = Name_Identity
                then
                   Subp := RTE (RE_Raise_Exception_Always);
-                  Set_Entity (Name (N), Subp);
+                  Set_Name (N, New_Occurrence_Of (Subp, Loc));
                end if;
             end;
          end if;
@@ -1928,8 +1981,14 @@ package body Exp_Ch6 is
          Prev := Actual;
          Prev_Orig := Original_Node (Prev);
 
+         --  The original actual may have been a call written in prefix
+         --  form, and rewritten before analysis.
+
          if not Analyzed (Prev_Orig)
-           and then Nkind (Actual) = N_Function_Call
+           and then
+             (Nkind (Actual) = N_Function_Call
+                or else
+              Nkind (Actual) = N_Identifier)
          then
             Prev_Orig := Prev;
          end if;
@@ -2026,6 +2085,23 @@ package body Exp_Ch6 is
          --  Create possible extra actual for accessibility level
 
          if Present (Extra_Accessibility (Formal)) then
+
+            --  Ada 2005 (AI-252): If the actual was rewritten as an Access
+            --  attribute, then the original actual may be an aliased object
+            --  occurring as the prefix in a call using "Object.Operation"
+            --  notation. In that case we must pass the level of the object,
+            --  so Prev_Orig is reset to Prev and the attribute will be
+            --  processed by the code for Access attributes further below.
+
+            if Prev_Orig /= Prev
+              and then Nkind (Prev) = N_Attribute_Reference
+              and then
+                Get_Attribute_Id (Attribute_Name (Prev)) = Attribute_Access
+              and then Is_Aliased_View (Prev_Orig)
+            then
+               Prev_Orig := Prev;
+            end if;
+
             if Is_Entity_Name (Prev_Orig) then
 
                --  When passing an access parameter as the actual to another
@@ -2063,8 +2139,8 @@ package body Exp_Ch6 is
                      end if;
                   end;
 
-               --  The actual is a normal access value, so just pass the
-               --  level of the actual's access type.
+               --  The actual is a normal access value, so just pass the level
+               --  of the actual's access type.
 
                else
                   Add_Extra_Actual
@@ -2173,10 +2249,12 @@ package body Exp_Ch6 is
                null;
 
             --  Suppress null checks when passing to access parameters of Java
-            --  subprograms. (Should this be done for other foreign conventions
-            --  as well ???)
+            --  and CIL subprograms. (Should this be done for other foreign
+            --  conventions as well ???)
 
-            elsif Convention (Subp) = Convention_Java then
+            elsif Convention (Subp) = Convention_Java
+              or else Convention (Subp) = Convention_CIL
+            then
                null;
 
             else
@@ -2194,14 +2272,28 @@ package body Exp_Ch6 is
                 (Ekind (Formal) = E_In_Out_Parameter
                    and then Validity_Check_In_Out_Params)
             then
-               --  If the actual is an indexed component of a packed
-               --  type, it has not been expanded yet. It will be
-               --  copied in the validity code that follows, and has
-               --  to be expanded appropriately, so reanalyze it.
+               --  If the actual is an indexed component of a packed type (or
+               --  is an indexed or selected component whose prefix recursively
+               --  meets this condition), it has not been expanded yet. It will
+               --  be copied in the validity code that follows, and has to be
+               --  expanded appropriately, so reanalyze it.
 
-               if Nkind (Actual) = N_Indexed_Component then
-                  Set_Analyzed (Actual, False);
-               end if;
+               --  What we do is just to unset analyzed bits on prefixes till
+               --  we reach something that does not have a prefix.
+
+               declare
+                  Nod : Node_Id;
+
+               begin
+                  Nod := Actual;
+                  while Nkind (Nod) = N_Indexed_Component
+                          or else
+                        Nkind (Nod) = N_Selected_Component
+                  loop
+                     Set_Analyzed (Nod, False);
+                     Nod := Prefix (Nod);
+                  end loop;
+               end;
 
                Ensure_Valid (Actual);
             end if;
@@ -2266,21 +2358,10 @@ package body Exp_Ch6 is
          --  In a remote call, if the formal is of a class-wide type, check
          --  that the actual meets the requirements described in E.4(18).
 
-         if Remote
-           and then Is_Class_Wide_Type (Etype (Formal))
-         then
+         if Remote and then Is_Class_Wide_Type (Etype (Formal)) then
             Insert_Action (Actual,
-              Make_Implicit_If_Statement (N,
-                Condition       =>
-                  Make_Op_Not (Loc,
-                    Build_Get_Remotely_Callable (Loc,
-                      Make_Selected_Component (Loc,
-                        Prefix => Duplicate_Subexpr_Move_Checks (Actual),
-                        Selector_Name =>
-                          Make_Identifier (Loc, Name_uTag)))),
-                Then_Statements => New_List (
-                  Make_Raise_Program_Error (Loc,
-                    Reason => PE_Illegal_RACW_E_4_18))));
+              Make_Transportable_Check (Loc,
+                Duplicate_Subexpr_Move_Checks (Actual)));
          end if;
 
          --  This label is required when skipping extra actual generation for
@@ -2366,14 +2447,14 @@ package body Exp_Ch6 is
       --  extra actuals since this will be done on the re-analysis of the
       --  dispatching call. Note that we do not try to shorten the actual
       --  list for a dispatching call, it would not make sense to do so.
-      --  Expansion of dispatching calls is suppressed when Java_VM, because
-      --  the JVM back end directly handles the generation of dispatching
+      --  Expansion of dispatching calls is suppressed when VM_Target, because
+      --  the VM back-ends directly handle the generation of dispatching
       --  calls and would have to undo any expansion to an indirect call.
 
       if (Nkind (N) = N_Function_Call
            or else Nkind (N) =  N_Procedure_Call_Statement)
         and then Present (Controlling_Argument (N))
-        and then not Java_VM
+        and then VM_Target = No_VM
       then
          Expand_Dispatching_Call (N);
 
@@ -2780,9 +2861,12 @@ package body Exp_Ch6 is
       end if;
 
       --  Functions returning controlled objects need special attention
+      --  If the return type is limited the context is an initialization
+      --  and different processing applies.
 
       if Controlled_Type (Etype (Subp))
         and then not Is_Inherently_Limited_Type (Etype (Subp))
+        and then not Is_Limited_Interface (Etype (Subp))
       then
          Expand_Ctrl_Function_Call (N);
       end if;
@@ -2871,9 +2955,6 @@ package body Exp_Ch6 is
                   Temp   : Node_Id;
                   Passoc : Node_Id;
 
-                  Discard : Node_Id;
-                  pragma Warnings (Off, Discard);
-
                begin
                   --  First step, remove all the named parameters from the
                   --  list (they are still chained using First_Named_Actual
@@ -2896,7 +2977,7 @@ package body Exp_Ch6 is
                      end loop;
 
                      while Present (Next (Temp)) loop
-                        Discard := Remove_Next (Temp);
+                        Remove (Next (Temp));
                      end loop;
                   end if;
 
@@ -2936,9 +3017,15 @@ package body Exp_Ch6 is
       --  parameter to Raise_Exception is a use of Identity, since in these
       --  cases we know that the parameter is never null.
 
+      --  Note: We must check that the node has not been inlined. This is
+      --  required because under zfp the Raise_Exception subprogram has the
+      --  pragma inline_always (and hence the call has been expanded above
+      --  into a block containing the code of the subprogram).
+
       if Ada_Version >= Ada_05
         and then not GNAT_Mode
         and then Is_RTE (Subp, RE_Raise_Exception)
+        and then Nkind (N) = N_Procedure_Call_Statement
         and then (Nkind (First_Actual (N)) /= N_Attribute_Reference
                    or else Attribute_Name (First_Actual (N)) /= Name_Identity)
       then
@@ -3036,7 +3123,7 @@ package body Exp_Ch6 is
          elsif Nkind (Orig_Bod) /= N_Subprogram_Body then
             return False;
 
-         --  Check if this is an ada 2005 null procedure
+         --  Check if this is an Ada 2005 null procedure
 
          elsif Nkind (Decl) = N_Subprogram_Declaration
            and then Null_Present (Specification (Decl))
@@ -3508,6 +3595,10 @@ package body Exp_Ch6 is
          --  If the actual is a simple name or a literal, no need to
          --  create a temporary, object can be used directly.
 
+         --  If the actual is a literal and the formal has its address taken,
+         --  we cannot pass the literal itself as an argument, so its value
+         --  must be captured in a temporary.
+
          if (Is_Entity_Name (A)
               and then
                (not Is_Scalar_Type (Etype (A))
@@ -3520,9 +3611,11 @@ package body Exp_Ch6 is
            or else (Nkind (A) = N_Identifier
              and then Formal_Is_Used_Once (F))
 
-           or else Nkind (A) = N_Real_Literal
-           or else Nkind (A) = N_Integer_Literal
-           or else Nkind (A) = N_Character_Literal
+           or else
+             ((Nkind (A) = N_Real_Literal    or else
+               Nkind (A) = N_Integer_Literal or else
+               Nkind (A) = N_Character_Literal)
+              and then not Address_Taken (F))
          then
             if Etype (F) /= Etype (A) then
                Set_Renamed_Object
@@ -3563,7 +3656,7 @@ package body Exp_Ch6 is
 
             --  If the actual has a by-reference type, it cannot be copied, so
             --  its value is captured in a renaming declaration. Otherwise
-            --  declare a local constant initalized with the actual.
+            --  declare a local constant initialized with the actual.
 
             if Ekind (F) = E_In_Parameter
               and then not Is_Limited_Type (Etype (A))
@@ -3745,7 +3838,7 @@ package body Exp_Ch6 is
       --  If the return type is returned through the secondary stack; that is
       --  by reference, we don't want to create a temp to force stack checking.
       --  ???"sec stack" is not right -- Ada 95 return-by-reference object are
-      --  returned whereever they are.
+      --  returned wherever they are.
       --  Shouldn't this function be moved to exp_util???
 
       function Rhs_Of_Assign_Or_Decl (N : Node_Id) return Boolean;
@@ -3828,7 +3921,7 @@ package body Exp_Ch6 is
       --  because otherwise gigi may generate a large temporary on the fly and
       --  this can cause trouble with stack checking.
 
-      --  This is unecessary if the call is the expression in an object
+      --  This is unnecessary if the call is the expression in an object
       --  declaration, or if it appears outside of any library unit. This can
       --  only happen if it appears as an actual in a library-level instance,
       --  in which case a temporary will be generated for it once the instance
@@ -3941,6 +4034,9 @@ package body Exp_Ch6 is
    --  Add poll call if ATC polling is enabled, unless the body will be
    --  inlined by the back-end.
 
+   --  Add dummy push/pop label nodes at start and end to clear any local
+   --  exception indications if local-exception-to-goto optimization active.
+
    --  Add return statement if last statement in body is not a return statement
    --  (this makes things easier on Gigi which does not want to have to handle
    --  a missing return).
@@ -3977,189 +4073,49 @@ package body Exp_Ch6 is
       --  the latter test is not critical, it does not matter if we add a
       --  few extra returns, since they get eliminated anyway later on.
 
-      procedure Expand_Thread_Body;
-      --  Perform required expansion of a thread body
-
       ----------------
       -- Add_Return --
       ----------------
 
       procedure Add_Return (S : List_Id) is
-      begin
-         if not Is_Transfer (Last (S)) then
-
-            --  The source location for the return is the end label
-            --  of the procedure in all cases. This is a bit odd when
-            --  there are exception handlers, but not much else we can do.
-
-            Append_To (S, Make_Return_Statement (Sloc (End_Label (H))));
-         end if;
-      end Add_Return;
-
-      ------------------------
-      -- Expand_Thread_Body --
-      ------------------------
-
-      --  The required expansion of a thread body is as follows
-
-      --  procedure <thread body procedure name> is
-
-      --    _Secondary_Stack : aliased
-      --       Storage_Elements.Storage_Array
-      --         (1 .. Storage_Offset (Sec_Stack_Size));
-      --    for _Secondary_Stack'Alignment use Standard'Maximum_Alignment;
-
-      --    _Process_ATSD : aliased System.Threads.ATSD;
-
-      --  begin
-      --     System.Threads.Thread_Body_Enter;
-      --       (_Secondary_Stack'Address,
-      --        _Secondary_Stack'Length,
-      --        _Process_ATSD'Address);
-
-      --     declare
-      --        <user declarations>
-      --     begin
-      --        <user statements>
-      --     <user exception handlers>
-      --     end;
-
-      --    System.Threads.Thread_Body_Leave;
-
-      --  exception
-      --     when E : others =>
-      --       System.Threads.Thread_Body_Exceptional_Exit (E);
-      --  end;
-
-      --  Note the exception handler is omitted if pragma Restriction
-      --  No_Exception_Handlers is currently active.
-
-      procedure Expand_Thread_Body is
-         User_Decls    : constant List_Id := Declarations (N);
-         Sec_Stack_Len : Node_Id;
-
-         TB_Pragma  : constant Node_Id :=
-                        Get_Rep_Pragma (Spec_Id, Name_Thread_Body);
-
-         Ent_SS   : Entity_Id;
-         Ent_ATSD : Entity_Id;
-         Ent_EO   : Entity_Id;
-
-         Decl_SS   : Node_Id;
-         Decl_ATSD : Node_Id;
-
-         Excep_Handlers : List_Id;
+         Last_Stm : Node_Id;
+         Loc      : Source_Ptr;
 
       begin
-         New_Scope (Spec_Id);
-
-         --  Get proper setting for secondary stack size
-
-         if List_Length (Pragma_Argument_Associations (TB_Pragma)) = 2 then
-            Sec_Stack_Len :=
-              Expression (Last (Pragma_Argument_Associations (TB_Pragma)));
-         else
-            Sec_Stack_Len :=
-              New_Occurrence_Of (RTE (RE_Default_Secondary_Stack_Size), Loc);
-         end if;
+         --  Get last statement, ignoring any Pop_xxx_Label nodes, which are
+         --  not relevant in this context since they are not executable.
 
-         Sec_Stack_Len := Convert_To (RTE (RE_Storage_Offset), Sec_Stack_Len);
-
-         --  Build and set declarations for the wrapped thread body
-
-         Ent_SS   :=
-           Make_Defining_Identifier (Loc,
-             Chars => Name_uSecondary_Stack);
-         Ent_ATSD :=
-           Make_Defining_Identifier (Loc,
-             Chars => Name_uProcess_ATSD);
+         Last_Stm := Last (S);
+         while Nkind (Last_Stm) in N_Pop_xxx_Label loop
+            Prev (Last_Stm);
+         end loop;
 
-         Decl_SS :=
-           Make_Object_Declaration (Loc,
-             Defining_Identifier => Ent_SS,
-             Aliased_Present     => True,
-             Object_Definition   =>
-               Make_Subtype_Indication (Loc,
-                 Subtype_Mark =>
-                   New_Occurrence_Of (RTE (RE_Storage_Array), Loc),
-                 Constraint   =>
-                   Make_Index_Or_Discriminant_Constraint (Loc,
-                     Constraints => New_List (
-                       Make_Range (Loc,
-                         Low_Bound  => Make_Integer_Literal (Loc, 1),
-                         High_Bound => Sec_Stack_Len)))));
-
-         Decl_ATSD :=
-           Make_Object_Declaration (Loc,
-             Defining_Identifier => Ent_ATSD,
-             Aliased_Present     => True,
-             Object_Definition   => New_Occurrence_Of (RTE (RE_ATSD), Loc));
+         --  Now insert return unless last statement is a transfer
 
-         Set_Declarations (N, New_List (Decl_SS, Decl_ATSD));
-         Analyze (Decl_SS);
-         Analyze (Decl_ATSD);
-         Set_Alignment (Ent_SS, UI_From_Int (Maximum_Alignment));
+         if not Is_Transfer (Last_Stm) then
 
-         --  Create new exception handler
+            --  The source location for the return is the end label of the
+            --  procedure if present. Otherwise use the sloc of the last
+            --  statement in the list. If the list comes from a generated
+            --  exception handler and we are not debugging generated code,
+            --  all the statements within the handler are made invisible
+            --  to the debugger.
 
-         if Restriction_Active (No_Exception_Handlers) then
-            Excep_Handlers := No_List;
+            if Nkind (Parent (S)) = N_Exception_Handler
+              and then not Comes_From_Source (Parent (S))
+            then
+               Loc := Sloc (Last_Stm);
 
-         else
-            Check_Restriction (No_Exception_Handlers, N);
+            elsif Present (End_Label (H)) then
+               Loc := Sloc (End_Label (H));
 
-            Ent_EO :=
-              Make_Defining_Identifier (Loc,
-                Chars => Name_uE);
+            else
+               Loc := Sloc (Last_Stm);
+            end if;
 
-            Excep_Handlers := New_List (
-              Make_Implicit_Exception_Handler (Loc,
-                Choice_Parameter => Ent_EO,
-                Exception_Choices => New_List (
-                  Make_Others_Choice (Loc)),
-                Statements => New_List (
-                  Make_Procedure_Call_Statement (Loc,
-                    Name =>
-                      New_Occurrence_Of
-                        (RTE (RE_Thread_Body_Exceptional_Exit), Loc),
-                    Parameter_Associations => New_List (
-                      New_Occurrence_Of (Ent_EO, Loc))))));
+            Append_To (S, Make_Return_Statement (Loc));
          end if;
-
-         --  Now build new handled statement sequence and analyze it
-
-         Set_Handled_Statement_Sequence (N,
-           Make_Handled_Sequence_Of_Statements (Loc,
-             Statements => New_List (
-
-               Make_Procedure_Call_Statement (Loc,
-                 Name => New_Occurrence_Of (RTE (RE_Thread_Body_Enter), Loc),
-                 Parameter_Associations => New_List (
-
-                   Make_Attribute_Reference (Loc,
-                     Prefix => New_Occurrence_Of (Ent_SS, Loc),
-                     Attribute_Name => Name_Address),
-
-                   Make_Attribute_Reference (Loc,
-                     Prefix => New_Occurrence_Of (Ent_SS, Loc),
-                     Attribute_Name => Name_Length),
-
-                   Make_Attribute_Reference (Loc,
-                     Prefix => New_Occurrence_Of (Ent_ATSD, Loc),
-                     Attribute_Name => Name_Address))),
-
-               Make_Block_Statement (Loc,
-                 Declarations => User_Decls,
-                 Handled_Statement_Sequence => H),
-
-               Make_Procedure_Call_Statement (Loc,
-                 Name => New_Occurrence_Of (RTE (RE_Thread_Body_Leave), Loc))),
-
-             Exception_Handlers => Excep_Handlers));
-
-         Analyze (Handled_Statement_Sequence (N));
-         End_Scope;
-      end Expand_Thread_Body;
+      end Add_Return;
 
    --  Start of processing for Expand_N_Subprogram_Body
 
@@ -4171,7 +4127,45 @@ package body Exp_Ch6 is
       if Is_Non_Empty_List (Declarations (N)) then
          L := Declarations (N);
       else
-         L := Statements (Handled_Statement_Sequence (N));
+         L := Statements (H);
+      end if;
+
+      --  If local-exception-to-goto optimization active, insert dummy push
+      --  statements at start, and dummy pop statements at end.
+
+      if (Debug_Flag_Dot_G
+           or else Restriction_Active (No_Exception_Propagation))
+        and then Is_Non_Empty_List (L)
+      then
+         declare
+            FS  : constant Node_Id    := First (L);
+            FL  : constant Source_Ptr := Sloc (FS);
+            LS  : Node_Id;
+            LL  : Source_Ptr;
+
+         begin
+            --  LS points to either last statement, if statements are present
+            --  or to the last declaration if there are no statements present.
+            --  It is the node after which the pop's are generated.
+
+            if Is_Non_Empty_List (Statements (H)) then
+               LS := Last (Statements (H));
+            else
+               LS := Last (L);
+            end if;
+
+            LL := Sloc (LS);
+
+            Insert_List_Before_And_Analyze (FS, New_List (
+              Make_Push_Constraint_Error_Label (FL),
+              Make_Push_Program_Error_Label    (FL),
+              Make_Push_Storage_Error_Label    (FL)));
+
+            Insert_List_After_And_Analyze (LS, New_List (
+              Make_Pop_Constraint_Error_Label  (LL),
+              Make_Pop_Program_Error_Label     (LL),
+              Make_Pop_Storage_Error_Label     (LL)));
+         end;
       end if;
 
       --  Find entity for subprogram
@@ -4184,11 +4178,11 @@ package body Exp_Ch6 is
          Spec_Id := Body_Id;
       end if;
 
-      --  Need poll on entry to subprogram if polling enabled. We only
-      --  do this for non-empty subprograms, since it does not seem
-      --  necessary to poll for a dummy null subprogram. Do not add polling
-      --  point if calls to this subprogram will be inlined by the back-end,
-      --  to avoid repeated polling points in nested inlinings.
+      --  Need poll on entry to subprogram if polling enabled. We only do this
+      --  for non-empty subprograms, since it does not seem necessary to poll
+      --  for a dummy null subprogram. Do not add polling point if calls to
+      --  this subprogram will be inlined by the back-end, to avoid repeated
+      --  polling points in nested inlinings.
 
       if Is_Non_Empty_List (L) then
          if Is_Inlined (Spec_Id)
@@ -4393,7 +4387,7 @@ package body Exp_Ch6 is
               Make_Handled_Sequence_Of_Statements (Hloc,
                 Statements => New_List (Blok, Rais)));
 
-            New_Scope (Spec_Id);
+            Push_Scope (Spec_Id);
             Analyze (Blok);
             Analyze (Rais);
             Pop_Scope;
@@ -4442,12 +4436,6 @@ package body Exp_Ch6 is
          end;
       end if;
 
-      --  Deal with thread body
-
-      if Is_Thread_Body (Spec_Id) then
-         Expand_Thread_Body;
-      end if;
-
       --  Set to encode entity names in package body before gigi is called
 
       Qualify_Entity_Names (N);
@@ -4517,7 +4505,7 @@ package body Exp_Ch6 is
             Insert_Before (Prot_Bod, Prot_Decl);
             Prot_Id := Defining_Unit_Name (Specification (Prot_Decl));
 
-            New_Scope (Scope (Scop));
+            Push_Scope (Scope (Scop));
             Analyze (Prot_Decl);
             Create_Extra_Formals (Prot_Id);
             Set_Protected_Body_Subprogram (Subp, Prot_Id);
@@ -4650,7 +4638,7 @@ package body Exp_Ch6 is
                   New_Occurrence_Of (Param, Loc)));
 
             --  Analyze new actual. Other actuals in calls are already analyzed
-            --  and the list of actuals is not renalyzed after rewriting.
+            --  and the list of actuals is not reanalyzed after rewriting.
 
             Set_Parent (Rec, N);
             Analyze (Rec);
@@ -4747,6 +4735,13 @@ package body Exp_Ch6 is
          then
             return False;
 
+         --  If the return type is a limited interface it has to be treated
+         --  as a return in place, even if the actual object is some non-
+         --  limited descendant.
+
+         elsif Is_Limited_Interface (Etype (E)) then
+            return True;
+
          else
             return Is_Inherently_Limited_Type (Etype (E))
               and then Ada_Version >= Ada_05
@@ -4808,7 +4803,6 @@ package body Exp_Ch6 is
 
    procedure Freeze_Subprogram (N : Node_Id) is
       Loc : constant Source_Ptr := Sloc (N);
-      E   : constant Entity_Id  := Entity (N);
 
       procedure Register_Predefined_DT_Entry (Prim : Entity_Id);
       --  (Ada 2005): Register a predefined primitive in all the secondary
@@ -4822,6 +4816,7 @@ package body Exp_Ch6 is
          Iface_DT_Ptr : Elmt_Id;
          Tagged_Typ   : Entity_Id;
          Thunk_Id     : Entity_Id;
+         Thunk_Code   : Node_Id;
 
       begin
          Tagged_Typ := Find_Dispatching_Type (Prim);
@@ -4843,131 +4838,118 @@ package body Exp_Ch6 is
          Iface_DT_Ptr :=
            Next_Elmt (First_Elmt (Access_Disp_Table (Tagged_Typ)));
 
-         while Present (Iface_DT_Ptr) loop
-            Thunk_Id :=
-              Make_Defining_Identifier (Loc,
-                Chars => New_Internal_Name ('T'));
-
-            Insert_Actions (N, New_List (
-              Expand_Interface_Thunk
-               (N           => Prim,
-                Thunk_Alias => Prim,
-                Thunk_Id    => Thunk_Id),
-
-              Build_Set_Predefined_Prim_Op_Address (Loc,
-                Tag_Node =>
-                  New_Reference_To (Node (Iface_DT_Ptr), Loc),
-                Position_Node =>
-                  Make_Integer_Literal (Loc, DT_Position (Prim)),
-                Address_Node =>
-                  Make_Attribute_Reference (Loc,
-                    Prefix         => New_Reference_To (Thunk_Id, Loc),
-                    Attribute_Name => Name_Address))));
+         while Present (Iface_DT_Ptr)
+            and then Ekind (Node (Iface_DT_Ptr)) = E_Constant
+         loop
+            Expand_Interface_Thunk
+              (N           => Prim,
+               Thunk_Alias => Prim,
+               Thunk_Id    => Thunk_Id,
+               Thunk_Code  => Thunk_Code);
+
+            if Present (Thunk_Code) then
+               Insert_Actions (N, New_List (
+                 Thunk_Code,
+
+                 Build_Set_Predefined_Prim_Op_Address (Loc,
+                   Tag_Node => New_Reference_To (Node (Iface_DT_Ptr), Loc),
+                   Position => DT_Position (Prim),
+                   Address_Node =>
+                     Make_Attribute_Reference (Loc,
+                       Prefix         => New_Reference_To (Thunk_Id, Loc),
+                       Attribute_Name => Name_Address))));
+            end if;
 
             Next_Elmt (Iface_DT_Ptr);
          end loop;
       end Register_Predefined_DT_Entry;
 
-   --  Start of processing for Freeze_Subprogram
+      --  Local variables
 
-   begin
-      --  We assume that imported CPP primitives correspond with objects
-      --  whose constructor is in the CPP side (and therefore we don't need
-      --  to generate code to register them in the dispatch table).
-
-      if Is_Imported (E)
-        and then Convention (E) = Convention_CPP
-      then
-         return;
-      end if;
-
-      --  When a primitive is frozen, enter its name in the corresponding
-      --  dispatch table. If the DTC_Entity field is not set this is an
-      --  overridden primitive that can be ignored. We suppress the
-      --  initialization of the dispatch table entry when Java_VM because
-      --  the dispatching mechanism is handled internally by the JVM.
-
-      if Is_Dispatching_Operation (E)
-        and then not Is_Abstract_Subprogram (E)
-        and then Present (DTC_Entity (E))
-        and then not Java_VM
-        and then not Is_CPP_Class (Scope (DTC_Entity (E)))
-      then
-         Check_Overriding_Operation (E);
+      Subp : constant Entity_Id := Entity (N);
+      Typ  : constant Entity_Id := Etype (Subp);
+      Utyp : constant Entity_Id := Underlying_Type (Typ);
 
-         --  Ada 95 case: Register the subprogram in the primary dispatch table
+   begin
+      if not Static_Dispatch_Tables then
+         declare
+            E   : constant Entity_Id := Subp;
+            Typ : Entity_Id;
 
-         --  Do not register the subprogram in the dispatch table if we are
-         --  compiling under No_Dispatching_Calls restriction.
+         begin
+            --  We assume that imported CPP primitives correspond with objects
+            --  whose constructor is in the CPP side (and therefore we don't
+            --  need to generate code to register them in the dispatch table).
 
-         if not Restriction_Active (No_Dispatching_Calls) then
+            if Is_Imported (E)
+              and then Convention (E) = Convention_CPP
+            then
+               return;
+            end if;
 
-            if Ada_Version < Ada_05 then
-               Insert_After (N,
-                 Fill_DT_Entry (Sloc (N), Prim => E));
+            --  When a primitive is frozen, enter its name in the corresponding
+            --  dispatch table. If the DTC_Entity field is not set this is
+            --  an overridden primitive that can be ignored. We suppress the
+            --  initialization of the dispatch table entry when VM_Target
+            --  because the dispatching mechanism is handled internally by
+            --  the VM.
+
+            if Is_Dispatching_Operation (E)
+              and then not Is_Abstract_Subprogram (E)
+              and then Present (DTC_Entity (E))
+              and then VM_Target = No_VM
+              and then not Is_CPP_Class (Scope (DTC_Entity (E)))
+            then
+               Check_Overriding_Operation (E);
 
-            --  Ada 2005 case: Register the subprogram in all the dispatch
-            --  tables associated with the type
+               --  Register the primitive in its dispatch table if we are not
+               --  compiling under No_Dispatching_Calls restriction
 
-            else
-               declare
-                  Typ : constant Entity_Id := Scope (DTC_Entity (E));
+               if not Restriction_Active (No_Dispatching_Calls)
+                 and then RTE_Available (RE_Tag)
+               then
+                  Typ := Scope (DTC_Entity (E));
 
-               begin
                   if not Is_Interface (Typ)
-                    and then Is_Predefined_Dispatching_Operation (E)
-                  then
-                     Register_Predefined_DT_Entry (E);
-                     Insert_After (N, Fill_DT_Entry (Sloc (N), Prim => E));
-
-                  --  There is no dispatch table associated with abstract
-                  --  interface types. Each type implementing interfaces will
-                  --  fill the associated secondary DT entries.
-
-                  elsif not Is_Interface (Typ)
-                    or else Present (Alias (E))
+                    or else Present (Abstract_Interface_Alias (E))
                   then
-                     --  Ada 2005 (AI-251): Check if this entry corresponds
-                     --  with a subprogram that covers an abstract interface
-                     --  type.
-
-                     if Present (Abstract_Interface_Alias (E)) then
-                        Register_Interface_DT_Entry (N, E);
+                     if Is_Predefined_Dispatching_Operation (E) then
+                        Register_Predefined_DT_Entry (E);
+                     end if;
 
-                     --  Common case: Primitive subprogram
+                     Register_Primitive (Loc,
+                       Prim    => E,
+                       Ins_Nod => N);
+                  end if;
+               end if;
+            end if;
+         end;
 
-                     else
-                        --  Generate thunks for all the predefined operations
+      --  GCC 4.1 backend
 
-                        if Is_Predefined_Dispatching_Operation (E) then
-                           Register_Predefined_DT_Entry (E);
-                        end if;
+      else
+         --  Handle private overriden primitives
 
-                        Insert_After (N,
-                          Fill_DT_Entry (Sloc (N), Prim => E));
-                     end if;
-                  end if;
-               end;
-            end if;
+         if Is_Dispatching_Operation (Subp)
+           and then not Is_Abstract_Subprogram (Subp)
+           and then Present (DTC_Entity (Subp))
+           and then VM_Target = No_VM
+           and then not Is_CPP_Class (Scope (DTC_Entity (Subp)))
+         then
+            Check_Overriding_Operation (Subp);
          end if;
       end if;
 
-      --  Mark functions that return by reference. Note that it cannot be
-      --  part of the normal semantic analysis of the spec since the
-      --  underlying returned type may not be known yet (for private types).
+      --  Mark functions that return by reference. Note that it cannot be part
+      --  of the normal semantic analysis of the spec since the underlying
+      --  returned type may not be known yet (for private types).
 
-      declare
-         Typ  : constant Entity_Id := Etype (E);
-         Utyp : constant Entity_Id := Underlying_Type (Typ);
+      if Is_Inherently_Limited_Type (Typ) then
+         Set_Returns_By_Ref (Subp);
 
-      begin
-         if Is_Inherently_Limited_Type (Typ) then
-            Set_Returns_By_Ref (E);
-
-         elsif Present (Utyp) and then CW_Or_Controlled_Type (Utyp) then
-            Set_Returns_By_Ref (E);
-         end if;
-      end;
+      elsif Present (Utyp) and then CW_Or_Controlled_Type (Utyp) then
+         Set_Returns_By_Ref (Subp);
+      end if;
    end Freeze_Subprogram;
 
    -------------------------------------------
@@ -5009,7 +4991,12 @@ package body Exp_Ch6 is
       --  allocated on the caller side, and access to it is passed to the
       --  function.
 
-      if Is_Constrained (Result_Subt) then
+      --  Here and in related routines, we must examine the full view of the
+      --  type, because the view at the point of call may differ from that
+      --  that in the function body, and the expansion mechanism depends on
+      --  the characteristics of the full view.
+
+      if Is_Constrained (Underlying_Type (Result_Subt)) then
 
          --  Replace the initialized allocator of form "new T'(Func (...))"
          --  with an uninitialized allocator of form "new T", where T is the
@@ -5038,14 +5025,26 @@ package body Exp_Ch6 is
              Object_Definition   => New_Reference_To (Acc_Type, Loc),
              Expression          => Relocate_Node (Allocator)));
 
+         --  When the function has a controlling result, an allocation-form
+         --  parameter must be passed indicating that the caller is allocating
+         --  the result object. This is needed because such a function can be
+         --  called as a dispatching operation and must be treated similarly
+         --  to functions with unconstrained result subtypes.
+
+         Add_Alloc_Form_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
+
+         Add_Final_List_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Acc_Type);
+
+         Add_Task_Actuals_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Master_Actual => Master_Id (Acc_Type));
+
          --  Add an implicit actual to the function call that provides access
          --  to the allocated object. An unchecked conversion to the (specific)
          --  result subtype of the function is inserted to handle cases where
          --  the access type of the allocator has a class-wide designated type.
 
-         Add_Final_List_Actual_To_Build_In_Place_Call (Func_Call, Function_Id);
-         Add_Task_Actuals_To_Build_In_Place_Call
-           (Func_Call, Function_Id, Master_Actual => Master_Id (Acc_Type));
          Add_Access_Actual_To_Build_In_Place_Call
            (Func_Call,
             Function_Id,
@@ -5063,18 +5062,22 @@ package body Exp_Ch6 is
       --  operations. ???
 
       else
+
          --  Pass an allocation parameter indicating that the function should
          --  allocate its result on the heap.
 
          Add_Alloc_Form_Actual_To_Build_In_Place_Call
            (Func_Call, Function_Id, Alloc_Form => Global_Heap);
 
-         --  The caller does not provide the return object in this case, so we
-         --  have to pass null for the object access actual.
+         Add_Final_List_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Acc_Type);
 
-         Add_Final_List_Actual_To_Build_In_Place_Call (Func_Call, Function_Id);
          Add_Task_Actuals_To_Build_In_Place_Call
            (Func_Call, Function_Id, Master_Actual => Master_Id (Acc_Type));
+
+         --  The caller does not provide the return object in this case, so we
+         --  have to pass null for the object access actual.
+
          Add_Access_Actual_To_Build_In_Place_Call
            (Func_Call, Function_Id, Return_Object => Empty);
       end if;
@@ -5123,7 +5126,7 @@ package body Exp_Ch6 is
       --  When the result subtype is constrained, an object of the subtype is
       --  declared and an access value designating it is passed as an actual.
 
-      if Is_Constrained (Result_Subt) then
+      if Is_Constrained (Underlying_Type (Result_Subt)) then
 
          --  Create a temporary object to hold the function result
 
@@ -5142,12 +5145,24 @@ package body Exp_Ch6 is
 
          Insert_Action (Func_Call, Return_Obj_Decl);
 
-         --  Add an implicit actual to the function call that provides access
-         --  to the caller's return object.
+         --  When the function has a controlling result, an allocation-form
+         --  parameter must be passed indicating that the caller is allocating
+         --  the result object. This is needed because such a function can be
+         --  called as a dispatching operation and must be treated similarly
+         --  to functions with unconstrained result subtypes.
+
+         Add_Alloc_Form_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
+
+         Add_Final_List_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Acc_Type => Empty);
 
-         Add_Final_List_Actual_To_Build_In_Place_Call (Func_Call, Function_Id);
          Add_Task_Actuals_To_Build_In_Place_Call
            (Func_Call, Function_Id, Make_Identifier (Loc, Name_uMaster));
+
+         --  Add an implicit actual to the function call that provides access
+         --  to the caller's return object.
+
          Add_Access_Actual_To_Build_In_Place_Call
            (Func_Call, Function_Id, New_Reference_To (Return_Obj_Id, Loc));
 
@@ -5157,18 +5172,22 @@ package body Exp_Ch6 is
       --  scope is established to ensure eventual cleanup of the result.
 
       else
+
          --  Pass an allocation parameter indicating that the function should
          --  allocate its result on the secondary stack.
 
          Add_Alloc_Form_Actual_To_Build_In_Place_Call
            (Func_Call, Function_Id, Alloc_Form => Secondary_Stack);
 
-         --  Pass a null value to the function since no return object is
-         --  available on the caller side.
+         Add_Final_List_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Acc_Type => Empty);
 
-         Add_Final_List_Actual_To_Build_In_Place_Call (Func_Call, Function_Id);
          Add_Task_Actuals_To_Build_In_Place_Call
            (Func_Call, Function_Id, Make_Identifier (Loc, Name_uMaster));
+
+         --  Pass a null value to the function since no return object is
+         --  available on the caller side.
+
          Add_Access_Actual_To_Build_In_Place_Call
            (Func_Call, Function_Id, Empty);
 
@@ -5215,18 +5234,22 @@ package body Exp_Ch6 is
 
       --  When the result subtype is unconstrained, an additional actual must
       --  be passed to indicate that the caller is providing the return object.
+      --  This parameter must also be passed when the called function has a
+      --  controlling result, because dispatching calls to the function needs
+      --  to be treated effectively the same as calls to class-wide functions.
 
-      if not Is_Constrained (Result_Subt) then
-         Add_Alloc_Form_Actual_To_Build_In_Place_Call
-           (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
-      end if;
+      Add_Alloc_Form_Actual_To_Build_In_Place_Call
+        (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
 
-      --  Add an implicit actual to the function call that provides access to
-      --  the caller's return object.
+      Add_Final_List_Actual_To_Build_In_Place_Call
+        (Func_Call, Function_Id, Acc_Type => Empty);
 
-      Add_Final_List_Actual_To_Build_In_Place_Call (Func_Call, Function_Id);
       Add_Task_Actuals_To_Build_In_Place_Call
         (Func_Call, Function_Id, Make_Identifier (Loc, Name_uMaster));
+
+      --  Add an implicit actual to the function call that provides access to
+      --  the caller's return object.
+
       Add_Access_Actual_To_Build_In_Place_Call
         (Func_Call,
          Function_Id,
@@ -5282,6 +5305,7 @@ package body Exp_Ch6 is
       Loc             : Source_Ptr;
       Obj_Def_Id      : constant Entity_Id :=
                           Defining_Identifier (Object_Decl);
+
       Func_Call       : Node_Id := Function_Call;
       Function_Id     : Entity_Id;
       Result_Subt     : Entity_Id;
@@ -5318,12 +5342,21 @@ package body Exp_Ch6 is
       --  to the (specific) result type of the function is inserted to handle
       --  the case where the object is declared with a class-wide type.
 
-      if Is_Constrained (Result_Subt) then
+      if Is_Constrained (Underlying_Type (Result_Subt)) then
          Caller_Object :=
             Make_Unchecked_Type_Conversion (Loc,
               Subtype_Mark => New_Reference_To (Result_Subt, Loc),
               Expression   => New_Reference_To (Obj_Def_Id, Loc));
 
+         --  When the function has a controlling result, an allocation-form
+         --  parameter must be passed indicating that the caller is allocating
+         --  the result object. This is needed because such a function can be
+         --  called as a dispatching operation and must be treated similarly
+         --  to functions with unconstrained result subtypes.
+
+         Add_Alloc_Form_Actual_To_Build_In_Place_Call
+           (Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
+
       --  If the function's result subtype is unconstrained and the object is
       --  a return object of an enclosing build-in-place function, then the
       --  implicit build-in-place parameters of the enclosing function must be
@@ -5343,7 +5376,7 @@ package body Exp_Ch6 is
 
          --  Otherwise, when the enclosing function has an unconstrained result
          --  type, the BIP_Alloc_Form formal of the enclosing function must be
-         --  passed long to the callee.
+         --  passed along to the callee.
 
          else
             Add_Alloc_Form_Actual_To_Build_In_Place_Call
@@ -5385,22 +5418,28 @@ package body Exp_Ch6 is
          Establish_Transient_Scope (Object_Decl, Sec_Stack => True);
       end if;
 
-      Add_Final_List_Actual_To_Build_In_Place_Call (Func_Call, Function_Id);
+      Add_Final_List_Actual_To_Build_In_Place_Call
+        (Func_Call, Function_Id, Acc_Type => Empty);
+
       if Nkind (Parent (Object_Decl)) = N_Extended_Return_Statement
         and then Has_Task (Result_Subt)
       then
          Enclosing_Func := Enclosing_Subprogram (Obj_Def_Id);
+
+         --  Here we're passing along the master that was passed in to this
+         --  function.
+
          Add_Task_Actuals_To_Build_In_Place_Call
            (Func_Call, Function_Id,
             Master_Actual =>
               New_Reference_To
                 (Build_In_Place_Formal (Enclosing_Func, BIP_Master), Loc));
-         --  Here we're passing along the master that was passed in to this
-         --  function.
+
       else
          Add_Task_Actuals_To_Build_In_Place_Call
            (Func_Call, Function_Id, Make_Identifier (Loc, Name_uMaster));
       end if;
+
       Add_Access_Actual_To_Build_In_Place_Call
         (Func_Call, Function_Id, Caller_Object, Is_Access => Pass_Caller_Acc);
 
@@ -5425,7 +5464,7 @@ package body Exp_Ch6 is
       --  the object declaration is rewritten to be a renaming of a dereference
       --  of the access object.
 
-      if Is_Constrained (Result_Subt) then
+      if Is_Constrained (Underlying_Type (Result_Subt)) then
          Insert_After_And_Analyze (Object_Decl, Ptr_Typ_Decl);
       else
          Insert_Before_And_Analyze (Object_Decl, Ptr_Typ_Decl);
@@ -5449,7 +5488,7 @@ package body Exp_Ch6 is
           Object_Definition   => New_Reference_To (Ref_Type, Loc),
           Expression          => New_Expr));
 
-      if Is_Constrained (Result_Subt) then
+      if Is_Constrained (Underlying_Type (Result_Subt)) then
          Set_Expression (Object_Decl, Empty);
          Set_No_Initialization (Object_Decl);
 
@@ -5501,51 +5540,4 @@ package body Exp_Ch6 is
       end if;
    end Make_Build_In_Place_Call_In_Object_Declaration;
 
-   ---------------------------------
-   -- Register_Interface_DT_Entry --
-   ---------------------------------
-
-   procedure Register_Interface_DT_Entry
-     (Related_Nod : Node_Id;
-      Prim        : Entity_Id)
-   is
-      Loc        : constant Source_Ptr := Sloc (Prim);
-      Iface_Typ  : Entity_Id;
-      Tagged_Typ : Entity_Id;
-      Thunk_Id   : Entity_Id;
-
-   begin
-      --  Nothing to do if the run-time does not support abstract interfaces
-
-      if not (RTE_Available (RE_Interface_Tag)) then
-         return;
-      end if;
-
-      Tagged_Typ := Find_Dispatching_Type (Alias (Prim));
-      Iface_Typ  := Find_Dispatching_Type (Abstract_Interface_Alias (Prim));
-
-      --  Generate the code of the thunk only if the abstract interface type is
-      --  not an immediate ancestor of Tagged_Type; otherwise the dispatch
-      --  table associated with the interface is the primary dispatch table.
-
-      pragma Assert (Is_Interface (Iface_Typ));
-
-      if not Is_Parent (Iface_Typ, Tagged_Typ) then
-         Thunk_Id  :=
-           Make_Defining_Identifier (Loc,
-             Chars => New_Internal_Name ('T'));
-
-         Insert_Actions (Related_Nod, New_List (
-           Expand_Interface_Thunk
-             (N           => Prim,
-              Thunk_Alias => Alias (Prim),
-              Thunk_Id    => Thunk_Id),
-
-           Fill_Secondary_DT_Entry (Sloc (Prim),
-             Prim         => Prim,
-             Iface_DT_Ptr => Find_Interface_ADT (Tagged_Typ, Iface_Typ),
-             Thunk_Id     => Thunk_Id)));
-      end if;
-   end Register_Interface_DT_Entry;
-
 end Exp_Ch6;
index 436654c..415fad2 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2006, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2007, 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- --
@@ -61,10 +61,10 @@ package Exp_Ch6 is
    --  enumeration literals matches the order in which the formals are
    --  declared. See Sem_Ch6.Create_Extra_Formals.
      (BIP_Alloc_Form,
-      --  Present if result subtype is unconstrained. Indicates whether the
-      --  return object is allocated by the caller or callee, and if the
-      --  callee, whether to use the secondary stack or the heap. See
-      --  Create_Extra_Formals.
+      --  Present if result subtype is unconstrained, or if the result type
+      --  is tagged. Indicates whether the return object is allocated by the
+      --  caller or callee, and if the callee, whether to use the secondary
+      --  stack or the heap. See Create_Extra_Formals.
       BIP_Final_List,
       --  Present if result type has controlled parts. Pointer to caller's
       --  finalization list.
@@ -162,10 +162,4 @@ package Exp_Ch6 is
    --  for which Is_Build_In_Place_Call is True, or an N_Qualified_Expression
    --  node applied to such a function call.
 
-   procedure Register_Interface_DT_Entry
-     (Related_Nod : Node_Id;
-      Prim        : Entity_Id);
-   --  Ada 2005 (AI-251): Register a primitive in a secondary dispatch table.
-   --  Related_Nod is the node after which the expanded code will be inserted.
-
 end Exp_Ch6;