For GNAT-LLVM, subprograms nested within protected subprograms become
part of the new unprotected body created by
Build_Unprotected_Subprogram_Body, but the entity of the unprotected
subprogram was not getting marked as Has_Nested_Subprogram, and the
declarations now nested within the new body didn't have their scopes set
properly. This is fixed by applying the Has_Nested_Subprogram flag from
the original subprogram's entity to the new subprogram's entity and
calling Reset_Scopes_To on the new body. Ideally this would be done
within Build_Protected_Sub_Specification, but the subprogram entity that
will be associated with the new body isn't available at that point, and
we have to wait until after the analysis of the newly created body to
retrieve it via Corresponding_Spec.
Tested on x86_64-pc-linux-gnu, committed on trunk
2020-06-17 Gary Dismukes <dismu...@adacore.com>
gcc/ada/
* exp_ch9.adb (Build_Protected_Subp_Specification): Add ???
comment about the flag Has_Nested_Subprogram not being set here.
(Expand_N_Protected_Body): If the original body for a protected
subprogram has the flag Has_Nested_Subprogram set, then set that
flag on the new unprotected subprogram body that's created for
it, and reset the Scope fields of its top level declarations,
which have been effectively taken from the original protected
subprogram body. Add ??? comment about unclear testing of
Corresponding_Spec.
--- gcc/ada/exp_ch9.adb
+++ gcc/ada/exp_ch9.adb
@@ -3933,6 +3933,13 @@ package body Exp_Ch9 is
Set_Is_Eliminated (New_Id, Is_Eliminated (Def_Id));
+ -- It seems we should set Has_Nested_Subprogram here, but instead we
+ -- currently set it in Expand_N_Protected_Body, because the entity
+ -- created here isn't the one that Corresponding_Spec of the body
+ -- will later be set to, and that's the entity where it's needed. ???
+
+ Set_Has_Nested_Subprogram (New_Id, Has_Nested_Subprogram (Def_Id));
+
if Nkind (Specification (Decl)) = N_Procedure_Specification then
New_Spec :=
Make_Procedure_Specification (Loc,
@@ -8716,10 +8723,32 @@ package body Exp_Ch9 is
Current_Node := New_Op_Body;
Analyze (New_Op_Body);
+ -- When the original protected body has nested subprograms,
+ -- the new body also has them, so set the flag accordingly
+ -- and reset the scopes of the top-level nested subprograms
+ -- and other declaration entities so that they now refer to
+ -- the new body's entity. (It would preferable to do this
+ -- within Build_Protected_Sub_Specification, which is called
+ -- from Build_Unprotected_Subprogram_Body, but the needed
+ -- subprogram entity isn't available via Corresponding_Spec
+ -- until after the above Analyze call.)
+
+ if Has_Nested_Subprogram (Corresponding_Spec (Op_Body)) then
+ Set_Has_Nested_Subprogram
+ (Corresponding_Spec (New_Op_Body));
+
+ Reset_Scopes_To
+ (New_Op_Body, Corresponding_Spec (New_Op_Body));
+ end if;
+
-- Build the corresponding protected operation. This is
-- needed only if this is a public or private operation of
-- the type.
+ -- Why do we need to test for Corresponding_Spec being
+ -- present here when it's assumed to be set further above
+ -- in the Is_Eliminated test???
+
if Present (Corresponding_Spec (Op_Body)) then
Op_Decl :=
Unit_Declaration_Node (Corresponding_Spec (Op_Body));