]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/ada/sem_elab.adb
[multiple changes]
[gcc.git] / gcc / ada / sem_elab.adb
index b4c214ddeeb8d7f55d2cb7a4497fea18d6d2321b..4a98db6f1d9e10e206fc3ea9f344f77b92a8e7a8 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1997-2010, Free Software Foundation, Inc.         --
+--          Copyright (C) 1997-2012, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -43,6 +43,7 @@ with Output;   use Output;
 with Restrict; use Restrict;
 with Rident;   use Rident;
 with Sem;      use Sem;
+with Sem_Aux;  use Sem_Aux;
 with Sem_Cat;  use Sem_Cat;
 with Sem_Ch7;  use Sem_Ch7;
 with Sem_Ch8;  use Sem_Ch8;
@@ -55,6 +56,7 @@ with Snames;   use Snames;
 with Stand;    use Stand;
 with Table;
 with Tbuild;   use Tbuild;
+with Uintp;    use Uintp;
 with Uname;    use Uname;
 
 package body Sem_Elab is
@@ -176,16 +178,24 @@ package body Sem_Elab is
       E                 : Entity_Id;
       Outer_Scope       : Entity_Id;
       Inter_Unit_Only   : Boolean;
-      Generate_Warnings : Boolean := True);
-   --  This is the internal recursive routine that is called to check for a
+      Generate_Warnings : Boolean := True;
+      In_Init_Proc      : Boolean := False);
+   --  This is the internal recursive routine that is called to check for
    --  possible elaboration error. The argument N is a subprogram call or
-   --  generic instantiation to be checked, and E is the entity of the called
-   --  subprogram, or instantiated generic unit. The flag Outer_Scope is the
-   --  outer level scope for the original call. Inter_Unit_Only is set if the
-   --  call is only to be checked in the case where it is to another unit (and
-   --  skipped if within a unit). Generate_Warnings is set to False to suppress
-   --  warning messages about missing pragma Elaborate_All's. These messages
-   --  are not wanted for inner calls in the dynamic model.
+   --  generic instantiation, or 'Access attribute reference to be checked, and
+   --  E is the entity of the called subprogram, or instantiated generic unit,
+   --  or subprogram referenced by 'Access.
+   --
+   --  The flag Outer_Scope is the outer level scope for the original call.
+   --  Inter_Unit_Only is set if the call is only to be checked in the
+   --  case where it is to another unit (and skipped if within a unit).
+   --  Generate_Warnings is set to False to suppress warning messages about
+   --  missing pragma Elaborate_All's. These messages are not wanted for
+   --  inner calls in the dynamic model. Note that an instance of the Access
+   --  attribute applied to a subprogram also generates a call to this
+   --  procedure (since the referenced subprogram may be called later
+   --  indirectly). Flag In_Init_Proc should be set whenever the current
+   --  context is a type init proc.
 
    procedure Check_Bad_Instantiation (N : Node_Id);
    --  N is a node for an instantiation (if called with any other node kind,
@@ -228,29 +238,6 @@ package body Sem_Elab is
    --  Check_Internal_Call. Outer_Scope is the outer level scope for the
    --  original call.
 
-   procedure Set_Elaboration_Constraint
-    (Call : Node_Id;
-     Subp : Entity_Id;
-     Scop : Entity_Id);
-   --  The current unit U may depend semantically on some unit P which is not
-   --  in the current context. If there is an elaboration call that reaches P,
-   --  we need to indicate that P requires an Elaborate_All, but this is not
-   --  effective in U's ali file, if there is no with_clause for P. In this
-   --  case we add the Elaborate_All on the unit Q that directly or indirectly
-   --  makes P available. This can happen in two cases:
-   --
-   --    a) Q declares a subtype of a type declared in P, and the call is an
-   --    initialization call for an object of that subtype.
-   --
-   --    b) Q declares an object of some tagged type whose root type is
-   --    declared in P, and the initialization call uses object notation on
-   --    that object to reach a primitive operation or a classwide operation
-   --    declared in P.
-   --
-   --  If P appears in the context of U, the current processing is correct.
-   --  Otherwise we must identify these two cases to retrieve Q and place the
-   --  Elaborate_All_Desirable on it.
-
    function Has_Generic_Body (N : Node_Id) return Boolean;
    --  N is a generic package instantiation node, and this routine determines
    --  if this package spec does in fact have a generic body. If so, then
@@ -272,6 +259,9 @@ package body Sem_Elab is
    --  or instantiation node for which the check code is required. C is the
    --  test whose failure triggers the raise.
 
+   function Is_Finalization_Procedure (Id : Entity_Id) return Boolean;
+   --  Determine whether entity Id denotes a [Deep_]Finalize procedure
+
    procedure Output_Calls (N : Node_Id);
    --  Outputs chain of calls stored in the Elab_Call table. The caller has
    --  already generated the main warning message, so the warnings generated
@@ -286,6 +276,36 @@ package body Sem_Elab is
    --  On entry C_Scope is set to some scope. On return, C_Scope is reset
    --  to be the enclosing compilation unit of this scope.
 
+   function Get_Referenced_Ent (N : Node_Id) return Entity_Id;
+   --  N is either a function or procedure call or an access attribute that
+   --  references a subprogram. This call retrieves the relevant 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 Empty is
+   --  returned. This happens with non-analyzed calls in nested generics.
+
+   procedure Set_Elaboration_Constraint
+    (Call : Node_Id;
+     Subp : Entity_Id;
+     Scop : Entity_Id);
+   --  The current unit U may depend semantically on some unit P which is not
+   --  in the current context. If there is an elaboration call that reaches P,
+   --  we need to indicate that P requires an Elaborate_All, but this is not
+   --  effective in U's ali file, if there is no with_clause for P. In this
+   --  case we add the Elaborate_All on the unit Q that directly or indirectly
+   --  makes P available. This can happen in two cases:
+   --
+   --    a) Q declares a subtype of a type declared in P, and the call is an
+   --    initialization call for an object of that subtype.
+   --
+   --    b) Q declares an object of some tagged type whose root type is
+   --    declared in P, and the initialization call uses object notation on
+   --    that object to reach a primitive operation or a classwide operation
+   --    declared in P.
+   --
+   --  If P appears in the context of U, the current processing is correct.
+   --  Otherwise we must identify these two cases to retrieve Q and place the
+   --  Elaborate_All_Desirable on it.
+
    function Spec_Entity (E : Entity_Id) return Entity_Id;
    --  Given a compilation unit entity, if it is a spec entity, it is returned
    --  unchanged. If it is a body entity, then the spec for the corresponding
@@ -471,7 +491,8 @@ package body Sem_Elab is
       E                 : Entity_Id;
       Outer_Scope       : Entity_Id;
       Inter_Unit_Only   : Boolean;
-      Generate_Warnings : Boolean := True)
+      Generate_Warnings : Boolean := True;
+      In_Init_Proc      : Boolean := False)
    is
       Loc  : constant Source_Ptr := Sloc (N);
       Ent  : Entity_Id;
@@ -501,6 +522,9 @@ package body Sem_Elab is
       Inst_Case : constant Boolean := Nkind (N) in N_Generic_Instantiation;
       --  Indicates if we have instantiation case
 
+      Access_Case : constant Boolean := Nkind (N) = N_Attribute_Reference;
+      --  Indicates if we have Access attribute case
+
       Caller_Unit_Internal : Boolean;
       Callee_Unit_Internal : Boolean;
 
@@ -521,8 +545,7 @@ package body Sem_Elab is
       --  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)
+      if Nkind (N) in N_Subprogram_Call
         and then No_Elaboration_Check (N)
       then
          return;
@@ -658,11 +681,10 @@ package body Sem_Elab is
          if Body_Acts_As_Spec then
             if Is_TSS (Ent, TSS_Deep_Initialize) then
                declare
-                  Typ  : Entity_Id;
+                  Typ  : constant Entity_Id := Etype (First_Formal (Ent));
                   Init : Entity_Id;
-               begin
-                  Typ  := Etype (Next_Formal (First_Formal (Ent)));
 
+               begin
                   if not Is_Controlled (Typ) then
                      return;
                   else
@@ -687,9 +709,9 @@ package body Sem_Elab is
            Is_Internal_File_Name
              (Unit_File_Name (Get_Source_Unit (E_Scope)));
 
-         --  Do not give a warning if the with'ed unit is internal
-         --  and this is the generic instantiation case (this saves a
-         --  lot of hassle dealing with the Text_IO special child units)
+         --  Do not give a warning if the with'ed unit is internal and this is
+         --  the generic instantiation case (this saves a lot of hassle dealing
+         --  with the Text_IO special child units)
 
          if Callee_Unit_Internal and Inst_Case then
             return;
@@ -703,9 +725,9 @@ package body Sem_Elab is
                 (Unit_File_Name (Get_Source_Unit (C_Scope)));
          end if;
 
-         --  Do not give a warning if the with'ed unit is internal
-         --  and the caller is not internal (since the binder always
-         --  elaborates internal units first).
+         --  Do not give a warning if the with'ed unit is internal and the
+         --  caller is not internal (since the binder always elaborates
+         --  internal units first).
 
          if Callee_Unit_Internal and (not Caller_Unit_Internal) then
             return;
@@ -726,15 +748,15 @@ package body Sem_Elab is
          end if;
 
          --  If the call is in an instance, and the called entity is not
-         --  defined in the same instance, then the elaboration issue
-         --  focuses around the unit containing the template, it is
-         --  this unit which requires an Elaborate_All.
+         --  defined in the same instance, then the elaboration issue focuses
+         --  around the unit containing the template, it is this unit which
+         --  requires an Elaborate_All.
 
-         --  However, if we are doing dynamic elaboration, we need to
-         --  chase the call in the usual manner.
+         --  However, if we are doing dynamic elaboration, we need to chase the
+         --  call in the usual manner.
 
-         --  We do not handle the case of calling a generic formal correctly
-         --  in the static case. See test 4703-004 to explore this gap ???
+         --  We do not handle the case of calling a generic formal correctly in
+         --  the static case.???
 
          Inst_Caller := Instantiation (Get_Source_File_Index (Sloc (N)));
          Inst_Callee := Instantiation (Get_Source_File_Index (Sloc (Ent)));
@@ -820,14 +842,19 @@ package body Sem_Elab is
          --  the init proc is in the root package, and we start from the entity
          --  of the name in the call.
 
-         if Is_Entity_Name (Name (N))
-           and then Is_Init_Proc (Entity (Name (N)))
-           and then not In_Same_Extended_Unit (N, Entity (Name (N)))
-         then
-            W_Scope := Scope (Entity (Name (N)));
-         else
-            W_Scope := E;
-         end if;
+         declare
+            Ent : constant Entity_Id := Get_Referenced_Ent (N);
+         begin
+            if Is_Init_Proc (Ent)
+              and then not In_Same_Extended_Unit (N, Ent)
+            then
+               W_Scope := Scope (Ent);
+            else
+               W_Scope := E;
+            end if;
+         end;
+
+         --  Now loop through scopes to get to the enclosing compilation unit
 
          while not Is_Compilation_Unit (W_Scope) loop
             W_Scope := Scope (W_Scope);
@@ -849,6 +876,8 @@ package body Sem_Elab is
                   Ent   : Node_Or_Entity_Id);
                --  Generate a call to Error_Msg_NE with parameters Msg_D or
                --  Msg_S (for dynamic or static elaboration model), N and Ent.
+               --  Msg_D is suppressed for the attribute reference case, since
+               --  we never raise Program_Error for an attribute reference.
 
                ------------------
                -- Elab_Warning --
@@ -861,7 +890,9 @@ package body Sem_Elab is
                is
                begin
                   if Dynamic_Elaboration_Checks then
-                     Error_Msg_NE (Msg_D, N, Ent);
+                     if not Access_Case then
+                        Error_Msg_NE (Msg_D, N, Ent);
+                     end if;
                   else
                      Error_Msg_NE (Msg_S, N, Ent);
                   end if;
@@ -870,11 +901,23 @@ package body Sem_Elab is
             --  Start of processing for Generate_Elab_Warnings
 
             begin
+               --  Instantiation case
+
                if Inst_Case then
                   Elab_Warning
                     ("instantiation of& may raise Program_Error?",
                      "info: instantiation of& during elaboration?", Ent);
 
+               --  Indirect call case, warning only in static elaboration
+               --  case, because the attribute reference itself cannot raise
+               --  an exception.
+
+               elsif Access_Case then
+                  Elab_Warning
+                    ("", "info: access to& during elaboration?", Ent);
+
+               --  Subprogram call case
+
                else
                   if Nkind (Name (N)) in N_Has_Entity
                     and then Is_Init_Proc (Entity (Name (N)))
@@ -900,6 +943,7 @@ package body Sem_Elab is
                     ("\missing pragma Elaborate for&?",
                      "\info: implicit pragma Elaborate for& generated?",
                      W_Scope);
+
                else
                   Elab_Warning
                     ("\missing pragma Elaborate_All for&?",
@@ -938,7 +982,16 @@ package body Sem_Elab is
                Insert_Elab_Check (N,
                  Make_Attribute_Reference (Loc,
                    Attribute_Name => Name_Elaborated,
-                   Prefix => New_Occurrence_Of (Spec_Entity (E_Scope), Loc)));
+                   Prefix         =>
+                     New_Occurrence_Of (Spec_Entity (E_Scope), Loc)));
+
+               --  Prevent duplicate elaboration checks on the same call,
+               --  which can happen if the body enclosing the call appears
+               --  itself in a call whose elaboration check is delayed.
+
+               if Nkind (N) in N_Subprogram_Call then
+                  Set_No_Elaboration_Check (N);
+               end if;
             end if;
 
          --  Case of static elaboration model
@@ -955,6 +1008,12 @@ package body Sem_Elab is
             then
                null;
 
+            --  Do not generate an Elaborate_All for finalization routines
+            --  which perform partial clean up as part of initialization.
+
+            elsif In_Init_Proc and then Is_Finalization_Procedure (Ent) then
+               null;
+
             --  Here we need to generate an implicit elaborate all
 
             else
@@ -1094,42 +1153,13 @@ package body Sem_Elab is
    ---------------------
 
    procedure Check_Elab_Call
-     (N           : Node_Id;
-      Outer_Scope : Entity_Id := Empty)
+     (N            : Node_Id;
+      Outer_Scope  : Entity_Id := Empty;
+      In_Init_Proc : Boolean   := False)
    is
       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
@@ -1148,11 +1178,11 @@ package body Sem_Elab is
       then
          Check_Restriction (No_Entry_Calls_In_Elaboration_Code, N);
 
-      --  Nothing to do if this is not a call (happens in some error
-      --  conditions, and in some cases where rewriting occurs).
+      --  Nothing to do if this is not a call or attribute reference (happens
+      --  in some error conditions, and in some cases where rewriting occurs).
 
-      elsif Nkind (N) /= N_Function_Call
-        and then Nkind (N) /= N_Procedure_Call_Statement
+      elsif Nkind (N) not in N_Subprogram_Call
+        and then Nkind (N) /= N_Attribute_Reference
       then
          return;
 
@@ -1241,6 +1271,7 @@ package body Sem_Elab is
             if Comes_From_Source (N)
               and then In_Preelaborated_Unit
               and then not In_Inlined_Body
+              and then Nkind (N) /= N_Attribute_Reference
             then
                --  This is a warning in GNAT mode allowing such calls to be
                --  used in the predefined library with appropriate care.
@@ -1326,12 +1357,10 @@ package body Sem_Elab is
 
                      elsif Dynamic_Elaboration_Checks then
 
-                        --  This is a rather new check, going into version
-                        --  3.14a1 for the first time (V1.80 of this unit), so
-                        --  we provide a debug flag to enable it. That way we
-                        --  have an easy work around for regressions that are
-                        --  caused by this new check. This debug flag can be
-                        --  removed later.
+                        --  We provide a debug flag to disable this check. That
+                        --  way we have an easy work around for regressions
+                        --  that are caused by this new check. This debug flag
+                        --  can be removed later.
 
                         if Debug_Flag_DD then
                            return;
@@ -1347,7 +1376,7 @@ package body Sem_Elab is
                         --  but we need to capture local suppress pragmas
                         --  that may inhibit checks on this call.
 
-                        Ent := Get_Called_Ent;
+                        Ent := Get_Referenced_Ent (N);
 
                         if No (Ent) then
                            return;
@@ -1374,7 +1403,7 @@ package body Sem_Elab is
          end if;
       end if;
 
-      Ent := Get_Called_Ent;
+      Ent := Get_Referenced_Ent (N);
 
       if No (Ent) then
          return;
@@ -1404,14 +1433,19 @@ package body Sem_Elab is
 
       C_Scope := Current_Scope;
 
-      --  If not outer level call, then we follow it if it is within
-      --  the original scope of the outer call.
+      --  If not outer level call, then we follow it if it is within the
+      --  original scope of the outer call.
 
       if Present (Outer_Scope)
         and then Within (Scope (Ent), Outer_Scope)
       then
          Set_C_Scope;
-         Check_A_Call (N, Ent, Outer_Scope, Inter_Unit_Only => False);
+         Check_A_Call
+           (N               => N,
+            E               => Ent,
+            Outer_Scope     => Outer_Scope,
+            Inter_Unit_Only => False,
+            In_Init_Proc    => In_Init_Proc);
 
       elsif Elaboration_Checks_Suppressed (Current_Scope) then
          null;
@@ -1436,7 +1470,7 @@ package body Sem_Elab is
            (N,
             Ent,
             Standard_Standard,
-            Inter_Unit_Only => True,
+            Inter_Unit_Only   => True,
             Generate_Warnings => False);
 
       --  Otherwise nothing to do
@@ -1472,8 +1506,7 @@ package body Sem_Elab is
                Func : Entity_Id;
 
             begin
-               if (Nkind (Nod) = N_Function_Call
-                    or else Nkind (Nod) = N_Procedure_Call_Statement)
+               if Nkind (Nod) in N_Subprogram_Call
                  and then Is_Entity_Name (Name (Nod))
                then
                   Func := Entity (Name (Nod));
@@ -1968,7 +2001,7 @@ package body Sem_Elab is
          --  arguments that are assignments (OUT or IN OUT mode formals).
 
          elsif Nkind (N) = N_Procedure_Call_Statement then
-            Check_Elab_Call (N, Outer_Scope);
+            Check_Elab_Call (N, Outer_Scope, In_Init_Proc => Is_Init_Proc (E));
 
             Actual := First_Actual (N);
             while Present (Actual) loop
@@ -1981,6 +2014,20 @@ package body Sem_Elab is
 
             return OK;
 
+         --  If we have an access attribute for a subprogram, check
+         --  it. Suppress this behavior under debug flag.
+
+         elsif not Debug_Flag_Dot_UU
+           and then Nkind (N) = N_Attribute_Reference
+           and then (Attribute_Name (N) = Name_Access
+                       or else
+                     Attribute_Name (N) = Name_Unrestricted_Access)
+           and then Is_Entity_Name (Prefix (N))
+           and then Is_Subprogram (Entity (Prefix (N)))
+         then
+            Check_Elab_Call (N, Outer_Scope);
+            return OK;
+
          --  If we have a generic instantiation, check it
 
          elsif Nkind (N) in N_Generic_Instantiation then
@@ -2100,7 +2147,32 @@ package body Sem_Elab is
       end if;
 
       --  Here is the case of calling a subprogram where the body has not yet
-      --  been encountered, a warning message is needed.
+      --  been encountered. A warning message is needed, except if this is the
+      --  case of appearing within an aspect specification that results in
+      --  a check call, we do not really have such a situation, so no warning
+      --  is needed (e.g. the case of a precondition, where the call appears
+      --  textually before the body, but in actual fact is moved to the
+      --  appropriate subprogram body and so does not need a check).
+
+      declare
+         P : Node_Id;
+      begin
+         P := Parent (N);
+         loop
+            if Nkind (P) in N_Subexpr then
+               P := Parent (P);
+            elsif Nkind (P) = N_If_Statement
+              and then Nkind (Original_Node (P)) = N_Pragma
+              and then Present (Corresponding_Aspect (Original_Node (P)))
+            then
+               return;
+            else
+               exit;
+            end if;
+         end loop;
+      end;
+
+      --  Not that special case, warning and dynamic check is required
 
       --  If we have nothing in the call stack, then this is at the outer
       --  level, and the ABE is bound to occur.
@@ -2147,9 +2219,10 @@ package body Sem_Elab is
                   Insert_Action (Declaration_Node (E),
                     Make_Object_Declaration (Loce,
                       Defining_Identifier => Ent,
-                      Object_Definition =>
-                        New_Occurrence_Of (Standard_Boolean, Loce),
-                      Expression => New_Occurrence_Of (Standard_False, Loce)));
+                      Object_Definition   =>
+                        New_Occurrence_Of (Standard_Short_Integer, Loce),
+                      Expression          =>
+                        Make_Integer_Literal (Loc, Uint_0)));
 
                   --  Set elaboration flag at the point of the body
 
@@ -2168,10 +2241,12 @@ package body Sem_Elab is
                end;
             end if;
 
-            --  Generate check of the elaboration Boolean
+            --  Generate check of the elaboration counter
 
             Insert_Elab_Check (N,
-              New_Occurrence_Of (Elaboration_Entity (E), Loc));
+               Make_Attribute_Reference (Loc,
+                 Attribute_Name => Name_Elaborated,
+                 Prefix         => New_Occurrence_Of (E, Loc)));
          end if;
 
          --  Generate the warning
@@ -2411,7 +2486,7 @@ package body Sem_Elab is
                 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.
+               --  elaboration counter for the unit containing the entity.
 
                Insert_Elab_Check (N,
                  Make_Attribute_Reference (Loc,
@@ -2546,6 +2621,31 @@ package body Sem_Elab is
       Set_Suppress_Elaboration_Warnings (Elab_Unit, True);
    end Set_Elaboration_Constraint;
 
+   ------------------------
+   -- Get_Referenced_Ent --
+   ------------------------
+
+   function Get_Referenced_Ent (N : Node_Id) return Entity_Id is
+      Nam : Node_Id;
+
+   begin
+      if Nkind (N) = N_Attribute_Reference then
+         Nam := Prefix (N);
+      else
+         Nam := Name (N);
+      end if;
+
+      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_Referenced_Ent;
+
    ----------------------
    -- Has_Generic_Body --
    ----------------------
@@ -2899,6 +2999,53 @@ package body Sem_Elab is
       end if;
    end Insert_Elab_Check;
 
+   -------------------------------
+   -- Is_Finalization_Procedure --
+   -------------------------------
+
+   function Is_Finalization_Procedure (Id : Entity_Id) return Boolean is
+   begin
+      --  Check whether Id is a procedure with at least one parameter
+
+      if Ekind (Id) = E_Procedure
+        and then Present (First_Formal (Id))
+      then
+         declare
+            Typ      : constant Entity_Id := Etype (First_Formal (Id));
+            Deep_Fin : Entity_Id := Empty;
+            Fin      : Entity_Id := Empty;
+
+         begin
+            --  If the type of the first formal does not require finalization
+            --  actions, then this is definitely not [Deep_]Finalize.
+
+            if not Needs_Finalization (Typ) then
+               return False;
+            end if;
+
+            --  At this point we have the following scenario:
+
+            --    procedure Name (Param1 : [in] [out] Ctrl[; Param2 : ...]);
+
+            --  Recover the two possible versions of [Deep_]Finalize using the
+            --  type of the first parameter and compare with the input.
+
+            Deep_Fin := TSS (Typ, TSS_Deep_Finalize);
+
+            if Is_Controlled (Typ) then
+               Fin := Find_Prim_Op (Typ, Name_Finalize);
+            end if;
+
+            return
+                (Present (Deep_Fin) and then Id = Deep_Fin)
+              or else
+                (Present (Fin) and then Id = Fin);
+         end;
+      end if;
+
+      return False;
+   end Is_Finalization_Procedure;
+
    ------------------
    -- Output_Calls --
    ------------------
This page took 0.0607490000000001 seconds and 5 git commands to generate.