1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- R T S F I N D --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2024, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
with Atree; use Atree;
with Casing; use Casing;
with Csets; use Csets;
with Debug; use Debug;
with Einfo; use Einfo;
with Einfo.Entities; use Einfo.Entities;
with Einfo.Utils; use Einfo.Utils;
with Elists; use Elists;
with Errout; use Errout;
with Exp_Dist;
with Fname; use Fname;
with Fname.UF; use Fname.UF;
with Ghost; use Ghost;
with Lib; use Lib;
with Lib.Load; use Lib.Load;
with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Output; use Output;
with Opt; use Opt;
with Restrict; use Restrict;
with Sem; use Sem;
with Sem_Aux; use Sem_Aux;
with Sem_Ch7; use Sem_Ch7;
with Sem_Dist; use Sem_Dist;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Sinfo.Nodes; use Sinfo.Nodes;
with Sinfo.Utils; use Sinfo.Utils;
with Stand; use Stand;
with Snames; use Snames;
with Tbuild; use Tbuild;
with Uname; use Uname;
package body Rtsfind is
RTE_Available_Call : Boolean := False;
-- Set True during call to RTE from RTE_Available (or from call to
-- RTE_Record_Component from RTE_Record_Component_Available). Tells
-- the called subprogram to set RTE_Is_Available to False rather than
-- generating an error message.
RTE_Is_Available : Boolean;
-- Set True by RTE_Available on entry. When RTE_Available_Call is set
-- True, set False if RTE would otherwise generate an error message.
----------------
-- Unit table --
----------------
-- The unit table has one entry for each unit included in the definition
-- of the type RTU_Id in the spec. The table entries are initialized in
-- Initialize to set the Entity field to Empty, indicating that the
-- corresponding unit has not yet been loaded. The fields are set when
-- a unit is loaded to contain the defining entity for the unit, the
-- unit name, and the unit number.
-- Note that a unit can be loaded either by a call to find an entity
-- within the unit (e.g. RTE), or by an explicit with of the unit. In
-- the latter case it is critical to make a call to Set_RTU_Loaded to
-- ensure that the entry in this table reflects the load.
-- A unit retrieved through rtsfind may end up in the context of several
-- other units, in addition to the main unit. These additional with_clauses
-- are needed to generate a proper traversal order for CodePeer. To
-- minimize somewhat the redundancy created by numerous calls to rtsfind
-- from different units, we keep track of the list of implicit with_clauses
-- already created for the current loaded unit.
type RT_Unit_Table_Record is record
Entity : Entity_Id;
Uname : Unit_Name_Type;
First_Implicit_With : Node_Id;
Unum : Unit_Number_Type;
end record;
RT_Unit_Table : array (RTU_Id) of RT_Unit_Table_Record;
--------------------------
-- Runtime Entity Table --
--------------------------
-- There is one entry in the runtime entity table for each entity that is
-- included in the definition of the RE_Id type in the spec. The entries
-- are set by Initialize_Rtsfind to contain Empty, indicating that the
-- entity has not yet been located. Once the entity is located for the
-- first time, its ID is stored in this array, so that subsequent calls
-- for the same entity can be satisfied immediately.
-- NOTE: In order to avoid conflicts between record components and subprgs
-- that have the same name (i.e. subprogram External_Tag and
-- component External_Tag of package Ada.Tags) this table is not used
-- with Record_Components.
RE_Table : array (RE_Id) of Entity_Id;
--------------------------------
-- Generation of with_clauses --
--------------------------------
-- When a unit is implicitly loaded as a result of a call to RTE, it is
-- necessary to create one or two implicit with_clauses. We add such
-- with_clauses to the extended main unit if needed, and also to whatever
-- unit needs them, which is not necessarily the main unit. The former
-- ensures that the object is correctly loaded by the binder. The latter
-- is necessary for CodePeer.
-- The field First_Implicit_With in the unit table record are used to
-- avoid creating duplicate with_clauses.
----------------------------------------------
-- Table of Predefined RE_Id Error Messages --
----------------------------------------------
-- If an attempt is made to load an entity, given an RE_Id value, and the
-- entity is not available in the current configuration, an error message
-- is given (see Entity_Not_Defined below). The general form of such an
-- error message is for example:
-- entity "System.Pack_43.Bits_43" not defined
-- The following table defines a set of RE_Id image values for which this
-- error message is specialized and replaced by specific text indicating
-- the exact message to be output. For example, in the case above, for the
-- RE_Id value RE_Bits_43, we do indeed specialize the message, and the
-- above generic message is replaced by:
-- packed component size of 43 is not supported
type CString_Ptr is access constant String;
type PRE_Id_Entry is record
Str : CString_Ptr;
-- Pointer to string with the RE_Id image. The sequence ?? may appear
-- in which case it will match any characters in the RE_Id image value.
-- This is used to avoid the need for dozens of entries for RE_Bits_??.
Msg : CString_Ptr;
-- Pointer to string with the corresponding error text. The sequence
-- ?? may appear, in which case, it is replaced by the corresponding
-- sequence ?? in the Str value (if the first ? is zero, then it is
-- omitted from the message).
end record;
Str1 : aliased constant String := "RE_BITS_??";
Str2 : aliased constant String := "RE_GET_??";
Str3 : aliased constant String := "RE_SET_??";
Str4 : aliased constant String := "RE_CALL_SIMPLE";
MsgPack : aliased constant String :=
"packed component size of ?? is not supported";
MsgRV : aliased constant String :=
"task rendezvous is not supported";
PRE_Id_Table : constant array (Natural range <>) of PRE_Id_Entry :=
(1 => (Str1'Access, MsgPack'Access),
2 => (Str2'Access, MsgPack'Access),
3 => (Str3'Access, MsgPack'Access),
4 => (Str4'Access, MsgRV'Access));
-- We will add entries to this table as we find cases where it is a good
-- idea to do so. By no means all the RE_Id values need entries, because
-- the expander often gives clear messages before it makes the Rtsfind
-- call expecting to find the entity.
-----------------------
-- Local Subprograms --
-----------------------
function Check_CRT (E : RE_Id; Eid : Entity_Id) return Entity_Id;
-- Check entity Eid to ensure that configurable run-time restrictions are
-- met. May generate an error message (if RTE_Available_Call is false) and
-- raise RE_Not_Available if entity E does not exist (e.g. Eid is Empty).
-- Also check that entity is not overloaded.
procedure Entity_Not_Defined (Id : RE_Id);
-- Outputs error messages for an entity that is not defined in the run-time
-- library (the form of the error message is tailored for no run time or
-- configurable run time mode as required). See also table of pre-defined
-- messages for entities above (RE_Id_Messages).
function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type;
-- Retrieves the Unit Name given a unit id represented by its enumeration
-- value in RTU_Id.
procedure Load_Fail (S : String; U_Id : RTU_Id; Id : RE_Id);
pragma No_Return (Load_Fail);
-- Internal procedure called if we can't successfully locate or process a
-- run-time unit. The parameters give information about the error message
-- to be given. S is a reason for failing to compile the file and U_Id is
-- the unit id. RE_Id is the RE_Id originally passed to RTE. The message in
-- S is one of the following:
--
-- "not found"
-- "had parser errors"
-- "had semantic errors"
--
-- The "not found" case is treated specially in that it is considered
-- a normal situation in configurable run-time mode, and generates
-- a warning, but is otherwise ignored.
procedure Load_RTU
(U_Id : RTU_Id;
Id : RE_Id := RE_Null;
Use_Setting : Boolean := False);
-- Load the unit whose Id is given if not already loaded. The unit is
-- loaded and analyzed, and the entry in RT_Unit_Table is updated to
-- reflect the load. Use_Setting is used to indicate the initial setting
-- for the Is_Potentially_Use_Visible flag of the entity for the loaded
-- unit (if it is indeed loaded). A value of False means nothing special
-- need be done. A value of True indicates that this flag must be set to
-- True. It is needed only in the Check_Text_IO_Special_Unit procedure,
-- which may materialize an entity of Text_IO (or [Wide_]Wide_Text_IO) that
-- was previously unknown. Id is the RE_Id value of the entity which was
-- originally requested. Id is used only for error message detail, and if
-- it is RE_Null, then the attempt to output the entity name is ignored.
function Make_Unit_Name
(U : RT_Unit_Table_Record;
N : Node_Id) return Node_Id;
-- If the unit is a child unit, build fully qualified name for use in
-- With_Clause.
procedure Maybe_Add_With (U : in out RT_Unit_Table_Record);
-- If necessary, add an implicit with_clause from the current unit to the
-- one represented by U.
procedure Output_Entity_Name (Id : RE_Id; Msg : String);
-- Output continuation error message giving qualified name of entity
-- corresponding to Id, appending the string given by Msg.
function RE_Chars (E : RE_Id) return Name_Id;
-- Given a RE_Id value returns the Chars of the corresponding entity
procedure RTE_Error_Msg (Msg : String);
-- Generates a message by calling Error_Msg_N specifying Current_Error_Node
-- as the node location using the given Msg text. Special processing in the
-- case where RTE_Available_Call is set. In this case, no message is output
-- and instead RTE_Is_Available is set to False. Note that this can only be
-- used if you are sure that the message comes directly or indirectly from
-- a call to the RTE function.
---------------
-- Check_CRT --
---------------
function Check_CRT (E : RE_Id; Eid : Entity_Id) return Entity_Id is
U_Id : constant RTU_Id := RE_Unit_Table (E);
begin
if No (Eid) then
if RTE_Available_Call then
RTE_Is_Available := False;
else
Entity_Not_Defined (E);
end if;
raise RE_Not_Available;
-- Entity is available
else
-- If in No_Run_Time mode and entity is neither in the current unit
-- nor in one of the specially permitted units, raise the exception.
if No_Run_Time_Mode
and then not OK_No_Run_Time_Unit (U_Id)
-- If the entity being referenced is defined in the current scope,
-- using it is always fine as such usage can never introduce any
-- dependency on an additional unit. The presence of this test
-- helps generating meaningful error messages for CRT violations.
and then Scope (Eid) /= Current_Scope
then
Entity_Not_Defined (E);
raise RE_Not_Available;
end if;
-- Check entity is not overloaded, checking for special exceptions
if Has_Homonym (Eid)
and then E /= RE_Save_Occurrence
then
Set_Standard_Error;
Write_Str ("Run-time configuration error (");
Write_Str ("rtsfind entity """);
Get_Decoded_Name_String (Chars (Eid));
Set_Casing (Mixed_Case);
Write_Str (Name_Buffer (1 .. Name_Len));
Write_Str (""" is overloaded)");
Write_Eol;
raise Unrecoverable_Error;
end if;
-- Otherwise entity is accessible
return Eid;
end if;
end Check_CRT;
--------------------------------
-- Check_Text_IO_Special_Unit --
--------------------------------
procedure Check_Text_IO_Special_Unit (Nam : Node_Id) is
Chrs : Name_Id;
type Name_Map_Type is array (Text_IO_Package_Name) of RTU_Id;
Name_Map : constant Name_Map_Type := Name_Map_Type'(
Name_Decimal_IO => Ada_Text_IO_Decimal_IO,
Name_Enumeration_IO => Ada_Text_IO_Enumeration_IO,
Name_Fixed_IO => Ada_Text_IO_Fixed_IO,
Name_Float_IO => Ada_Text_IO_Float_IO,
Name_Integer_IO => Ada_Text_IO_Integer_IO,
Name_Modular_IO => Ada_Text_IO_Modular_IO);
Wide_Name_Map : constant Name_Map_Type := Name_Map_Type'(
Name_Decimal_IO => Ada_Wide_Text_IO_Decimal_IO,
Name_Enumeration_IO => Ada_Wide_Text_IO_Enumeration_IO,
Name_Fixed_IO => Ada_Wide_Text_IO_Fixed_IO,
Name_Float_IO => Ada_Wide_Text_IO_Float_IO,
Name_Integer_IO => Ada_Wide_Text_IO_Integer_IO,
Name_Modular_IO => Ada_Wide_Text_IO_Modular_IO);
Wide_Wide_Name_Map : constant Name_Map_Type := Name_Map_Type'(
Name_Decimal_IO => Ada_Wide_Wide_Text_IO_Decimal_IO,
Name_Enumeration_IO => Ada_Wide_Wide_Text_IO_Enumeration_IO,
Name_Fixed_IO => Ada_Wide_Wide_Text_IO_Fixed_IO,
Name_Float_IO => Ada_Wide_Wide_Text_IO_Float_IO,
Name_Integer_IO => Ada_Wide_Wide_Text_IO_Integer_IO,
Name_Modular_IO => Ada_Wide_Wide_Text_IO_Modular_IO);
To_Load : RTU_Id;
-- Unit to be loaded, from one of the above maps
begin
-- Nothing to do if name is not an identifier or a selected component
-- whose selector_name is an identifier.
if Nkind (Nam) = N_Identifier then
Chrs := Chars (Nam);
elsif Nkind (Nam) = N_Selected_Component
and then Nkind (Selector_Name (Nam)) = N_Identifier
then
Chrs := Chars (Selector_Name (Nam));
else
return;
end if;
-- Nothing to do if name is not one of the Text_IO subpackages
-- Otherwise look through loaded units, and if we find Text_IO
-- or [Wide_]Wide_Text_IO already loaded, then load the proper child.
if Chrs in Text_IO_Package_Name then
for U in Main_Unit .. Last_Unit loop
Get_Name_String (Unit_File_Name (U));
if Name_Len = 12 then
-- Here is where we do the loads if we find one of the units
-- Ada.Text_IO or Ada.[Wide_]Wide_Text_IO. An interesting
-- detail is that these units may already be used (i.e. their
-- In_Use flags may be set). Normally when the In_Use flag is
-- set, the Is_Potentially_Use_Visible flag of all entities in
-- the package is set, but the new entity we are mysteriously
-- adding was not there to have its flag set at the time. So
-- that's why we pass the extra parameter to RTU_Find, to make
-- sure the flag does get set now. Given that those generic
-- packages are in fact child units, we must indicate that
-- they are visible.
if Name_Buffer (1 .. 12) = "a-textio.ads" then
To_Load := Name_Map (Chrs);
elsif Name_Buffer (1 .. 12) = "a-witeio.ads" then
To_Load := Wide_Name_Map (Chrs);
elsif Name_Buffer (1 .. 12) = "a-ztexio.ads" then
To_Load := Wide_Wide_Name_Map (Chrs);
else
goto Continue;
end if;
Load_RTU (To_Load, Use_Setting => In_Use (Cunit_Entity (U)));
Set_Is_Visible_Lib_Unit (RT_Unit_Table (To_Load).Entity);
-- Prevent creation of an implicit 'with' from (for example)
-- Ada.Wide_Text_IO.Integer_IO to Ada.Text_IO.Integer_IO,
-- because these could create cycles. First check whether the
-- simple names match ("integer_io" = "integer_io"), and then
-- check whether the parent is indeed one of the
-- [[Wide_]Wide_]Text_IO packages.
if Chrs = Chars (Cunit_Entity (Current_Sem_Unit)) then
declare
Parent_Name : constant Unit_Name_Type :=
Get_Parent_Spec_Name
(Unit_Name (Current_Sem_Unit));
begin
if Present (Parent_Name) then
Get_Name_String (Parent_Name);
declare
P : String renames Name_Buffer (1 .. Name_Len);
begin
if P = "ada.text_io%s" or else
P = "ada.wide_text_io%s" or else
P = "ada.wide_wide_text_io%s"
then
goto Continue;
end if;
end;
end if;
end;
end if;
-- Add an implicit with clause from the current unit to the
-- [[Wide_]Wide_]Text_IO child (if necessary).
Maybe_Add_With (RT_Unit_Table (To_Load));
end if;
<<Continue>> null;
end loop;
end if;
exception
-- Generate error message if run-time unit not available
when RE_Not_Available =>
Error_Msg_N ("& not available", Nam);
end Check_Text_IO_Special_Unit;
------------------------
-- Entity_Not_Defined --
------------------------
procedure Entity_Not_Defined (Id : RE_Id) is
begin
if No_Run_Time_Mode then
-- If the error occurs when compiling the body of a predefined
-- unit for inlining purposes, the body must be illegal in this
-- mode, and there is no point in continuing.
if In_Predefined_Unit (Current_Error_Node) then
Error_Msg_N
("construct not allowed in no run time mode!",
Current_Error_Node);
raise Unrecoverable_Error;
else
RTE_Error_Msg ("|construct not allowed in no run time mode");
end if;
elsif Configurable_Run_Time_Mode then
RTE_Error_Msg ("|construct not allowed in this configuration>");
else
RTE_Error_Msg ("run-time configuration error");
end if;
-- See if this entry is to be found in the PRE_Id table that provides
-- specialized messages for some RE_Id values.
for J in PRE_Id_Table'Range loop
declare
TStr : constant String := PRE_Id_Table (J).Str.all;
RStr : constant String := RE_Id'Image (Id);
TMsg : String := PRE_Id_Table (J).Msg.all;
LMsg : Natural := TMsg'Length;
begin
if TStr'Length = RStr'Length then
for J in TStr'Range loop
if TStr (J) /= RStr (J) and then TStr (J) /= '?' then
goto Continue;
end if;
end loop;
for J in TMsg'First .. TMsg'Last - 1 loop
if TMsg (J) = '?' then
for K in 1 .. TStr'Last loop
if TStr (K) = '?' then
if RStr (K) = '0' then
TMsg (J) := RStr (K + 1);
TMsg (J + 1 .. LMsg - 1) := TMsg (J + 2 .. LMsg);
LMsg := LMsg - 1;
else
TMsg (J .. J + 1) := RStr (K .. K + 1);
end if;
exit;
end if;
end loop;
end if;
end loop;
RTE_Error_Msg (TMsg (1 .. LMsg));
return;
end if;
end;
<<Continue>> null;
end loop;
-- We did not find an entry in the table, so output the generic entity
-- not found message, where the name of the entity corresponds to the
-- given RE_Id value.
Output_Entity_Name (Id, "not defined");
end Entity_Not_Defined;
-------------------
-- Get_Unit_Name --
-------------------
-- The following subtypes include all the proper descendants of each unit
-- that has such descendants. For example, Ada_Calendar_Descendant includes
-- all the descendents of Ada.Calendar (except Ada.Calendar itself). These
-- are used by Get_Unit_Name to know where to change "_" to ".", and by
-- Is_Text_IO_Special_Package to detect the special generic pseudo-children
-- of [[Wide_]Wide_]Text_IO.
subtype Ada_Descendant is RTU_Id
range Ada_Calendar .. Ada_Wide_Wide_Text_IO_Modular_IO;
subtype Ada_Calendar_Descendant is Ada_Descendant
range Ada_Calendar_Delays .. Ada_Calendar_Delays;
subtype Ada_Dispatching_Descendant is Ada_Descendant
range Ada_Dispatching_EDF .. Ada_Dispatching_EDF;
subtype Ada_Interrupts_Descendant is Ada_Descendant range
Ada_Interrupts_Names .. Ada_Interrupts_Names;
subtype Ada_Numerics_Descendant is Ada_Descendant
range Ada_Numerics_Big_Numbers ..
Ada_Numerics_Big_Numbers_Big_Integers_Ghost;
subtype Ada_Numerics_Big_Numbers_Descendant is Ada_Descendant
range Ada_Numerics_Big_Numbers_Big_Integers ..
Ada_Numerics_Big_Numbers_Big_Integers_Ghost;
subtype Ada_Real_Time_Descendant is Ada_Descendant
range Ada_Real_Time_Delays .. Ada_Real_Time_Timing_Events;
subtype Ada_Streams_Descendant is Ada_Descendant
range Ada_Streams_Stream_IO .. Ada_Streams_Stream_IO;
subtype Ada_Strings_Descendant is Ada_Descendant
range Ada_Strings_Superbounded .. Ada_Strings_Text_Buffers_Unbounded;
subtype Ada_Strings_Text_Buffers_Descendant is Ada_Strings_Descendant
range Ada_Strings_Text_Buffers_Unbounded ..
Ada_Strings_Text_Buffers_Unbounded;
subtype Ada_Text_IO_Descendant is Ada_Descendant
range Ada_Text_IO_Decimal_IO .. Ada_Text_IO_Modular_IO;
subtype Ada_Wide_Text_IO_Descendant is Ada_Descendant
range Ada_Wide_Text_IO_Decimal_IO .. Ada_Wide_Text_IO_Modular_IO;
subtype Ada_Wide_Wide_Text_IO_Descendant is Ada_Descendant
range Ada_Wide_Wide_Text_IO_Decimal_IO ..
Ada_Wide_Wide_Text_IO_Modular_IO;
subtype CUDA_Descendant is RTU_Id
range CUDA_Driver_Types .. CUDA_Vector_Types;
subtype Interfaces_Descendant is RTU_Id
range Interfaces_C .. Interfaces_C_Strings;
subtype Interfaces_C_Descendant is Interfaces_Descendant
range Interfaces_C_Strings .. Interfaces_C_Strings;
subtype System_Descendant is RTU_Id
range System_Address_Image .. System_Tasking_Stages;
subtype System_Atomic_Operations_Descendant is System_Descendant
range System_Atomic_Operations_Test_And_Set ..
System_Atomic_Operations_Test_And_Set;
subtype System_Dim_Descendant is System_Descendant
range System_Dim_Float_IO .. System_Dim_Integer_IO;
subtype System_Multiprocessors_Descendant is System_Descendant
range System_Multiprocessors_Dispatching_Domains ..
System_Multiprocessors_Dispatching_Domains;
subtype System_Storage_Pools_Descendant is System_Descendant
range System_Storage_Pools_Subpools .. System_Storage_Pools_Subpools;
subtype System_Strings_Descendant is System_Descendant
range System_Strings_Stream_Ops .. System_Strings_Stream_Ops;
subtype System_Tasking_Descendant is System_Descendant
range System_Tasking_Async_Delays .. System_Tasking_Stages;
subtype System_Tasking_Protected_Objects_Descendant is
System_Tasking_Descendant
range System_Tasking_Protected_Objects_Entries ..
System_Tasking_Protected_Objects_Single_Entry;
subtype System_Tasking_Restricted_Descendant is System_Tasking_Descendant
range System_Tasking_Restricted_Stages ..
System_Tasking_Restricted_Stages;
subtype System_Tasking_Async_Delays_Descendant is System_Tasking_Descendant
range System_Tasking_Async_Delays_Enqueue_Calendar ..
System_Tasking_Async_Delays_Enqueue_RT;
function Get_Unit_Name (U_Id : RTU_Id) return Unit_Name_Type is
Uname_Chars : constant String := RTU_Id'Image (U_Id);
begin
Name_Len := Uname_Chars'Length;
Name_Buffer (1 .. Name_Len) := Uname_Chars;
Set_Casing (All_Lower_Case);
if U_Id in Ada_Descendant then
Name_Buffer (4) := '.';
if U_Id in Ada_Calendar_Descendant then
Name_Buffer (13) := '.';
elsif U_Id in Ada_Dispatching_Descendant then
Name_Buffer (16) := '.';
elsif U_Id in Ada_Interrupts_Descendant then
Name_Buffer (15) := '.';
elsif U_Id in Ada_Numerics_Descendant then
Name_Buffer (13) := '.';
if U_Id in Ada_Numerics_Big_Numbers_Descendant then
Name_Buffer (25) := '.';
end if;
elsif U_Id in Ada_Real_Time_Descendant then
Name_Buffer (14) := '.';
elsif U_Id in Ada_Streams_Descendant then
Name_Buffer (12) := '.';
elsif U_Id in Ada_Strings_Descendant then
Name_Buffer (12) := '.';
if U_Id in Ada_Strings_Text_Buffers_Descendant then
Name_Buffer (25) := '.';
end if;
elsif U_Id in Ada_Text_IO_Descendant then
Name_Buffer (12) := '.';
elsif U_Id in Ada_Wide_Text_IO_Descendant then
Name_Buffer (17) := '.';
elsif U_Id in Ada_Wide_Wide_Text_IO_Descendant then
Name_Buffer (22) := '.';
end if;
elsif U_Id in CUDA_Descendant then
Name_Buffer (5) := '.';
elsif U_Id in Interfaces_Descendant then
Name_Buffer (11) := '.';
if U_Id in Interfaces_C_Descendant then
Name_Buffer (13) := '.';
end if;
elsif U_Id in System_Descendant then
Name_Buffer (7) := '.';
if U_Id in System_Atomic_Operations_Descendant then
Name_Buffer (25) := '.';
end if;
if U_Id in System_Dim_Descendant then
Name_Buffer (11) := '.';
end if;
if U_Id in System_Multiprocessors_Descendant then
Name_Buffer (23) := '.';
end if;
if U_Id in System_Storage_Pools_Descendant then
Name_Buffer (21) := '.';
end if;
if U_Id in System_Strings_Descendant then
Name_Buffer (15) := '.';
end if;
if U_Id in System_Tasking_Descendant then
Name_Buffer (15) := '.';
end if;
if U_Id in System_Tasking_Restricted_Descendant then
Name_Buffer (26) := '.';
end if;
if U_Id in System_Tasking_Protected_Objects_Descendant then
Name_Buffer (33) := '.';
end if;
if U_Id in System_Tasking_Async_Delays_Descendant then
Name_Buffer (28) := '.';
end if;
end if;
-- Add %s at end for spec
Name_Buffer (Name_Len + 1) := '%';
Name_Buffer (Name_Len + 2) := 's';
Name_Len := Name_Len + 2;
return Name_Find;
end Get_Unit_Name;
----------------
-- Initialize --
----------------
procedure Initialize is
begin
-- Initialize the unit table
for J in RTU_Id loop
RT_Unit_Table (J).Entity := Empty;
RT_Unit_Table (J).First_Implicit_With := Empty;
end loop;
for J in RE_Id loop
RE_Table (J) := Empty;
end loop;
RTE_Is_Available := False;
end Initialize;
------------
-- Is_RTE --
------------
function Is_RTE (Ent : Entity_Id; E : RE_Id) return Boolean is
E_Unit_Name : Unit_Name_Type;
Ent_Unit_Name : Unit_Name_Type;
S : Entity_Id;
E1 : Entity_Id;
E2 : Entity_Id;
begin
if No (Ent) then
return False;
-- If E has already a corresponding entity, check it directly,
-- going to full views if they exist to deal with the incomplete
-- and private type cases properly.
elsif Present (RE_Table (E)) then
E1 := Ent;
if Is_Type (E1) and then Present (Full_View (E1)) then
E1 := Full_View (E1);
end if;
E2 := RE_Table (E);
if Is_Type (E2) and then Present (Full_View (E2)) then
E2 := Full_View (E2);
end if;
return E1 = E2;
end if;
-- If the unit containing E is not loaded, we already know that the
-- entity we have cannot have come from this unit.
E_Unit_Name := Get_Unit_Name (RE_Unit_Table (E));
if not Is_Loaded (E_Unit_Name) then
return False;
end if;
-- Here the unit containing the entity is loaded. We have not made
-- an explicit call to RTE to get the entity in question, but we may
-- have obtained a reference to it indirectly from some other entity
-- in the same unit, or some other unit that references it.
-- Get the defining unit of the entity
S := Scope (Ent);
if No (S) or else Ekind (S) /= E_Package then
return False;
end if;
Ent_Unit_Name := Get_Unit_Name (Unit_Declaration_Node (S));
-- If the defining unit of the entity we are testing is not the
-- unit containing E, then they cannot possibly match.
if Ent_Unit_Name /= E_Unit_Name then
return False;
end if;
-- If the units match, then compare the names (remember that no
-- overloading is permitted in entities fetched using Rtsfind).
if RE_Chars (E) = Chars (Ent) then
RE_Table (E) := Ent;
-- If front-end inlining is enabled, we may be within a body that
-- contains inlined functions, which has not been retrieved through
-- rtsfind, and therefore is not yet recorded in the RT_Unit_Table.
-- Add the unit information now, it must be fully available.
declare
U : RT_Unit_Table_Record
renames RT_Unit_Table (RE_Unit_Table (E));
begin
if No (U.Entity) then
U.Entity := S;
U.Uname := E_Unit_Name;
U.Unum := Get_Source_Unit (S);
end if;
end;
return True;
else
return False;
end if;
end Is_RTE;
------------
-- Is_RTU --
------------
function Is_RTU (Ent : Entity_Id; U : RTU_Id) return Boolean is
E : constant Entity_Id := RT_Unit_Table (U).Entity;
begin
return Present (E) and then E = Ent;
end Is_RTU;
--------------------------------
-- Is_Text_IO_Special_Package --
--------------------------------
function Is_Text_IO_Special_Package (E : Entity_Id) return Boolean is
begin
pragma Assert (Is_Package_Or_Generic_Package (E));
-- ??? detection with a scope climbing might be more efficient
for U in Ada_Text_IO_Descendant loop
if Is_RTU (E, U) then
return True;
end if;
end loop;
for U in Ada_Wide_Text_IO_Descendant loop
if Is_RTU (E, U) then
return True;
end if;
end loop;
for U in Ada_Wide_Wide_Text_IO_Descendant loop
if Is_RTU (E, U) then
return True;
end if;
end loop;
return False;
end Is_Text_IO_Special_Package;
-----------------------------
-- Is_Text_IO_Special_Unit --
-----------------------------
function Is_Text_IO_Special_Unit (Nam : Node_Id) return Boolean is
Prf : Node_Id;
Sel : Node_Id;
begin
if Nkind (Nam) /= N_Expanded_Name then
return False;
end if;
Prf := Prefix (Nam);
Sel := Selector_Name (Nam);
if Nkind (Sel) /= N_Expanded_Name
or else Nkind (Prf) /= N_Identifier
or else Chars (Prf) /= Name_Ada
then
return False;
end if;
Prf := Prefix (Sel);
Sel := Selector_Name (Sel);
return
Nkind (Prf) = N_Identifier
and then
Chars (Prf) in Name_Text_IO
| Name_Wide_Text_IO
| Name_Wide_Wide_Text_IO
and then Nkind (Sel) = N_Identifier
and then Chars (Sel) in Text_IO_Package_Name;
end Is_Text_IO_Special_Unit;
---------------
-- Load_Fail --
---------------
procedure Load_Fail (S : String; U_Id : RTU_Id; Id : RE_Id) is
M : String (1 .. 100);
P : Natural := 0;
begin
-- Output header message
if Configurable_Run_Time_Mode then
RTE_Error_Msg ("construct not allowed in configurable run-time mode");
else
RTE_Error_Msg ("run-time library configuration error");
end if;
-- Output file name and reason string
M (1 .. 6) := "\file ";
P := 6;
Get_Name_String
(Get_File_Name (RT_Unit_Table (U_Id).Uname, Subunit => False));
M (P + 1 .. P + Name_Len) := Name_Buffer (1 .. Name_Len);
P := P + Name_Len;
M (P + 1) := ' ';
P := P + 1;
M (P + 1 .. P + S'Length) := S;
P := P + S'Length;
RTE_Error_Msg (M (1 .. P));
-- Output entity name
Output_Entity_Name (Id, "not available");
-- In configurable run time mode, we raise RE_Not_Available, and the
-- caller is expected to deal gracefully with this. In the case of a
-- call to RTE_Available, this exception will be caught in Rtsfind,
-- and result in a returned value of False for the call.
if Configurable_Run_Time_Mode then
raise RE_Not_Available;
-- Here we have a load failure in normal full run time mode. See if we
-- are in the context of an RTE_Available call. If so, we just raise
-- RE_Not_Available. This can happen if a unit is unavailable, which
-- happens for example in the VM case, where the run-time is not
-- complete, but we do not regard it as a configurable run-time.
-- If the caller has done an explicit call to RTE_Available, then
-- clearly the caller is prepared to deal with a result of False.
elsif RTE_Available_Call then
RTE_Is_Available := False;
raise RE_Not_Available;
-- If we are not in the context of an RTE_Available call, we are really
-- trying to load an entity that is not there, and that should never
-- happen, so in this case we signal a fatal error.
else
raise Unrecoverable_Error;
end if;
end Load_Fail;
--------------
-- Load_RTU --
--------------
-- WARNING: This routine manages Ghost and SPARK regions. Return statements
-- must be replaced by gotos which jump to the end of the routine in order
-- to restore the Ghost and SPARK modes.
procedure Load_RTU
(U_Id : RTU_Id;
Id : RE_Id := RE_Null;
Use_Setting : Boolean := False)
is
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
Priv_Par : constant Elist_Id := New_Elmt_List;
Lib_Unit : Node_Id;
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
Saved_SMP : constant Node_Id := SPARK_Mode_Pragma;
-- Save Ghost and SPARK mode-related data to restore on exit
procedure Save_Private_Visibility;
-- If the current unit is the body of child unit or the spec of a
-- private child unit, the private declarations of the parent(s) are
-- visible. If the unit to be loaded is another public sibling, its
-- compilation will affect the visibility of the common ancestors.
-- Indicate those that must be restored.
procedure Restore_Private_Visibility;
-- Restore the visibility of ancestors after compiling RTU
procedure Restore_SPARK_Context;
-- Restore Ghost and SPARK mode-related data saved on procedure entry
--------------------------------
-- Restore_Private_Visibility --
--------------------------------
procedure Restore_Private_Visibility is
E_Par : Elmt_Id;
begin
E_Par := First_Elmt (Priv_Par);
while Present (E_Par) loop
if not In_Private_Part (Node (E_Par)) then
Install_Private_Declarations (Node (E_Par));
end if;
Next_Elmt (E_Par);
end loop;
end Restore_Private_Visibility;
-----------------------------
-- Save_Private_Visibility --
-----------------------------
procedure Save_Private_Visibility is
Par : Entity_Id;
begin
Par := Scope (Current_Scope);
while Present (Par)
and then Par /= Standard_Standard
loop
if Ekind (Par) = E_Package
and then Is_Compilation_Unit (Par)
and then In_Private_Part (Par)
then
Append_Elmt (Par, Priv_Par);
end if;
Par := Scope (Par);
end loop;
end Save_Private_Visibility;
---------------------------
-- Restore_SPARK_Context --
---------------------------
procedure Restore_SPARK_Context is
begin
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
Restore_Ghost_Region (Saved_GM, Saved_IGR);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
end Restore_SPARK_Context;
-- Start of processing for Load_RTU
begin
-- Nothing to do if unit is already loaded
if Present (U.Entity) then
return;
end if;
-- Provide a clean environment for the unit
Ignore_SPARK_Mode_Pragmas_In_Instance := False;
Install_Ghost_Region (None, Empty);
Install_SPARK_Mode (None, Empty);
-- Otherwise we need to load the unit, First build unit name from the
-- enumeration literal name in type RTU_Id.
U.Uname := Get_Unit_Name (U_Id);
U.First_Implicit_With := Empty;
-- Now do the load call, note that setting Error_Node to Empty is a
-- signal to Load_Unit that we will regard a failure to find the file as
-- a fatal error, and that it should not output any kind of diagnostics,
-- since we will take care of it here.
-- We save style checking switches and turn off style checking for
-- loading the unit, since we don't want any style checking.
declare
Save_Style_Check : constant Boolean := Style_Check;
begin
Style_Check := False;
U.Unum :=
Load_Unit
(Load_Name => U.Uname,
Required => False,
Subunit => False,
Error_Node => Empty);
Style_Check := Save_Style_Check;
end;
-- Check for bad unit load
if U.Unum = No_Unit then
Load_Fail ("not found", U_Id, Id);
elsif Fatal_Error (U.Unum) = Error_Detected then
Load_Fail ("had parser errors", U_Id, Id);
end if;
-- Make sure that the unit is analyzed
declare
Was_Analyzed : constant Boolean :=
Analyzed (Cunit (Current_Sem_Unit));
begin
-- Pretend that the current unit is analyzed, in case it is System
-- or some such. This allows us to put some declarations, such as
-- exceptions and packed arrays of Boolean, into System even though
-- expanding them requires System...
-- This is a bit odd but works fine. If the RTS unit does not depend
-- in any way on the current unit, then it never gets back into the
-- current unit's tree, and the change we make to the current unit
-- tree is never noticed by anyone (it is undone in a moment). That
-- is the normal situation.
-- If the RTS Unit *does* depend on the current unit, for instance,
-- when you are compiling System, then you had better have finished
-- analyzing the part of System that is depended on before you try to
-- load the RTS Unit. This means having the code in System ordered in
-- an appropriate manner.
Set_Analyzed (Cunit (Current_Sem_Unit), True);
if not Analyzed (Cunit (U.Unum)) then
-- If the unit is already loaded through a limited_with_clause,
-- the relevant entities must already be available. We do not
-- want to load and analyze the unit because this would create
-- a real semantic dependence when the purpose of the limited_with
-- is precisely to avoid such.
if From_Limited_With (Cunit_Entity (U.Unum)) then
null;
else
Save_Private_Visibility;
Semantics (Cunit (U.Unum));
Restore_Private_Visibility;
if Fatal_Error (U.Unum) = Error_Detected then
Load_Fail ("had semantic errors", U_Id, Id);
end if;
end if;
end if;
-- Undo the pretence
Set_Analyzed (Cunit (Current_Sem_Unit), Was_Analyzed);
end;
Lib_Unit := Unit (Cunit (U.Unum));
U.Entity := Defining_Entity (Lib_Unit);
if Use_Setting then
Set_Is_Potentially_Use_Visible (U.Entity, True);
end if;
Restore_SPARK_Context;
exception
-- The Load_Fail procedure that is called when the result of Load_Unit
-- is not satisfactory raises an exception. As the compiler is able to
-- recover in some cases (i.e. when RE_Not_Available is raised), we need
-- to restore the SPARK/Ghost context correctly.
when others =>
Restore_SPARK_Context;
raise;
end Load_RTU;
--------------------
-- Make_Unit_Name --
--------------------
function Make_Unit_Name
(U : RT_Unit_Table_Record;
N : Node_Id) return Node_Id is
Nam : Node_Id;
Scop : Entity_Id;
begin
Nam := New_Occurrence_Of (U.Entity, Standard_Location);
Scop := Scope (U.Entity);
if Nkind (N) = N_Defining_Program_Unit_Name then
while Scop /= Standard_Standard loop
Nam :=
Make_Expanded_Name (Standard_Location,
Chars => Chars (U.Entity),
Prefix => New_Occurrence_Of (Scop, Standard_Location),
Selector_Name => Nam);
Set_Entity (Nam, U.Entity);
Scop := Scope (Scop);
end loop;
end if;
return Nam;
end Make_Unit_Name;
--------------------
-- Maybe_Add_With --
--------------------
procedure Maybe_Add_With (U : in out RT_Unit_Table_Record) is
begin
-- We do not need to generate a with_clause for a call issued from
-- RTE_Component_Available. However, for CodePeer, we need these
-- additional with's, because for a sequence like "if RTE_Available (X)
-- then ... RTE (X)" the RTE call fails to create some necessary with's.
if RTE_Available_Call and not Generate_SCIL then
return;
end if;
-- Avoid creating directly self-referential with clauses
if Current_Sem_Unit = U.Unum then
return;
end if;
-- Add the with_clause, if we have not already added an implicit with
-- for this unit to the current compilation unit.
declare
LibUnit : constant Node_Id := Unit (Cunit (U.Unum));
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
Clause : Node_Id;
Withn : Node_Id;
begin
Clause := U.First_Implicit_With;
while Present (Clause) loop
if Parent (Clause) = Cunit (Current_Sem_Unit) then
return;
end if;
Clause := Next_Implicit_With (Clause);
end loop;
-- We want to make sure that the "with" we create below isn't
-- marked as ignored ghost code because this list may be walked
-- later, after ignored ghost code is converted to a null
-- statement.
Ghost_Mode := None;
Withn :=
Make_With_Clause (Standard_Location,
Name =>
Make_Unit_Name
(U, Defining_Unit_Name (Specification (LibUnit))));
Ghost_Mode := Saved_GM;
Set_Corresponding_Spec (Withn, U.Entity);
Set_First_Name (Withn);
Set_Implicit_With (Withn);
Set_Library_Unit (Withn, Cunit (U.Unum));
Set_Next_Implicit_With (Withn, U.First_Implicit_With);
U.First_Implicit_With := Withn;
Mark_Rewrite_Insertion (Withn);
Append (Withn, Context_Items (Cunit (Current_Sem_Unit)));
Check_Restriction_No_Dependence (Name (Withn), Current_Error_Node);
end;
end Maybe_Add_With;
------------------------
-- Output_Entity_Name --
------------------------
procedure Output_Entity_Name (Id : RE_Id; Msg : String) is
M : String (1 .. 2048);
P : Natural := 0;
-- M (1 .. P) is current message to be output
RE_Image : constant String := RE_Id'Image (Id);
S : Natural;
-- RE_Image (S .. RE_Image'Last) is the name of the entity without the
-- "RE_" or "RO_XX_" prefix.
begin
if Id = RE_Null then
return;
end if;
M (1 .. 9) := "\entity """;
P := 9;
-- Add unit name to message, excluding %s or %b at end
Get_Name_String (Get_Unit_Name (RE_Unit_Table (Id)));
Name_Len := Name_Len - 2;
Set_Casing (Mixed_Case);
M (P + 1 .. P + Name_Len) := Name_Buffer (1 .. Name_Len);
P := P + Name_Len;
-- Add a qualifying period
M (P + 1) := '.';
P := P + 1;
-- Strip "RE"
if RE_Image (2) = 'E' then
S := 4;
-- Strip "RO_XX"
else
S := 7;
end if;
-- Add entity name and closing quote to message
Name_Len := RE_Image'Length - S + 1;
Name_Buffer (1 .. Name_Len) := RE_Image (S .. RE_Image'Last);
Set_Casing (Mixed_Case);
M (P + 1 .. P + Name_Len) := Name_Buffer (1 .. Name_Len);
P := P + Name_Len;
M (P + 1) := '"';
P := P + 1;
-- Add message
M (P + 1) := ' ';
P := P + 1;
M (P + 1 .. P + Msg'Length) := Msg;
P := P + Msg'Length;
-- Output message at current error node location
RTE_Error_Msg (M (1 .. P));
end Output_Entity_Name;
--------------
-- RE_Chars --
--------------
function RE_Chars (E : RE_Id) return Name_Id is
RE_Name_Chars : constant String := RE_Id'Image (E);
begin
-- Copy name skipping initial RE_ or RO_XX characters
if RE_Name_Chars (1 .. 2) = "RE" then
for J in 4 .. RE_Name_Chars'Last loop
Name_Buffer (J - 3) := Fold_Lower (RE_Name_Chars (J));
end loop;
Name_Len := RE_Name_Chars'Length - 3;
else
for J in 7 .. RE_Name_Chars'Last loop
Name_Buffer (J - 6) := Fold_Lower (RE_Name_Chars (J));
end loop;
Name_Len := RE_Name_Chars'Length - 6;
end if;
return Name_Find;
end RE_Chars;
---------
-- RTE --
---------
function RTE (E : RE_Id) return Entity_Id is
procedure Check_RPC;
-- Reject programs that make use of distribution features not supported
-- on the current target. Also check that the PCS is compatible with the
-- code generator version. On such targets (Vxworks, others?) we provide
-- a minimal body for System.Rpc that only supplies an implementation of
-- Partition_Id.
function Find_Local_Entity (E : RE_Id) return Entity_Id;
-- This function is used when entity E is in this compilation's main
-- unit. It gets the value from the already compiled declaration.
---------------
-- Check_RPC --
---------------
procedure Check_RPC is
begin
-- Bypass this check if debug flag -gnatdR set
if Debug_Flag_RR then
return;
end if;
-- Otherwise we need the check if we are going after one of the
-- critical entities in System.RPC / System.Partition_Interface.
if E = RE_Do_Rpc
or else
E = RE_Do_Apc
or else
E = RE_Params_Stream_Type
or else
E = RE_Request_Access
then
-- If generating RCI stubs, check that we have a real PCS
if (Distribution_Stub_Mode = Generate_Receiver_Stub_Body
or else
Distribution_Stub_Mode = Generate_Caller_Stub_Body)
and then Get_PCS_Name = Name_No_DSA
then
Set_Standard_Error;
Write_Str ("distribution feature not supported");
Write_Eol;
raise Unrecoverable_Error;
-- In all cases, check Exp_Dist and System.Partition_Interface
-- consistency.
elsif Get_PCS_Version /=
Exp_Dist.PCS_Version_Number (Get_PCS_Name)
then
Set_Standard_Error;
Write_Str ("PCS version mismatch: expander ");
Write_Int (Exp_Dist.PCS_Version_Number (Get_PCS_Name));
Write_Str (", PCS (");
Write_Name (Get_PCS_Name);
Write_Str (") ");
Write_Int (Get_PCS_Version);
Write_Eol;
raise Unrecoverable_Error;
end if;
end if;
end Check_RPC;
-----------------------
-- Find_Local_Entity --
-----------------------
function Find_Local_Entity (E : RE_Id) return Entity_Id is
RE_Str : constant String := RE_Id'Image (E);
Nam : Name_Id;
Ent : Entity_Id;
Save_Nam : constant String := Name_Buffer (1 .. Name_Len);
-- Save name buffer and length over call
begin
Name_Len := Natural'Max (0, RE_Str'Length - 3);
Name_Buffer (1 .. Name_Len) :=
RE_Str (RE_Str'First + 3 .. RE_Str'Last);
Nam := Name_Find;
Ent := Entity_Id (Get_Name_Table_Int (Nam));
Name_Len := Save_Nam'Length;
Name_Buffer (1 .. Name_Len) := Save_Nam;
return Ent;
end Find_Local_Entity;
-- Local variables
U_Id : constant RTU_Id := RE_Unit_Table (E);
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
Ename : Name_Id;
Lib_Unit : Node_Id;
Pkg_Ent : Entity_Id;
Save_Front_End_Inlining : constant Boolean := Front_End_Inlining;
-- This flag is used to disable front-end inlining when RTE is invoked.
-- This prevents the analysis of other runtime bodies when a particular
-- spec is loaded through Rtsfind. This is both efficient, and prevents
-- spurious visibility conflicts between use-visible user entities, and
-- entities in run-time packages.
-- Start of processing for RTE
begin
-- Doing a rtsfind in system.ads is special, as we cannot do this
-- when compiling System itself. So if we are compiling system then
-- we should already have acquired and processed the declaration
-- of the entity. The test is to see if this compilation's main unit
-- is System. If so, return the value from the already compiled
-- declaration and otherwise do a regular find.
-- Not pleasant, but these kinds of annoying recursion scenarios when
-- writing an Ada compiler in Ada have to be broken somewhere.
if Present (Main_Unit_Entity)
and then Chars (Main_Unit_Entity) = Name_System
and then Analyzed (Main_Unit_Entity)
and then not Is_Child_Unit (Main_Unit_Entity)
then
return Check_CRT (E, Find_Local_Entity (E));
end if;
Front_End_Inlining := False;
-- Load unit if unit not previously loaded
if No (RE_Table (E)) then
Load_RTU (U_Id, Id => E);
Lib_Unit := Unit (Cunit (U.Unum));
-- In the subprogram case, we are all done, the entity we want
-- is the entity for the subprogram itself. Note that we do not
-- bother to check that it is the entity that was requested.
-- the only way that could fail to be the case is if runtime is
-- hopelessly misconfigured, and it isn't worth testing for this.
if Nkind (Lib_Unit) = N_Subprogram_Declaration then
RE_Table (E) := U.Entity;
-- Otherwise we must have the package case. First check package
-- entity itself (e.g. RTE_Name for System.Interrupts.Name)
else
pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
Ename := RE_Chars (E);
-- First we search the package entity chain. If the package
-- only has a limited view, scan the corresponding list of
-- incomplete types.
if From_Limited_With (U.Entity) then
Pkg_Ent := First_Entity (Limited_View (U.Entity));
else
Pkg_Ent := First_Entity (U.Entity);
end if;
while Present (Pkg_Ent) loop
if Ename = Chars (Pkg_Ent) then
RE_Table (E) := Pkg_Ent;
Check_RPC;
goto Found;
end if;
Next_Entity (Pkg_Ent);
end loop;
-- If we did not find the entity in the package entity chain,
-- then check if the package entity itself matches. Note that
-- we do this check after searching the entity chain, since
-- the rule is that in case of ambiguity, we prefer the entity
-- defined within the package, rather than the package itself.
if Ename = Chars (U.Entity) then
RE_Table (E) := U.Entity;
end if;
-- If we didn't find the entity we want, something is wrong.
-- We just leave RE_Table (E) set to Empty and the appropriate
-- action will be taken by Check_CRT when we exit.
end if;
end if;
<<Found>>
-- Record whether the secondary stack is in use in order to generate
-- the proper binder code. No action is taken when the secondary stack
-- is pulled within an ignored Ghost context because all this code will
-- disappear.
if U_Id = System_Secondary_Stack and then Ghost_Mode /= Ignore then
Sec_Stack_Used := True;
end if;
Maybe_Add_With (U);
Front_End_Inlining := Save_Front_End_Inlining;
return Check_CRT (E, RE_Table (E));
end RTE;
-------------------
-- RTE_Available --
-------------------
function RTE_Available (E : RE_Id) return Boolean is
Dummy : Entity_Id;
pragma Warnings (Off, Dummy);
Result : Boolean;
Save_RTE_Available_Call : constant Boolean := RTE_Available_Call;
Save_RTE_Is_Available : constant Boolean := RTE_Is_Available;
-- These are saved recursively because the call to load a unit
-- caused by an upper level call may perform a recursive call
-- to this routine during analysis of the corresponding unit.
begin
RTE_Available_Call := True;
RTE_Is_Available := True;
Dummy := RTE (E);
Result := RTE_Is_Available;
RTE_Available_Call := Save_RTE_Available_Call;
RTE_Is_Available := Save_RTE_Is_Available;
return Result;
exception
when RE_Not_Available =>
RTE_Available_Call := Save_RTE_Available_Call;
RTE_Is_Available := Save_RTE_Is_Available;
return False;
end RTE_Available;
--------------------------
-- RTE_Record_Component --
--------------------------
function RTE_Record_Component (E : RE_Id) return Entity_Id is
U_Id : constant RTU_Id := RE_Unit_Table (E);
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
E1 : Entity_Id;
Ename : Name_Id;
Found_E : Entity_Id;
Lib_Unit : Node_Id;
Pkg_Ent : Entity_Id;
-- The following flag is used to disable front-end inlining when
-- RTE_Record_Component is invoked. This prevents the analysis of other
-- runtime bodies when a particular spec is loaded through Rtsfind. This
-- is both efficient, and it prevents spurious visibility conflicts
-- between use-visible user entities, and entities in run-time packages.
Save_Front_End_Inlining : Boolean;
begin
-- Note: Contrary to subprogram RTE, there is no need to do any special
-- management with package system.ads because it has no record type
-- declarations.
Save_Front_End_Inlining := Front_End_Inlining;
Front_End_Inlining := False;
-- Load unit if unit not previously loaded
if No (U.Entity) then
Load_RTU (U_Id, Id => E);
end if;
Lib_Unit := Unit (Cunit (U.Unum));
pragma Assert (Nkind (Lib_Unit) = N_Package_Declaration);
Ename := RE_Chars (E);
-- Search the entity in the components of record type declarations
-- found in the package entity chain.
Found_E := Empty;
Pkg_Ent := First_Entity (U.Entity);
Search : while Present (Pkg_Ent) loop
if Is_Record_Type (Pkg_Ent) then
E1 := First_Entity (Pkg_Ent);
while Present (E1) loop
if Ename = Chars (E1) then
pragma Assert (No (Found_E));
Found_E := E1;
end if;
Next_Entity (E1);
end loop;
end if;
Next_Entity (Pkg_Ent);
end loop Search;
-- If we didn't find the entity we want, something is wrong. The
-- appropriate action will be taken by Check_CRT when we exit.
Maybe_Add_With (U);
Front_End_Inlining := Save_Front_End_Inlining;
return Check_CRT (E, Found_E);
end RTE_Record_Component;
------------------------------------
-- RTE_Record_Component_Available --
------------------------------------
function RTE_Record_Component_Available (E : RE_Id) return Boolean is
Dummy : Entity_Id;
pragma Warnings (Off, Dummy);
Result : Boolean;
Save_RTE_Available_Call : constant Boolean := RTE_Available_Call;
Save_RTE_Is_Available : constant Boolean := RTE_Is_Available;
-- These are saved recursively because the call to load a unit
-- caused by an upper level call may perform a recursive call
-- to this routine during analysis of the corresponding unit.
begin
RTE_Available_Call := True;
RTE_Is_Available := True;
Dummy := RTE_Record_Component (E);
Result := RTE_Is_Available;
RTE_Available_Call := Save_RTE_Available_Call;
RTE_Is_Available := Save_RTE_Is_Available;
return Result;
exception
when RE_Not_Available =>
RTE_Available_Call := Save_RTE_Available_Call;
RTE_Is_Available := Save_RTE_Is_Available;
return False;
end RTE_Record_Component_Available;
-------------------
-- RTE_Error_Msg --
-------------------
procedure RTE_Error_Msg (Msg : String) is
begin
if RTE_Available_Call then
RTE_Is_Available := False;
else
Error_Msg_N (Msg, Current_Error_Node);
-- Bump count of violations if we are in configurable run-time
-- mode and this is not a continuation message.
if Configurable_Run_Time_Mode and then Msg (Msg'First) /= '\' then
Configurable_Run_Time_Violations :=
Configurable_Run_Time_Violations + 1;
end if;
end if;
end RTE_Error_Msg;
----------------
-- RTU_Entity --
----------------
function RTU_Entity (U : RTU_Id) return Entity_Id is
begin
return RT_Unit_Table (U).Entity;
end RTU_Entity;
----------------
-- RTU_Loaded --
----------------
function RTU_Loaded (U : RTU_Id) return Boolean is
begin
return Present (RT_Unit_Table (U).Entity);
end RTU_Loaded;
--------------------
-- Set_RTU_Loaded --
--------------------
procedure Set_RTU_Loaded (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Unum : constant Unit_Number_Type := Get_Source_Unit (Loc);
Uname : constant Unit_Name_Type := Unit_Name (Unum);
E : constant Entity_Id :=
Defining_Entity (Unit (Cunit (Unum)));
begin
pragma Assert (Is_Predefined_Unit (Unum));
-- Loop through entries in RTU table looking for matching entry
for U_Id in RTU_Id'Range loop
-- Here we have a match
if Get_Unit_Name (U_Id) = Uname then
declare
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
-- The RT_Unit_Table entry that may need updating
begin
-- If entry is not set, set it now, and indicate that it was
-- loaded through an explicit context clause.
if No (U.Entity) then
U := (Entity => E,
Uname => Get_Unit_Name (U_Id),
Unum => Unum,
First_Implicit_With => Empty);
end if;
return;
end;
end if;
end loop;
end Set_RTU_Loaded;
-------------------------
-- SPARK_Implicit_Load --
-------------------------
procedure SPARK_Implicit_Load (E : RE_Id) is
begin
pragma Assert (GNATprove_Mode);
-- Force loading of a predefined unit
Discard_Node (RTE (E));
end SPARK_Implicit_Load;
end Rtsfind;
|