diff mbox

[Ada] Handling of child instances within a sibling

Message ID 20100909130834.GA27000@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Sept. 9, 2010, 1:08 p.m. UTC
When a child generic is instantiated within a sibling, the common parent units
are on the scope stack and must remain visible to compile the rest of the
enclosing sibling. The parent units are also placed ahead of the current scope
to provide the proper visibility in the instance. After each of these parent
instances is removed, if it is a parent of the enclosing sibling its private
views must be re-installed. When the instance is declared within a block, this
block must be ignored when determining whether a parent instance must remain
visible.

The following must compile quietly:
   gcc -c p.adb

---
generic
package G is
  type T is private;
private
  type T is record
    J : Integer := 42;
  end record;
end G;
--
generic
function G.F (Parameter : in T) return T;
--
function G.F (Parameter : in T) return T is
begin
  return T'(J => Parameter.J + 1);
end G.F;
--
generic
procedure G.Proc (Parameter : in out T);
--
with G.F;
procedure G.Proc (Parameter : in out T) is
begin
  declare
    function A is new G.F;
  begin
    Parameter := T'(J => Parameter.J + 2); 
    Parameter.J := Parameter.J + 1;        
  end;
  Parameter.J := Parameter.J + 2;          
end G.Proc;
---
with G.Proc;
procedure P is
  package Instance is new G;
  procedure B is new Instance.Proc;
  Object : Instance.T;
begin
  B (Parameter => Object);
end P;

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

2010-09-09  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch12.adb (Remove_Parent): If the scope containing the child
	instance is a block, examine the enclosing scope to determine if it is
	a parent instance.
diff mbox

Patch

Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb	(revision 164055)
+++ sem_ch12.adb	(working copy)
@@ -11212,6 +11212,7 @@  package body Sem_Ch12 is
       --  stack contains the parent instances of the instantiation, followed by
       --  the original S.
 
+      Cur_P  : Entity_Id;
       E      : Entity_Id;
       P      : Entity_Id;
       Hidden : Elmt_Id;
@@ -11234,9 +11235,17 @@  package body Sem_Ch12 is
                   Next_Entity (E);
                end loop;
 
-               if Is_Generic_Instance (Current_Scope)
-                 and then P /= Current_Scope
-               then
+               --  If instantiation is declared in a block, it is the enclosing
+               --  scope that might be a parent instance. Note that only one
+               --  block can be involved, because the parent instances have
+               --  been installed within it.
+
+               Cur_P := P;
+               if Ekind (P) = E_Block then
+                  Cur_P := Scope (Cur_P);
+               end if;
+
+               if Is_Generic_Instance (Cur_P) and then P /= Current_Scope then
                   --  We are within an instance of some sibling. Retain
                   --  visibility of parent, for proper subsequent cleanup, and
                   --  reinstall private declarations as well.
@@ -11246,7 +11255,7 @@  package body Sem_Ch12 is
                end if;
 
             --  If the ultimate parent is a top-level unit recorded in
-            --  Instance_Parent_Unit, then reset its visibility to what is was
+            --  Instance_Parent_Unit, then reset its visibility to what it was
             --  before instantiation. (It's not clear what the purpose is of
             --  testing whether Scope (P) is In_Open_Scopes, but that test was
             --  present before the ultimate parent test was added.???)
@@ -11389,11 +11398,11 @@  package body Sem_Ch12 is
       while Present (M) loop
          Typ := Node (M);
 
-         --  Subtypes of types whose views have been exchanged, and that
-         --  are defined within the instance, were not on the list of
-         --  Private_Dependents on entry to the instance, so they have to be
-         --  exchanged explicitly now, in order to remain consistent with the
-         --  view of the parent type.
+         --  Subtypes of types whose views have been exchanged, and that are
+         --  defined within the instance, were not on the Private_Dependents
+         --  list on entry to the instance, so they have to be exchanged
+         --  explicitly now, in order to remain consistent with the view of the
+         --  parent type.
 
          if Ekind_In (Typ, E_Private_Type,
                            E_Limited_Private_Type,
@@ -11437,11 +11446,11 @@  package body Sem_Ch12 is
             --  An unusual case of aliasing: the actual may also be directly
             --  visible in the generic, and be private there, while it is fully
             --  visible in the context of the instance. The internal subtype
-            --  is private in the instance, but has full visibility like its
+            --  is private in the instance but has full visibility like its
             --  parent in the enclosing scope. This enforces the invariant that
             --  the privacy status of all private dependents of a type coincide
             --  with that of the parent type. This can only happen when a
-            --  generic child unit is instantiated within sibling.
+            --  generic child unit is instantiated within a sibling.
 
             if Is_Private_Type (E)
               and then not Is_Private_Type (Etype (E))
@@ -11457,16 +11466,14 @@  package body Sem_Ch12 is
             --  a formal package, make its own formals private as well. The
             --  actual in this case is itself the renaming of an instantiation.
             --  If the entity is not a package renaming, it is the entity
-            --  created to validate formal package actuals: ignore.
+            --  created to validate formal package actuals: ignore it.
 
             --  If the actual is itself a formal package for the enclosing
             --  generic, or the actual for such a formal package, it remains
             --  visible on exit from the instance, and therefore nothing needs
             --  to be done either, except to keep it accessible.
 
-            if Is_Package
-              and then Renamed_Object (E) = Pack_Id
-            then
+            if Is_Package and then Renamed_Object (E) = Pack_Id then
                exit;
 
             elsif Nkind (Parent (E)) /= N_Package_Renaming_Declaration then