[Ada] Handling up-level references in protected entries and freeze nodes

Message ID 20191212100430.GA114731@adacore.com
State New
Headers show
  • [Ada] Handling up-level references in protected entries and freeze nodes
Related show

Commit Message

Pierre-Marie de Rodat Dec. 12, 2019, 10:04 a.m.
For GNAT-LLVM, up-level references within the procedure created for a
protected entry were not being handled right inside the block created to
hold the declarations and statements of the entry. Calls to procedures
declared within the block that make up-level references (such as to the
init proc for a task declared within the entry, as occurred in one test)
weren't passing an AREC parameter. Part of the fix is to analyze the
block and reset Scope fields on declarations within the block right
after the block is created (in Build_Protected_Entry), so that they
refer to the block rather than the original entry declaration. However,
there were still cases where subprograms occurring within an
N_Freeze_Entity weren't getting their scope set. This is addressed by
traversing the Actions list of the freeze node, recursively calling
Reset_Scopes on each of the actions, plus also adding specific handling
for subprogram bodies, ensuring that their entity's Scope is reset
(deals with cases where there is not a separate subprogram declaration).

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

2019-12-12  Gary Dismukes  <dismukes@adacore.com>


	* exp_ch9.adb (Build_Protected_Entry): Analyze the block created
	to hold the declarations and statements of the protected entry
	body right after it's created, and then call Reset_Scopes_To on
	that block to reset the Scope of nested entities to the block
	(Reset_Scope): Add handling for N_Freeze_Entity nodes, calling
	Reset_Scopes recursively on the Actions of such nodes. Also, for
	subprogram bodies that are encountered that might not have a
	separate declaration (such as type init procedures), reset the
	Scope of the subprogram's entity.


--- gcc/ada/exp_ch9.adb
+++ gcc/ada/exp_ch9.adb
@@ -48,6 +48,7 @@  with Rident;   use Rident;
 with Rtsfind;  use Rtsfind;
 with Sem;      use Sem;
 with Sem_Aux;  use Sem_Aux;
+with Sem_Ch5;  use Sem_Ch5;
 with Sem_Ch6;  use Sem_Ch6;
 with Sem_Ch8;  use Sem_Ch8;
 with Sem_Ch9;  use Sem_Ch9;
@@ -3722,6 +3723,14 @@  package body Exp_Ch9 is
             Declarations               => Decls,
             Handled_Statement_Sequence => Handled_Statement_Sequence (N)));
+      --  Analyze now and reset scopes for declarations so that Scope fields
+      --  currently denoting the entry will now denote the block scope.
+      Analyze_Statements (Bod_Stmts);
+      Reset_Scopes_To
+        (First (Bod_Stmts), Entity (Identifier (First (Bod_Stmts))));
       case Corresponding_Runtime_Package (Pid) is
          when System_Tasking_Protected_Objects_Entries =>
             Append_To (Bod_Stmts,
@@ -14977,7 +14986,27 @@  package body Exp_Ch9 is
                Next (Decl);
             end loop;
+         elsif Nkind (N) = N_Freeze_Entity then
+            --  Scan the actions associated with a freeze node, which may
+            --  actually be declarations with entities that need to have
+            --  their scopes reset.
+            Decl := First (Actions (N));
+            while Present (Decl) loop
+               Reset_Scopes (Decl);
+               Next (Decl);
+            end loop;
          elsif N /= Bod and then Nkind (N) in N_Proper_Body then
+            --  A subprogram without a separate declaration may be encountered,
+            --  and we need to reset the subprogram's entity's scope.
+            if Nkind (N) = N_Subprogram_Body then
+               Set_Scope (Defining_Entity (Specification (N)), E);
+            end if;
             return Skip;
          end if;