diff mbox

[Ada] Handling of implicit dereference in instantiations

Message ID 20141031110308.GA26965@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Oct. 31, 2014, 11:03 a.m. UTC
The use of reference types and generalized indexing leads to multiple tree
rewritings. When these uses are in a generic unit, the transformations are not
propagated to instantiations, and the analysis of the instance must replicate
that of the generic to recognize the presence of implicit dereferences. This
patch removes some global information from selected components whose prefix
involves an implicit dereference, to force the re-analysis and resolution in
the instantiation.

Executing;

   gnatmake -q cont
   cont

must yield:

   1234
   1234
   1234
   2468

---
with Par; use Par;
with Par.Child;
with Ada.Finalization; use Ada.Finalization;
procedure Cont is
   use My_Lists;
   Bunch : List;
   Ptr   : Cursor;
   package Inst is new Par.Child;
   use Inst;
begin
   Append (Bunch, R'(Controlled with Kind => 1234));
   Try (Bunch, Bunch.First);
end;
---
with ada.containers.doubly_linked_lists;
with Ada.Finalization; use Ada.Finalization;
use ada.containers;
package Par is
 type R is new Ada.Finalization.Controlled with record
      Kind : Integer;
   end record;

   package My_Lists is new Doubly_Linked_Lists (R);
end Par;
---
generic
package Par.Child is
   use My_Lists;
   procedure Try (Bunch: List; C : Cursor);
end Par.Child;
--
with Text_IO; use Text_IO;
package body Par.Child is
   use My_Lists;
   procedure Try (Bunch: List; C : Cursor) is
      V1 : Integer := Constant_Reference (Bunch, C).Element.Kind;
      V2 : Integer := Constant_Reference (Bunch, C).Kind;
      V3 : Integer := Bunch (C).Kind;
   begin
      Put_Line (Integer'Image (V1));
      Put_Line (Integer'Image (V2));
      Put_Line (Integer'Image (V3));

      for Elmt of Bunch loop
         Put_Line (Integer'Image (2 * Elmt.Kind));
      end loop;
   end;
end Par.Child;

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

2014-10-31  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch4.adb (Try_Container_Indexing): Use Check_Implicit_Dereference.
	* sem_util.adb (Check_Implicit_Dereference): a)	Handle generalized
	indexing as well as function calls.  b)  If the context is a
	selected component and whe are in an instance, remove entity from
	selector name to force resolution of the node, so that explicit
	dereferences can be generated in the instance if they were in
	the generic unit.
diff mbox

Patch

Index: sem_util.adb
===================================================================
--- sem_util.adb	(revision 216925)
+++ sem_util.adb	(working copy)
@@ -2673,17 +2673,29 @@ 
    -- Check_Implicit_Dereference --
    --------------------------------
 
-   procedure Check_Implicit_Dereference (Nam : Node_Id;  Typ : Entity_Id) is
+   procedure Check_Implicit_Dereference (N : Node_Id;  Typ : Entity_Id) is
       Disc  : Entity_Id;
       Desig : Entity_Id;
+      Nam   : Node_Id;
 
    begin
+      if Nkind (N) = N_Indexed_Component
+        and then Present (Generalized_Indexing (N))
+      then
+         Nam := Generalized_Indexing (N);
+
+      else
+         Nam := N;
+      end if;
+
       if Ada_Version < Ada_2012
         or else not Has_Implicit_Dereference (Base_Type (Typ))
       then
          return;
 
-      elsif not Comes_From_Source (Nam) then
+      elsif not Comes_From_Source (N)
+        and then Nkind (N) /= N_Indexed_Component
+      then
          return;
 
       elsif Is_Entity_Name (Nam) and then Is_Type (Entity (Nam)) then
@@ -2695,6 +2707,26 @@ 
             if Has_Implicit_Dereference (Disc) then
                Desig := Designated_Type (Etype (Disc));
                Add_One_Interp (Nam, Disc, Desig);
+
+               --  If the node is a generalized indexing, add interpretation
+               --  to that node as well, for subsequent resolution.
+
+               if Nkind (N) = N_Indexed_Component then
+                  Add_One_Interp (N, Disc, Desig);
+               end if;
+
+               --  If the operation comes from a generic unit and the context
+               --  is a selected component, the selector name may be global
+               --  and set in the instance already. Remove the entity to
+               --  force resolution of the selected component, and the
+               --  generation of an explicit dereference if needed.
+
+               if In_Instance
+                 and then Nkind (Parent (Nam)) = N_Selected_Component
+               then
+                  Set_Entity (Selector_Name (Parent (Nam)), Empty);
+               end if;
+
                exit;
             end if;
 
@@ -16543,11 +16575,21 @@ 
    begin
       --  Nothing to do if argument is Empty or has Debug_Info_Off set, which
       --  indicates that Debug_Info_Needed is never required for the entity.
+      --  Nothing to do if entity comes from a predefined file. Library files
+      --  are compiled without debug information, but inlined bodies of these
+      --  routines may appear in user code, and debug information on them ends
+      --  up complicating debugging the user code.
 
       if No (T)
         or else Debug_Info_Off (T)
       then
          return;
+
+      elsif In_Inlined_Body
+        and then Is_Predefined_File_Name
+           (Unit_File_Name (Get_Source_Unit (Sloc (T))))
+      then
+         Set_Needs_Debug_Info (T, False);
       end if;
 
       --  Set flag in entity itself. Note that we will go through the following
Index: sem_util.ads
===================================================================
--- sem_util.ads	(revision 216925)
+++ sem_util.ads	(working copy)
@@ -285,10 +285,12 @@ 
    --  the one containing C2, that is known to refer to the same object (RM
    --  6.4.1(6.17/3)).
 
-   procedure Check_Implicit_Dereference (Nam : Node_Id; Typ : Entity_Id);
+   procedure Check_Implicit_Dereference (N : Node_Id; Typ : Entity_Id);
    --  AI05-139-2: Accessors and iterators for containers. This procedure
    --  checks whether T is a reference type, and if so it adds an interprettion
-   --  to Expr whose type is the designated type of the reference_discriminant.
+   --  to N whose type is the designated type of the reference_discriminant.
+   --  If N is a generalized indexing operation, the interpretation is added
+   --  both to the corresponding function call, and to the indexing node.
 
    procedure Check_Internal_Protected_Use (N : Node_Id; Nam : Entity_Id);
    --  Within a protected function, the current object is a constant, and
Index: sem_ch4.adb
===================================================================
--- sem_ch4.adb	(revision 216925)
+++ sem_ch4.adb	(working copy)
@@ -7036,7 +7036,6 @@ 
       Loc       : constant Source_Ptr := Sloc (N);
       C_Type    : Entity_Id;
       Assoc     : List_Id;
-      Disc      : Entity_Id;
       Func      : Entity_Id;
       Func_Name : Node_Id;
       Indexing  : Node_Id;
@@ -7149,21 +7148,7 @@ 
          --  discriminant is not the first discriminant.
 
          if Has_Discriminants (Etype (Func)) then
-            Disc := First_Discriminant (Etype (Func));
-            while Present (Disc) loop
-               declare
-                  Elmt_Type : Entity_Id;
-               begin
-                  if Has_Implicit_Dereference (Disc) then
-                     Elmt_Type := Designated_Type (Etype (Disc));
-                     Add_One_Interp (Indexing, Disc, Elmt_Type);
-                     Add_One_Interp (N, Disc, Elmt_Type);
-                     exit;
-                  end if;
-               end;
-
-               Next_Discriminant (Disc);
-            end loop;
+            Check_Implicit_Dereference (N, Etype (Func));
          end if;
 
       else
@@ -7194,18 +7179,7 @@ 
                   --  Add implicit dereference interpretation
 
                   if Has_Discriminants (Etype (It.Nam)) then
-                     Disc := First_Discriminant (Etype (It.Nam));
-                     while Present (Disc) loop
-                        if Has_Implicit_Dereference (Disc) then
-                           Add_One_Interp
-                             (Indexing, Disc, Designated_Type (Etype (Disc)));
-                           Add_One_Interp
-                             (N, Disc, Designated_Type (Etype (Disc)));
-                           exit;
-                        end if;
-
-                        Next_Discriminant (Disc);
-                     end loop;
+                     Check_Implicit_Dereference (N, Etype (It.Nam));
                   end if;
 
                   exit;