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
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S E M _ E V A L --
-- --
-- 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. --
-- --
------------------------------------------------------------------------------
-- This package contains various subprograms involved in compile time
-- evaluation of expressions and checks for staticness of expressions and
-- types. It also contains the circuitry for checking for violations of pure
-- and preelaborated conditions (this naturally goes here, since these rules
-- involve consideration of staticness).
-- Note: the static evaluation for attributes is found in Sem_Attr even though
-- logically it belongs here. We have done this so that it is easier to add
-- new attributes to GNAT.
with Types; use Types;
with Uintp; use Uintp;
with Urealp; use Urealp;
package Sem_Eval is
------------------------------------
-- Handling of Static Expressions --
------------------------------------
-- This package contains a set of routines that process individual
-- subexpression nodes with the objective of folding (precomputing) the
-- value of static expressions that are known at compile time and properly
-- computing the setting of two flags that appear in every subexpression
-- node:
-- Is_Static_Expression
-- True for static expressions, as defined in RM-4.9.
-- Raises_Constraint_Error
-- This flag indicates that it is known at compile time that the
-- evaluation of an expression raises constraint error. If the
-- expression is static, and this flag is off, then it is also known at
-- compile time that the expression does not raise constraint error
-- (i.e. the flag is accurate for static expressions, and conservative
-- for non-static expressions.
-- See also Is_OK_Static_Expression, which is True for static
-- expressions that do not raise Constraint_Error. This is used in most
-- legality checks, because static expressions that raise Constraint_Error
-- are usually illegal.
-- See also Compile_Time_Known_Value, which is True for an expression whose
-- value is known at compile time. In this case, the expression is folded
-- to a literal or to a constant that is itself (recursively) either a
-- literal or a constant
-- Is_[OK_]Static_Expression are used for legality checks, whereas
-- Compile_Time_Known_Value is used for optimization purposes.
-- When we are analyzing and evaluating static expressions, we propagate
-- both flags. Usually if a subexpression raises a Constraint_Error, then
-- so will its parent expression, and Raise_Constraint_Error will be
-- propagated to this parent. The exception is conditional cases like
-- (True or else 1/0 = 0), which results in an expression that has the
-- Is_Static_Expression flag True, and Raises_Constraint_Error False. Even
-- though 1/0 would raise an exception, the right operand is never actually
-- executed, so the expression as a whole does not raise CE.
-- Finally, the case of static predicates. These are applied only to entire
-- expressions, not to subexpressions, so we do not have the case of having
-- to propagate this information. We handle this case simply by resetting
-- the Is_Static_Expression flag if a static predicate fails. Note that we
-- can't use this simpler approach for the constraint error case because of
-- the (True or else 1/0 = 0) example discussed above.
-------------------------------
-- Compile-Time Known Values --
-------------------------------
-- For most legality checking purposes the flag Is_Static_Expression
-- defined in Sinfo should be used. This package also provides a routine
-- called Is_OK_Static_Expression which in addition of checking that an
-- expression is static in the RM 4.9 sense, it checks that the expression
-- does not raise constraint error. In fact for certain legality checks not
-- only do we need to ascertain that the expression is static, but we must
-- also ensure that it does not raise constraint error.
-- Neither of Is_Static_Expression and Is_OK_Static_Expression should be
-- used for compile time evaluation purposes. In fact certain expression
-- whose value may be known at compile time are not static in the RM 4.9
-- sense. A typical example is:
-- C : constant Integer := Record_Type'Size;
-- The expression 'C' is not static in the technical RM sense, but for many
-- simple record types, the size is in fact known at compile time. When we
-- are trying to perform compile time constant folding (for instance for
-- expressions like C + 1), Is_Static_Expression or Is_OK_Static_Expression
-- are not the right functions to test if folding is possible. Instead, we
-- use Compile_Time_Known_Value. All static expressions that do not raise
-- constraint error (i.e. those for which Is_OK_Static_Expression is true)
-- are known at compile time, but as shown by the above example, there may
-- be cases of non-static expressions which are known at compile time.
-----------------
-- Subprograms --
-----------------
procedure Check_Expression_Against_Static_Predicate
(Expr : Node_Id;
Typ : Entity_Id;
Static_Failure_Is_Error : Boolean := False);
-- Determine whether an arbitrary expression satisfies the static predicate
-- of a type. The routine does nothing if Expr is not known at compile time
-- or Typ lacks a static predicate; otherwise it may emit a warning if the
-- expression is prohibited by the predicate, or if Static_Failure_Is_Error
-- is True then an error will be flagged. If the expression is a static
-- expression, it fails a predicate that was not explicitly stated to be
-- a dynamic predicate, and Static_Failure_Is_Error is False, then an
-- additional warning is given, and the flag Is_Static_Expression is reset
-- on Expr.
procedure Check_Non_Static_Context (N : Node_Id);
-- Deals with the special check required for a static expression that
-- appears in a non-static context, i.e. is not part of a larger static
-- expression (see RM 4.9(35)), i.e. the value of the expression must be
-- within the base range of the base type of its expected type. A check is
-- also made for expressions that are inside the base range, but outside
-- the range of the expected subtype (this is a warning message rather than
-- an illegality).
--
-- Note: most cases of non-static context checks are handled within
-- Sem_Eval itself, including all cases of expressions at the outer level
-- (i.e. those that are not a subexpression). The outside customers for
-- this procedure are Sem_Aggr, Sem_Attr (because Eval_Attribute is there)
-- and Sem_Res (for a special case arising from ranges, see Resolve_Range).
--
-- Note: this procedure is also called by GNATprove on real literals
-- that are not sub-expressions of static expressions, to convert them to
-- machine numbers, as GNATprove cannot perform this conversion contrary
-- to gigi.
procedure Check_String_Literal_Length (N : Node_Id; Ttype : Entity_Id);
-- N is either a string literal, or a constraint error node. In the latter
-- case, the situation is already dealt with, and the call has no effect.
-- In the former case, if the target type, Ttyp is constrained, then a
-- check is made to see if the string literal is of appropriate length.
function Checking_Potentially_Static_Expression return Boolean;
-- Returns True if the checking for potentially static expressions is
-- enabled; otherwise returns False.
procedure Set_Checking_Potentially_Static_Expression (Value : Boolean);
-- Enables checking for potentially static expressions if Value is True,
-- and disables such checking if Value is False.
type Compare_Result is (LT, LE, EQ, GT, GE, NE, Unknown);
subtype Compare_GE is Compare_Result range EQ .. GE;
subtype Compare_LE is Compare_Result range LT .. EQ;
-- Result subtypes for Compile_Time_Compare subprograms
function Compile_Time_Compare
(L, R : Node_Id;
Assume_Valid : Boolean) return Compare_Result;
pragma Inline (Compile_Time_Compare);
-- Given two expression nodes, finds out whether it can be determined at
-- compile time how the runtime values will compare. An Unknown result
-- means that the result of a comparison cannot be determined at compile
-- time, otherwise the returned result indicates the known result of the
-- comparison, given as tightly as possible (i.e. EQ or LT is preferred
-- returned value to LE). If Assume_Valid is true, the result reflects
-- the result of assuming that entities involved in the comparison have
-- valid representations. If Assume_Valid is false, then the base type of
-- any involved entity is used so that no assumption of validity is made.
function Compile_Time_Compare
(L, R : Node_Id;
Diff : access Uint;
Assume_Valid : Boolean;
Rec : Boolean := False) return Compare_Result;
-- This version of Compile_Time_Compare returns extra information if the
-- result is GT or LT. In these cases, if the magnitude of the difference
-- can be determined at compile time, this (positive) magnitude is returned
-- in Diff.all. If the magnitude of the difference cannot be determined
-- then Diff.all contains No_Uint on return. Rec is a parameter that is set
-- True for a recursive call from within Compile_Time_Compare to avoid some
-- infinite recursion cases. It should never be set by a client.
function Compile_Time_Known_Bounds (T : Entity_Id) return Boolean;
-- If T is an array whose index bounds are all known at compile time, then
-- True is returned. If T is not an array type, or one or more of its index
-- bounds is not known at compile time, then False is returned.
function Compile_Time_Known_Value (Op : Node_Id) return Boolean;
-- Returns true if Op is an expression not raising Constraint_Error whose
-- value is known at compile time and for which a call to Expr_Value can
-- be used to determine this value. This is always true if Op is a static
-- expression, but can also be true for expressions which are technically
-- non-static but which are in fact known at compile time. Some examples of
-- such expressions are the static lower bound of a non-static range or the
-- value of a constant object whose initial value is itself compile time
-- known in the sense of this routine. Note that this routine is defended
-- against unanalyzed expressions. Such expressions will not cause a
-- blowup, they may cause pessimistic (i.e. False) results to be returned.
-- In general we take a pessimistic view. False does not mean the value
-- could not be known at compile time, but True means that absolutely
-- definition it is known at compile time and it is safe to call
-- Expr_Value[_XX] on the expression Op.
--
-- Note that we don't define precisely the set of expressions that return
-- True. Callers should not make any assumptions regarding the value that
-- is returned for non-static expressions. Functional behavior should never
-- be affected by whether a given non-static expression returns True or
-- False when this function is called. In other words this is purely for
-- efficiency optimization purposes. The code generated can often be more
-- efficient with compile time known values, e.g. range analysis for the
-- purpose of removing checks is more effective if we know precise bounds.
-- WARNING: There is a matching C declaration of this subprogram in fe.h
function CRT_Safe_Compile_Time_Known_Value (Op : Node_Id) return Boolean;
-- In the case of configurable run-times, there may be an issue calling
-- Compile_Time_Known_Value with non-static expressions where the legality
-- of the program is not well-defined. Consider this example:
--
-- X := B ** C;
--
-- Now if C is compile time known, and has the value 4, then inline code
-- can be generated at compile time, instead of calling a run-time routine.
-- That's fine in the normal case, but when we have a configurable run-time
-- the run-time routine may not be available. This means that the program
-- will be rejected if C is not known at compile time. We don't want the
-- legality of a program to depend on how clever the implementation of this
-- function is. If the run-time in use lacks the exponentiation routine,
-- then what we say is that exponentiation is permitted if the exponent is
-- officially static and has a value in the range 0 .. 4.
--
-- In a case like this, we use CRT_Safe_Compile_Time_Known_Value to avoid
-- this effect. This routine will return False for a non-static expression
-- if we are in configurable run-time mode, even if the expression would
-- normally be considered compile-time known.
function Expr_Rep_Value (N : Node_Id) return Uint;
-- This is identical to Expr_Value, except in the case of enumeration
-- literals of types for which an enumeration representation clause has
-- been given, in which case it returns the representation value rather
-- than the pos value. This is the value that is needed for generating code
-- sequences, while the Expr_Value value is appropriate for compile time
-- constraint errors or getting the logical value. Note that this function
-- does NOT concern itself with biased values, if the caller needs a
-- properly biased value, the subtraction of the bias must be handled
-- explicitly.
function Expr_Value (N : Node_Id) return Uint;
-- Returns the folded value of the expression N. This function is called in
-- instances where it has already been determined that the expression is
-- static or its value is compile time known (Compile_Time_Known_Value (N)
-- returns True). This version is used for integer values, and enumeration
-- or character literals. In the latter two cases, the value returned is
-- the Pos value in the relevant enumeration type. It can also be used for
-- fixed-point values, in which case it returns the corresponding integer
-- value, but it cannot be used for floating-point values. Finally, it can
-- also be used for the Null access value, as well as for the result of an
-- unchecked conversion of the aforementioned handled values.
function Expr_Value_E (N : Node_Id) return Entity_Id;
-- Returns the folded value of the expression. This function is called in
-- instances where it has already been determined that the expression is
-- static or its value known at compile time. This version is used for
-- enumeration types and returns the corresponding enumeration literal.
function Expr_Value_R (N : Node_Id) return Ureal;
-- Returns the folded value of the expression. This function is called in
-- instances where it has already been determined that the expression is
-- static or its value known at compile time. This version is used for real
-- values (including both the floating-point and fixed-point cases). In the
-- case of a fixed-point type, the real value is returned (cf above version
-- returning Uint).
function Expr_Value_S (N : Node_Id) return Node_Id;
-- Returns the folded value of the expression. This function is called
-- in instances where it has already been determined that the expression
-- is static or its value is known at compile time. This version is used
-- for string types and returns the corresponding N_String_Literal node.
procedure Eval_Actual (N : Node_Id);
procedure Eval_Allocator (N : Node_Id);
procedure Eval_Arithmetic_Op (N : Node_Id);
procedure Eval_Call (N : Node_Id);
procedure Eval_Case_Expression (N : Node_Id);
procedure Eval_Character_Literal (N : Node_Id);
procedure Eval_Concatenation (N : Node_Id);
procedure Eval_Entity_Name (N : Node_Id);
procedure Eval_If_Expression (N : Node_Id);
procedure Eval_Indexed_Component (N : Node_Id);
procedure Eval_Integer_Literal (N : Node_Id);
procedure Eval_Logical_Op (N : Node_Id);
procedure Eval_Membership_Op (N : Node_Id);
procedure Eval_Named_Integer (N : Node_Id);
procedure Eval_Named_Real (N : Node_Id);
procedure Eval_Op_Expon (N : Node_Id);
procedure Eval_Op_Not (N : Node_Id);
procedure Eval_Real_Literal (N : Node_Id);
procedure Eval_Relational_Op (N : Node_Id);
procedure Eval_Selected_Component (N : Node_Id);
procedure Eval_Shift (N : Node_Id);
procedure Eval_Short_Circuit (N : Node_Id);
procedure Eval_Slice (N : Node_Id);
procedure Eval_String_Literal (N : Node_Id);
procedure Eval_Qualified_Expression (N : Node_Id);
procedure Eval_Type_Conversion (N : Node_Id);
procedure Eval_Unary_Op (N : Node_Id);
procedure Eval_Unchecked_Conversion (N : Node_Id);
procedure Flag_Non_Static_Expr (Msg : String; Expr : Node_Id);
-- This procedure is called after it has been determined that Expr is not
-- static when it is required to be. Msg is the text of a message that
-- explains the error. This procedure checks if an error is already posted
-- on Expr, if so, it does nothing unless All_Errors_Mode is set in which
-- case this flag is ignored. Otherwise the given message is posted using
-- Error_Msg_F, and then Why_Not_Static is called on Expr to generate
-- additional messages. The string given as Msg should end with ! to make
-- it an unconditional message, to ensure that if it is posted, the entire
-- set of messages is all posted.
procedure Fold_Str (N : Node_Id; Val : String_Id; Static : Boolean);
-- Rewrite N with a new N_String_Literal node as the result of the compile
-- time evaluation of the node N. Val is the resulting string value from
-- the folding operation. The Is_Static_Expression flag is set in the
-- result node. The result is fully analyzed and resolved. Static indicates
-- whether the result should be considered static or not (True = consider
-- static). The point here is that normally all string literals are static,
-- but if this was the result of some sequence of evaluation where values
-- were known at compile time but not static, then the result is not
-- static. The call has no effect if Raises_Constraint_Error (N) is True,
-- since there is no point in folding if we have an error.
procedure Fold_Uint (N : Node_Id; Val : Uint; Static : Boolean);
-- Rewrite N with a (N_Integer_Literal, N_Identifier, N_Character_Literal)
-- node as the result of the compile time evaluation of the node N. Val is
-- the result in the integer case and is the position of the literal in the
-- literals list for the enumeration case. Is_Static_Expression is set True
-- in the result node. The result is fully analyzed/resolved. Static
-- indicates whether the result should be considered static or not (True =
-- consider static). The point here is that normally all integer literals
-- are static, but if this was the result of some sequence of evaluation
-- where values were known at compile time but not static, then the result
-- is not static. The call has no effect if Raises_Constraint_Error (N) is
-- True, since there is no point in folding if we have an error.
procedure Fold_Ureal (N : Node_Id; Val : Ureal; Static : Boolean);
-- Rewrite N with a new N_Real_Literal node as the result of the compile
-- time evaluation of the node N. Val is the resulting real value from the
-- folding operation. The Is_Static_Expression flag is set in the result
-- node. The result is fully analyzed and result. Static indicates whether
-- the result should be considered static or not (True = consider static).
-- The point here is that normally all string literals are static, but if
-- this was the result of some sequence of evaluation where values were
-- known at compile time but not static, then the result is not static.
-- The call has no effect if Raises_Constraint_Error (N) is True, since
-- there is no point in folding if we have an error.
procedure Fold (N : Node_Id);
-- Rewrite N with the relevant value if Compile_Time_Known_Value (N) is
-- True, otherwise a no-op.
function Is_In_Range
(N : Node_Id;
Typ : Entity_Id;
Assume_Valid : Boolean := False;
Fixed_Int : Boolean := False;
Int_Real : Boolean := False) return Boolean;
-- Returns True if it can be guaranteed at compile time that expression
-- N is known to be in range of the subtype Typ. A result of False does
-- not mean that the expression is out of range, merely that it cannot be
-- determined at compile time that it is in range. If Typ is a floating
-- point type or Int_Real is set, any integer value is treated as though it
-- was a real value (i.e. the underlying real value is used). In this case
-- we use the corresponding real value, both for the bounds of Typ, and for
-- the value of the expression N. If Typ is a fixed type or a discrete type
-- and Int_Real is False but flag Fixed_Int is True then any fixed-point
-- value is treated as though it was discrete value (i.e. the underlying
-- integer value is used). In this case we use the corresponding integer
-- value, both for the bounds of Typ, and for the value of the expression
-- N. If Typ is a discrete type and Fixed_Int as well as Int_Real are
-- false, integer values are used throughout.
--
-- If Assume_Valid is set True, then N is always assumed to contain a valid
-- value. If Assume_Valid is set False, then N may be invalid (unless there
-- is some independent way of knowing that it is valid, i.e. either it is
-- an entity with Is_Known_Valid set, or Assume_No_Invalid_Values is True.
function Is_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean;
-- Returns True if it can guarantee that Lo .. Hi is a null range. If it
-- cannot (because the value of Lo or Hi is not known at compile time) then
-- it returns False.
function Is_OK_Static_Expression (N : Node_Id) return Boolean;
-- An OK static expression is one that is static in the RM definition sense
-- and which does not raise constraint error. For most legality checking
-- purposes you should use Is_Static_Expression. For those legality checks
-- where the expression N should not raise constraint error use this
-- routine. This routine is *not* to be used in contexts where the test is
-- for compile time evaluation purposes. Use Compile_Time_Known_Value
-- instead (see section on "Compile-Time Known Values" above).
function Is_OK_Static_Range (N : Node_Id) return Boolean;
-- Determines if range is static, as defined in RM 4.9(26), and also checks
-- that neither bound of the range raises constraint error, thus ensuring
-- that both bounds of the range are compile-time evaluable (i.e. do not
-- raise constraint error). A result of true means that the bounds are
-- compile time evaluable. A result of false means they are not (either
-- because the range is not static, or because one or the other bound
-- raises CE).
function Is_OK_Static_Subtype (Typ : Entity_Id) return Boolean;
-- Determines whether a subtype fits the definition of an Ada static
-- subtype as given in (RM 4.9(26)) with the additional check that neither
-- bound raises constraint error (meaning that Expr_Value[_R|S] can be used
-- on these bounds).
--
-- This differs from Is_Static_Subtype in that it includes the constraint
-- error checks, which are missing from Is_Static_Subtype.
function Is_Out_Of_Range
(N : Node_Id;
Typ : Entity_Id;
Assume_Valid : Boolean := False;
Fixed_Int : Boolean := False;
Int_Real : Boolean := False) return Boolean;
-- Returns True if it can be guaranteed at compile time that expression is
-- known to be out of range of the subtype Typ. True is returned if Typ is
-- a scalar type, and the value of N can be determined to be outside the
-- range of Typ. A result of False does not mean that the expression is in
-- range, but rather merely that it cannot be determined at compile time
-- that it is out of range. The parameters Assume_Valid, Fixed_Int, and
-- Int_Real are as described for Is_In_Range above.
function Is_Static_Subtype (Typ : Entity_Id) return Boolean;
-- Determines whether a subtype fits the definition of an Ada static
-- subtype as given in (RM 4.9(26)).
--
-- This differs from Is_OK_Static_Subtype (which is what must be used by
-- clients) in that it does not care whether the bounds raise a constraint
-- error exception or not. Used for checking whether expressions are static
-- in the 4.9 sense (without worrying about exceptions).
function Is_Statically_Unevaluated (Expr : Node_Id) return Boolean;
-- This function returns True if the given expression Expr is statically
-- unevaluated, as defined in (RM 4.9 (32.1-32.6)).
function In_Subrange_Of
(T1 : Entity_Id;
T2 : Entity_Id;
Fixed_Int : Boolean := False) return Boolean;
-- Returns True if it can be guaranteed at compile time that the range of
-- values for scalar type T1 are always in the range of scalar type T2. A
-- result of False does not mean that T1 is not in T2's subrange, only that
-- it cannot be determined at compile time. Flag Fixed_Int is used as in
-- routine Is_In_Range above.
function Machine_Number
(Typ : Entity_Id;
Val : Ureal;
N : Node_Id) return Ureal;
-- Return the machine number of Typ corresponding to the specified Val as
-- per RM 4.9(38/2). N is a node only used to post warnings.
function Not_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean;
-- Returns True if it can guarantee that Lo .. Hi is not a null range. If
-- it cannot (because the value of Lo or Hi is not known at compile time)
-- then it returns False.
function Predicates_Compatible (T1, T2 : Entity_Id) return Boolean;
-- In Ada 2012, subtypes are statically compatible if the predicates are
-- compatible as well. This function performs the required check that
-- predicates are compatible. Split from Subtypes_Statically_Compatible
-- so that it can be used in specializing error messages.
function Predicates_Match (T1, T2 : Entity_Id) return Boolean;
-- In Ada 2012, subtypes statically match if their predicates match as
-- as well. This function performs the required check that predicates
-- match. Separated out from Subtypes_Statically_Match so that it can
-- be used in specializing error messages.
function Subtypes_Statically_Compatible
(T1 : Entity_Id;
T2 : Entity_Id;
Formal_Derived_Matching : Boolean := False) return Boolean;
-- Returns true if the subtypes are unconstrained or the constraint on
-- on T1 is statically compatible with T2 (as defined by 4.9.1(4)).
-- Otherwise returns false. Formal_Derived_Matching indicates whether
-- the type T1 is a generic actual being checked against ancestor T2
-- in a formal derived type association.
function Subtypes_Statically_Match
(T1 : Entity_Id;
T2 : Entity_Id;
Formal_Derived_Matching : Boolean := False) return Boolean;
-- Determine whether two types T1, T2, which have the same base type,
-- are statically matching subtypes (RM 4.9.1(1-2)). Also includes the
-- extra GNAT rule that object sizes must match (this can be false for
-- types that match in the RM sense because of use of 'Object_Size),
-- except when testing a generic actual T1 against an ancestor T2 in a
-- formal derived type association (indicated by Formal_Derived_Matching).
procedure Test_Comparison
(Op : Node_Id;
Assume_Valid : Boolean;
True_Result : out Boolean;
False_Result : out Boolean);
-- Determine the outcome of evaluating comparison operator Op using routine
-- Compile_Time_Compare. Assume_Valid should be set when the operands are
-- to be assumed valid. Flags True_Result and False_Result are set when the
-- comparison evaluates to True or False respectively.
procedure Why_Not_Static (Expr : Node_Id);
-- This procedure may be called after generating an error message that
-- complains that something is non-static. If it finds good reasons, it
-- generates one or more error messages pointing the appropriate offending
-- component of the expression. If no good reasons can be figured out, then
-- no messages are generated. The expectation here is that the caller has
-- already issued a message complaining that the expression is non-static.
-- Note that this message should be placed using Error_Msg_F or
-- Error_Msg_FE, so that it will sort before any messages placed by this
-- call. Note that it is fine to call Why_Not_Static with something that
-- is not an expression, and usually this has no effect, but in some cases
-- (N_Parameter_Association or N_Range), it makes sense for the internal
-- recursive calls.
--
-- Note that these messages are not continuation messages, instead they are
-- separate unconditional messages, marked with '!'. The reason for this is
-- that they can be posted at a different location from the main message as
-- documented above ("appropriate offending component"), and continuation
-- messages must always point to the same location as the parent message.
procedure Initialize;
-- Initializes the internal data structures
private
-- The Eval routines are all marked inline, since they are called once
pragma Inline (Eval_Actual);
pragma Inline (Eval_Allocator);
pragma Inline (Eval_Character_Literal);
pragma Inline (Eval_If_Expression);
pragma Inline (Eval_Indexed_Component);
pragma Inline (Eval_Named_Integer);
pragma Inline (Eval_Named_Real);
pragma Inline (Eval_Real_Literal);
pragma Inline (Eval_Shift);
pragma Inline (Eval_Slice);
pragma Inline (Eval_String_Literal);
pragma Inline (Eval_Unchecked_Conversion);
pragma Inline (Is_OK_Static_Expression);
pragma Inline (Machine_Number);
end Sem_Eval;
|