diff mbox

[Ada] Resolving self-references to a child generic unit in an instance

Message ID 20131010123020.GA4370@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Oct. 10, 2013, 12:30 p.m. UTC
This patch fixes a name resolution problem in a child instance. involving a
name of the form A.B.C, where A. B and C constitute a generic hierarchy.
Within an instance of C, this name must be rewritten to denote the instances
of A, B and C. Previously the compiler only handled one level of child units.

The following must compile quietly:

      gnatmake -q pack-td.ads

---
with Gen_Pack.Child.TD;
with Gen_Pack.Child.TD.T;
package Pack.TD is
   package TD_Inst is new Pack.Smth2.TD;
   package T_Inst is new TD_Inst.T;
end Pack.TD;
--
with Gen_Pack;
with Gen_Pack.Child;

package Pack is
   package Smth  is new Gen_Pack (Integer);
   package Smth2 is new Smth.Child;
end Pack;
--
generic
   type Formal_Type is range <>;
package Gen_Pack is
   function Self (X : Formal_Type) return Formal_Type is (X);
end Gen_Pack;
--
generic
package Gen_Pack.Child is
   function Minus_Self (X : Formal_Type) return Formal_Type is (-X);
end Gen_Pack.Child;
--
generic
package Gen_Pack.Child.TD is
   type Tst is tagged null record;
end Gen_Pack.Child.TD;
--
generic
package Gen_Pack.Child.TD.T is
   type Tst is new Gen_Pack.Child.TD.Tst with null record;
end Gen_Pack.Child.TD.T;

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

2013-10-10  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch8.adb (Find_Expanded_Name): Handle properly a fully
	qualified reference to a generic child unit within itself,
	in an instantiation.
diff mbox

Patch

Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb	(revision 203342)
+++ sem_ch8.adb	(working copy)
@@ -5157,12 +5157,10 @@ 
       Selector  : constant Node_Id := Selector_Name (N);
       Candidate : Entity_Id        := Empty;
       P_Name    : Entity_Id;
-      O_Name    : Entity_Id;
       Id        : Entity_Id;
 
    begin
       P_Name := Entity (Prefix (N));
-      O_Name := P_Name;
 
       --  If the prefix is a renamed package, look for the entity in the
       --  original package.
@@ -5340,15 +5338,22 @@ 
             else
                --  Within the instantiation of a child unit, the prefix may
                --  denote the parent instance, but the selector has the name
-               --  of the original child. Find whether we are within the
-               --  corresponding instance, and get the proper entity, which
-               --  can only be an enclosing scope.
+               --  of the original child. That is to say, when A.B appears
+               --  within an instantiation of generic child unit B, the scope
+               --  stack includes an instance of A (P_Name) and an instance
+               --  of B under some other name. We scan the scope to find this
+               --  child instance, which is the desired entity.
+               --  Note that the parent may itself be a child instance, if
+               --  the reference is of the form A.B.C, in which case A.B has
+               --  already been rewritten with the proper entity.
 
-               if O_Name /= P_Name
-                 and then In_Open_Scopes (P_Name)
+               if In_Open_Scopes (P_Name)
                  and then Is_Generic_Instance (P_Name)
                then
                   declare
+                     Gen_Par : constant Entity_Id :=
+                                 Generic_Parent (Specification
+                                   (Unit_Declaration_Node (P_Name)));
                      S : Entity_Id := Current_Scope;
                      P : Entity_Id;
 
@@ -5365,9 +5370,12 @@ 
                            P := Generic_Parent (Specification
                                   (Unit_Declaration_Node (S)));
 
+                           --  Check that P is a generic child of the generic
+                           --  parent of the prefix.
+
                            if Present (P)
-                             and then Chars (Scope (P)) = Chars (O_Name)
                              and then Chars (P) = Chars (Selector)
+                             and then Scope (P) = Gen_Par
                            then
                               Id := S;
                               goto Found;