diff mbox

[Ada] Spurious visibility error in instance with nested packages

Message ID 20170427100054.GA59303@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 27, 2017, 10 a.m. UTC
This patch corrects the visibility machinery to properly infer the original
visibility of a use-visible entity defined within a nested package within a
generic when the generic is instantiated and there is already another use-
visible entity which satisfies the referenced.

------------
-- Source --
------------

--  my_generic.ads

generic
package My_Generic is
   package Nested is
      package M is
         function F (X : Integer) return Integer is (X);
      end M;
   end Nested;
   use Nested;

   function G (X : Integer) return Integer is (M.F (X));
end My_Generic;

--  my_instance.ads

with My_Generic;

package My_Instance is
   package Nested is
      package M is
         function F (X : Integer) return Integer is (X);
      end M;
   end Nested;
   use Nested;

   package I is new My_Generic;
end My_Instance;

-----------------
-- Compilation --
-----------------

$ gcc -c my_instance.ads

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

2017-04-27  Hristian Kirtchev  <kirtchev@adacore.com>

	* sem_ch8.adb (Find_Direct_Name): Account for the case where
	a use-visible entity is defined within a nested scope of an
	instance when giving priority to entities which were visible in
	the original generic.
	* sem_util.ads, sem_util.adb (Nearest_Enclosing_Instance): New routine.
diff mbox

Patch

Index: sem_util.adb
===================================================================
--- sem_util.adb	(revision 247298)
+++ sem_util.adb	(working copy)
@@ -16750,6 +16750,26 @@ 
       Mark_Allocators (Root_Nod);
    end Mark_Coextensions;
 
+   --------------------------------
+   -- Nearest_Enclosing_Instance --
+   --------------------------------
+
+   function Nearest_Enclosing_Instance (E : Entity_Id) return Entity_Id is
+      Inst : Entity_Id;
+
+   begin
+      Inst := Scope (E);
+      while Present (Inst) and then Inst /= Standard_Standard loop
+         if Is_Generic_Instance (Inst) then
+            return Inst;
+         end if;
+
+         Inst := Scope (Inst);
+      end loop;
+
+      return Empty;
+   end Nearest_Enclosing_Instance;
+
    ----------------------
    -- Needs_One_Actual --
    ----------------------
Index: sem_util.ads
===================================================================
--- sem_util.ads	(revision 247298)
+++ sem_util.ads	(working copy)
@@ -1941,6 +1941,10 @@ 
    --  to guarantee this in all cases. Note that it is more possible to give
    --  correct answer if the tree is fully analyzed.
 
+   function Nearest_Enclosing_Instance (E : Entity_Id) return Entity_Id;
+   --  Return the entity of the nearest enclosing instance which encapsulates
+   --  entity E. If no such instance exits, return Empty.
+
    function Needs_One_Actual (E : Entity_Id) return Boolean;
    --  Returns True if a function has defaults for all but its first
    --  formal. Used in Ada 2005 mode to solve the syntactic ambiguity that
Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb	(revision 247293)
+++ sem_ch8.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2016, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2017, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -4764,16 +4764,16 @@ 
    ----------------------
 
    procedure Find_Direct_Name (N : Node_Id) is
-      E    : Entity_Id;
-      E2   : Entity_Id;
-      Msg  : Boolean;
+      E   : Entity_Id;
+      E2  : Entity_Id;
+      Msg : Boolean;
 
+      Homonyms : Entity_Id;
+      --  Saves start of homonym chain
+
       Inst : Entity_Id := Empty;
       --  Enclosing instance, if any
 
-      Homonyms : Entity_Id;
-      --  Saves start of homonym chain
-
       Nvis_Entity : Boolean;
       --  Set True to indicate that there is at least one entity on the homonym
       --  chain which, while not visible, is visible enough from the user point
@@ -4835,8 +4835,6 @@ 
          Scop : constant Entity_Id := Scope (E);
          --  Declared scope of candidate entity
 
-         Act : Entity_Id;
-
          function Declared_In_Actual (Pack : Entity_Id) return Boolean;
          --  Recursive function that does the work and examines actuals of
          --  actual packages of current instance.
@@ -4858,7 +4856,7 @@ 
                   if Renamed_Object (Pack) = Scop then
                      return True;
 
-                  --  Check for end of list of actuals.
+                  --  Check for end of list of actuals
 
                   elsif Ekind (Act) = E_Package
                     and then Renamed_Object (Act) = Pack
@@ -4878,6 +4876,10 @@ 
             end if;
          end Declared_In_Actual;
 
+         --  Local variables
+
+         Act : Entity_Id;
+
       --  Start of processing for From_Actual_Package
 
       begin
@@ -5331,6 +5333,11 @@ 
          Msg := True;
       end Undefined;
 
+      --  Local variables
+
+      Nested_Inst : Entity_Id := Empty;
+      --  The entity of a nested instance which appears within Inst (if any)
+
    --  Start of processing for Find_Direct_Name
 
    begin
@@ -5497,15 +5504,17 @@ 
          --  If there is more than one potentially use-visible entity and at
          --  least one of them non-overloadable, we have an error (RM 8.4(11)).
          --  Note that E points to the first such entity on the homonym list.
-         --  Special case: if one of the entities is declared in an actual
-         --  package, it was visible in the generic, and takes precedence over
-         --  other entities that are potentially use-visible. Same if it is
-         --  declared in a local instantiation of the current instance.
 
          else
+            --  If one of the entities is declared in an actual package, it
+            --  was visible in the generic, and takes precedence over other
+            --  entities that are potentially use-visible. The same applies
+            --  if the entity is declared in a local instantiation of the
+            --  current instance.
+
             if In_Instance then
 
-               --  Find current instance
+               --  Find the current instance
 
                Inst := Current_Scope;
                while Present (Inst) and then Inst /= Standard_Standard loop
@@ -5516,12 +5525,21 @@ 
                   Inst := Scope (Inst);
                end loop;
 
+               --  Reexamine the candidate entities, giving priority to those
+               --  that were visible within the generic.
+
                E2 := E;
                while Present (E2) loop
+                  Nested_Inst := Nearest_Enclosing_Instance (E2);
+
+                  --  The entity is declared within an actual package, or in a
+                  --  nested instance. The ">=" accounts for the case where the
+                  --  current instance and the nested instance are the same.
+
                   if From_Actual_Package (E2)
-                    or else
-                      (Is_Generic_Instance (Scope (E2))
-                        and then Scope_Depth (Scope (E2)) > Scope_Depth (Inst))
+                    or else (Present (Nested_Inst)
+                              and then Scope_Depth (Nested_Inst) >=
+                                       Scope_Depth (Inst))
                   then
                      E := E2;
                      goto Found;
@@ -5533,8 +5551,7 @@ 
                Nvis_Messages;
                goto Done;
 
-            elsif
-              Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
+            elsif Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
             then
                --  A use-clause in the body of a system file creates conflict
                --  with some entity in a user scope, while rtsfind is active.
@@ -5543,7 +5560,7 @@ 
                E2 := E;
                while Present (E2) loop
                   if Is_Predefined_File_Name
-                    (Unit_File_Name (Get_Source_Unit (Sloc (E2))))
+                       (Unit_File_Name (Get_Source_Unit (Sloc (E2))))
                   then
                      E := E2;
                      goto Found;