summaryrefslogtreecommitdiff
path: root/gcc/ada/checks.ads
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/checks.ads')
-rw-r--r--gcc/ada/checks.ads155
1 files changed, 132 insertions, 23 deletions
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index 8ccafdea7c0..d6ad2bde5a5 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2002 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- --
@@ -71,9 +71,8 @@ package Checks is
-- operate anyway since they may generate useful compile time warnings.
procedure Apply_Access_Check (N : Node_Id);
- -- Determines whether an expression node should be flagged as needing
- -- a runtime access check. If the node requires such a check, the
- -- Do_Access_Check flag is turned on.
+ -- Determines whether an expression node requires a runtime access
+ -- check and if so inserts the appropriate run-time check.
procedure Apply_Accessibility_Check (N : Node_Id; Typ : Entity_Id);
-- Given a name N denoting an access parameter, emits a run-time
@@ -171,6 +170,81 @@ package Checks is
-- Thus the significance of OK being False on return is that no
-- useful information is available on the range of the expression.
+ -------------------------------------------------------
+ -- Control and Optimization of Range/Overflow Checks --
+ -------------------------------------------------------
+
+ -- Range checks are controlled by the Do_Range_Check flag. The front end
+ -- is responsible for setting this flag in relevant nodes. Originally
+ -- the back end generated all corresponding range checks. But later on
+ -- we decided to generate all range checks in the front end. We are now
+ -- in the transitional phase where some of these checks are still done
+ -- by the back end, but many are done by the front end.
+
+ -- Overflow checks are similarly controlled by the Do_Overflow_Check
+ -- flag. The difference here is that if Backend_Overflow_Checks is
+ -- is (Backend_Overflow_Checks_On_Target set False), then the actual
+ -- overflow checks are generated by the front end, but if back end
+ -- overflow checks are active (Backend_Overflow_Checks_On_Target
+ -- set True), then the back end does generate the checks.
+
+ -- The following two routines are used to set these flags, they allow
+ -- for the possibility of eliminating checks. Checks can be eliminated
+ -- if an identical check has already been performed.
+
+ procedure Enable_Overflow_Check (N : Node_Id);
+ -- First this routine determines if an overflow check is needed by doing
+ -- an appropriate range check. If a check is not needed, then the call
+ -- has no effect. If a check is needed then this routine sets the flag
+ -- Set Do_Overflow_Check in node N to True, unless it can be determined
+ -- that the check is not needed. The only condition under which this is
+ -- the case is if there was an identical check earlier on.
+
+ procedure Enable_Range_Check (N : Node_Id);
+ -- Set Do_Range_Check flag in node N True, unless it can be determined
+ -- that the check is not needed. The only condition under which this is
+ -- the case is if there was an identical check earlier on. This routine
+ -- is not responsible for doing range analysis to determine whether or
+ -- not such a check is needed -- the caller is expected to do this. The
+ -- one other case in which the request to set the flag is ignored is
+ -- when Kill_Range_Check is set in an N_Unchecked_Conversion node.
+
+ -- The following routines are used to keep track of processing sequences
+ -- of statements (e.g. the THEN statements of an IF statement). A check
+ -- that appears within such a sequence can eliminate an identical check
+ -- within this sequence of statements. However, after the end of the
+ -- sequence of statements, such a check is no longer of interest, since
+ -- it may not have been executed.
+
+ procedure Conditional_Statements_Begin;
+ -- This call marks the start of processing of a sequence of statements.
+ -- Every call to this procedure must be followed by a matching call to
+ -- Conditional_Statements_End.
+
+ procedure Conditional_Statements_End;
+ -- This call removes from consideration all saved checks since the
+ -- corresponding call to Conditional_Statements_Begin. These two
+ -- procedures operate in a stack like manner.
+
+ -- The mechanism for optimizing checks works by remembering checks
+ -- that have already been made, but certain conditions, for example
+ -- an assignment to a variable involved in a check, may mean that the
+ -- remembered check is no longer valid, in the sense that if the same
+ -- expression appears again, another check is required because the
+ -- value may have changed.
+
+ -- The following routines are used to note conditions which may render
+ -- some or all of the stored and remembered checks to be invalidated.
+
+ procedure Kill_Checks (V : Entity_Id);
+ -- This procedure records an assignment or other condition that causes
+ -- the value of the variable to be changed, invalidating any stored
+ -- checks that reference the value. Note that all such checks must
+ -- be discarded, even if they are not in the current statement range.
+
+ procedure Kill_All_Checks;
+ -- This procedure kills all remembered checks.
+
-----------------------------
-- Length and Range Checks --
-----------------------------
@@ -293,12 +367,6 @@ package Checks is
-- flag. Checks_On is a boolean value that says if range and index checking
-- is on or not.
- procedure Enable_Range_Check (N : Node_Id);
- pragma Inline (Enable_Range_Check);
- -- Set Do_Range_Check flag in node N to True unless Kill_Range_Check flag
- -- is set in N (the purpose of the latter flag is precisely to prevent
- -- Do_Range_Check from being set).
-
procedure Insert_Range_Checks
(Checks : Check_Result;
Node : Node_Id;
@@ -331,12 +399,65 @@ package Checks is
-- in constructing the check.
-----------------------
+ -- Expander Routines --
+ -----------------------
+
+ -- Some of the earlier processing for checks results in temporarily
+ -- setting the Do_Range_Check flag rather than actually generating
+ -- checks. Now we are moving the generation of such checks into the
+ -- front end for reasons of efficiency and simplicity (there were
+ -- difficutlies in handling this in the back end when side effects
+ -- were present in the expressions being checked).
+
+ -- Probably we could eliminate the Do_Range_Check flag entirely and
+ -- generate the checks earlier, but this is a delicate area and it
+ -- seemed safer to implement the following routines, which are called
+ -- late on in the expansion process. They check the Do_Range_Check flag
+ -- and if it is set, generate the actual checks and reset the flag.
+
+ procedure Generate_Range_Check
+ (N : Node_Id;
+ Target_Type : Entity_Id;
+ Reason : RT_Exception_Code);
+ -- This procedure is called to actually generate and insert a range
+ -- check. A check is generated to ensure that the value of N lies
+ -- within the range of the target type. Note that the base type of
+ -- N may be different from the base type of the target type. This
+ -- happens in the conversion case. The Reason parameter is the
+ -- exception code to be used for the exception if raised.
+ --
+ -- Note on the relation of this routine to the Do_Range_Check flag.
+ -- Mostly for historical reasons, we often set the Do_Range_Check
+ -- flag and then later we call Generate_Range_Check if this flag is
+ -- set. Most probably we could eliminate this intermediate setting
+ -- of the flag (historically the back end dealt with range checks,
+ -- using this flag to indicate if a check was required, then we
+ -- moved checks into the front end).
+
+ procedure Generate_Index_Checks (N : Node_Id);
+ -- This procedure is called to generate index checks on the subscripts
+ -- for the indexed component node N. Each subscript expression is
+ -- examined, and if the Do_Range_Check flag is set, an appropriate
+ -- index check is generated and the flag is reset.
+
+ -- Similarly, we set the flag Do_Discriminant_Check in the semantic
+ -- analysis to indicate that a discriminant check is required for a
+ -- selected component of a discriminated type. The following routine
+ -- is called from the expander to actually generate the call.
+
+ procedure Generate_Discriminant_Check (N : Node_Id);
+ -- N is a selected component for which a discriminant check is required
+ -- to make sure that the discriminants have appropriate values for the
+ -- selection. This is done by calling the appropriate discriminant
+ -- checking routine for the selector.
+
+ -----------------------
-- Validity Checking --
-----------------------
-- In (RM 13.9.1(9-11)) we have the following rules on invalid values
- -- 9 If the representation of a scalar object does not represent a
+ -- If the representation of a scalar object does not represent a
-- value of the object's subtype (perhaps because the object was not
-- initialized), the object is said to have an invalid representation.
-- It is a bounded error to evaluate the value of such an object. If
@@ -518,18 +639,6 @@ private
-- For external clients, the required processing on this result is
-- achieved using the Insert_Range_Checks routine.
- pragma Inline (Access_Checks_Suppressed);
- pragma Inline (Accessibility_Checks_Suppressed);
- pragma Inline (Discriminant_Checks_Suppressed);
- pragma Inline (Division_Checks_Suppressed);
- pragma Inline (Elaboration_Checks_Suppressed);
- pragma Inline (Index_Checks_Suppressed);
- pragma Inline (Length_Checks_Suppressed);
- pragma Inline (Overflow_Checks_Suppressed);
- pragma Inline (Range_Checks_Suppressed);
- pragma Inline (Storage_Checks_Suppressed);
- pragma Inline (Tag_Checks_Suppressed);
-
pragma Inline (Apply_Length_Check);
pragma Inline (Apply_Range_Check);
pragma Inline (Apply_Static_Length_Check);