Ada2012 introduces the notion of a reference type, to generalize the use of
cursors in containers. A reference type is a type with an access discriminant,
with the semantics that a reference to an object of the type is in fact a
reference to the object denoted by the access discriminant.
The following must compile and execute quietly in Ada2012 mode:

with Deref; use Deref;
procedure Test_Deref is
   C : Cursor := Index (5);
   V : Integer := Index (5);
   Fifteen : Float := Index (1234);

   Obj : Wrapper;

  C1 : Cursor := Obj.Ptr;
  V2 : Integer := Obj.Ptr;
begin
   if Value /= 1234 
     or else Value2 /= 1234
     or else V /= 1234
     or else V2 /= 1234
   then
      raise Program_Error;
   end if;
end;
---
package deref is
   type Cursor (E : access Integer) is tagged null record
   with  Implicit_Dereference => E;

   function Index (N : Integer) return Cursor;
   function Index (N : Integer) return Float;
   Thing : Cursor := (E => New Integer'(1234));
   Value : aliased Integer := Thing;

   type Wrapper is record
      Ptr : Cursor (Value'access);
   end record;

   type Table is array (1..10) of Cursor (Value'access);
   It : Table;
   Value2 : Integer :=  It (5);
end;
--

The following compilation:

   gcc -c -gnat12 -gnatf ambig_deref.ads

must yield the following errors:

   ambig_deref.ads:12:23: can be interpreted as implicit dereference
   ambig_deref.ads:12:30: ambiguous operands for equality
   ambig_deref.ads:12:32: can be interpreted as implicit dereference

---
package ambig_deref is
   type Cursor (E : access Integer) is tagged null record
   with  Implicit_Dereference => E;

   Thing : Cursor := (E => New Integer'(1234));
   Value : aliased Integer := Thing;

   type Table is array (1..10) of Cursor (Value'access);
   It : Table;
   Value2 : Integer :=  It (5);

   Maybe : Boolean := It (4) = It (5);
end;

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

2011-08-05  Ed Schonberg  <schonb...@adacore.com>

        * sem_util.adb, sem_util.ads (Check_Implicit_Dereference): If a
        possible interpretation of name is a reference type, add an
        interpretation that is the designated type of the reference
        discriminant of that type.
        * sem_res.adb (resolve): If the interpretation imposed by context is an
        implicit dereference, rewrite the node as the deference of the
        reference discriminant.
        * sem_ch3.adb (Analyze_Subtype_Declaration, Build_Derived_Record_Type,
        Build_Discriminated_Subtype): Inherit Has_Implicit_Dereference from
        parent type or base type.
        * sem_ch4.adb (Process_Indexed_Component,
        Process_Overloaded_Indexed_Component, Indicate_Name_And_Type,
        Analyze_Overloaded_Selected_Component, Analyze_Selected_Component):
        Check for implicit dereference.
        (List_Operand_Interps): Indicate when an implicit dereference is
        ambiguous.
        * sem_ch8.adb (Find_Direct_Name): Check for implicit dereference.

Index: sem_ch3.adb
===================================================================
--- sem_ch3.adb (revision 177441)
+++ sem_ch3.adb (working copy)
@@ -4215,6 +4215,8 @@
                Set_Has_Discriminants    (Id, Has_Discriminants  (T));
                Set_Is_Constrained       (Id, Is_Constrained     (T));
                Set_Is_Limited_Record    (Id, Is_Limited_Record  (T));
+               Set_Has_Implicit_Dereference
+                                        (Id, Has_Implicit_Dereference (T));
                Set_Has_Unknown_Discriminants
                                         (Id, Has_Unknown_Discriminants (T));
 
@@ -4248,6 +4250,8 @@
                Set_Last_Entity        (Id, Last_Entity           (T));
                Set_Private_Dependents (Id, New_Elmt_List);
                Set_Is_Limited_Record  (Id, Is_Limited_Record     (T));
+               Set_Has_Implicit_Dereference
+                                        (Id, Has_Implicit_Dereference (T));
                Set_Has_Unknown_Discriminants
                                       (Id, Has_Unknown_Discriminants (T));
                Set_Known_To_Have_Preelab_Init
@@ -7875,6 +7879,8 @@
             Set_Stored_Constraint
               (Derived_Type, Expand_To_Stored_Constraint (Parent_Type, Discs));
             Replace_Components (Derived_Type, New_Decl);
+            Set_Has_Implicit_Dereference
+              (Derived_Type, Has_Implicit_Dereference (Parent_Type));
          end if;
 
          --  Insert the new derived type declaration
@@ -8586,6 +8592,8 @@
 
       Set_First_Entity      (Def_Id, First_Entity   (T));
       Set_Last_Entity       (Def_Id, Last_Entity    (T));
+      Set_Has_Implicit_Dereference
+                            (Def_Id, Has_Implicit_Dereference (T));
 
       --  If the subtype is the completion of a private declaration, there may
       --  have been representation clauses for the partial view, and they must
Index: sem_util.adb
===================================================================
--- sem_util.adb        (revision 177433)
+++ sem_util.adb        (working copy)
@@ -1104,6 +1104,43 @@
       end if;
    end Cannot_Raise_Constraint_Error;
 
+   --------------------------------
+   -- Check_Implicit_Dereference --
+   --------------------------------
+
+   procedure Check_Implicit_Dereference (Nam : Node_Id;  Typ : Entity_Id)
+   is
+      Disc  : Entity_Id;
+      Desig : Entity_Id;
+
+   begin
+      if Ada_Version < Ada_2012
+        or else not Has_Implicit_Dereference (Base_Type (Typ))
+      then
+         return;
+
+      elsif not Comes_From_Source (Nam) then
+         return;
+
+      elsif Is_Entity_Name (Nam)
+        and then Is_Type (Entity (Nam))
+      then
+         null;
+
+      else
+         Disc := First_Discriminant (Typ);
+         while Present (Disc) loop
+            if Has_Implicit_Dereference (Disc) then
+               Desig := Designated_Type (Etype (Disc));
+               Add_One_Interp (Nam, Disc, Desig);
+               exit;
+            end if;
+
+            Next_Discriminant (Disc);
+         end loop;
+      end if;
+   end Check_Implicit_Dereference;
+
    ---------------------------------------
    -- Check_Later_Vs_Basic_Declarations --
    ---------------------------------------
Index: sem_util.ads
===================================================================
--- sem_util.ads        (revision 177433)
+++ sem_util.ads        (working copy)
@@ -147,6 +147,11 @@
    --  not necessarily mean that CE could be raised, but a response of True
    --  means that for sure CE cannot be raised.
 
+   procedure Check_Implicit_Dereference (Nam : 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.
+
    procedure Check_Later_Vs_Basic_Declarations
      (Decls          : List_Id;
       During_Parsing : Boolean);
Index: sem_res.adb
===================================================================
--- sem_res.adb (revision 177431)
+++ sem_res.adb (working copy)
@@ -1753,6 +1753,15 @@
       It1       : Interp;
       Seen      : Entity_Id := Empty; -- prevent junk warning
 
+      procedure Build_Explicit_Dereference
+        (Expr : Node_Id;
+         Disc : Entity_Id);
+      --  AI05-139 : names with implicit dereference. If the expression N is a
+      --  reference type and the context imposes the corresponding designated
+      --  type, convert N into N.Disc.all. Such expressions are always over-
+      --  loaded with both interpretations, and the dereference interpretation
+      --  carries the name of the reference discriminant.
+
       function Comes_From_Predefined_Lib_Unit (Nod : Node_Id) return Boolean;
       --  Determine whether a node comes from a predefined library unit or
       --  Standard.
@@ -1768,6 +1777,30 @@
       procedure Resolution_Failed;
       --  Called when attempt at resolving current expression fails
 
+      --------------------------------
+      -- Build_Explicit_Dereference --
+      --------------------------------
+
+      procedure Build_Explicit_Dereference
+        (Expr : Node_Id;
+         Disc : Entity_Id)
+      is
+         Loc : constant Source_Ptr := Sloc (Expr);
+
+      begin
+         Set_Is_Overloaded (Expr, False);
+         Rewrite (Expr,
+           Make_Explicit_Dereference (Loc,
+             Prefix =>
+               Make_Selected_Component (Loc,
+                 Prefix => Relocate_Node (Expr),
+                 Selector_Name =>
+               New_Occurrence_Of (Disc, Loc))));
+
+         Set_Etype (Prefix (Expr), Etype (Disc));
+         Set_Etype (Expr, Typ);
+      end Build_Explicit_Dereference;
+
       ------------------------------------
       -- Comes_From_Predefined_Lib_Unit --
       -------------------------------------
@@ -2279,6 +2312,22 @@
                elsif Nkind (N) = N_Conditional_Expression then
                   Set_Etype (N, Expr_Type);
 
+               --  AI05-0139-2 : expression is overloaded because
+               --  type has implicit dereference. If type matches
+               --  context, no implicit dereference is involved.
+
+               elsif Has_Implicit_Dereference (Expr_Type) then
+                  Set_Etype (N, Expr_Type);
+                  Set_Is_Overloaded (N, False);
+                  exit Interp_Loop;
+
+               elsif Is_Overloaded (N)
+                 and then Present (It.Nam)
+                 and then Ekind (It.Nam) = E_Discriminant
+                 and then Has_Implicit_Dereference (It.Nam)
+               then
+                  Build_Explicit_Dereference (N, It.Nam);
+
                --  For an explicit dereference, attribute reference, range,
                --  short-circuit form (which is not an operator node), or call
                --  with a name that is an explicit dereference, there is
Index: sem_ch4.adb
===================================================================
--- sem_ch4.adb (revision 177431)
+++ sem_ch4.adb (working copy)
@@ -301,7 +301,24 @@
                Nam := Opnd;
             elsif Nkind (Opnd) = N_Function_Call then
                Nam := Name (Opnd);
-            else
+            elsif Ada_Version >= Ada_2012 then
+               declare
+                  It : Interp;
+                  I  : Interp_Index;
+
+               begin
+                  Get_First_Interp (Opnd, I, It);
+                  while Present (It.Nam) loop
+                     if Has_Implicit_Dereference (It.Typ) then
+                        Error_Msg_N
+                          ("can be interpreted as implicit dereference", Opnd);
+                        return;
+                     end if;
+
+                     Get_Next_Interp (I, It);
+                  end loop;
+               end;
+
                return;
             end if;
 
@@ -2068,6 +2085,7 @@
             end loop;
 
             Set_Etype (N, Component_Type (Array_Type));
+            Check_Implicit_Dereference (N, Etype (N));
 
             if Present (Index) then
                Error_Msg_N
@@ -2164,9 +2182,13 @@
                end loop;
 
                if Found and then No (Index) and then No (Exp) then
-                  Add_One_Interp (N,
-                     Etype (Component_Type (Typ)),
-                     Etype (Component_Type (Typ)));
+                  declare
+                     CT : constant Entity_Id :=
+                            Base_Type (Component_Type (Typ));
+                  begin
+                     Add_One_Interp (N, CT, CT);
+                     Check_Implicit_Dereference (N, CT);
+                  end;
                end if;
             end if;
 
@@ -2644,6 +2666,7 @@
       procedure Indicate_Name_And_Type is
       begin
          Add_One_Interp (N, Nam, Etype (Nam));
+         Check_Implicit_Dereference (N, Etype (Nam));
          Success := True;
 
          --  If the prefix of the call is a name, indicate the entity
@@ -3133,6 +3156,7 @@
                      Set_Entity (Sel, Comp);
                      Set_Etype (Sel, Etype (Comp));
                      Add_One_Interp (N, Etype (Comp), Etype (Comp));
+                     Check_Implicit_Dereference (N, Etype (Comp));
 
                      --  This also specifies a candidate to resolve the name.
                      --  Further overloading will be resolved from context.
@@ -3740,6 +3764,7 @@
            New_Occurrence_Of (Comp, Sloc (N)));
          Set_Original_Discriminant (Selector_Name (N), Comp);
          Set_Etype (N, Etype (Comp));
+         Check_Implicit_Dereference (N, Etype (Comp));
 
          if Is_Access_Type (Etype (Name)) then
             Insert_Explicit_Dereference (Name);
@@ -3876,6 +3901,7 @@
                   Set_Etype (N, Etype (Comp));
                end if;
 
+               Check_Implicit_Dereference (N, Etype (N));
                return;
             end if;
 
@@ -3941,6 +3967,7 @@
 
                   Set_Etype (Sel, Etype (Comp));
                   Set_Etype (N,   Etype (Comp));
+                  Check_Implicit_Dereference (N, Etype (N));
 
                   if Is_Generic_Type (Prefix_Type)
                     or else Is_Generic_Type (Root_Type (Prefix_Type))
Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb (revision 177431)
+++ sem_ch8.adb (working copy)
@@ -4818,6 +4818,7 @@
             end if;
 
             Set_Entity_Or_Discriminal (N, E);
+            Check_Implicit_Dereference (N, Etype (E));
          end if;
       end;
    end Find_Direct_Name;

Reply via email to