--  visible entity with that name.
 
    procedure Install_Entity (E : Entity_Id);
-   --  Make single entity visible. Used for generic formals as well.
+   --  Make single entity visible. Used for generic formals as well
 
    procedure Install_Formals (Id : Entity_Id);
    --  On entry to a subprogram body, make the formals visible. Note
             end loop;
          end if;
 
-         --  Visible generic entity is callable within its own body.
+         --  Visible generic entity is callable within its own body
 
          Set_Ekind (Gen_Id, Ekind (Body_Id));
          Set_Ekind (Body_Id, E_Subprogram_Body);
 
          if Nkind (N) = N_Subprogram_Body_Stub then
 
-            --  No body to analyze, so restore state of generic unit.
+            --  No body to analyze, so restore state of generic unit
 
             Set_Ekind (Gen_Id, Kind);
             Set_Ekind (Body_Id, Kind);
       End_Scope;
       Check_Subprogram_Order (N);
 
-      --  Outside of its body, unit is generic again.
+      --  Outside of its body, unit is generic again
 
       Set_Ekind (Gen_Id, Kind);
       Generate_Reference (Gen_Id, Body_Id, 'b', Set_Ref => False);
          Analyze (P);
          Analyze_Call_And_Resolve;
 
-      --  Anything else is an error.
+      --  Anything else is an error
 
       else
          Error_Msg_N ("Invalid procedure or entry call", N);
       if Nkind (Parent (N)) = N_Subunit
         and then Comes_From_Source (N)
         and then not Error_Posted (Body_Id)
+        and then Nkind (Corresponding_Stub (Parent (N))) =
+                                                N_Subprogram_Body_Stub
       then
          declare
             Old_Id : constant Entity_Id :=
       then
          Set_Categorization_From_Scope (Designator, Scop);
       else
-         --  For a compilation unit, check for library-unit pragmas.
+         --  For a compilation unit, check for library-unit pragmas
 
          New_Scope (Designator);
          Set_Categorization_From_Pragmas (N);
       Stat_Count      : Integer := 0;
 
       function Has_Excluded_Declaration (Decls : List_Id) return Boolean;
-      --  Check for declarations that make inlining not worthwhile.
+      --  Check for declarations that make inlining not worthwhile
 
       function Has_Excluded_Statement   (Stats : List_Id) return Boolean;
       --  Check for statements that make inlining not worthwhile: any
       --  Remove it from body to inline. The analysis of the non-inlined
       --  body will handle the pragma properly.
 
+      function Uses_Secondary_Stack (Bod : Node_Id) return Boolean;
+      --  If the body of the subprogram includes a call that returns an
+      --  unconstrained type, the secondary stack is involved, and it
+      --  is not worth inlining.
+
       ------------------------------
       -- Has_Excluded_Declaration --
       ------------------------------
          end loop;
       end Remove_Pragmas;
 
+      --------------------------
+      -- Uses_Secondary_Stack --
+      --------------------------
+
+      function Uses_Secondary_Stack (Bod : Node_Id) return Boolean is
+         function Check_Call (N : Node_Id) return Traverse_Result;
+         --  Look for function calls that return an unconstrained type
+
+         ----------------
+         -- Check_Call --
+         ----------------
+
+         function Check_Call (N : Node_Id) return Traverse_Result is
+         begin
+            if Nkind (N) = N_Function_Call
+              and then Is_Entity_Name (Name (N))
+              and then Is_Composite_Type (Etype (Entity (Name (N))))
+              and then not Is_Constrained (Etype (Entity (Name (N))))
+            then
+               Cannot_Inline
+                 ("cannot inline & (call returns unconstrained type)?",
+                    N, Subp);
+               return Abandon;
+            else
+               return OK;
+            end if;
+         end Check_Call;
+
+         function Check_Calls is new Traverse_Func (Check_Call);
+
+      begin
+         return Check_Calls (Bod) = Abandon;
+      end Uses_Secondary_Stack;
+
    --  Start of processing for Build_Body_To_Inline
 
    begin
       Remove (Body_To_Analyze);
 
       Expander_Mode_Restore;
-      Set_Body_To_Inline (Decl, Original_Body);
-      Set_Ekind (Defining_Entity (Original_Body), Ekind (Subp));
-      Set_Is_Inlined (Subp);
 
       if In_Instance then
          Restore_Env;
       end if;
+
+      --  If secondary stk used there is no point in inlining. We have
+      --  already issued the warning in this case, so nothing to do.
+
+      if Uses_Secondary_Stack (Body_To_Analyze) then
+         return;
+      end if;
+
+      Set_Body_To_Inline (Decl, Original_Body);
+      Set_Ekind (Defining_Entity (Original_Body), Ekind (Subp));
+      Set_Is_Inlined (Subp);
    end Build_Body_To_Inline;
 
    -------------------
          null;
 
       elsif Is_Always_Inlined (Subp) then
+
+         --  Remove last character (question mark) to make this into an error,
+         --  because the Inline_Always pragma cannot be obeyed.
+
          Error_Msg_NE (Msg (1 .. Msg'Length - 1), N, Subp);
 
       elsif Ineffective_Inline_Warnings then
       --  match explicit actuals with the same value.
 
       function FCO (Op_Node, Call_Node : Node_Id) return Boolean;
-      --  Compare an operator node with a function call.
+      --  Compare an operator node with a function call
 
       ---------
       -- FCL --
       --  body is replaced with the discriminal of the enclosing type.
 
       function Conforming_Ranges (R1, R2 : Node_Id) return Boolean;
-      --  Check both bounds.
+      --  Check both bounds
 
       function Conforming_Bounds (B1, B2 : Node_Id) return Boolean is
       begin
       B : Entity_Id;
 
    begin
-      --  Check that equality was properly defined.
+      --  Check that equality was properly defined
 
       if  No (Next_Formal (First_Formal (S))) then
          return;
                            if not Is_Dispatching_Operation (E) then
                               Set_Is_Immediately_Visible (E, False);
                            else
-
-                              --  work done in Override_Dispatching_Operation.
+                              --  Work done in Override_Dispatching_Operation,
+                              --  so nothing else need to be done here.
 
                               null;
                            end if;
       while Present (Formal) loop
          T := Etype (Formal);
 
-         --  We never need an actual subtype for a constrained formal.
+         --  We never need an actual subtype for a constrained formal
 
          if Is_Constrained (T) then
             AS_Needed := False;