https://gcc.gnu.org/g:1f679fd10f93d23ad274a5c583b9cef463bf7954

commit r13-9437-g1f679fd10f93d23ad274a5c583b9cef463bf7954
Author: Eric Botcazou <ebotca...@adacore.com>
Date:   Wed Mar 19 08:22:33 2025 +0100

    Fix spurious visibility error with partially parameterized formal package
    
    This is not a regression but the issue is quite annoying and the fix is
    trivial.  The problem is that a formal parameter covered by a box in the
    formal package is not visible in the instance when it comes after another
    formal parameter that is also a formal package.
    
    It comes from a discrepancy internal to Instantiate_Formal_Package, where
    a specific construct (the abbreviated instance) built for the nested formal
    package discombobulates the processing done for the outer formal package.
    
    gcc/ada/
            * gen_il-gen-gen_nodes.adb (N_Formal_Package_Declaration): Use
            N_Declaration instead of Node_Kind as ancestor.
            * sem_ch12.adb (Get_Formal_Entity): Remove obsolete alternative.
            (Instantiate_Formal_Package): Take into account the abbreviated
            instances in the main loop running over the actuals of the local
            package created for the formal package.
    
    gcc/testsuite/
            * gnat.dg/generic_inst14.adb: New test.
            * gnat.dg/generic_inst14_pkg.ads: New helper.
            * gnat.dg/generic_inst14_pkg-child.ads: Likewise.

Diff:
---
 gcc/ada/gen_il-gen-gen_nodes.adb                   |  2 +-
 gcc/ada/sem_ch12.adb                               | 31 ++++++++++++++++++----
 gcc/testsuite/gnat.dg/generic_inst14.adb           | 20 ++++++++++++++
 gcc/testsuite/gnat.dg/generic_inst14_pkg-child.ads | 27 +++++++++++++++++++
 gcc/testsuite/gnat.dg/generic_inst14_pkg.ads       | 16 +++++++++++
 5 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb
index 389c9a0f005c..ecac44c798d5 100644
--- a/gcc/ada/gen_il-gen-gen_nodes.adb
+++ b/gcc/ada/gen_il-gen-gen_nodes.adb
@@ -1393,7 +1393,7 @@ begin -- Gen_IL.Gen.Gen_Nodes
 
    Cc (N_Formal_Ordinary_Fixed_Point_Definition, Node_Kind);
 
-   Cc (N_Formal_Package_Declaration, Node_Kind,
+   Cc (N_Formal_Package_Declaration, N_Declaration,
        (Sy (Defining_Identifier, Node_Id),
         Sy (Name, Node_Id, Default_Empty),
         Sy (Generic_Associations, List_Id, Default_No_List),
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 89581bd5bb60..9290e88d51e4 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -10546,6 +10546,7 @@ package body Sem_Ch12 is
 
       function Get_Formal_Entity (N : Node_Id) return Entity_Id is
          Kind : constant Node_Kind := Nkind (Original_Node (N));
+
       begin
          case Kind is
             when N_Formal_Object_Declaration =>
@@ -10560,9 +10561,6 @@ package body Sem_Ch12 is
             when N_Formal_Package_Declaration =>
                return Defining_Identifier (Original_Node (N));
 
-            when N_Generic_Package_Declaration =>
-               return Defining_Identifier (Original_Node (N));
-
             --  All other declarations are introduced by semantic analysis and
             --  have no match in the actual.
 
@@ -10801,6 +10799,26 @@ package body Sem_Ch12 is
                   end if;
 
                   Next_Non_Pragma (Formal_Node);
+
+                  --  If the actual of the local package created for the formal
+                  --  is itself an instantiated formal package, then it could
+                  --  have given rise to additional declarations, see the code
+                  --  dealing with conformance checking below.
+
+                  if Nkind (Actual_Of_Formal) = N_Package_Renaming_Declaration
+                    and then Requires_Conformance_Checking
+                               (Declaration_Node
+                                 (Associated_Formal_Package
+                                   (Defining_Entity (Actual_Of_Formal))))
+                  then
+                     Next (Actual_Of_Formal);
+                     pragma Assert
+                       (Nkind (Actual_Of_Formal) = N_Package_Declaration);
+                     Next (Actual_Of_Formal);
+                     pragma Assert
+                       (Nkind (Actual_Of_Formal) = N_Package_Instantiation);
+                  end if;
+
                   Next (Actual_Of_Formal);
 
                   --  A formal subprogram may be overloaded, so advance in
@@ -10856,11 +10874,14 @@ package body Sem_Ch12 is
          --  checking, because it contains formal declarations for those
          --  defaulted parameters, and those should not reach the back-end.
 
+         --  This processing needs to be synchronized with the pattern matching
+         --  done in the main loop of the above block that starts with the test
+         --  on Requires_Conformance_Checking.
+
          if Requires_Conformance_Checking (Formal) then
             declare
                I_Pack : constant Entity_Id := Make_Temporary (Loc, 'P');
-
-               I_Nam : Node_Id;
+               I_Nam  : Node_Id;
 
             begin
                Set_Is_Internal (I_Pack);
diff --git a/gcc/testsuite/gnat.dg/generic_inst14.adb 
b/gcc/testsuite/gnat.dg/generic_inst14.adb
new file mode 100644
index 000000000000..562bde604560
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst14.adb
@@ -0,0 +1,20 @@
+--  { dg-do compile }
+
+with Generic_Inst14_Pkg;
+with Generic_Inst14_Pkg.Child;
+
+procedure Generic_Inst14 is
+
+   type T is null record;
+
+   package Tree is new Generic_Inst14_Pkg.Definite_Value_Tree (T);
+
+   package Base is new Generic_Inst14_Pkg.Child.Simple (T, Tree);
+
+   package OK is new Generic_Inst14_Pkg.Child.OK (T, Base.Strat);
+
+   package Not_OK is new Generic_Inst14_Pkg.Child.Not_OK (T, Tree, Base.Strat);
+
+begin
+   null;
+end;
diff --git a/gcc/testsuite/gnat.dg/generic_inst14_pkg-child.ads 
b/gcc/testsuite/gnat.dg/generic_inst14_pkg-child.ads
new file mode 100644
index 000000000000..8ad17c4389f0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst14_pkg-child.ads
@@ -0,0 +1,27 @@
+package Generic_Inst14_Pkg.Child is
+
+   generic
+      type Value is private;
+      with package Value_Tree is new Definite_Value_Tree (Value => Value);
+   package Simple is
+      type Node is new Value_Tree.Value_Node with null record;
+      package Strat is new Def_Strat (Value, Value_Tree, Node);
+   end Simple;
+
+   generic
+      type Value is private;
+      with package A_Strat is new Def_Strat (Value => Value, others => <>);
+   package OK is
+      procedure Plop (N : A_Strat.Node) is null;
+   end OK;
+
+   generic
+      type Value is private;
+      with package Value_Tree is new Definite_Value_Tree (Value => Value);
+      with package A_Strat is
+         new Def_Strat (Value => Value, Value_Tree => Value_Tree, others => 
<>);
+   package Not_OK is
+      procedure Plop (N : A_Strat.Node) is null;
+   end Not_OK;
+   
+end Generic_Inst14_Pkg.Child;
diff --git a/gcc/testsuite/gnat.dg/generic_inst14_pkg.ads 
b/gcc/testsuite/gnat.dg/generic_inst14_pkg.ads
new file mode 100644
index 000000000000..b1334f6d6351
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst14_pkg.ads
@@ -0,0 +1,16 @@
+package Generic_Inst14_Pkg is
+
+   generic
+      type Value is limited private;
+   package Definite_Value_Tree is
+      type Value_Node is abstract tagged null record; 
+   end Definite_Value_Tree;
+   
+   generic
+      type Value is limited private;
+      with package Value_Tree is new Definite_Value_Tree (Value);
+      type Node (<>) is new Value_Tree.Value_Node with private;
+   package Def_Strat is
+   end Def_Strat;
+
+end Generic_Inst14_Pkg;

Reply via email to