The previous change implemented the rule in Freeze_Expression that
expression functions that are not completions are not freeze points.
However, for code generation purposes, the artificial entities that
are created during the expansion of the expressions must still be
frozen inside the body created for the functions.  Now the existing
mechanism aimed at ensuring this had a loophole for entities created
in nested blocks, which is plugged by the change.

The change also removes some unreachable code in In_Expanded_Body.

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

2020-06-16  Eric Botcazou  <ebotca...@adacore.com>

gcc/ada/

        * freeze.adb (In_Expanded_Body): Remove unreachable code.
        (Freeze_Expression): Rename a couple of local variables.
        In the case of an expanded body, also freeze locally the
        entities declared in a nested block.
--- gcc/ada/freeze.adb
+++ gcc/ada/freeze.adb
@@ -7114,22 +7114,15 @@ package body Freeze is
       ----------------------
 
       function In_Expanded_Body (N : Node_Id) return Boolean is
-         P  : Node_Id;
+         P  : constant Node_Id := Parent (N);
          Id : Entity_Id;
 
       begin
-         if Nkind (N) = N_Subprogram_Body then
-            P := N;
-         else
-            P := Parent (N);
-         end if;
-
          if Nkind (P) /= N_Subprogram_Body then
             return False;
 
-         --  AI12-0152 : an expression function that is a completion
-         --  is a freeze point. If the body is the result of expansion
-         --  it is not.
+         --  AI12-0157: An expression function that is a completion is a freeze
+         --  point. If the body is the result of expansion, it is not.
 
          elsif Was_Expression_Function (P) then
             return not Comes_From_Source (P);
@@ -7146,9 +7139,8 @@ package body Freeze is
                          or else Is_TSS (Id, TSS_Stream_Output)
                          or else Is_TSS (Id, TSS_Stream_Read)
                          or else Is_TSS (Id, TSS_Stream_Write)
-                         or else Nkind_In (Original_Node (P),
-                                           N_Subprogram_Renaming_Declaration,
-                                           N_Expression_Function))
+                         or else Nkind (Original_Node (P)) =
+                                             N_Subprogram_Renaming_Declaration)
             then
                return True;
             else
@@ -7518,45 +7510,61 @@ package body Freeze is
 
                   if In_Expanded_Body (Parent_P) then
                      declare
-                        Subp : constant Node_Id := Parent (Parent_P);
-                        Spec : Entity_Id;
+                        Subp_Body : constant Node_Id := Parent (Parent_P);
+                        Spec_Id   : Entity_Id;
 
                      begin
                         --  Freeze the entity only when it is declared inside
-                        --  the body of the expander generated procedure.
-                        --  This case is recognized by the scope of the entity
-                        --  or its type, which is either the spec for some
-                        --  enclosing body, or (in the case of init_procs,
-                        --  for which there are no separate specs) the current
-                        --  scope.
-
-                        if Nkind (Subp) = N_Subprogram_Body then
-                           Spec := Corresponding_Spec (Subp);
-
-                           if (Present (Typ) and then Scope (Typ) = Spec)
-                                or else
-                              (Present (Nam) and then Scope (Nam) = Spec)
-                           then
-                              exit;
+                        --  the body of the expander generated procedure. This
+                        --  case is recognized by the subprogram scope of the
+                        --  entity or its type, which is either the spec of an
+                        --  enclosing body, or (in the case of init_procs for
+                        --  which there is no separate spec) the current scope.
+
+                        if Nkind (Subp_Body) = N_Subprogram_Body then
+                           declare
+                              S : Entity_Id;
+
+                           begin
+                              Spec_Id := Corresponding_Spec (Subp_Body);
+
+                              if Present (Typ) then
+                                 S := Scope (Typ);
+                              elsif Present (Nam) then
+                                 S := Scope (Nam);
+                              else
+                                 S := Standard_Standard;
+                              end if;
 
-                           elsif Present (Typ)
-                             and then Scope (Typ) = Current_Scope
-                             and then Defining_Entity (Subp) = Current_Scope
-                           then
-                              exit;
-                           end if;
+                              while S /= Standard_Standard
+                                and then not Is_Subprogram (S)
+                              loop
+                                 S := Scope (S);
+                              end loop;
+
+                              if S = Spec_Id then
+                                 exit;
+
+                              elsif Present (Typ)
+                                and then Scope (Typ) = Current_Scope
+                                and then
+                                  Defining_Entity (Subp_Body) = Current_Scope
+                              then
+                                 exit;
+                              end if;
+                           end;
                         end if;
 
                         --  If the entity is not frozen by an expression
-                        --  function that is a completion, continue climing
-                        --  the tree.
+                        --  function that is not a completion, continue
+                        --  climbing the tree.
 
-                        if Nkind (Subp) = N_Subprogram_Body
-                          and then Was_Expression_Function (Subp)
+                        if Nkind (Subp_Body) = N_Subprogram_Body
+                          and then Was_Expression_Function (Subp_Body)
                         then
                            null;
 
-                           --  Freeze outside the body
+                        --  Freeze outside the body
 
                         else
                            Parent_P := Parent (Parent_P);

Reply via email to