comparison gcc/ada/ghost.adb @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
4 -- -- 4 -- --
5 -- G H O S T -- 5 -- G H O S T --
6 -- -- 6 -- --
7 -- B o d y -- 7 -- B o d y --
8 -- -- 8 -- --
9 -- Copyright (C) 2014-2017, Free Software Foundation, Inc. -- 9 -- Copyright (C) 2014-2018, Free Software Foundation, Inc. --
10 -- -- 10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under -- 11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- -- 12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- -- 13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
27 with Aspects; use Aspects; 27 with Aspects; use Aspects;
28 with Atree; use Atree; 28 with Atree; use Atree;
29 with Einfo; use Einfo; 29 with Einfo; use Einfo;
30 with Elists; use Elists; 30 with Elists; use Elists;
31 with Errout; use Errout; 31 with Errout; use Errout;
32 with Lib; use Lib;
33 with Namet; use Namet; 32 with Namet; use Namet;
34 with Nlists; use Nlists; 33 with Nlists; use Nlists;
35 with Nmake; use Nmake; 34 with Nmake; use Nmake;
36 with Sem; use Sem; 35 with Sem; use Sem;
37 with Sem_Aux; use Sem_Aux; 36 with Sem_Aux; use Sem_Aux;
44 with Snames; use Snames; 43 with Snames; use Snames;
45 with Table; 44 with Table;
46 45
47 package body Ghost is 46 package body Ghost is
48 47
49 -- The following table contains the N_Compilation_Unit node for a unit that 48 ---------------------
50 -- is either subject to pragma Ghost with policy Ignore or contains ignored 49 -- Data strictures --
51 -- Ghost code. The table is used in the removal of ignored Ghost code from 50 ---------------------
52 -- units. 51
53 52 -- The following table contains all ignored Ghost nodes that must be
54 package Ignored_Ghost_Units is new Table.Table ( 53 -- eliminated from the tree by routine Remove_Ignored_Ghost_Code.
54
55 package Ignored_Ghost_Nodes is new Table.Table (
55 Table_Component_Type => Node_Id, 56 Table_Component_Type => Node_Id,
56 Table_Index_Type => Int, 57 Table_Index_Type => Int,
57 Table_Low_Bound => 0, 58 Table_Low_Bound => 0,
58 Table_Initial => Alloc.Ignored_Ghost_Units_Initial, 59 Table_Initial => Alloc.Ignored_Ghost_Nodes_Initial,
59 Table_Increment => Alloc.Ignored_Ghost_Units_Increment, 60 Table_Increment => Alloc.Ignored_Ghost_Nodes_Increment,
60 Table_Name => "Ignored_Ghost_Units"); 61 Table_Name => "Ignored_Ghost_Nodes");
61 62
62 ----------------------- 63 -----------------------
63 -- Local Subprograms -- 64 -- Local subprograms --
64 ----------------------- 65 -----------------------
65 66
66 function Ghost_Entity (N : Node_Id) return Entity_Id; 67 function Ghost_Entity (N : Node_Id) return Entity_Id;
67 -- Find the entity of a reference to a Ghost entity. Return Empty if there 68 -- Find the entity of a reference to a Ghost entity. Return Empty if there
68 -- is no such entity. 69 -- is no such entity.
69 70
70 procedure Install_Ghost_Mode (Mode : Name_Id); 71 procedure Install_Ghost_Mode (Mode : Ghost_Mode_Type);
71 -- Install a specific Ghost mode denoted by Mode by setting global variable 72 pragma Inline (Install_Ghost_Mode);
72 -- Ghost_Mode. 73 -- Install Ghost mode Mode as the Ghost mode in effect
74
75 procedure Install_Ghost_Region (Mode : Name_Id; N : Node_Id);
76 pragma Inline (Install_Ghost_Region);
77 -- Install a Ghost region comprised of mode Mode and ignored region start
78 -- node N.
73 79
74 function Is_Subject_To_Ghost (N : Node_Id) return Boolean; 80 function Is_Subject_To_Ghost (N : Node_Id) return Boolean;
75 -- Determine whether declaration or body N is subject to aspect or pragma 81 -- Determine whether declaration or body N is subject to aspect or pragma
76 -- Ghost. This routine must be used in cases where pragma Ghost has not 82 -- Ghost. This routine must be used in cases where pragma Ghost has not
77 -- been analyzed yet, but the context needs to establish the "ghostness" 83 -- been analyzed yet, but the context needs to establish the "ghostness"
82 Mode : Name_Id); 88 Mode : Name_Id);
83 -- Mark the defining entity of declaration or body N as Ghost depending on 89 -- Mark the defining entity of declaration or body N as Ghost depending on
84 -- mode Mode. Mark all formals parameters when N denotes a subprogram or a 90 -- mode Mode. Mark all formals parameters when N denotes a subprogram or a
85 -- body. 91 -- body.
86 92
87 procedure Propagate_Ignored_Ghost_Code (N : Node_Id); 93 function Name_To_Ghost_Mode (Mode : Name_Id) return Ghost_Mode_Type;
88 -- Signal all enclosing scopes that they now contain at least one ignored 94 pragma Inline (Name_To_Ghost_Mode);
89 -- Ghost node denoted by N. Add the compilation unit containing N to table 95 -- Convert a Ghost mode denoted by name Mode into its respective enumerated
90 -- Ignored_Ghost_Units for post processing. 96 -- value.
91 97
92 ---------------------------- 98 procedure Record_Ignored_Ghost_Node (N : Node_Or_Entity_Id);
93 -- Add_Ignored_Ghost_Unit -- 99 -- Save ignored Ghost node or entity N in table Ignored_Ghost_Nodes for
94 ---------------------------- 100 -- later elimination.
95
96 procedure Add_Ignored_Ghost_Unit (Unit : Node_Id) is
97 begin
98 pragma Assert (Nkind (Unit) = N_Compilation_Unit);
99
100 -- Avoid duplicates in the table as pruning the same unit more than once
101 -- is wasteful. Since ignored Ghost code tends to be grouped up, check
102 -- the contents of the table in reverse.
103
104 for Index in reverse Ignored_Ghost_Units.First ..
105 Ignored_Ghost_Units.Last
106 loop
107 -- If the unit is already present in the table, do not add it again
108
109 if Unit = Ignored_Ghost_Units.Table (Index) then
110 return;
111 end if;
112 end loop;
113
114 -- If we get here, then this is the first time the unit is being added
115
116 Ignored_Ghost_Units.Append (Unit);
117 end Add_Ignored_Ghost_Unit;
118 101
119 ---------------------------- 102 ----------------------------
120 -- Check_Ghost_Completion -- 103 -- Check_Ghost_Completion --
121 ---------------------------- 104 ----------------------------
122 105
804 Constit, State_Id); 787 Constit, State_Id);
805 end if; 788 end if;
806 end if; 789 end if;
807 end Check_Ghost_Refinement; 790 end Check_Ghost_Refinement;
808 791
792 ----------------------
793 -- Check_Ghost_Type --
794 ----------------------
795
796 procedure Check_Ghost_Type (Typ : Entity_Id) is
797 Conc_Typ : Entity_Id;
798 Full_Typ : Entity_Id;
799
800 begin
801 if Is_Ghost_Entity (Typ) then
802 Conc_Typ := Empty;
803 Full_Typ := Typ;
804
805 if Is_Single_Concurrent_Type (Typ) then
806 Conc_Typ := Anonymous_Object (Typ);
807 Full_Typ := Conc_Typ;
808
809 elsif Is_Concurrent_Type (Typ) then
810 Conc_Typ := Typ;
811 end if;
812
813 -- A Ghost type cannot be concurrent (SPARK RM 6.9(19)). Verify this
814 -- legality rule first to give a finer-grained diagnostic.
815
816 if Present (Conc_Typ) then
817 Error_Msg_N ("ghost type & cannot be concurrent", Conc_Typ);
818 end if;
819
820 -- A Ghost type cannot be effectively volatile (SPARK RM 6.9(7))
821
822 if Is_Effectively_Volatile (Full_Typ) then
823 Error_Msg_N ("ghost type & cannot be volatile", Full_Typ);
824 end if;
825 end if;
826 end Check_Ghost_Type;
827
809 ------------------ 828 ------------------
810 -- Ghost_Entity -- 829 -- Ghost_Entity --
811 ------------------ 830 ------------------
812 831
813 function Ghost_Entity (N : Node_Id) return Entity_Id is 832 function Ghost_Entity (N : Node_Id) return Entity_Id is
861 -- Initialize -- 880 -- Initialize --
862 ---------------- 881 ----------------
863 882
864 procedure Initialize is 883 procedure Initialize is
865 begin 884 begin
866 Ignored_Ghost_Units.Init; 885 Ignored_Ghost_Nodes.Init;
886
887 -- Set the soft link which enables Atree.Mark_New_Ghost_Node to record
888 -- an ignored Ghost node or entity.
889
890 Set_Ignored_Ghost_Recording_Proc (Record_Ignored_Ghost_Node'Access);
867 end Initialize; 891 end Initialize;
868 892
869 ------------------------ 893 ------------------------
870 -- Install_Ghost_Mode -- 894 -- Install_Ghost_Mode --
871 ------------------------ 895 ------------------------
872 896
873 procedure Install_Ghost_Mode (Mode : Ghost_Mode_Type) is 897 procedure Install_Ghost_Mode (Mode : Ghost_Mode_Type) is
874 begin 898 begin
899 Install_Ghost_Region (Mode, Empty);
900 end Install_Ghost_Mode;
901
902 --------------------------
903 -- Install_Ghost_Region --
904 --------------------------
905
906 procedure Install_Ghost_Region (Mode : Ghost_Mode_Type; N : Node_Id) is
907 begin
908 -- The context is already within an ignored Ghost region. Maintain the
909 -- start of the outermost ignored Ghost region.
910
911 if Present (Ignored_Ghost_Region) then
912 null;
913
914 -- The current region is the outermost ignored Ghost region. Save its
915 -- starting node.
916
917 elsif Present (N) and then Mode = Ignore then
918 Ignored_Ghost_Region := N;
919
920 -- Otherwise the current region is not ignored, nothing to save
921
922 else
923 Ignored_Ghost_Region := Empty;
924 end if;
925
875 Ghost_Mode := Mode; 926 Ghost_Mode := Mode;
876 end Install_Ghost_Mode; 927 end Install_Ghost_Region;
877 928
878 procedure Install_Ghost_Mode (Mode : Name_Id) is 929 procedure Install_Ghost_Region (Mode : Name_Id; N : Node_Id) is
879 begin 930 begin
880 if Mode = Name_Check then 931 Install_Ghost_Region (Name_To_Ghost_Mode (Mode), N);
881 Ghost_Mode := Check; 932 end Install_Ghost_Region;
882
883 elsif Mode = Name_Ignore then
884 Ghost_Mode := Ignore;
885
886 elsif Mode = Name_None then
887 Ghost_Mode := None;
888 end if;
889 end Install_Ghost_Mode;
890 933
891 ------------------------- 934 -------------------------
892 -- Is_Ghost_Assignment -- 935 -- Is_Ghost_Assignment --
893 ------------------------- 936 -------------------------
894 937
959 --------------------------- 1002 ---------------------------
960 -- Is_Ignored_Ghost_Unit -- 1003 -- Is_Ignored_Ghost_Unit --
961 --------------------------- 1004 ---------------------------
962 1005
963 function Is_Ignored_Ghost_Unit (N : Node_Id) return Boolean is 1006 function Is_Ignored_Ghost_Unit (N : Node_Id) return Boolean is
1007 function Ultimate_Original_Node (Nod : Node_Id) return Node_Id;
1008 -- Obtain the original node of arbitrary node Nod following a potential
1009 -- chain of rewritings.
1010
1011 ----------------------------
1012 -- Ultimate_Original_Node --
1013 ----------------------------
1014
1015 function Ultimate_Original_Node (Nod : Node_Id) return Node_Id is
1016 Res : Node_Id;
1017
1018 begin
1019 Res := Nod;
1020 while Original_Node (Res) /= Res loop
1021 Res := Original_Node (Res);
1022 end loop;
1023
1024 return Res;
1025 end Ultimate_Original_Node;
1026
1027 -- Start of processing for Is_Ignored_Ghost_Unit
1028
964 begin 1029 begin
965 -- Inspect the original node of the unit in case removal of ignored 1030 -- Inspect the original node of the unit in case removal of ignored
966 -- Ghost code has already taken place. 1031 -- Ghost code has already taken place.
967 1032
968 return 1033 return
969 Nkind (N) = N_Compilation_Unit 1034 Nkind (N) = N_Compilation_Unit
970 and then Is_Ignored_Ghost_Entity 1035 and then Is_Ignored_Ghost_Entity
971 (Defining_Entity (Original_Node (Unit (N)))); 1036 (Defining_Entity (Ultimate_Original_Node (Unit (N))));
972 end Is_Ignored_Ghost_Unit; 1037 end Is_Ignored_Ghost_Unit;
973 1038
974 ------------------------- 1039 -------------------------
975 -- Is_Subject_To_Ghost -- 1040 -- Is_Subject_To_Ghost --
976 ------------------------- 1041 -------------------------
1105 -- Lock -- 1170 -- Lock --
1106 ---------- 1171 ----------
1107 1172
1108 procedure Lock is 1173 procedure Lock is
1109 begin 1174 begin
1110 Ignored_Ghost_Units.Release; 1175 Ignored_Ghost_Nodes.Release;
1111 Ignored_Ghost_Units.Locked := True; 1176 Ignored_Ghost_Nodes.Locked := True;
1112 end Lock; 1177 end Lock;
1113 1178
1114 ----------------------------------- 1179 -----------------------------------
1115 -- Mark_And_Set_Ghost_Assignment -- 1180 -- Mark_And_Set_Ghost_Assignment --
1116 ----------------------------------- 1181 -----------------------------------
1124 1189
1125 Id := Ghost_Entity (Name (N)); 1190 Id := Ghost_Entity (Name (N));
1126 1191
1127 if Present (Id) then 1192 if Present (Id) then
1128 if Is_Checked_Ghost_Entity (Id) then 1193 if Is_Checked_Ghost_Entity (Id) then
1129 Install_Ghost_Mode (Check); 1194 Install_Ghost_Region (Check, N);
1130 1195
1131 elsif Is_Ignored_Ghost_Entity (Id) then 1196 elsif Is_Ignored_Ghost_Entity (Id) then
1132 Install_Ghost_Mode (Ignore); 1197 Install_Ghost_Region (Ignore, N);
1133 1198
1134 Set_Is_Ignored_Ghost_Node (N); 1199 Set_Is_Ignored_Ghost_Node (N);
1135 Propagate_Ignored_Ghost_Code (N); 1200 Record_Ignored_Ghost_Node (N);
1136 end if; 1201 end if;
1137 end if; 1202 end if;
1138 end Mark_And_Set_Ghost_Assignment; 1203 end Mark_And_Set_Ghost_Assignment;
1139 1204
1140 ----------------------------- 1205 -----------------------------
1184 1249
1185 -- Mark the body as its formals as Ghost 1250 -- Mark the body as its formals as Ghost
1186 1251
1187 Mark_Ghost_Declaration_Or_Body (N, Policy); 1252 Mark_Ghost_Declaration_Or_Body (N, Policy);
1188 1253
1189 -- Install the appropriate Ghost mode 1254 -- Install the appropriate Ghost region
1190 1255
1191 Install_Ghost_Mode (Policy); 1256 Install_Ghost_Region (Policy, N);
1192 end Mark_And_Set_Ghost_Body; 1257 end Mark_And_Set_Ghost_Body;
1193 1258
1194 ----------------------------------- 1259 -----------------------------------
1195 -- Mark_And_Set_Ghost_Completion -- 1260 -- Mark_And_Set_Ghost_Completion --
1196 ----------------------------------- 1261 -----------------------------------
1231 1296
1232 -- Mark the completion as Ghost 1297 -- Mark the completion as Ghost
1233 1298
1234 Mark_Ghost_Declaration_Or_Body (N, Policy); 1299 Mark_Ghost_Declaration_Or_Body (N, Policy);
1235 1300
1236 -- Install the appropriate Ghost mode 1301 -- Install the appropriate Ghost region
1237 1302
1238 Install_Ghost_Mode (Policy); 1303 Install_Ghost_Region (Policy, N);
1239 end Mark_And_Set_Ghost_Completion; 1304 end Mark_And_Set_Ghost_Completion;
1240 1305
1241 ------------------------------------ 1306 ------------------------------------
1242 -- Mark_And_Set_Ghost_Declaration -- 1307 -- Mark_And_Set_Ghost_Declaration --
1243 ------------------------------------ 1308 ------------------------------------
1288 1353
1289 -- Mark the declaration and its formals as Ghost 1354 -- Mark the declaration and its formals as Ghost
1290 1355
1291 Mark_Ghost_Declaration_Or_Body (N, Policy); 1356 Mark_Ghost_Declaration_Or_Body (N, Policy);
1292 1357
1293 -- Install the appropriate Ghost mode 1358 -- Install the appropriate Ghost region
1294 1359
1295 Install_Ghost_Mode (Policy); 1360 Install_Ghost_Region (Policy, N);
1296 end Mark_And_Set_Ghost_Declaration; 1361 end Mark_And_Set_Ghost_Declaration;
1297 1362
1298 -------------------------------------- 1363 --------------------------------------
1299 -- Mark_And_Set_Ghost_Instantiation -- 1364 -- Mark_And_Set_Ghost_Instantiation --
1300 -------------------------------------- 1365 --------------------------------------
1368 1433
1369 -- Mark the instantiation as Ghost 1434 -- Mark the instantiation as Ghost
1370 1435
1371 Mark_Ghost_Declaration_Or_Body (N, Policy); 1436 Mark_Ghost_Declaration_Or_Body (N, Policy);
1372 1437
1373 -- Install the appropriate Ghost mode 1438 -- Install the appropriate Ghost region
1374 1439
1375 Install_Ghost_Mode (Policy); 1440 Install_Ghost_Region (Policy, N);
1376 1441
1377 -- Check ghost actuals. Given that this routine is unconditionally 1442 -- Check Ghost actuals. Given that this routine is unconditionally
1378 -- invoked with subprogram and package instantiations, this check 1443 -- invoked with subprogram and package instantiations, this check
1379 -- verifies the context of all the ghost entities passed in generic 1444 -- verifies the context of all the ghost entities passed in generic
1380 -- instantiations. 1445 -- instantiations.
1381 1446
1382 Check_Ghost_Actuals; 1447 Check_Ghost_Actuals;
1395 1460
1396 Id := Ghost_Entity (Name (N)); 1461 Id := Ghost_Entity (Name (N));
1397 1462
1398 if Present (Id) then 1463 if Present (Id) then
1399 if Is_Checked_Ghost_Entity (Id) then 1464 if Is_Checked_Ghost_Entity (Id) then
1400 Install_Ghost_Mode (Check); 1465 Install_Ghost_Region (Check, N);
1401 1466
1402 elsif Is_Ignored_Ghost_Entity (Id) then 1467 elsif Is_Ignored_Ghost_Entity (Id) then
1403 Install_Ghost_Mode (Ignore); 1468 Install_Ghost_Region (Ignore, N);
1404 1469
1405 Set_Is_Ignored_Ghost_Node (N); 1470 Set_Is_Ignored_Ghost_Node (N);
1406 Propagate_Ignored_Ghost_Code (N); 1471 Record_Ignored_Ghost_Node (N);
1407 end if; 1472 end if;
1408 end if; 1473 end if;
1409 end Mark_And_Set_Ghost_Procedure_Call; 1474 end Mark_And_Set_Ghost_Procedure_Call;
1475
1476 -----------------------
1477 -- Mark_Ghost_Clause --
1478 -----------------------
1479
1480 procedure Mark_Ghost_Clause (N : Node_Id) is
1481 Nam : Node_Id := Empty;
1482
1483 begin
1484 if Nkind (N) = N_Use_Package_Clause then
1485 Nam := Name (N);
1486
1487 elsif Nkind (N) = N_Use_Type_Clause then
1488 Nam := Subtype_Mark (N);
1489
1490 elsif Nkind (N) = N_With_Clause then
1491 Nam := Name (N);
1492 end if;
1493
1494 if Present (Nam)
1495 and then Is_Entity_Name (Nam)
1496 and then Present (Entity (Nam))
1497 and then Is_Ignored_Ghost_Entity (Entity (Nam))
1498 then
1499 Set_Is_Ignored_Ghost_Node (N);
1500 Record_Ignored_Ghost_Node (N);
1501 end if;
1502 end Mark_Ghost_Clause;
1410 1503
1411 ------------------------------------ 1504 ------------------------------------
1412 -- Mark_Ghost_Declaration_Or_Body -- 1505 -- Mark_Ghost_Declaration_Or_Body --
1413 ------------------------------------ 1506 ------------------------------------
1414 1507
1431 1524
1432 elsif Mode = Name_Ignore then 1525 elsif Mode = Name_Ignore then
1433 Mark_Formals := True; 1526 Mark_Formals := True;
1434 Set_Is_Ignored_Ghost_Entity (Id); 1527 Set_Is_Ignored_Ghost_Entity (Id);
1435 Set_Is_Ignored_Ghost_Node (N); 1528 Set_Is_Ignored_Ghost_Node (N);
1436 Propagate_Ignored_Ghost_Code (N); 1529 Record_Ignored_Ghost_Node (N);
1437 end if; 1530 end if;
1438 1531
1439 -- Mark all formal parameters when the related node denotes a subprogram 1532 -- Mark all formal parameters when the related node denotes a subprogram
1440 -- or a body. The traversal is performed via the specification because 1533 -- or a body. The traversal is performed via the specification because
1441 -- the related subprogram or body may be unanalyzed. 1534 -- the related subprogram or body may be unanalyzed.
1467 end loop; 1560 end loop;
1468 end if; 1561 end if;
1469 end Mark_Ghost_Declaration_Or_Body; 1562 end Mark_Ghost_Declaration_Or_Body;
1470 1563
1471 ----------------------- 1564 -----------------------
1472 -- Mark_Ghost_Clause --
1473 -----------------------
1474
1475 procedure Mark_Ghost_Clause (N : Node_Id) is
1476 Nam : Node_Id := Empty;
1477
1478 begin
1479 if Nkind (N) = N_Use_Package_Clause then
1480 Nam := Name (N);
1481
1482 elsif Nkind (N) = N_Use_Type_Clause then
1483 Nam := Subtype_Mark (N);
1484
1485 elsif Nkind (N) = N_With_Clause then
1486 Nam := Name (N);
1487 end if;
1488
1489 if Present (Nam)
1490 and then Is_Entity_Name (Nam)
1491 and then Present (Entity (Nam))
1492 and then Is_Ignored_Ghost_Entity (Entity (Nam))
1493 then
1494 Set_Is_Ignored_Ghost_Node (N);
1495 Propagate_Ignored_Ghost_Code (N);
1496 end if;
1497 end Mark_Ghost_Clause;
1498
1499 -----------------------
1500 -- Mark_Ghost_Pragma -- 1565 -- Mark_Ghost_Pragma --
1501 ----------------------- 1566 -----------------------
1502 1567
1503 procedure Mark_Ghost_Pragma 1568 procedure Mark_Ghost_Pragma
1504 (N : Node_Id; 1569 (N : Node_Id;
1512 Set_Is_Checked_Ghost_Pragma (N); 1577 Set_Is_Checked_Ghost_Pragma (N);
1513 1578
1514 elsif Is_Ignored_Ghost_Entity (Id) then 1579 elsif Is_Ignored_Ghost_Entity (Id) then
1515 Set_Is_Ignored_Ghost_Pragma (N); 1580 Set_Is_Ignored_Ghost_Pragma (N);
1516 Set_Is_Ignored_Ghost_Node (N); 1581 Set_Is_Ignored_Ghost_Node (N);
1517 Propagate_Ignored_Ghost_Code (N); 1582 Record_Ignored_Ghost_Node (N);
1518 end if; 1583 end if;
1519 end Mark_Ghost_Pragma; 1584 end Mark_Ghost_Pragma;
1520 1585
1521 ------------------------- 1586 -------------------------
1522 -- Mark_Ghost_Renaming -- 1587 -- Mark_Ghost_Renaming --
1539 end if; 1604 end if;
1540 1605
1541 Mark_Ghost_Declaration_Or_Body (N, Policy); 1606 Mark_Ghost_Declaration_Or_Body (N, Policy);
1542 end Mark_Ghost_Renaming; 1607 end Mark_Ghost_Renaming;
1543 1608
1544 ---------------------------------- 1609 ------------------------
1545 -- Propagate_Ignored_Ghost_Code -- 1610 -- Name_To_Ghost_Mode --
1546 ---------------------------------- 1611 ------------------------
1547 1612
1548 procedure Propagate_Ignored_Ghost_Code (N : Node_Id) is 1613 function Name_To_Ghost_Mode (Mode : Name_Id) return Ghost_Mode_Type is
1549 Nod : Node_Id; 1614 begin
1550 Scop : Entity_Id; 1615 if Mode = Name_Check then
1551 1616 return Check;
1552 begin 1617
1553 -- Traverse the parent chain looking for blocks, packages, and 1618 elsif Mode = Name_Ignore then
1554 -- subprograms or their respective bodies. 1619 return Ignore;
1555 1620
1556 Nod := Parent (N); 1621 -- Otherwise the mode must denote one of the following:
1557 while Present (Nod) loop 1622 --
1558 Scop := Empty; 1623 -- * Disable indicates that the Ghost policy in effect is Disable
1559 1624 --
1560 if Nkind (Nod) = N_Block_Statement 1625 -- * None or No_Name indicates that the associated construct is not
1561 and then Present (Identifier (Nod)) 1626 -- subject to any Ghost annotation.
1562 then 1627
1563 Scop := Entity (Identifier (Nod)); 1628 else
1564 1629 pragma Assert (Nam_In (Mode, Name_Disable, Name_None, No_Name));
1565 elsif Nkind_In (Nod, N_Package_Body, 1630 return None;
1566 N_Package_Declaration, 1631 end if;
1567 N_Subprogram_Body, 1632 end Name_To_Ghost_Mode;
1568 N_Subprogram_Declaration) 1633
1569 then 1634 -------------------------------
1570 Scop := Defining_Entity (Nod); 1635 -- Record_Ignored_Ghost_Node --
1571 end if; 1636 -------------------------------
1572 1637
1573 -- The current node denotes a scoping construct 1638 procedure Record_Ignored_Ghost_Node (N : Node_Or_Entity_Id) is
1574 1639 begin
1575 if Present (Scop) then 1640 -- Save all "top level" ignored Ghost nodes which can be safely replaced
1576 1641 -- with a null statement. Note that there is need to save other kinds of
1577 -- Stop the traversal when the scope already contains ignored 1642 -- nodes because those will always be enclosed by some top level ignored
1578 -- Ghost code as all enclosing scopes have already been marked. 1643 -- Ghost node.
1579 1644
1580 if Contains_Ignored_Ghost_Code (Scop) then 1645 if Is_Body (N)
1581 exit; 1646 or else Is_Declaration (N)
1582 1647 or else Nkind (N) in N_Generic_Instantiation
1583 -- Otherwise mark this scope and keep climbing 1648 or else Nkind (N) in N_Push_Pop_xxx_Label
1584 1649 or else Nkind (N) in N_Raise_xxx_Error
1585 else 1650 or else Nkind (N) in N_Representation_Clause
1586 Set_Contains_Ignored_Ghost_Code (Scop); 1651 or else Nkind_In (N, N_Assignment_Statement,
1587 end if; 1652 N_Call_Marker,
1588 end if; 1653 N_Freeze_Entity,
1589 1654 N_Freeze_Generic_Entity,
1590 Nod := Parent (Nod); 1655 N_Itype_Reference,
1591 end loop; 1656 N_Pragma,
1592 1657 N_Procedure_Call_Statement,
1593 -- The unit containing the ignored Ghost code must be post processed 1658 N_Use_Package_Clause,
1594 -- before invoking the back end. 1659 N_Use_Type_Clause,
1595 1660 N_Variable_Reference_Marker,
1596 Add_Ignored_Ghost_Unit (Cunit (Get_Code_Unit (N))); 1661 N_With_Clause)
1597 end Propagate_Ignored_Ghost_Code; 1662 then
1663 -- Only ignored Ghost nodes must be recorded in the table
1664
1665 pragma Assert (Is_Ignored_Ghost_Node (N));
1666 Ignored_Ghost_Nodes.Append (N);
1667 end if;
1668 end Record_Ignored_Ghost_Node;
1598 1669
1599 ------------------------------- 1670 -------------------------------
1600 -- Remove_Ignored_Ghost_Code -- 1671 -- Remove_Ignored_Ghost_Code --
1601 ------------------------------- 1672 -------------------------------
1602 1673
1603 procedure Remove_Ignored_Ghost_Code is 1674 procedure Remove_Ignored_Ghost_Code is
1604 procedure Prune_Tree (Root : Node_Id); 1675 procedure Remove_Ignored_Ghost_Node (N : Node_Id);
1605 -- Remove all code marked as ignored Ghost from the tree of denoted by 1676 -- Eliminate ignored Ghost node N from the tree
1606 -- Root. 1677
1607 1678 -------------------------------
1608 ---------------- 1679 -- Remove_Ignored_Ghost_Node --
1609 -- Prune_Tree -- 1680 -------------------------------
1610 ---------------- 1681
1611 1682 procedure Remove_Ignored_Ghost_Node (N : Node_Id) is
1612 procedure Prune_Tree (Root : Node_Id) is 1683 begin
1613 procedure Prune (N : Node_Id); 1684 -- The generation and processing of ignored Ghost nodes may cause the
1614 -- Remove a given node from the tree by rewriting it into null 1685 -- same node to be saved multiple times. Reducing the number of saves
1615 1686 -- to one involves costly solutions such as a hash table or the use
1616 function Prune_Node (N : Node_Id) return Traverse_Result; 1687 -- of a flag shared by all nodes. To solve this problem, the removal
1617 -- Determine whether node N denotes an ignored Ghost construct. If 1688 -- machinery allows for multiple saves, but does not eliminate a node
1618 -- this is the case, rewrite N as a null statement. See the body for 1689 -- which has already been eliminated.
1619 -- special cases. 1690
1620 1691 if Nkind (N) = N_Null_Statement then
1621 ----------- 1692 null;
1622 -- Prune -- 1693
1623 ----------- 1694 -- Otherwise the ignored Ghost node must be eliminated
1624 1695
1625 procedure Prune (N : Node_Id) is 1696 else
1626 begin 1697 -- Only ignored Ghost nodes must be eliminated from the tree
1627 -- Destroy any aspects that may be associated with the node 1698
1628 1699 pragma Assert (Is_Ignored_Ghost_Node (N));
1629 if Permits_Aspect_Specifications (N) and then Has_Aspects (N) then 1700
1630 Remove_Aspects (N); 1701 -- Eliminate the node by rewriting it into null. Another option
1631 end if; 1702 -- is to remove it from the tree, however multiple corner cases
1703 -- emerge which have be dealt individually.
1632 1704
1633 Rewrite (N, Make_Null_Statement (Sloc (N))); 1705 Rewrite (N, Make_Null_Statement (Sloc (N)));
1634 end Prune; 1706
1635 1707 -- Eliminate any aspects hanging off the ignored Ghost node
1636 ---------------- 1708
1637 -- Prune_Node -- 1709 Remove_Aspects (N);
1638 ---------------- 1710 end if;
1639 1711 end Remove_Ignored_Ghost_Node;
1640 function Prune_Node (N : Node_Id) return Traverse_Result is
1641 Id : Entity_Id;
1642
1643 begin
1644 -- Do not prune compilation unit nodes because many mechanisms
1645 -- depend on their presence. Note that context items are still
1646 -- being processed.
1647
1648 if Nkind (N) = N_Compilation_Unit then
1649 return OK;
1650
1651 -- The node is either declared as ignored Ghost or is a byproduct
1652 -- of expansion. Destroy it and stop the traversal on this branch.
1653
1654 elsif Is_Ignored_Ghost_Node (N) then
1655 Prune (N);
1656 return Skip;
1657
1658 -- Scoping constructs such as blocks, packages, subprograms and
1659 -- bodies offer some flexibility with respect to pruning.
1660
1661 elsif Nkind_In (N, N_Block_Statement,
1662 N_Package_Body,
1663 N_Package_Declaration,
1664 N_Subprogram_Body,
1665 N_Subprogram_Declaration)
1666 then
1667 if Nkind (N) = N_Block_Statement then
1668 Id := Entity (Identifier (N));
1669 else
1670 Id := Defining_Entity (N);
1671 end if;
1672
1673 -- The scoping construct contains both living and ignored Ghost
1674 -- code, let the traversal prune all relevant nodes.
1675
1676 if Contains_Ignored_Ghost_Code (Id) then
1677 return OK;
1678
1679 -- Otherwise the construct contains only living code and should
1680 -- not be pruned.
1681
1682 else
1683 return Skip;
1684 end if;
1685
1686 -- Otherwise keep searching for ignored Ghost nodes
1687
1688 else
1689 return OK;
1690 end if;
1691 end Prune_Node;
1692
1693 procedure Prune_Nodes is new Traverse_Proc (Prune_Node);
1694
1695 -- Start of processing for Prune_Tree
1696
1697 begin
1698 Prune_Nodes (Root);
1699 end Prune_Tree;
1700 1712
1701 -- Start of processing for Remove_Ignored_Ghost_Code 1713 -- Start of processing for Remove_Ignored_Ghost_Code
1702 1714
1703 begin 1715 begin
1704 for Index in Ignored_Ghost_Units.First .. Ignored_Ghost_Units.Last loop 1716 for Index in Ignored_Ghost_Nodes.First .. Ignored_Ghost_Nodes.Last loop
1705 Prune_Tree (Ignored_Ghost_Units.Table (Index)); 1717 Remove_Ignored_Ghost_Node (Ignored_Ghost_Nodes.Table (Index));
1706 end loop; 1718 end loop;
1707 end Remove_Ignored_Ghost_Code; 1719 end Remove_Ignored_Ghost_Code;
1708 1720
1709 ------------------------ 1721 --------------------------
1710 -- Restore_Ghost_Mode -- 1722 -- Restore_Ghost_Region --
1711 ------------------------ 1723 --------------------------
1712 1724
1713 procedure Restore_Ghost_Mode (Mode : Ghost_Mode_Type) is 1725 procedure Restore_Ghost_Region (Mode : Ghost_Mode_Type; N : Node_Id) is
1714 begin 1726 begin
1715 Ghost_Mode := Mode; 1727 Ghost_Mode := Mode;
1716 end Restore_Ghost_Mode; 1728 Ignored_Ghost_Region := N;
1729 end Restore_Ghost_Region;
1717 1730
1718 -------------------- 1731 --------------------
1719 -- Set_Ghost_Mode -- 1732 -- Set_Ghost_Mode --
1720 -------------------- 1733 --------------------
1721 1734