OSDN Git Service

2004-05-17 Steve Kargl <kargls@comcast.net>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_elab.adb
index 4ff0358..78b5663 100644 (file)
@@ -6,8 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                                                                          --
---          Copyright (C) 1997-2002 Free Software Foundation, Inc.          --
+--          Copyright (C) 1997-2004 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- --
@@ -31,6 +30,7 @@ with Debug;    use Debug;
 with Einfo;    use Einfo;
 with Elists;   use Elists;
 with Errout;   use Errout;
+with Exp_Tss;  use Exp_Tss;
 with Exp_Util; use Exp_Util;
 with Expander; use Expander;
 with Fname;    use Fname;
@@ -42,6 +42,7 @@ with Nmake;    use Nmake;
 with Opt;      use Opt;
 with Output;   use Output;
 with Restrict; use Restrict;
+with Rident;   use Rident;
 with Sem;      use Sem;
 with Sem_Cat;  use Sem_Cat;
 with Sem_Ch7;  use Sem_Ch7;
@@ -300,7 +301,18 @@ package body Sem_Elab is
       Decl : Node_Id;
 
       E_Scope : Entity_Id;
-      --  Top level scope of entity for called subprogram
+      --  Top level scope of entity for called subprogram. This
+      --  value includes following renamings and derivations, so
+      --  this scope can be in a non-visible unit. This is the
+      --  scope that is to be investigated to see whether an
+      --  elaboration check is required.
+
+      W_Scope : Entity_Id;
+      --  Top level scope of directly called entity for subprogram.
+      --  This differs from E_Scope in the case where renamings or
+      --  derivations are involved, since it does not follow these
+      --  links, thus W_Scope is always in a visible unit. This is
+      --  the scope for the Elaborate_All if one is needed.
 
       Body_Acts_As_Spec : Boolean;
       --  Set to true if call is to body acting as spec (no separate spec)
@@ -317,23 +329,33 @@ package body Sem_Elab is
       Unit_Caller : Unit_Number_Type;
       Unit_Callee : Unit_Number_Type;
 
-      Cunit_SW : Boolean := False;
-      --  Set to suppress warnings for case of external reference where
-      --  one of the enclosing scopes has the Suppress_Elaboration_Warnings
-      --  flag set. For the internal case, we ignore this flag.
-
       Cunit_SC : Boolean := False;
       --  Set to suppress dynamic elaboration checks where one of the
-      --  enclosing scopes has Suppress_Elaboration_Checks set. For
-      --  the internal case, we ignore this flag.
+      --  enclosing scopes has Elaboration_Checks_Suppressed set, or else
+      --  if a pragma Elaborate (_All) applies to that scope, in which case
+      --  warnings on the scope are also suppressed. For the internal case,
+      --  we ignore this flag.
 
    begin
+      --  If the call is known to be within a local Suppress Elaboration
+      --  pragma, nothing to check. This can happen in task bodies.
+
+      if (Nkind (N) = N_Function_Call
+           or else Nkind (N) = N_Procedure_Call_Statement)
+        and then  No_Elaboration_Check (N)
+      then
+         return;
+      end if;
+
       --  Go to parent for derived subprogram, or to original subprogram
       --  in the case of a renaming (Alias covers both these cases)
 
       Ent := E;
       loop
-         if Suppress_Elaboration_Warnings (Ent) then
+         if (Suppress_Elaboration_Warnings (Ent)
+              or else Elaboration_Checks_Suppressed (Ent))
+           and then (Inst_Case or else No (Alias (Ent)))
+         then
             return;
          end if;
 
@@ -369,11 +391,9 @@ package body Sem_Elab is
 
       E_Scope := Ent;
       loop
-         if Suppress_Elaboration_Warnings (E_Scope) then
-            Cunit_SW := True;
-         end if;
-
-         if Suppress_Elaboration_Checks (E_Scope) then
+         if Elaboration_Checks_Suppressed (E_Scope)
+           or else Suppress_Elaboration_Warnings (E_Scope)
+         then
             Cunit_SC := True;
          end if;
 
@@ -436,9 +456,9 @@ package body Sem_Elab is
             return;
          end if;
 
-         --  Nothing to do if some scope said to ignore warnings
+         --  Nothing to do if some scope said that no checks were required
 
-         if Cunit_SW then
+         if Cunit_SC then
             return;
          end if;
 
@@ -450,10 +470,36 @@ package body Sem_Elab is
             return;
          end if;
 
-         --  Nothing to do if subprogram with no separate spec
+         --  Nothing to do if subprogram with no separate spec. However,
+         --  a call to Deep_Initialize may result in a call to a user-defined
+         --  Initialize procedure, which imposes a body dependency. This
+         --  happens only if the type is controlled and the Initialize
+         --  procedure is not inherited.
 
          if Body_Acts_As_Spec then
-            return;
+            if Is_TSS (Ent, TSS_Deep_Initialize) then
+               declare
+                  Typ  : Entity_Id;
+                  Init : Entity_Id;
+               begin
+                  Typ  := Etype (Next_Formal (First_Formal (Ent)));
+
+                  if not Is_Controlled (Typ) then
+                     return;
+                  else
+                     Init := Find_Prim_Op (Typ, Name_Initialize);
+
+                     if Comes_From_Source (Init) then
+                        Ent := Init;
+                     else
+                        return;
+                     end if;
+                  end if;
+               end;
+
+            else
+               return;
+            end if;
          end if;
 
          --  Check cases of internal units
@@ -496,7 +542,9 @@ package body Sem_Elab is
             return;
          end if;
 
-         Ent := E;
+         if Is_TSS (E, TSS_Deep_Initialize) then
+            Ent := E;
+         end if;
 
          --  If the call is in an instance, and the called entity is not
          --  defined in the same instance, then the elaboration issue
@@ -574,6 +622,12 @@ package body Sem_Elab is
                exit when E_Scope /= C_Scope;
                Ent := Alias (Ent);
                E_Scope := Ent;
+
+               --  If no alias, there is a previous error
+
+               if No (Ent) then
+                  return;
+               end if;
             end loop;
          end if;
 
@@ -581,47 +635,61 @@ package body Sem_Elab is
             return;
          end if;
 
+         --  Find top level scope for called entity (not following renamings
+         --  or derivations). This is where the Elaborate_All will go if it
+         --  is needed. We start with the called entity, except in the case
+         --  of initialization procedures, where the init proc is in the root
+         --  package, where we start fromn the entity of the name in the call.
+
+         if Is_Entity_Name (Name (N))
+           and then Is_Init_Proc (Entity (Name (N)))
+         then
+            W_Scope := Scope (Entity (Name (N)));
+         else
+            W_Scope := E;
+         end if;
+
+         while not Is_Compilation_Unit (W_Scope) loop
+            W_Scope := Scope (W_Scope);
+         end loop;
+
+         --  Now check if an elaborate_all (or dynamic check) is needed
+
          if not Suppress_Elaboration_Warnings (Ent)
+           and then not Elaboration_Checks_Suppressed (Ent)
            and then not Suppress_Elaboration_Warnings (E_Scope)
+           and then not Elaboration_Checks_Suppressed (E_Scope)
            and then Elab_Warnings
            and then Generate_Warnings
          then
-            Warn_On_Instance := True;
-
             if Inst_Case then
                Error_Msg_NE
                  ("instantiation of& may raise Program_Error?", N, Ent);
-            else
-               Error_Msg_NE
-                 ("call to & may raise Program_Error?", N, Ent);
 
-               if Unit_Callee = No_Unit
-                 and then E_Scope = Current_Scope
+            else
+               if Is_Init_Proc (Entity (Name (N)))
+                 and then Comes_From_Source (Ent)
                then
-                  --  The missing pragma cannot be on the current unit, so
-                  --  place it on the compilation unit that contains the
-                  --  called entity, which is more likely to be right.
-
-                  E_Scope := Ent;
+                  Error_Msg_NE
+                    ("implicit call to & may raise Program_Error?", N, Ent);
 
-                  while not Is_Compilation_Unit (E_Scope) loop
-                     E_Scope := Scope (E_Scope);
-                  end loop;
+               else
+                  Error_Msg_NE
+                    ("call to & may raise Program_Error?", N, Ent);
                end if;
             end if;
 
             Error_Msg_Qual_Level := Nat'Last;
             Error_Msg_NE
-              ("\missing pragma Elaborate_All for&?", N, E_Scope);
+              ("\missing pragma Elaborate_All for&?", N, W_Scope);
             Error_Msg_Qual_Level := 0;
             Output_Calls (N);
-            Warn_On_Instance := False;
 
             --  Set flag to prevent further warnings for same unit
             --  unless in All_Errors_Mode.
 
             if not All_Errors_Mode and not Dynamic_Elaboration_Checks then
-               Set_Suppress_Elaboration_Warnings (E_Scope);
+               Set_Suppress_Elaboration_Warnings (W_Scope, True);
             end if;
          end if;
 
@@ -629,12 +697,18 @@ package body Sem_Elab is
 
          if Dynamic_Elaboration_Checks then
             if not Elaboration_Checks_Suppressed (Ent)
-              and then not Suppress_Elaboration_Checks (E_Scope)
+              and then not Elaboration_Checks_Suppressed (W_Scope)
+              and then not Elaboration_Checks_Suppressed (E_Scope)
               and then not Cunit_SC
             then
-               --  Runtime elaboration check required. generate check of the
+               --  Runtime elaboration check required. Generate check of the
                --  elaboration Boolean for the unit containing the entity.
 
+               --  Note that for this case, we do check the real unit (the
+               --  one from following renamings, since that is the issue!)
+
+               --  Could this possibly miss a useless but required PE???
+
                Insert_Elab_Check (N,
                  Make_Attribute_Reference (Loc,
                    Attribute_Name => Name_Elaborated,
@@ -643,23 +717,41 @@ package body Sem_Elab is
                        (Spec_Entity (E_Scope), Loc)));
             end if;
 
-         --  If no dynamic check required, then ask binder to guarantee
-         --  that the necessary elaborations will be done properly!
+         --  Case of static elaboration model
 
          else
-            if not Suppress_Elaboration_Warnings (E)
-              and then not Suppress_Elaboration_Warnings (E_Scope)
-              and then Elab_Warnings
-              and then Generate_Warnings
-              and then not Inst_Case
+            --  Do not do anything if elaboration checks suppressed. Note
+            --  that we check Ent here, not E, since we want the real entity
+            --  for the body to see if checks are suppressed for it, not the
+            --  dummy entry for renamings or derivations.
+
+            if Elaboration_Checks_Suppressed (Ent)
+              or else Elaboration_Checks_Suppressed (E_Scope)
+              or else Elaboration_Checks_Suppressed (W_Scope)
             then
-               Error_Msg_Node_2 := E_Scope;
-               Error_Msg_NE ("call to& in elaboration code " &
-                  "requires pragma Elaborate_All on&?", N, E);
-            end if;
+               null;
+
+            --  Here we need to generate an implicit elaborate all
+
+            else
+               --  Generate elaborate_all warning unless suppressed
+
+               if (Elab_Warnings and Generate_Warnings and not Inst_Case)
+                 and then not Suppress_Elaboration_Warnings (Ent)
+                 and then not Suppress_Elaboration_Warnings (E_Scope)
+                 and then not Suppress_Elaboration_Warnings (W_Scope)
+               then
+                  Error_Msg_Node_2 := W_Scope;
+                  Error_Msg_NE
+                    ("call to& in elaboration code " &
+                     "requires pragma Elaborate_All on&?", N, E);
+               end if;
+
+               --  Set indication for binder to generate Elaborate_All
 
-            Set_Elaborate_All_Desirable (E_Scope);
-            Set_Suppress_Elaboration_Warnings (E_Scope);
+               Set_Elaborate_All_Desirable (W_Scope);
+               Set_Suppress_Elaboration_Warnings (W_Scope, True);
+            end if;
          end if;
 
       --  Case of entity is in same unit as call or instantiation
@@ -667,7 +759,6 @@ package body Sem_Elab is
       elsif not Inter_Unit_Only then
          Check_Internal_Call (N, Ent, Outer_Scope, E);
       end if;
-
    end Check_A_Call;
 
    -----------------------------
@@ -675,7 +766,6 @@ package body Sem_Elab is
    -----------------------------
 
    procedure Check_Bad_Instantiation (N : Node_Id) is
-      Nam : Node_Id;
       Ent : Entity_Id;
 
    begin
@@ -714,7 +804,6 @@ package body Sem_Elab is
          return;
       end if;
 
-      Nam := Name (N);
       Ent := Get_Generic_Entity (N);
 
       --  The case we are interested in is when the generic spec is in the
@@ -786,10 +875,41 @@ package body Sem_Elab is
      (N           : Node_Id;
       Outer_Scope : Entity_Id := Empty)
    is
-      Nam : Node_Id;
       Ent : Entity_Id;
       P   : Node_Id;
 
+      function Get_Called_Ent return Entity_Id;
+      --  Retrieve called entity. If this is a call to a protected subprogram,
+      --  entity is a selected component. The callable entity may be absent,
+      --  in which case there is no check to perform.  This happens with
+      --  non-analyzed calls in nested generics.
+
+      --------------------
+      -- Get_Called_Ent --
+      --------------------
+
+      function Get_Called_Ent return Entity_Id is
+         Nam : Node_Id;
+
+      begin
+         Nam := Name (N);
+
+         if No (Nam) then
+            return Empty;
+
+         elsif Nkind (Nam) = N_Selected_Component then
+            return Entity (Selector_Name (Nam));
+
+         elsif not Is_Entity_Name (Nam) then
+            return Empty;
+
+         else
+            return Entity (Nam);
+         end if;
+      end Get_Called_Ent;
+
+   --  Start of processing for Check_Elab_Call
+
    begin
       --  For an entry call, check relevant restriction
 
@@ -843,7 +963,10 @@ package body Sem_Elab is
       --  will be doing the actual call later, not now, and it
       --  is at the time of the actual call (statically speaking)
       --  that we must do our static check, not at the time of
-      --  its initial analysis).
+      --  its initial analysis). However, we have to check calls
+      --  within component definitions (e.g., a function call
+      --  that determines an array component bound), so we
+      --  terminate the loop in that case.
 
       P := Parent (N);
       while Present (P) loop
@@ -852,6 +975,13 @@ package body Sem_Elab is
             Nkind (P) = N_Component_Declaration
          then
             return;
+
+         --  The call occurs within the constraint of a component,
+         --  so it must be checked.
+
+         elsif Nkind (P) = N_Component_Definition then
+            exit;
+
          else
             P := Parent (P);
          end if;
@@ -874,7 +1004,6 @@ package body Sem_Elab is
          --  First case, we are in elaboration code
 
          From_Elab_Code := not In_Subprogram_Or_Concurrent_Unit;
-
          if From_Elab_Code then
 
             --  Complain if call that comes from source in preelaborated
@@ -975,6 +1104,26 @@ package body Sem_Elab is
 
                         exit;
 
+                     elsif Nkind (P) = N_Task_Body then
+
+                        --  The check is deferred until Check_Task_Activation
+                        --  but we need to capture local suppress pragmas
+                        --  that may inhibit checks on this call.
+
+                        Ent := Get_Called_Ent;
+
+                        if No (Ent) then
+                           return;
+
+                        elsif Elaboration_Checks_Suppressed (Current_Scope)
+                          or else Elaboration_Checks_Suppressed (Ent)
+                          or else Elaboration_Checks_Suppressed (Scope (Ent))
+                        then
+                           Set_No_Elaboration_Check (N);
+                        end if;
+
+                        return;
+
                      --  Static model, call is not in elaboration code, we
                      --  never need to worry, because in the static model
                      --  the top level caller always takes care of things.
@@ -988,25 +1137,7 @@ package body Sem_Elab is
          end if;
       end if;
 
-      --  Retrieve called entity. If this is a call to a protected subprogram,
-      --  the entity is a selected component.
-      --  The callable entity may be absent, in which case there is nothing
-      --  to do. This happens with non-analyzed calls in nested generics.
-
-      Nam := Name (N);
-
-      if No (Nam) then
-         return;
-
-      elsif Nkind (Nam) = N_Selected_Component then
-         Ent := Entity (Selector_Name (Nam));
-
-      elsif not Is_Entity_Name (Nam) then
-         return;
-
-      else
-         Ent := Entity (Nam);
-      end if;
+      Ent := Get_Called_Ent;
 
       if No (Ent) then
          return;
@@ -1071,9 +1202,60 @@ package body Sem_Elab is
             Inter_Unit_Only => True,
             Generate_Warnings => False);
 
+      --  Otherwise nothing to do
+
       else
          return;
       end if;
+
+      --  A call to an Init_Proc in elaboration code may bring additional
+      --  dependencies, if some of the record components thereof have
+      --  initializations that are function calls that come from source.
+      --  We treat the current node as a call to each of these functions,
+      --  to check their elaboration impact.
+
+      if Is_Init_Proc (Ent)
+        and then From_Elab_Code
+      then
+         Process_Init_Proc : declare
+            Unit_Decl : constant Node_Id := Unit_Declaration_Node (Ent);
+
+            function Process (Nod : Node_Id) return Traverse_Result;
+            --  Find subprogram calls within body of init_proc for
+            --  Traverse instantiation below.
+
+            function Process (Nod : Node_Id) return Traverse_Result is
+               Func : Entity_Id;
+
+            begin
+               if (Nkind (Nod) = N_Function_Call
+                    or else Nkind (Nod) = N_Procedure_Call_Statement)
+                 and then Is_Entity_Name (Name (Nod))
+               then
+                  Func := Entity (Name (Nod));
+
+                  if Comes_From_Source (Func) then
+                     Check_A_Call
+                       (N, Func, Standard_Standard, Inter_Unit_Only => True);
+                  end if;
+
+                  return OK;
+
+               else
+                  return OK;
+               end if;
+            end Process;
+
+            procedure Traverse_Body is new Traverse_Proc (Process);
+
+         --  Start of processing for Process_Init_Proc
+
+         begin
+            if Nkind (Unit_Decl) = N_Subprogram_Body then
+               Traverse_Body (Handled_Statement_Sequence (Unit_Decl));
+            end if;
+         end Process_Init_Proc;
+      end if;
    end Check_Elab_Call;
 
    ----------------------
@@ -1087,7 +1269,10 @@ package body Sem_Elab is
       --  case we lack the full information that we need, and no object
       --  file will be created in any case.
 
-      if not Expander_Active or else Subunits_Missing then
+      if not Expander_Active
+        or else Is_Generic_Unit (Cunit_Entity (Main_Unit))
+        or else Subunits_Missing
+      then
          return;
       end if;
 
@@ -1125,8 +1310,7 @@ package body Sem_Elab is
      (N           : Node_Id;
       Outer_Scope : Entity_Id := Empty)
    is
-      Nam     : Node_Id;
-      Ent     : Entity_Id;
+      Ent : Entity_Id;
 
    begin
       --  Check for and deal with bad instantiation case. There is some
@@ -1151,7 +1335,6 @@ package body Sem_Elab is
          return;
       end if;
 
-      Nam := Name (N);
       Ent := Get_Generic_Entity (N);
       From_Elab_Code := not In_Subprogram_Or_Concurrent_Unit;
 
@@ -1305,6 +1488,10 @@ package body Sem_Elab is
       --  Checks for call that needs checking, and if so checks
       --  it. Always returns OK, so entire tree is traversed.
 
+      -------------
+      -- Process --
+      -------------
+
       function Process (N : Node_Id) return Traverse_Result is
       begin
          --  If user has specified that there are no entry calls in elaboration
@@ -1313,7 +1500,7 @@ package body Sem_Elab is
 
          if (Nkind (Original_Node (N)) = N_Accept_Statement
               or else Nkind (Original_Node (N)) = N_Selective_Accept)
-           and then Restrictions (No_Entry_Calls_In_Elaboration_Code)
+           and then Restriction_Active (No_Entry_Calls_In_Elaboration_Code)
          then
             return Abandon;
 
@@ -1446,13 +1633,10 @@ package body Sem_Elab is
       --  Here is the case of calling a subprogram where the body has
       --  not yet been encountered, a warning message is needed.
 
-      Warn_On_Instance := True;
-
       --  If we have nothing in the call stack, then this is at the
       --  outer level, and the ABE is bound to occur.
 
       if Elab_Call.Last = 0 then
-
          if Inst_Case then
             Error_Msg_NE
               ("?cannot instantiate& before body seen", N, Orig_Ent);
@@ -1502,6 +1686,14 @@ package body Sem_Elab is
 
                   Set_Elaboration_Flag (Sbody, E);
 
+                  --  Kill current value indication. This is necessary
+                  --  because the tests of this flag are inserted out of
+                  --  sequence and must not pick up bogus indications of
+                  --  the wrong constant value. Also, this is never a true
+                  --  constant, since one way or another, it gets reset.
+
+                  Set_Current_Value    (Ent, Empty);
+                  Set_Is_True_Constant (Ent, False);
                   Pop_Scope;
                end;
             end if;
@@ -1514,7 +1706,9 @@ package body Sem_Elab is
 
          --  Generate the warning
 
-         if not Suppress_Elaboration_Warnings (E) then
+         if not Suppress_Elaboration_Warnings (E)
+           and then not Elaboration_Checks_Suppressed (E)
+         then
             if Inst_Case then
                Error_Msg_NE
                  ("instantiation of& may occur before body is seen?",
@@ -1531,8 +1725,6 @@ package body Sem_Elab is
          end if;
       end if;
 
-      Warn_On_Instance := False;
-
       --  Set flag to suppress further warnings on same subprogram
       --  unless in all errors mode
 
@@ -1541,20 +1733,20 @@ package body Sem_Elab is
       end if;
    end Check_Internal_Call_Continue;
 
-   ----------------------------
-   --  Check_Task_Activation --
-   ----------------------------
+   ---------------------------
+   -- Check_Task_Activation --
+   ---------------------------
 
    procedure Check_Task_Activation (N : Node_Id) is
       Loc         : constant Source_Ptr := Sloc (N);
+      Inter_Procs : constant Elist_Id   := New_Elmt_List;
+      Intra_Procs : constant Elist_Id   := New_Elmt_List;
       Ent         : Entity_Id;
       P           : Entity_Id;
       Task_Scope  : Entity_Id;
       Cunit_SC    : Boolean := False;
       Decl        : Node_Id;
       Elmt        : Elmt_Id;
-      Inter_Procs : Elist_Id := New_Elmt_List;
-      Intra_Procs : Elist_Id := New_Elmt_List;
       Enclosing   : Entity_Id;
 
       procedure Add_Task_Proc (Typ : Entity_Id);
@@ -1610,7 +1802,7 @@ package body Sem_Elab is
          --  Skip this test if errors have occurred, since in this case
          --  we can get false indications.
 
-         if Total_Errors_Detected /= 0 then
+         if Serious_Errors_Detected /= 0 then
             return;
          end if;
 
@@ -1684,7 +1876,7 @@ package body Sem_Elab is
 
       begin
          while Present (Outer) loop
-            if Suppress_Elaboration_Checks (Outer) then
+            if Elaboration_Checks_Suppressed (Outer) then
                Cunit_SC := True;
             end if;
 
@@ -1740,13 +1932,16 @@ package body Sem_Elab is
          if not Is_Compilation_Unit (Task_Scope) then
             null;
 
-         elsif Suppress_Elaboration_Warnings (Task_Scope) then
+         elsif Suppress_Elaboration_Warnings (Task_Scope)
+           or else Elaboration_Checks_Suppressed (Task_Scope)
+         then
             null;
 
          elsif Dynamic_Elaboration_Checks then
             if not Elaboration_Checks_Suppressed (Ent)
               and then not Cunit_SC
-              and then not Restrictions (No_Entry_Calls_In_Elaboration_Code)
+              and then
+                not Restriction_Active (No_Entry_Calls_In_Elaboration_Code)
             then
                --  Runtime elaboration check required. generate check of the
                --  elaboration Boolean for the unit containing the entity.
@@ -1760,11 +1955,13 @@ package body Sem_Elab is
             end if;
 
          else
-            --  Force the binder to elaborate other unit first.
+            --  Force the binder to elaborate other unit first
 
             if not Suppress_Elaboration_Warnings (Ent)
+              and then not Elaboration_Checks_Suppressed (Ent)
               and then Elab_Warnings
               and then not Suppress_Elaboration_Warnings (Task_Scope)
+              and then not Elaboration_Checks_Suppressed (Task_Scope)
             then
                Error_Msg_Node_2 := Task_Scope;
                Error_Msg_NE ("activation of an instance of task type&" &
@@ -2082,12 +2279,18 @@ package body Sem_Elab is
       --  Unfortunately this does not work if the call has a dynamic size,
       --  because gigi regards it as a dynamic-sized temporary. If such a call
       --  appears in a short-circuit expression, the elaboration check will be
-      --  missed (rare enough ???).
+      --  missed (rare enough ???). Otherwise, the code below inserts the check
+      --  at the appropriate place before the call. Same applies in the even
+      --  rarer case the return type has a known size but is unconstrained.
 
       else
          if Nkind (N) = N_Function_Call
            and then Analyzed (Parent (N))
            and then Size_Known_At_Compile_Time (Etype (N))
+           and then
+            (not Has_Discriminants (Etype (N))
+              or else Is_Constrained (Etype (N)))
+
          then
             declare
                Typ : constant Entity_Id := Etype (N);
@@ -2176,7 +2379,7 @@ package body Sem_Elab is
          if Is_Generic_Unit (Ent) then
             Error_Msg_NE ("\?& instantiated #", N, Ent);
 
-         elsif Chars (Ent) = Name_uInit_Proc then
+         elsif Is_Init_Proc (Ent) then
             Error_Msg_N ("\?initialization procedure called #", N);
 
          elsif Is_Printable_Error_Name (Chars (Ent)) then
@@ -2341,9 +2544,17 @@ package body Sem_Elab is
          if Nkind (Item) = N_Pragma
            and then Get_Pragma_Id (Chars (Item)) = Pragma_Elaborate_All
          then
+            if Error_Posted (Item) then
+
+               --  Some previous error on the pragma itself
+
+               return False;
+            end if;
+
             Elab_Id :=
               Entity (
                 Expression (First (Pragma_Argument_Associations (Item))));
+
             Par   := Parent (Unit_Declaration_Node (Elab_Id));
             Item2 := First (Context_Items (Par));