Skip to content

Commit 6247ed3

Browse files
authored
Merge pull request #344 from tjj2017/implicit_deref
Implicit deref
2 parents 715262d + 5a06860 commit 6247ed3

File tree

16 files changed

+426
-54
lines changed

16 files changed

+426
-54
lines changed

experiments/golden-results/StratoX-summary.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,12 +1760,12 @@ Error detected at REDACTED
17601760
--
17611761
Occurs: 1 times
17621762
+===========================GNAT BUG DETECTED==============================+
1763-
| GNU Ada (ada2goto) Assert_Failure failed precondition from arrays.ads:51 |
1763+
| GNU Ada (ada2goto) Assert_Failure failed precondition from arrays.ads:71 |
17641764
Error detected at REDACTED
17651765
--
17661766
Occurs: 1 times
17671767
+===========================GNAT BUG DETECTED==============================+
1768-
| GNU Ada (ada2goto) Assert_Failure failed precondition from arrays.ads:51 |
1768+
| GNU Ada (ada2goto) Assert_Failure failed precondition from arrays.ads:71 |
17691769
Error detected at REDACTED
17701770
--
17711771
Occurs: 1 times
@@ -2223,19 +2223,19 @@ Occurs: 25 times
22232223
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from goto_utils.ads:147
22242224

22252225
--
2226-
Occurs: 4 times
2226+
Occurs: 2 times
22272227
<========================>
2228-
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from arrays.ads:57
2228+
raised CONSTRAINT_ERROR : Symbol_Table_Info.Symbol_Maps.Constant_Reference: key not in map
22292229

22302230
--
22312231
Occurs: 2 times
22322232
<========================>
2233-
raised CONSTRAINT_ERROR : Symbol_Table_Info.Symbol_Maps.Constant_Reference: key not in map
2233+
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from arrays.ads:51
22342234

22352235
--
22362236
Occurs: 2 times
22372237
<========================>
2238-
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from arrays.ads:51
2238+
raised SYSTEM.ASSERTIONS.ASSERT_FAILURE : failed precondition from ireps.ads:1648
22392239

22402240
--
22412241
Occurs: 2 times

gnat2goto/driver/arrays.adb

Lines changed: 106 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
with Nlists; use Nlists;
22
with Uintp; use Uintp;
3-
3+
with Namet; use Namet;
44
with Tree_Walk; use Tree_Walk;
55
with Follow; use Follow;
66
with Range_Check; use Range_Check;
@@ -791,19 +791,34 @@ package body Arrays is
791791

792792
function Do_Array_Length (N : Node_Id) return Irep
793793
is
794-
Array_Struct : constant Irep := Do_Expression (Prefix (N));
794+
-- It seems as though an N_Explicit_Drereference is placed in the tree
795+
-- even when the prefix of the Length attribute is an implicit
796+
-- dereference.
797+
-- Hence, implicit dereferences do not have to be seperately handled,
798+
-- they are handled as explicit dereferences.
799+
Array_Struct : constant Irep := Do_Expression (Prefix (N));
795800
begin
796801
return Build_Array_Size (Array_Struct);
797802
end Do_Array_Length;
798803

799804
function Do_Array_First (N : Node_Id) return Irep
800805
is
806+
-- It seems as though an N_Explicit_Drereference is placed in the tree
807+
-- even when the prefix of the Length attribute is an implicit
808+
-- dereference.
809+
-- Hence, implicit dereferences do not have to be seperately handled,
810+
-- they are handled as explicit dereferences.
801811
begin
802812
return Get_First_Index (Do_Expression (Prefix (N)));
803813
end Do_Array_First;
804814

805815
function Do_Array_Last (N : Node_Id) return Irep
806816
is
817+
-- It seems as though an N_Explicit_Drereference is placed in the tree
818+
-- even when the prefix of the Length attribute is an implicit
819+
-- dereference.
820+
-- Hence, implicit dereferences do not have to be seperately handled,
821+
-- they are handled as explicit dereferences.
807822
begin
808823
return Get_Last_Index (Do_Expression (Prefix (N)));
809824
end Do_Array_Last;
@@ -857,8 +872,28 @@ package body Arrays is
857872
-- }
858873
----------------------------------------------------------------------------
859874
function Do_Slice (N : Node_Id) return Irep is
875+
-- The prefix to the slice may be an access to an array object
876+
-- which must be implicitly dereferenced.
877+
The_Prefix : constant Node_Id := Prefix (N);
878+
Prefix_Etype : constant Node_Id := Etype (The_Prefix);
879+
Is_Implicit_Deref : constant Boolean := Is_Access_Type (Prefix_Etype);
880+
Prefix_Irep : constant Irep := Do_Expression (The_Prefix);
881+
Result_Type : constant Irep :=
882+
(if Is_Implicit_Deref then
883+
Do_Type_Reference (Designated_Type (Prefix_Etype))
884+
else
885+
Do_Type_Reference (Prefix_Etype));
886+
Base_Irep : constant Irep :=
887+
(if Is_Implicit_Deref then
888+
Make_Dereference_Expr
889+
(I_Type => Result_Type,
890+
Object => Prefix_Irep,
891+
Source_Location => Get_Source_Location (N))
892+
else
893+
Prefix_Irep);
894+
895+
-- Where required the prefix has been implicitly dereferenced.
860896
Source_Loc : constant Irep := Get_Source_Location (N);
861-
Result_Type : constant Irep := Do_Type_Reference (Etype (N));
862897
Slice_Params : constant Irep := Make_Parameter_List;
863898
Slice_Args : constant Irep := Make_Argument_List;
864899
Function_Name : constant String := "slice_expr";
@@ -937,7 +972,7 @@ package body Arrays is
937972
Func_Params => Slice_Params,
938973
FBody => Build_Slice_Func_Body,
939974
A_Symbol_Table => Global_Symbol_Table);
940-
Slice_Id : constant Irep := Do_Expression (Prefix (N));
975+
Slice_Id : constant Irep := Base_Irep;
941976
begin
942977
Append_Argument (Slice_Args,
943978
Slice_Id);
@@ -954,39 +989,74 @@ package body Arrays is
954989

955990
-- TODO: multi-dimensional arrays.
956991
function Do_Indexed_Component (N : Node_Id) return Irep is
957-
Base_Irep : constant Irep := Do_Expression (Prefix (N));
958-
Idx_Irep : constant Irep :=
959-
Typecast_If_Necessary (Do_Expression (First (Expressions (N))),
960-
CProver_Size_T, Global_Symbol_Table);
961-
962-
Source_Loc : constant Irep := Get_Source_Location (Base_Irep);
963-
First_Irep : constant Irep := Get_First_Index (Base_Irep);
964-
Last_Irep : constant Irep := Get_Last_Index (Base_Irep);
965-
Checked_Index : constant Irep :=
966-
Make_Index_Assert_Expr (N => N,
967-
Index => Idx_Irep,
968-
First_Index => First_Irep,
969-
Last_Index => Last_Irep);
970-
Zero_Based_Index : constant Irep :=
971-
Make_Op_Sub (Rhs => First_Irep,
972-
Lhs => Checked_Index,
973-
Source_Location => Source_Loc,
974-
Overflow_Check => False,
975-
I_Type => Get_Type (Idx_Irep),
976-
Range_Check => False);
977-
978-
Data_Irep : constant Irep :=
979-
Get_Data_Member (Base_Irep, Global_Symbol_Table);
980-
Data_Type : constant Irep := Get_Type (Data_Irep);
981-
Indexed_Data : constant Irep :=
982-
Offset_Array_Data (Base => Base_Irep,
983-
Offset => Zero_Based_Index);
984-
Element_Type : constant Irep := Get_Subtype (Data_Type);
992+
-- The prefix to an indexed component may be an access to an
993+
-- array object which must be implicitly dereferenced.
994+
The_Prefix : constant Node_Id := Prefix (N);
995+
Prefix_Etype : constant Node_Id := Etype (The_Prefix);
996+
Is_Implicit_Deref : constant Boolean := Is_Access_Type (Prefix_Etype);
985997
begin
986-
return
987-
Make_Dereference_Expr (Object => Indexed_Data,
988-
Source_Location => Source_Loc,
989-
I_Type => Element_Type);
998+
if (if Nkind (Prefix_Etype) = N_Defining_Identifier then
999+
Get_Name_String (Chars (Etype (Etype (Prefix (N)))))
1000+
elsif Is_Implicit_Deref then
1001+
Get_Name_String (Chars (Designated_Type (Prefix_Etype)))
1002+
else
1003+
"")
1004+
= "string"
1005+
then
1006+
return Report_Unhandled_Node_Irep (N, "Do_Expression",
1007+
"Index of string unsupported");
1008+
end if;
1009+
1010+
-- Where required the prefix has been implicitly dereferenced.
1011+
declare
1012+
Prefix_Irep : constant Irep := Do_Expression (The_Prefix);
1013+
Resolved_Type : constant Irep :=
1014+
(if Is_Implicit_Deref then
1015+
Do_Type_Reference (Designated_Type (Prefix_Etype))
1016+
else
1017+
Do_Type_Reference (Prefix_Etype));
1018+
Base_Irep : constant Irep :=
1019+
(if Is_Implicit_Deref then
1020+
Make_Dereference_Expr
1021+
(I_Type => Resolved_Type,
1022+
Object => Prefix_Irep,
1023+
Source_Location => Get_Source_Location (N))
1024+
else
1025+
Prefix_Irep);
1026+
1027+
Idx_Irep : constant Irep :=
1028+
Typecast_If_Necessary (Do_Expression (First (Expressions (N))),
1029+
CProver_Size_T, Global_Symbol_Table);
1030+
1031+
Source_Loc : constant Irep := Get_Source_Location (Base_Irep);
1032+
First_Irep : constant Irep := Get_First_Index (Base_Irep);
1033+
Last_Irep : constant Irep := Get_Last_Index (Base_Irep);
1034+
Checked_Index : constant Irep :=
1035+
Make_Index_Assert_Expr (N => N,
1036+
Index => Idx_Irep,
1037+
First_Index => First_Irep,
1038+
Last_Index => Last_Irep);
1039+
Zero_Based_Index : constant Irep :=
1040+
Make_Op_Sub (Rhs => First_Irep,
1041+
Lhs => Checked_Index,
1042+
Source_Location => Source_Loc,
1043+
Overflow_Check => False,
1044+
I_Type => Get_Type (Idx_Irep),
1045+
Range_Check => False);
1046+
1047+
Data_Irep : constant Irep :=
1048+
Get_Data_Member (Base_Irep, Global_Symbol_Table);
1049+
Data_Type : constant Irep := Get_Type (Data_Irep);
1050+
Indexed_Data : constant Irep :=
1051+
Offset_Array_Data (Base => Base_Irep,
1052+
Offset => Zero_Based_Index);
1053+
Element_Type : constant Irep := Get_Subtype (Data_Type);
1054+
begin
1055+
return
1056+
Make_Dereference_Expr (Object => Indexed_Data,
1057+
Source_Location => Source_Loc,
1058+
I_Type => Element_Type);
1059+
end;
9901060
end Do_Indexed_Component;
9911061

9921062
function Get_First_Index_Component (Array_Struct : Irep)

gnat2goto/driver/tree_walk.adb

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,17 +1477,7 @@ package body Tree_Walk is
14771477
when N_Explicit_Dereference => return Do_Dereference (N);
14781478
when N_Case_Expression => return Do_Case_Expression (N);
14791479
when N_Aggregate => return Do_Aggregate_Literal (N);
1480-
when N_Indexed_Component =>
1481-
if Nkind (Etype (Prefix (N))) = N_Defining_Identifier
1482-
and then
1483-
Get_Name_String (Chars (Etype (Etype (Prefix (N)))))
1484-
= "string"
1485-
then
1486-
return Report_Unhandled_Node_Irep (N, "Do_Expression",
1487-
"Index of string unsupported");
1488-
else
1489-
return Do_Indexed_Component (N);
1490-
end if;
1480+
when N_Indexed_Component => return Do_Indexed_Component (N);
14911481
when N_Slice => return Do_Slice (N);
14921482
when N_In => return Do_In (N);
14931483
when N_Real_Literal => return Do_Real_Constant (N);
@@ -1787,6 +1777,10 @@ package body Tree_Walk is
17871777
Func_Symbol : Symbol;
17881778

17891779
begin
1780+
-- It seems as though an N_Explicit_Drereference is placed in the tree
1781+
-- even when the function call is an implicit dereference.
1782+
-- Hence, implicit dereferences do not have to be seperately handled,
1783+
-- they are handled as explicit dereferences.
17901784
if Nkind (Name (N)) = N_Explicit_Dereference then
17911785
declare
17921786
Fun_Type : constant Irep :=
@@ -4213,6 +4207,10 @@ package body Tree_Walk is
42134207
function Do_Procedure_Call_Statement (N : Node_Id) return Irep
42144208
is
42154209
begin
4210+
-- It seems as though an N_Explicit_Drereference is placed in the tree
4211+
-- even when the procedure call is an implicit dereference.
4212+
-- Hence, implicit dereferences do not have to be seperately handled,
4213+
-- they are handled as explicit dereferences.
42164214
if Nkind (Name (N)) = N_Explicit_Dereference then
42174215
declare
42184216
Fun_Type : constant Irep :=
@@ -4589,7 +4587,27 @@ package body Tree_Walk is
45894587
---------------------------
45904588

45914589
function Do_Selected_Component (N : Node_Id) return Irep is
4592-
Root : constant Irep := Do_Expression (Prefix (N));
4590+
-- The prefix to a selected component may be an access to an
4591+
-- record object which must be implicitly dereferenced.
4592+
The_Prefix : constant Node_Id := Prefix (N);
4593+
Prefix_Etype : constant Node_Id := Etype (The_Prefix);
4594+
Prefix_Irep : constant Irep := Do_Expression (The_Prefix);
4595+
Is_Implicit_Deref : constant Boolean := Is_Access_Type (Prefix_Etype);
4596+
Resolved_Type : constant Irep :=
4597+
(if Is_Implicit_Deref then
4598+
Do_Type_Reference (Designated_Type (Prefix_Etype))
4599+
else
4600+
Do_Type_Reference (Prefix_Etype));
4601+
Root : constant Irep :=
4602+
(if Is_Implicit_Deref then
4603+
Make_Dereference_Expr
4604+
(I_Type => Resolved_Type,
4605+
Object => Prefix_Irep,
4606+
Source_Location => Get_Source_Location (N))
4607+
else
4608+
Prefix_Irep);
4609+
4610+
-- Where required the prefix has been implicitly dereferenced.
45934611
Component : constant Entity_Id := Entity (Selector_Name (N));
45944612

45954613
-- Example:
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
procedure Pointer_To_Array is
2+
type Count is range 0 .. 10;
3+
subtype Index is Count range 1 .. Count'Last;
4+
5+
type Arr_T is array (Index) of Count;
6+
type Arr_P is access all Arr_T;
7+
8+
type U_Arr_T is array (Integer range <>) of Integer;
9+
type U_Arr_P is access all U_Arr_T;
10+
11+
Arr : aliased Arr_T;
12+
Ptr : Arr_P;
13+
14+
U_Arr : aliased U_Arr_T := (1, 2, 3, 4);
15+
U_Ptr : U_Arr_P;
16+
17+
C_dummy : Count;
18+
19+
begin
20+
for I in Index loop
21+
Arr (I) := Index'Last - I + 1;
22+
end loop;
23+
24+
for I in Index loop
25+
pragma Assert (Arr (I) = Index'Last - I + 1);
26+
end loop;
27+
28+
Ptr := Arr'Access;
29+
30+
for I in Index loop
31+
pragma Assert (Ptr (I) = Index'Last - I + 1);
32+
end loop;
33+
34+
for I in Index loop
35+
Arr (I) := I;
36+
end loop;
37+
38+
for I in Index loop
39+
pragma Assert (Ptr (I) = I);
40+
end loop;
41+
42+
for I in Index loop
43+
pragma Assert (Arr (I) = I);
44+
end loop;
45+
46+
pragma Assert (Arr (3) = 5, "This should fail");
47+
pragma Assert (Ptr (5) = 3, "This should fail");
48+
pragma Assert (Ptr (3) = 3);
49+
pragma Assert (Ptr (5) = 5);
50+
pragma Assert (Ptr.all (3) = 3);
51+
pragma Assert (Ptr.all (3) = 5, "This should fail");
52+
53+
for I in Index loop
54+
Ptr.all (I) := Index'Last - I + 1;
55+
end loop;
56+
57+
for I in Index loop
58+
pragma Assert (Ptr.all (I) = Index'Last - I + 1);
59+
end loop;
60+
61+
for I in Index loop
62+
pragma Assert (Arr (I) = Index'Last - I + 1);
63+
end loop;
64+
65+
pragma Assert (Arr (1) = Index'Last);
66+
pragma Assert (Ptr (Index'Last) = 1);
67+
pragma Assert (Ptr (1) = Index'Last);
68+
pragma Assert (Ptr.all (1) = Index'Last);
69+
pragma Assert (Ptr.all (Index'Last) = 1);
70+
71+
pragma Assert (Ptr'Length = Index'Last);
72+
73+
U_Ptr := U_Arr'Access;
74+
C_dummy := U_Ptr'Length;
75+
C_dummy := Ptr'Length;
76+
77+
C_Dummy := Count (U_Ptr'First);
78+
C_Dummy := Count (U_Ptr'Last);
79+
80+
81+
end Pointer_To_Array;

0 commit comments

Comments
 (0)