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 <[email protected]>
* 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;