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
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S E M --
-- --
-- S p e c --
-- --
-- Copyright (C) 1992-2022, 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. --
-- --
------------------------------------------------------------------------------
--------------------------------------
-- Semantic Analysis: General Model --
--------------------------------------
-- Semantic processing involves 3 phases which are highly intertwined
-- (i.e. mutually recursive):
-- Analysis implements the bulk of semantic analysis such as
-- name analysis and type resolution for declarations,
-- instructions and expressions. The main routine
-- driving this process is procedure Analyze given below.
-- This analysis phase is really a bottom up pass that is
-- achieved during the recursive traversal performed by the
-- Analyze_... procedures implemented in the sem_* packages.
-- For expressions this phase determines unambiguous types
-- and collects sets of possible types where the
-- interpretation is potentially ambiguous.
-- Resolution is carried out only for expressions to finish type
-- resolution that was initiated but not necessarily
-- completed during analysis (because of overloading
-- ambiguities). Specifically, after completing the bottom
-- up pass carried out during analysis for expressions, the
-- Resolve routine (see the spec of sem_res for more info)
-- is called to perform a top down resolution with
-- recursive calls to itself to resolve operands.
-- Expansion if we are not generating code this phase is a no-op.
-- Otherwise this phase expands, i.e. transforms, original
-- declaration, expressions or instructions into simpler
-- structures that can be handled by the back-end. This
-- phase is also in charge of generating code which is
-- implicit in the original source (for instance for
-- default initializations, controlled types, etc.)
-- There are two separate instances where expansion is
-- invoked. For declarations and instructions, expansion is
-- invoked just after analysis since no resolution needs
-- to be performed. For expressions, expansion is done just
-- after resolution. In both cases expansion is done from the
-- bottom up just before the end of Analyze for instructions
-- and declarations or the call to Resolve for expressions.
-- The main routine driving expansion is Expand.
-- See the spec of Expander for more details.
-- To summarize, in normal code generation mode we recursively traverse the
-- abstract syntax tree top-down performing semantic analysis bottom
-- up. For instructions and declarations, before the call to the Analyze
-- routine completes we perform expansion since at that point we have all
-- semantic information needed. For expression nodes, after the call to
-- Analyze terminates we invoke the Resolve routine to transmit top-down
-- the type that was gathered by Analyze which will resolve possible
-- ambiguities in the expression. Just before the call to Resolve
-- terminates, the expression can be expanded since all the semantic
-- information is available at that point.
-- If we are not generating code then the expansion phase is a no-op
-- When generating code there are a number of exceptions to the basic
-- Analysis-Resolution-Expansion model for expressions. The most prominent
-- examples are the handling of default expressions and aggregates.
-----------------------------------------------------------------------
-- Handling of Default and Per-Object Expressions (Spec-Expressions) --
-----------------------------------------------------------------------
-- The default expressions in component declarations and in procedure
-- specifications (but not the ones in object declarations) are quite tricky
-- to handle. The problem is that some processing is required at the point
-- where the expression appears:
-- visibility analysis (including user defined operators)
-- freezing of static expressions
-- but other processing must be deferred until the enclosing entity (record or
-- procedure specification) is frozen:
-- freezing of any other types in the expression expansion
-- generation of code
-- A similar situation occurs with the argument of priority and interrupt
-- priority pragmas that appear in task and protected definition specs and
-- other cases of per-object expressions (see RM 3.8(18)).
-- Another similar case is the conditions in precondition and postcondition
-- pragmas that appear with subprogram specifications rather than in the body.
-- Collectively we call these Spec_Expressions. The routine that performs the
-- special analysis is called Analyze_Spec_Expression.
-- Expansion has to be deferred since you can't generate code for expressions
-- that reference types that have not been frozen yet. As an example, consider
-- the following:
-- type x is delta 0.5 range -10.0 .. +10.0;
-- ...
-- type q is record
-- xx : x := y * z;
-- end record;
-- for x'small use 0.25;
-- The expander is in charge of dealing with fixed-point, and of course the
-- small declaration, which is not too late, since the declaration of type q
-- does *not* freeze type x, definitely affects the expanded code.
-- Another reason that we cannot expand early is that expansion can generate
-- range checks. These range checks need to be inserted not at the point of
-- definition but at the point of use. The whole point here is that the value
-- of the expression cannot be obtained at the point of declaration, only at
-- the point of use.
-- Generally our model is to combine analysis resolution and expansion, but
-- this is the one case where this model falls down. Here is how we patch
-- it up without causing too much distortion to our basic model.
-- A flag (In_Spec_Expression) is set to show that we are in the initial
-- occurrence of a default expression. The analyzer is then called on this
-- expression with the switch set true. Analysis and resolution proceed almost
-- as usual, except that Freeze_Expression will not freeze non-static
-- expressions if this switch is set, and the call to Expand at the end of
-- resolution is skipped. This also skips the code that normally sets the
-- Analyzed flag to True. The result is that when we are done the tree is
-- still marked as unanalyzed, but all types for static expressions are frozen
-- as required, and all entities of variables have been recorded. We then turn
-- off the switch, and later on reanalyze the expression with the switch off.
-- The effect is that this second analysis freezes the rest of the types as
-- required, and generates code but visibility analysis is not repeated since
-- all the entities are marked.
-- The second analysis (the one that generates code) is in the context
-- where the code is required. For a record field default, this is in the
-- initialization procedure for the record and for a subprogram default
-- parameter, it is at the point the subprogram is frozen. For a priority or
-- storage size pragma it is in the context of the Init_Proc for the task or
-- protected object. For a pre/postcondition pragma it is in the body when
-- code for the pragma is generated.
------------------
-- Preanalysis --
------------------
-- For certain kind of expressions, such as aggregates, we need to defer
-- expansion of the aggregate and its inner expressions until after the whole
-- set of expressions appearing inside the aggregate have been analyzed.
-- Consider, for instance the following example:
--
-- (1 .. 100 => new Thing (Function_Call))
--
-- The normal Analysis-Resolution-Expansion mechanism where expansion of the
-- children is performed before expansion of the parent does not work if the
-- code generated for the children by the expander needs to be evaluated
-- repeatedly (for instance in the above aggregate "new Thing (Function_Call)"
-- needs to be called 100 times.)
-- The reason this mechanism does not work is that the expanded code for the
-- children is typically inserted above the parent and thus when the parent
-- gets expanded no re-evaluation takes place. For instance in the case of
-- aggregates if "new Thing (Function_Call)" is expanded before the aggregate
-- the expanded code will be placed outside of the aggregate and when
-- expanding the aggregate the loop from 1 to 100 will not surround the
-- expanded code for "new Thing (Function_Call)".
-- To remedy this situation we introduce a flag that signals whether we want a
-- full analysis (i.e. expansion is enabled) or a preanalysis which performs
-- Analysis and Resolution but no expansion.
-- After the complete preanalysis of an expression has been carried out we
-- can transform the expression and then carry out the full three stage
-- (Analyze-Resolve-Expand) cycle on the transformed expression top-down so
-- that the expansion of inner expressions happens inside the newly generated
-- node for the parent expression.
-- Note that the difference between processing of default expressions and
-- preanalysis of other expressions is that we do carry out freezing in
-- the latter but not in the former (except for static scalar expressions).
-- The routine that performs preanalysis and corresponding resolution is
-- called Preanalyze_And_Resolve and is in Sem_Res.
with Alloc;
with Opt; use Opt;
with Table;
with Types; use Types;
package Sem is
-----------------------------
-- Semantic Analysis Flags --
-----------------------------
Full_Analysis : Boolean := True;
-- Switch to indicate if we are doing a full analysis or a preanalysis.
-- In normal analysis mode (Analysis-Expansion for instructions or
-- declarations) or (Analysis-Resolution-Expansion for expressions) this
-- flag is set. Note that if we are not generating code the expansion phase
-- merely sets the Analyzed flag to True in this case. If we are in
-- Preanalysis mode (see above) this flag is set to False then the
-- expansion phase is skipped.
--
-- When this flag is False the flag Expander_Active is also False (the
-- Expander_Active flag defined in the spec of package Expander tells you
-- whether expansion is currently enabled). You should really regard this
-- as a read only flag.
In_Spec_Expression : Boolean := False;
-- Switch to indicate that we are in a spec-expression, as described
-- above. Note that this must be recursively saved on a Semantics call
-- since it is possible for the analysis of an expression to result in a
-- recursive call (e.g. to get the entity for System.Address as part of the
-- processing of an Address attribute reference). When this switch is True
-- then Full_Analysis above must be False. You should really regard this as
-- a read only flag.
In_Deleted_Code : Boolean := False;
-- If the condition in an if-statement is statically known, the branch
-- that is not taken is analyzed with expansion disabled, and the tree
-- is deleted after analysis. Itypes generated in deleted code must be
-- frozen from start, because the tree on which they depend will not
-- be available at the freeze point.
In_Assertion_Expr : Nat := 0;
-- This is set non-zero if we are within the expression of an assertion
-- pragma or aspect. It is incremented at the start of expanding such an
-- expression, and decremented on completion of expanding that
-- expression. This needs to be a counter, rather than a Boolean, because
-- assertions can contain declare_expressions, which can contain
-- assertions. As with In_Spec_Expression, it must be recursively saved and
-- restored for a Semantics call.
In_Declare_Expr : Nat := 0;
-- This is set non-zero if we are within a declare_expression. It is
-- incremented at the start of expanding such an expression, and
-- decremented on completion of expanding that expression. This needs to be
-- a counter, rather than a Boolean, because declare_expressions can
-- nest. As with In_Spec_Expression, it must be recursively saved and
-- restored for a Semantics call.
In_Compile_Time_Warning_Or_Error : Boolean := False;
-- Switch to indicate that we are validating a pragma Compile_Time_Warning
-- or Compile_Time_Error after the back end has been called (to check these
-- pragmas for size and alignment appropriateness).
In_Default_Expr : Boolean := False;
-- Switch to indicate that we are analyzing a default component expression.
-- As with In_Spec_Expression, it must be recursively saved and restored
-- for a Semantics call.
In_Inlined_Body : Boolean := False;
-- Switch to indicate that we are analyzing and resolving an inlined body.
-- Type checking is disabled in this context, because types are known to be
-- compatible. This avoids problems with private types whose full view is
-- derived from private types.
Inside_A_Generic : Boolean := False;
-- This flag is set if we are processing a generic specification, generic
-- definition, or generic body. When this flag is True the Expander_Active
-- flag is False to disable any code expansion (see package Expander). Only
-- the generic processing can modify the status of this flag, any other
-- client should regard it as read-only.
Inside_Freezing_Actions : Nat := 0;
-- Flag indicating whether we are within a call to Expand_N_Freeze_Actions.
-- Non-zero means we are inside (it is actually a level counter to deal
-- with nested calls). Used to avoid traversing the tree each time a
-- subprogram call is processed to know if we must not clear all constant
-- indications from entities in the current scope. Only the expansion of
-- freezing nodes can modify the status of this flag, any other client
-- should regard it as read-only.
Inside_Class_Condition_Preanalysis : Boolean := False;
-- Flag indicating whether we are preanalyzing a class-wide precondition
-- or postcondition.
Inside_Preanalysis_Without_Freezing : Nat := 0;
-- Flag indicating whether we are preanalyzing an expression performing no
-- freezing. Non-zero means we are inside (it is actually a level counter
-- to deal with nested calls).
Unloaded_Subunits : Boolean := False;
-- This flag is set True if we have subunits that are not loaded. This
-- occurs when the main unit is a subunit, and contains lower level
-- subunits that are not loaded. We use this flag to suppress warnings
-- about unused variables, since these warnings are unreliable in this
-- case. We could perhaps do a more accurate job and retain some of the
-- warnings, but it is quite a tricky job.
-----------------------------------
-- Handling of Check Suppression --
-----------------------------------
-- There are two kinds of suppress checks: scope based suppress checks,
-- and entity based suppress checks.
-- Scope based suppress checks for the predefined checks (from initial
-- command line arguments, or from Suppress pragmas not including an entity
-- name) are recorded in the Sem.Scope_Suppress variable, and all that
-- is necessary is to save the state of this variable on scope entry, and
-- restore it on scope exit. This mechanism allows for fast checking of the
-- scope suppress state without needing complex data structures.
-- Entity based checks, from Suppress/Unsuppress pragmas giving an
-- Entity_Id and scope based checks for non-predefined checks (introduced
-- using pragma Check_Name), are handled as follows. If a suppress or
-- unsuppress pragma is encountered for a given entity, then the flag
-- Checks_May_Be_Suppressed is set in the entity and an entry is made in
-- either the Local_Entity_Suppress stack (case of pragma that appears in
-- other than a package spec), or in the Global_Entity_Suppress stack (case
-- of pragma that appears in a package spec, which is by the rule of RM
-- 11.5(7) applicable throughout the life of the entity). Similarly, a
-- Suppress/Unsuppress pragma for a non-predefined check which does not
-- specify an entity is also stored in one of these stacks.
-- If the Checks_May_Be_Suppressed flag is set in an entity then the
-- procedure is to search first the local and then the global suppress
-- stacks (we search these in reverse order, top element first). The only
-- other point is that we have to make sure that we have proper nested
-- interaction between such specific pragmas and locally applied general
-- pragmas applying to all entities. This is achieved by including in the
-- Local_Entity_Suppress table dummy entries with an empty Entity field
-- that are applicable to all entities. A similar search is needed for any
-- non-predefined check even if no specific entity is involved.
Scope_Suppress : Suppress_Record;
-- This variable contains the current scope based settings of the suppress
-- switches. It is initialized from Suppress_Options in Gnat1drv, and then
-- modified by pragma Suppress. On entry to each scope, the current setting
-- is saved on the scope stack, and then restored on exit from the scope.
-- This record may be rapidly checked to determine the current status of
-- a check if no specific entity is involved or if the specific entity
-- involved is one for which no specific Suppress/Unsuppress pragma has
-- been set (as indicated by the Checks_May_Be_Suppressed flag being set).
-- This scheme is a little complex, but serves the purpose of enabling
-- a very rapid check in the common case where no entity specific pragma
-- applies, and gives the right result when such pragmas are used even
-- in complex cases of nested Suppress and Unsuppress pragmas.
-- The Local_Entity_Suppress and Global_Entity_Suppress stacks are handled
-- using dynamic allocation and linked lists. We do not often use this
-- approach in the compiler (preferring to use extensible tables instead).
-- The reason we do it here is that scope stack entries save a pointer to
-- the current local stack top, which is also saved and restored on scope
-- exit. Furthermore for processing of generics we save pointers to the
-- top of the stack, so that the local stack is actually a tree of stacks
-- rather than a single stack, a structure that is easy to represent using
-- linked lists, but impossible to represent using a single table. Note
-- that because of the generic issue, we never release entries in these
-- stacks, but that's no big deal, since we are unlikely to have a huge
-- number of Suppress/Unsuppress entries in a single compilation.
type Suppress_Stack_Entry;
type Suppress_Stack_Entry_Ptr is access all Suppress_Stack_Entry;
type Suppress_Stack_Entry is record
Entity : Entity_Id;
-- Entity to which the check applies, or Empty for a check that has
-- no entity name (and thus applies to all entities).
Check : Check_Id;
-- Check which is set (can be All_Checks for the All_Checks case)
Suppress : Boolean;
-- Set True for Suppress, and False for Unsuppress
Prev : Suppress_Stack_Entry_Ptr;
-- Pointer to previous entry on stack
Next : Suppress_Stack_Entry_Ptr;
-- All allocated Suppress_Stack_Entry records are chained together in
-- a linked list whose head is Suppress_Stack_Entries, and the Next
-- field is used as a forward pointer (null ends the list). This is
-- used to free all entries in Sem.Init (which will be important if
-- we ever setup the compiler to be reused).
end record;
Suppress_Stack_Entries : Suppress_Stack_Entry_Ptr := null;
-- Pointer to linked list of records (see comments for Next above)
Local_Suppress_Stack_Top : Suppress_Stack_Entry_Ptr;
-- Pointer to top element of local suppress stack. This is the entry that
-- is saved and restored in the scope stack, and also saved for generic
-- body expansion.
Global_Suppress_Stack_Top : Suppress_Stack_Entry_Ptr;
-- Pointer to top element of global suppress stack
procedure Push_Local_Suppress_Stack_Entry
(Entity : Entity_Id;
Check : Check_Id;
Suppress : Boolean);
-- Push a new entry on to the top of the local suppress stack, updating
-- the value in Local_Suppress_Stack_Top;
procedure Push_Global_Suppress_Stack_Entry
(Entity : Entity_Id;
Check : Check_Id;
Suppress : Boolean);
-- Push a new entry on to the top of the global suppress stack, updating
-- the value in Global_Suppress_Stack_Top;
-----------------
-- Scope Stack --
-----------------
-- The scope stack indicates the declarative regions that are currently
-- being processed (analyzed and/or expanded). The scope stack is one of
-- the basic visibility structures in the compiler: entities that are
-- declared in a scope that is currently on the scope stack are immediately
-- visible (leaving aside issues of hiding and overloading).
-- Initially, the scope stack only contains an entry for package Standard.
-- When a compilation unit, subprogram unit, block or declarative region
-- is being processed, the corresponding entity is pushed on the scope
-- stack. It is removed after the processing step is completed. A given
-- entity can be placed several times on the scope stack, for example
-- when processing derived type declarations, freeze nodes, etc. The top
-- of the scope stack is the innermost scope currently being processed.
-- It is obtained through function Current_Scope. After a compilation unit
-- has been processed, the scope stack must contain only Standard.
-- The predicate In_Open_Scopes specifies whether a scope is currently
-- on the scope stack.
-- This model is complicated by the need to compile units on the fly, in
-- the middle of the compilation of other units. This arises when compiling
-- instantiations, and when compiling run-time packages obtained through
-- rtsfind. Given that the scope stack is a single static and global
-- structure (not originally designed for the recursive processing required
-- by rtsfind for example) additional machinery is needed to indicate what
-- is currently being compiled. As a result, the scope stack holds several
-- contiguous sections that correspond to the compilation of a given
-- compilation unit. These sections are separated by distinct occurrences
-- of package Standard. The currently active section of the scope stack
-- goes from the current scope to the first (innermost) occurrence of
-- Standard, which is additionally marked with flag Is_Active_Stack_Base.
-- The basic visibility routine (Find_Direct_Name, in Sem_Ch8) uses this
-- contiguous section of the scope stack to determine whether a given
-- entity is or is not visible at a point. In_Open_Scopes only examines
-- the currently active section of the scope stack.
-- Similar complications arise when processing child instances. These
-- must be compiled in the context of parent instances, and therefore the
-- parents must be pushed on the stack before compiling the child, and
-- removed afterwards. Routines Save_Scope_Stack and Restore_Scope_Stack
-- are used to set/reset the visibility of entities declared in scopes
-- that are currently on the scope stack, and are used when compiling
-- instance bodies on the fly.
-- It is clear in retrospect that all semantic processing and visibility
-- structures should have been fully recursive. The rtsfind mechanism,
-- and the complexities brought about by subunits and by generic child
-- units and their instantiations, have led to a hybrid model that carries
-- more state than one would wish.
type Scope_Action_Kind is (Before, After, Cleanup);
type Scope_Actions is array (Scope_Action_Kind) of List_Id;
-- Transient blocks have three associated actions list, to be inserted
-- before and after the block's statements, and as cleanup actions.
Configuration_Component_Alignment : Component_Alignment_Kind :=
Calign_Default;
-- Used for handling the pragma Component_Alignment in the context of a
-- configuration file.
type Scope_Stack_Entry is record
Entity : Entity_Id;
-- Entity representing the scope
Last_Subprogram_Name : String_Ptr;
-- Pointer to name of last subprogram body in this scope. Used for
-- testing proper alpha ordering of subprogram bodies in scope.
Save_Scope_Suppress : Suppress_Record;
-- Save contents of Scope_Suppress on entry
Save_Local_Suppress_Stack_Top : Suppress_Stack_Entry_Ptr;
-- Save contents of Local_Suppress_Stack on entry to restore on exit
Save_Check_Policy_List : Node_Id;
-- Save contents of Check_Policy_List on entry to restore on exit. The
-- Check_Policy pragmas are chained with Check_Policy_List pointing to
-- the most recent entry. This list is searched starting here, so that
-- the search finds the most recent applicable entry. When we restore
-- Check_Policy_List on exit from the scope, the effect is to remove
-- all entries set in the scope being exited.
Save_Default_Storage_Pool : Node_Id;
-- Save contents of Default_Storage_Pool on entry to restore on exit
Save_SPARK_Mode : SPARK_Mode_Type;
-- Setting of SPARK_Mode on entry to restore on exit
Save_SPARK_Mode_Pragma : Node_Id;
-- Setting of SPARK_Mode_Pragma on entry to restore on exit
Save_No_Tagged_Streams : Node_Id;
-- Setting of No_Tagged_Streams to restore on exit
Save_Default_SSO : Character;
-- Setting of Default_SSO on entry to restore on exit
Save_Uneval_Old : Character;
-- Setting of Uneval_Old on entry to restore on exit
Is_Transient : Boolean;
-- Marks transient scopes (see Exp_Ch7 body for details)
Previous_Visibility : Boolean;
-- Used when installing the parent(s) of the current compilation unit.
-- The parent may already be visible because of an ongoing compilation,
-- and the proper visibility must be restored on exit. The flag is
-- typically needed when the context of a child unit requires
-- compilation of a sibling. In other cases the flag is set to False.
-- See Sem_Ch10 (Install_Parents, Remove_Parents).
Node_To_Be_Wrapped : Node_Id;
-- Only used in transient scopes. Records the node that will be wrapped
-- by the transient block.
Actions_To_Be_Wrapped : Scope_Actions;
-- Actions that have to be inserted at the start, at the end, or as
-- cleanup actions of a transient block. Used to temporarily hold these
-- actions until the block is created, at which time the actions are
-- moved to the block.
Pending_Freeze_Actions : List_Id;
-- Used to collect freeze entity nodes and associated actions that are
-- generated in an inner context but need to be analyzed outside, such
-- as records and initialization procedures. On exit from the scope,
-- this list of actions is inserted before the scope construct and
-- analyzed to generate the corresponding freeze processing and
-- elaboration of other associated actions.
First_Use_Clause : Node_Id;
-- Head of list of Use_Clauses in current scope. The list is built when
-- the declarations in the scope are processed. The list is traversed
-- on scope exit to undo the effect of the use clauses.
Component_Alignment_Default : Component_Alignment_Kind;
-- Component alignment to be applied to any record or array types that
-- are declared for which a specific component alignment pragma does not
-- set the alignment.
Is_Active_Stack_Base : Boolean;
-- Set to true only when entering the scope for Standard_Standard from
-- from within procedure Semantics. Indicates the base of the current
-- active set of scopes. Needed by In_Open_Scopes to handle cases where
-- Standard_Standard can be pushed anew on the scope stack to start a
-- new active section (see comment above).
Locked_Shared_Objects : Elist_Id;
-- List of shared passive protected objects that have been locked in
-- this transient scope (always No_Elist for non-transient scopes).
end record;
package Scope_Stack is new Table.Table (
Table_Component_Type => Scope_Stack_Entry,
Table_Index_Type => Int,
Table_Low_Bound => 0,
Table_Initial => Alloc.Scope_Stack_Initial,
Table_Increment => Alloc.Scope_Stack_Increment,
Table_Name => "Sem.Scope_Stack");
-----------------
-- Subprograms --
-----------------
procedure Initialize;
-- Initialize internal tables
procedure Lock;
-- Lock internal tables before calling back end
procedure Unlock;
-- Unlock internal tables
procedure Semantics (Comp_Unit : Node_Id);
-- This procedure is called to perform semantic analysis on the specified
-- node which is the N_Compilation_Unit node for the unit.
procedure Analyze (N : Node_Id);
procedure Analyze (N : Node_Id; Suppress : Check_Id);
-- This is the recursive procedure that is applied to individual nodes of
-- the tree, starting at the top level node (compilation unit node) and
-- then moving down the tree in a top down traversal. It calls individual
-- routines with names Analyze_xxx to analyze node xxx. Each of these
-- routines is responsible for calling Analyze on the components of the
-- subtree.
--
-- Note: In the case of expression components (nodes whose Nkind is in
-- N_Subexpr), the call to Analyze does not complete the semantic analysis
-- of the node, since the type resolution cannot be completed until the
-- complete context is analyzed. The completion of the type analysis occurs
-- in the corresponding Resolve routine (see Sem_Res).
--
-- Note: for integer and real literals, the analyzer sets the flag to
-- indicate that the result is a static expression. If the expander
-- generates a literal that does NOT correspond to a static expression,
-- e.g. by folding an expression whose value is known at compile time,
-- but is not technically static, then the caller should reset the
-- Is_Static_Expression flag after analyzing but before resolving.
--
-- If the Suppress argument is present, then the analysis is done
-- with the specified check suppressed (can be All_Checks to suppress
-- all checks).
procedure Analyze_List (L : List_Id);
procedure Analyze_List (L : List_Id; Suppress : Check_Id);
-- Analyzes each element of a list. If the Suppress argument is present,
-- then the analysis is done with the specified check suppressed (can
-- be All_Checks to suppress all checks).
procedure Copy_Suppress_Status
(C : Check_Id;
From : Entity_Id;
To : Entity_Id);
-- If From is an entity for which check C is explicitly suppressed
-- then also explicitly suppress the corresponding check in To.
procedure Insert_List_After_And_Analyze
(N : Node_Id; L : List_Id);
-- Inserts list L after node N using Nlists.Insert_List_After, and then,
-- after this insertion is complete, analyzes all the nodes in the list,
-- including any additional nodes generated by this analysis. If the list
-- is empty or No_List, the call has no effect.
procedure Insert_List_Before_And_Analyze
(N : Node_Id; L : List_Id);
-- Inserts list L before node N using Nlists.Insert_List_Before, and then,
-- after this insertion is complete, analyzes all the nodes in the list,
-- including any additional nodes generated by this analysis. If the list
-- is empty or No_List, the call has no effect.
procedure Insert_After_And_Analyze
(N : Node_Id; M : Node_Id);
procedure Insert_After_And_Analyze
(N : Node_Id; M : Node_Id; Suppress : Check_Id);
-- Inserts node M after node N and then after the insertion is complete,
-- analyzes the inserted node and all nodes that are generated by
-- this analysis. If the node is empty, the call has no effect. If the
-- Suppress argument is present, then the analysis is done with the
-- specified check suppressed (can be All_Checks to suppress all checks).
procedure Insert_Before_And_Analyze
(N : Node_Id; M : Node_Id);
procedure Insert_Before_And_Analyze
(N : Node_Id; M : Node_Id; Suppress : Check_Id);
-- Inserts node M before node N and then after the insertion is complete,
-- analyzes the inserted node and all nodes that could be generated by
-- this analysis. If the node is empty, the call has no effect. If the
-- Suppress argument is present, then the analysis is done with the
-- specified check suppressed (can be All_Checks to suppress all checks).
procedure Insert_Before_First_Source_Declaration
(Stmt : Node_Id;
Decls : List_Id);
-- Insert node Stmt before the first source declaration of the related
-- subprogram's body. If no such declaration exists, Stmt becomes the last
-- declaration.
function External_Ref_In_Generic (E : Entity_Id) return Boolean;
-- Return True if we are in the context of a generic and E is
-- external (more global) to it.
procedure Enter_Generic_Scope (S : Entity_Id);
-- Called each time a Generic subprogram or package scope is entered. S is
-- the entity of the scope.
--
-- ??? At the moment, only called for package specs because this mechanism
-- is only used for avoiding freezing of external references in generics
-- and this can only be an issue if the outer generic scope is a package
-- spec (otherwise all external entities are already frozen)
procedure Exit_Generic_Scope (S : Entity_Id);
-- Called each time a Generic subprogram or package scope is exited. S is
-- the entity of the scope.
--
-- ??? At the moment, only called for package specs exit.
function Explicit_Suppress (E : Entity_Id; C : Check_Id) return Boolean;
-- This function returns True if an explicit pragma Suppress for check C
-- is present in the package defining E.
function Preanalysis_Active return Boolean;
pragma Inline (Preanalysis_Active);
-- Determine whether preanalysis is active at the point of invocation
procedure Preanalyze (N : Node_Id);
-- Performs a preanalysis of node N. During preanalysis no expansion is
-- carried out for N or its children. See above for more info on
-- preanalysis.
generic
with procedure Action (Item : Node_Id);
procedure Walk_Library_Items;
-- Primarily for use by CodePeer and GNATprove. Must be called after
-- semantic analysis (and expansion in the case of CodePeer) are complete.
-- Walks each relevant library item, calling Action for each, in an order
-- such that one will not run across forward references. Each Item passed
-- to Action is the declaration or body of a library unit, including
-- generics and renamings. The first item is the N_Package_Declaration node
-- for package Standard. Bodies are not included, except for the main unit
-- itself, which always comes last.
--
-- Item is never a subunit
--
-- Item is never an instantiation. Instead, the instance declaration is
-- passed, and (if the instantiation is the main unit), the instance body.
------------------------
-- Debugging Routines --
------------------------
function ss (Index : Int) return Scope_Stack_Entry;
pragma Export (Ada, ss);
-- "ss" = "scope stack"; returns the Index'th entry in the Scope_Stack
function sst return Scope_Stack_Entry;
pragma Export (Ada, sst);
-- "sst" = "scope stack top"; same as ss(Scope_Stack.Last)
end Sem;
|