Patchwork [Ada] Visibility error in the presence of private limited with clauses

login
register
mail settings
Submitter Arnaud Charlet
Date Oct. 4, 2012, 9:08 a.m.
Message ID <20121004090836.GA30303@adacore.com>
Download mbox | patch
Permalink /patch/189068/
State New
Headers show

Comments

Arnaud Charlet - Oct. 4, 2012, 9:08 a.m.
This patch fixes a visibility error when compiling a unit DDP, when an
ancestor P of DDP has a private limited with clause on a descendant of P that
is itself an ancestor of DDP.

The following must compile quietly:
   
      gcc -c -gnat05 bg-el-lc.adb

---
package body BG.El.LC is
   overriding procedure Bind (E : access One_Port; K : in AKind) is
   begin
      null;
   end Bind;
end BG.El.LC;
---
package BG.El.LC is
   type Component is abstract new Element with null record;

private

   type One_Port is new Component with null record;

   overriding procedure Bind (E : access One_Port; K : in AKind);

end BG.El.LC;
---
with Ada.Strings.Bounded;
private
    package BG.El is

   type Element is abstract tagged private;

   type AKind is (A, B);

   procedure Bind (E : access Element; K : in AKind) is abstract;

private

   type Element is abstract tagged null record;
end BG.El;
---
limited private with BG.El;
package BG is

   type Object is abstract tagged limited private;

   procedure Bind (Graph : in out Object) is abstract;

private
   type Object is abstract tagged limited null record;
end BG;

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

2012-10-04  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch10.adb (Is_Ancestor_Unit): Make global, for use elsewhere.
	(Install_Private_with_Clauses): if clause is private and limited,
	do not install the limited view if the library unit is an ancestor
	of the unit being compiled.  This unusual configuration occurs
	when compiling a unit DDP, when an ancestor P of DDP has a
	private limited with clause on a descendant of P that is itself
	an ancestor of DDP.

Patch

Index: sem_ch10.adb
===================================================================
--- sem_ch10.adb	(revision 192066)
+++ sem_ch10.adb	(working copy)
@@ -164,6 +164,11 @@ 
    --  an enclosing scope. Iterate over context to find child units of U_Name
    --  or of some ancestor of it.
 
+   function Is_Ancestor_Unit (U1 : Node_Id; U2 : Node_Id) return Boolean;
+   --  When compiling a unit Q descended from some parent unit P, a limited
+   --  with_clause in the context of P that names some other ancestor of Q
+   --  must not be installed because the ancestor is immediately visible.
+
    function Is_Child_Spec (Lib_Unit : Node_Id) return Boolean;
    --  Lib_Unit is a library unit which may be a spec or a body. Is_Child_Spec
    --  returns True if Lib_Unit is a library spec which is a child spec, i.e.
@@ -3521,11 +3526,6 @@ 
       --  units. The shadow entities are created when the inserted clause is
       --  analyzed. Implements Ada 2005 (AI-50217).
 
-      function Is_Ancestor_Unit (U1 : Node_Id; U2 : Node_Id) return Boolean;
-      --  When compiling a unit Q descended from some parent unit P, a limited
-      --  with_clause in the context of P that names some other ancestor of Q
-      --  must not be installed because the ancestor is immediately visible.
-
       ---------------------
       -- Check_Renamings --
       ---------------------
@@ -3794,22 +3794,6 @@ 
          end if;
       end Expand_Limited_With_Clause;
 
-      ----------------------
-      -- Is_Ancestor_Unit --
-      ----------------------
-
-      function Is_Ancestor_Unit (U1 : Node_Id; U2 : Node_Id) return Boolean is
-         E1 : constant Entity_Id := Defining_Entity (Unit (U1));
-         E2 : Entity_Id;
-      begin
-         if Nkind_In (Unit (U2), N_Package_Body, N_Subprogram_Body) then
-            E2 := Defining_Entity (Unit (Library_Unit (U2)));
-            return Is_Ancestor_Package (E1, E2);
-         else
-            return False;
-         end if;
-      end Is_Ancestor_Unit;
-
    --  Start of processing for Install_Limited_Context_Clauses
 
    begin
@@ -4061,8 +4045,17 @@ 
             if Nkind (Item) = N_With_Clause
               and then Private_Present (Item)
             then
+               --  If the unit is an ancestor of the current one, it is the
+               --  case of a private limited with clause on a child unit, and
+               --  the compilation of one of its descendants, In that case the
+               --  limited view is errelevant.
+
                if Limited_Present (Item) then
-                  if not Limited_View_Installed (Item) then
+                  if not Limited_View_Installed (Item)
+                    and then
+                      not Is_Ancestor_Unit (Library_Unit (Item),
+                                            Cunit (Current_Sem_Unit))
+                  then
                      Install_Limited_Withed_Unit (Item);
                   end if;
                else
@@ -5269,6 +5262,22 @@ 
             (C_Unit, Cunit_Entity (Get_Source_Unit (Non_Limited_View (T))));
    end Is_Legal_Shadow_Entity_In_Body;
 
+   ----------------------
+   -- Is_Ancestor_Unit --
+   ----------------------
+
+   function Is_Ancestor_Unit (U1 : Node_Id; U2 : Node_Id) return Boolean is
+      E1 : constant Entity_Id := Defining_Entity (Unit (U1));
+      E2 : Entity_Id;
+   begin
+      if Nkind_In (Unit (U2), N_Package_Body, N_Subprogram_Body) then
+         E2 := Defining_Entity (Unit (Library_Unit (U2)));
+         return Is_Ancestor_Package (E1, E2);
+      else
+         return False;
+      end if;
+   end Is_Ancestor_Unit;
+
    -----------------------
    -- Load_Needed_Body --
    -----------------------