diff mbox

[Ada] Non-excluding subtypes and generics

Message ID 20100909093052.GA13931@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Sept. 9, 2010, 9:30 a.m. UTC
When a nul_excluding indication qualifies a subtype mark of some access type
in various kinds of declarations, we create an anonymous subtype of the
original access type, and use it to replace the original subtype mark  This
replacement must be undone when checking whether a given entity in a generic
unit is global to it, because what matters is the visibility of the oiginal
subtype_mark. The the null_excluding subtype will be recreated in the instance
or inlined body.

The following must compile quietly:

    gcc -c -gnat05 inst_test.adb

procedure Inst_Test is
   package Strings is
      type Ptr is access all String;
   end Strings;
   use Strings;

   generic
   package G is
      function Create return Ptr;
   end G;

   package body G is
      function Create return Ptr is
         Link : not null Ptr := new String'("Here");
      begin
         return Link;
      end;
   end G;

   package Inst is new G;
begin
   null;
end;

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

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

	* sem_ch12.adb (Reset_Entity): If the entity is an itype created as a
	subtype for a null-excluding access type, recover the original
	subtype_mark to get the proper visibility on the original name.
diff mbox

Patch

Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb	(revision 164000)
+++ sem_ch12.adb	(working copy)
@@ -11720,15 +11720,29 @@  package body Sem_Ch12 is
          N2 := Get_Associated_Node (N);
          E := Entity (N2);
 
+         --  If the entity is an itype created as a subtype of an access type
+         --  with a null exclusion restore source entity for proper visibility.
+         --  The itype will be created anew in the instance.
+
          if Present (E) then
+            if Is_Itype (E)
+              and then Ekind (E) = E_Access_Subtype
+              and then Is_Entity_Name (N)
+              and then Chars (Etype (E)) = Chars (N)
+            then
+               E := Etype (E);
+               Set_Entity (N2, E);
+               Set_Etype  (N2, E);
+            end if;
+
             if Is_Global (E) then
                Set_Global_Type (N, N2);
 
             elsif Nkind (N) = N_Op_Concat
               and then Is_Generic_Type (Etype (N2))
-              and then
-               (Base_Type (Etype (Right_Opnd (N2))) = Etype (N2)
-                  or else Base_Type (Etype (Left_Opnd (N2))) = Etype (N2))
+              and then (Base_Type (Etype (Right_Opnd (N2))) = Etype (N2)
+                         or else
+                        Base_Type (Etype (Left_Opnd (N2)))  = Etype (N2))
               and then Is_Intrinsic_Subprogram (E)
             then
                null;
@@ -11971,11 +11985,11 @@  package body Sem_Ch12 is
            and then Is_Generic_Unit (Scope (Gen_Id))
            and then In_Open_Scopes (Scope (Gen_Id))
          then
-            --  This is an instantiation of a child unit within a sibling,
-            --  so that the generic parent is in scope. An eventual instance
-            --  must occur within the scope of an instance of the parent.
-            --  Make name in instance into an expanded name, to preserve the
-            --  identifier of the parent, so it can be resolved subsequently.
+            --  This is an instantiation of a child unit within a sibling, so
+            --  that the generic parent is in scope. An eventual instance must
+            --  occur within the scope of an instance of the parent. Make name
+            --  in instance into an expanded name, to preserve the identifier
+            --  of the parent, so it can be resolved subsequently.
 
             Rewrite (Name (N2),
               Make_Expanded_Name (Loc,