[Ada] Spurious visibility error in a nested instance with formal package
authorEd Schonberg <schonberg@adacore.com>
Tue, 22 May 2018 13:23:46 +0000 (13:23 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Tue, 22 May 2018 13:23:46 +0000 (13:23 +0000)
This patch fixes a spurious visibility error with a nested instance of a
generic unit with a formal package, when the actual for it is a formal
package PA of an enclosing generic, and there are subsequent uses of the
formals of PA in that generic unit.

2018-05-22  Ed Schonberg  <schonberg@adacore.com>

gcc/ada/

* einfo.ads, einfo.adb: New attribute Hidden_In_Formal_Instance,
defined on packages that are actuals for formal packages, in order to
set/reset the visibility of the formals of a formal package with given
actuals, when there are subsequent uses of those formals in the
enclosing generic, as required by RN 12.7 (10).
* atree.ads, atree.adb: Add operations for Elist30.
* atree.h: Add Elist30.
* sem_ch12.adb (Analyze_Formal_Package_Instantiation): Collect formals
that are not defaulted and are thus not visible within the current
instance.
(Check_Formal_Packages): Reset visibility of formals of a formal
package that are not defaulted, on exit from current instance.

gcc/testsuite/

* gnat.dg/gen_formal_pkg.adb, gnat.dg/gen_formal_pkg_a.ads,
gnat.dg/gen_formal_pkg_b.ads, gnat.dg/gen_formal_pkg_w.ads: New
testcase.

From-SVN: r260520

12 files changed:
gcc/ada/ChangeLog
gcc/ada/atree.adb
gcc/ada/atree.ads
gcc/ada/atree.h
gcc/ada/einfo.adb
gcc/ada/einfo.ads
gcc/ada/sem_ch12.adb
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/gen_formal_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/gen_formal_pkg_a.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/gen_formal_pkg_b.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/gen_formal_pkg_w.ads [new file with mode: 0644]

index cef561e87fc21b7597755b3e900b84c35dadbbc7..37615e9fd069773e012892275765cf766ee77089 100644 (file)
@@ -1,3 +1,18 @@
+2018-05-22  Ed Schonberg  <schonberg@adacore.com>
+
+       * einfo.ads, einfo.adb: New attribute Hidden_In_Formal_Instance,
+       defined on packages that are actuals for formal packages, in order to
+       set/reset the visibility of the formals of a formal package with given
+       actuals, when there are subsequent uses of those formals in the
+       enclosing generic, as required by RN 12.7 (10).
+       * atree.ads, atree.adb: Add operations for Elist30.
+       * atree.h: Add Elist30.
+       * sem_ch12.adb (Analyze_Formal_Package_Instantiation): Collect formals
+       that are not defaulted and are thus not visible within the current
+       instance.
+       (Check_Formal_Packages): Reset visibility of formals of a formal
+       package that are not defaulted, on exit from current instance.
+
 2018-05-22  Hristian Kirtchev  <kirtchev@adacore.com>
 
        * sem_prag.adb (Analyze_Input_Output): Emit an error when a non-null,
index f82ddbffda82511021a17f7fbe58caf46e73078f..958cd5102a91680126f718e5fc5feb5e76b15ee9 100644 (file)
@@ -3408,6 +3408,17 @@ package body Atree is
          end if;
       end Elist29;
 
+      function Elist30 (N : Node_Id) return Elist_Id is
+         pragma Assert (Nkind (N) in N_Entity);
+         Value : constant Union_Id := Nodes.Table (N + 5).Field6;
+      begin
+         if Value = 0 then
+            return No_Elist;
+         else
+            return Elist_Id (Value);
+         end if;
+      end Elist30;
+
       function Elist36 (N : Node_Id) return Elist_Id is
          pragma Assert (Nkind (N) in N_Entity);
          Value : constant Union_Id := Nodes.Table (N + 6).Field6;
@@ -6318,6 +6329,13 @@ package body Atree is
          Nodes.Table (N + 4).Field11 := Union_Id (Val);
       end Set_Elist29;
 
+      procedure Set_Elist30 (N : Node_Id; Val : Elist_Id) is
+      begin
+         pragma Assert (not Locked);
+         pragma Assert (Nkind (N) in N_Entity);
+         Nodes.Table (N + 5).Field6 := Union_Id (Val);
+      end Set_Elist30;
+
       procedure Set_Elist36 (N : Node_Id; Val : Elist_Id) is
       begin
          pragma Assert (not Locked);
index c739f3a41d9c97104fe521607494c3dfad5afb63..24d491852ef02ab06e6060e60ee0bb857b3416a4 100644 (file)
@@ -1523,6 +1523,9 @@ package Atree is
       function Elist29 (N : Node_Id) return Elist_Id;
       pragma Inline (Elist29);
 
+      function Elist30 (N : Node_Id) return Elist_Id;
+      pragma Inline (Elist30);
+
       function Elist36 (N : Node_Id) return Elist_Id;
       pragma Inline (Elist36);
 
@@ -2889,6 +2892,9 @@ package Atree is
       procedure Set_Elist29 (N : Node_Id; Val : Elist_Id);
       pragma Inline (Set_Elist29);
 
+      procedure Set_Elist30 (N : Node_Id; Val : Elist_Id);
+      pragma Inline (Set_Elist30);
+
       procedure Set_Elist36 (N : Node_Id; Val : Elist_Id);
       pragma Inline (Set_Elist36);
 
index 60ec64bcfffbba830fd388ec984177c3fb1924b4..338affe4eb6da95a68e36e18b00b7baea80fde4f 100644 (file)
@@ -530,6 +530,7 @@ extern Node_Id Current_Error_Node;
 #define Elist25(N)    Field25 (N)
 #define Elist26(N)    Field26 (N)
 #define Elist29(N)    Field29 (N)
+#define Elist30(N)    Field30 (N)
 #define Elist36(N)    Field36 (N)
 
 #define Name1(N)      Field1  (N)
index 4352f42ea888f4ed622815a2a62f5484298437b6..a28cb4e2f73f31d81eb34614100506b2cc2602b5 100644 (file)
@@ -255,6 +255,7 @@ package body Einfo is
    --    Corresponding_Equality          Node30
    --    Last_Aggregate_Assignment       Node30
    --    Static_Initialization           Node30
+   --    Hidden_In_Formal_Instance       Elist30
 
    --    Derived_Type_Link               Node31
    --    Thunk_Entity                    Node31
@@ -1989,6 +1990,12 @@ package body Einfo is
       return Node8 (Id);
    end Hiding_Loop_Variable;
 
+   function Hidden_In_Formal_Instance (Id : E) return L is
+   begin
+      pragma Assert (Ekind (Id) = E_Package);
+      return Elist30 (Id);
+   end Hidden_In_Formal_Instance;
+
    function Homonym (Id : E) return E is
    begin
       return Node4 (Id);
@@ -5167,6 +5174,12 @@ package body Einfo is
       Set_Node8 (Id, V);
    end Set_Hiding_Loop_Variable;
 
+   procedure Set_Hidden_In_Formal_Instance (Id : E; V : L) is
+   begin
+      pragma Assert (Ekind (Id) = E_Package);
+      Set_Elist30 (Id, V);
+   end Set_Hidden_In_Formal_Instance;
+
    procedure Set_Homonym (Id : E; V : E) is
    begin
       pragma Assert (Id /= V);
index 36967fd2632eb878782a2f544cbbb0343332eee5..76da3b9da6c60c7df248887789d37a426f2ba536 100644 (file)
@@ -2172,6 +2172,14 @@ package Einfo is
 --       warning messages if the hidden variable turns out to be unused
 --       or is referenced without being set.
 
+--    Hidden_In_Formal_Instance (Elist30)
+--       Defined on actuals for formal packages. Entities on the list are
+--       formals that are hidden outside of the formal package when this
+--       package is not declared with a box, or the formal itself is not
+--       defaulted (see RM 12.7 (10)). Their visibility is restored on exit
+--       from the current generic, because the actual for the formal package
+--       may be used subsequently in the current unit.
+
 --    Homonym (Node4)
 --       Defined in all entities. Link for list of entities that have the
 --       same source name and that are declared in the same or enclosing
@@ -7210,6 +7218,7 @@ package Einfo is
    function Has_Volatile_Components             (Id : E) return B;
    function Has_Xref_Entry                      (Id : E) return B;
    function Hiding_Loop_Variable                (Id : E) return E;
+   function Hidden_In_Formal_Instance           (Id : E) return L;
    function Homonym                             (Id : E) return E;
    function Ignore_SPARK_Mode_Pragmas           (Id : E) return B;
    function Import_Pragma                       (Id : E) return E;
@@ -7904,6 +7913,7 @@ package Einfo is
    procedure Set_Has_Volatile_Components         (Id : E; V : B := True);
    procedure Set_Has_Xref_Entry                  (Id : E; V : B := True);
    procedure Set_Hiding_Loop_Variable            (Id : E; V : E);
+   procedure Set_Hidden_In_Formal_Instance       (Id : E; V : L);
    procedure Set_Homonym                         (Id : E; V : E);
    procedure Set_Ignore_SPARK_Mode_Pragmas       (Id : E; V : B := True);
    procedure Set_Import_Pragma                   (Id : E; V : E);
@@ -8717,6 +8727,7 @@ package Einfo is
    pragma Inline (Has_Volatile_Components);
    pragma Inline (Has_Xref_Entry);
    pragma Inline (Hiding_Loop_Variable);
+   pragma Inline (Hidden_In_Formal_Instance);
    pragma Inline (Homonym);
    pragma Inline (Ignore_SPARK_Mode_Pragmas);
    pragma Inline (Import_Pragma);
@@ -9247,6 +9258,7 @@ package Einfo is
    pragma Inline (Set_Has_Volatile_Components);
    pragma Inline (Set_Has_Xref_Entry);
    pragma Inline (Set_Hiding_Loop_Variable);
+   pragma Inline (Set_Hidden_In_Formal_Instance);
    pragma Inline (Set_Homonym);
    pragma Inline (Set_Ignore_SPARK_Mode_Pragmas);
    pragma Inline (Set_Import_Pragma);
index 3d93619c68505d9633c7749406cbb3595c4738c6..d8721a548ee4eb4d1679514fc9bd7489f4590980 100644 (file)
@@ -500,7 +500,10 @@ package body Sem_Ch12 is
    --  check on Ada version and the presence of an access definition in N.
 
    procedure Check_Formal_Packages (P_Id : Entity_Id);
-   --  Apply the following to all formal packages in generic associations
+   --  Apply the following to all formal packages in generic associations.
+   --  Restore the visibility of the formals of the instance that are not
+   --  defaulted (see RM 12.7 (10)). Remove the anonymous package declaration
+   --  created for formal instances that are not defaulted.
 
    procedure Check_Formal_Package_Instance
      (Formal_Pack : Entity_Id;
@@ -6561,7 +6564,6 @@ package body Sem_Ch12 is
       E           : Entity_Id;
       Formal_P    : Entity_Id;
       Formal_Decl : Node_Id;
-
    begin
       --  Iterate through the declarations in the instance, looking for package
       --  renaming declarations that denote instances of formal packages. Stop
@@ -6611,6 +6613,21 @@ package body Sem_Ch12 is
                      Check_Formal_Package_Instance (Formal_P, E);
                   end if;
 
+                  --  Restore the visibility of formals of the formal instance
+                  --  that are not defaulted, and are hidden within the current
+                  --  generic. These formals may be visible within an enclosing
+                  --  generic.
+
+                  declare
+                     Elmt : Elmt_Id;
+                  begin
+                     Elmt := First_Elmt (Hidden_In_Formal_Instance (Formal_P));
+                     while Present (Elmt) loop
+                        Set_Is_Hidden (Node (Elmt), False);
+                        Next_Elmt (Elmt);
+                     end loop;
+                  end;
+
                   --  After checking, remove the internal validating package.
                   --  It is only needed for semantic checks, and as it may
                   --  contain generic formal declarations it should not reach
@@ -9953,13 +9970,14 @@ package body Sem_Ch12 is
       Actual          : Node_Id;
       Analyzed_Formal : Node_Id) return List_Id
    is
-      Loc         : constant Source_Ptr := Sloc (Actual);
-      Actual_Pack : Entity_Id;
-      Formal_Pack : Entity_Id;
-      Gen_Parent  : Entity_Id;
-      Decls       : List_Id;
-      Nod         : Node_Id;
-      Parent_Spec : Node_Id;
+      Loc            : constant Source_Ptr := Sloc (Actual);
+      Hidden_Formals : constant Elist_Id   := New_Elmt_List;
+      Actual_Pack    : Entity_Id;
+      Formal_Pack    : Entity_Id;
+      Gen_Parent     : Entity_Id;
+      Decls          : List_Id;
+      Nod            : Node_Id;
+      Parent_Spec    : Node_Id;
 
       procedure Find_Matching_Actual
        (F    : Node_Id;
@@ -10351,6 +10369,10 @@ package body Sem_Ch12 is
                         end if;
 
                      else
+                        if not Is_Hidden (Actual_Ent) then
+                           Append_Elmt (Actual_Ent, Hidden_Formals);
+                        end if;
+
                         Set_Is_Hidden (Actual_Ent);
                         Set_Is_Potentially_Use_Visible (Actual_Ent, False);
                      end if;
@@ -10409,6 +10431,8 @@ package body Sem_Ch12 is
 
             begin
                Set_Is_Internal (I_Pack);
+               Set_Ekind (I_Pack, E_Package);
+               Set_Hidden_In_Formal_Instance (I_Pack, Hidden_Formals);
 
                Append_To (Decls,
                  Make_Package_Instantiation (Sloc (Actual),
index 642200308cb3ab0eefafa15e0ffcf06547b5c64f..a0a57222bc6b2c78f44a100435aea736940a7a1a 100644 (file)
@@ -1,3 +1,9 @@
+2018-05-22  Ed Schonberg  <schonberg@adacore.com>
+
+       * gnat.dg/gen_formal_pkg.adb, gnat.dg/gen_formal_pkg_a.ads,
+       gnat.dg/gen_formal_pkg_b.ads, gnat.dg/gen_formal_pkg_w.ads: New
+       testcase.
+
 2018-05-22  Ed Schonberg  <schonberg@adacore.com>
 
        * gnat.dg/fixedpnt3.adb: New testcase.
diff --git a/gcc/testsuite/gnat.dg/gen_formal_pkg.adb b/gcc/testsuite/gnat.dg/gen_formal_pkg.adb
new file mode 100644 (file)
index 0000000..b317e2b
--- /dev/null
@@ -0,0 +1,10 @@
+--  { dg-do compile }
+
+with Gen_Formal_Pkg_A, Gen_Formal_Pkg_B, Gen_Formal_Pkg_W;
+
+procedure Gen_Formal_Pkg is
+  package AI is new Gen_Formal_Pkg_A (Long_Float);
+  package WI is new Gen_Formal_Pkg_W (AI);
+begin
+   null;
+end;
diff --git a/gcc/testsuite/gnat.dg/gen_formal_pkg_a.ads b/gcc/testsuite/gnat.dg/gen_formal_pkg_a.ads
new file mode 100644 (file)
index 0000000..074129f
--- /dev/null
@@ -0,0 +1,3 @@
+generic
+   type T1 is private;
+package Gen_Formal_Pkg_A is end;
diff --git a/gcc/testsuite/gnat.dg/gen_formal_pkg_b.ads b/gcc/testsuite/gnat.dg/gen_formal_pkg_b.ads
new file mode 100644 (file)
index 0000000..60f7f94
--- /dev/null
@@ -0,0 +1,6 @@
+with Gen_Formal_Pkg_A;
+
+generic
+   type T1 is private;
+   with package Ai is new Gen_Formal_Pkg_A (T1);
+package Gen_Formal_Pkg_B is end;
diff --git a/gcc/testsuite/gnat.dg/gen_formal_pkg_w.ads b/gcc/testsuite/gnat.dg/gen_formal_pkg_w.ads
new file mode 100644 (file)
index 0000000..d3100b7
--- /dev/null
@@ -0,0 +1,13 @@
+with Gen_Formal_Pkg_A, Gen_Formal_Pkg_B;
+
+generic
+   with package Ai is new Gen_Formal_Pkg_A (<>);
+package Gen_Formal_Pkg_W is
+
+   procedure P1 (T : Ai.T1) is null;
+
+   package Bi is new Gen_Formal_Pkg_B (Ai.T1, Ai);
+
+   procedure P2 (T : Ai.T1) is null;
+
+end Gen_Formal_Pkg_W;