[Ada] Handling of library unit renamings in with_clauses

Message ID 20120222140707.GA15500@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Feb. 22, 2012, 2:07 p.m.
A library unit name that is a renaming can appear in the name of a with_clause.
When it is the prefix of a name, an implicit with_clause must be created for it,
as well as for the unit it renames. So if R renames A, and we have a with_clause
on R.B (where B is a child unit of A) we need with_clauses on both R an A (both
of which can themselves be child units). This is because R may be used as a
prefix within the current unit, and because A is needed to retrieve A.B.
This patch fixes a bug in the handling of such with_clauses, and simplifies the
processing by creating the with_clause for R when processing the with_clause
for R.B at load time, before any analysis has taken place.

The following must compile quietly:

      gcc -c with_child.ads

package Orig_Parent is
end Orig_Parent;
package Orig_Parent.Child is
end Orig_Parent.Child;
function Orig_Parent.Child.Grandchild return Integer;
package Renam_Parent is
end Renam_Parent;
with Orig_Parent.Child;
package Renam_Parent.Child renames Orig_Parent.Child;
with Renam_Parent.Child.Grandchild;
package With_Child is
   X : Integer := Renam_Parent.Child.Grandchild;
end With_Child;

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

2012-02-22  Ed Schonberg  <schonberg@adacore.com>

	* lib-load.adb (Load_Unit): If the prefix of the name in a
	with-clause is a renaming, add a with-clause on the original unit.
	* sem_ch10.adb (Build_Unit_Name): Remove code made obsolete by
	new handling of renamings in with-clauses.


Index: lib-load.adb
--- lib-load.adb	(revision 184470)
+++ lib-load.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2012, 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- --
@@ -406,9 +406,25 @@ 
                 (Load_Name, Get_Unit_Name (Name (Unit (Cunit (Unump)))));
+            --  If the load is for a with_clause, for visibility purposes both
+            --  the renamed entity and renaming one must be available in the
+            --  current unit: the renamed one in order to retrieve the child
+            --  unit, and the original one because it may be used as a prefix
+            --  in the body of the current unit. We add an explicit with_clause
+            --  for the original parent so that the renaming declaration is
+            --  properly loaded and analyzed.
+            if Present (With_Node) then
+               Insert_After (With_Node,
+                 Make_With_Clause (Sloc (With_Node),
+                   Name => Copy_Separate_Tree (Prefix (Name (With_Node)))));
+            end if;
             --  Save the renaming entity, to establish its visibility when
             --  installing the context. The implicit with is on this entity,
-            --  not on the package it renames.
+            --  not on the package it renames. This is somewhat redundant given
+            --  the with_clause just created, but it simplifies subsequent
+            --  expansion of the current with_clause. Optimizable ???
             if Nkind (Error_Node) = N_With_Clause
               and then Nkind (Name (Error_Node)) = N_Selected_Component
Index: sem_ch10.adb
--- sem_ch10.adb	(revision 184470)
+++ sem_ch10.adb	(working copy)
@@ -2936,33 +2936,12 @@ 
       function Build_Unit_Name (Nam : Node_Id) return Node_Id is
          Ent      : Entity_Id;
-         Renaming : Entity_Id;
          Result   : Node_Id;
          if Nkind (Nam) = N_Identifier then
+            return New_Occurrence_Of (Entity (Nam), Loc);
-            --  If the parent unit P in the name of the with_clause for P.Q is
-            --  a renaming of package R, then the entity of the parent is set
-            --  to R, but the identifier retains Chars (P) to be consistent
-            --  with the source (see details in lib-load). However the implicit
-            --  with_clause for the parent must make the entity for P visible,
-            --  because P.Q may be used as a prefix within the current unit.
-            --  The entity for P is the current_entity with that name, because
-            --  the package renaming declaration for it has just been analyzed.
-            --  Note that this case can only happen if P.Q has already appeared
-            --  in a previous with_clause in a related unit, such as the
-            --  library body of the current unit.
-            if Chars (Nam) /= Chars (Entity (Nam)) then
-               Renaming := Current_Entity (Nam);
-               pragma Assert (Renamed_Entity (Renaming) = Entity (Nam));
-               return New_Occurrence_Of (Renaming, Loc);
-            else
-               return New_Occurrence_Of (Entity (Nam), Loc);
-            end if;
             Ent := Entity (Nam);