CVS difference for ai05s/ai05-0144-1.txt
--- ai05s/ai05-0144-1.txt 2009/04/30 05:52:16 1.3
+++ ai05s/ai05-0144-1.txt 2009/05/01 01:15:34 1.4
@@ -1,4 +1,4 @@
-!standard 6.04 (09) 09-04-29 AI05-0144-1/02
+!standard 6.04 (09) 09-04-30 AI05-0144-1/03
!class Amendment 09-02-15
!status work item 09-02-15
!status received 09-02-15
@@ -45,19 +45,25 @@
P2(I2,...), the prefix P1 is known to denote the same object as the
prefix P2, and for each index of the indexed_component, I1 and I2 are
static expressions with the same value, or I1 and I2 are names that
- are known to denote the same object.
+ are known to denote the same object; or
+ * N1 is a slice P1(R1), N2 is a slice P2(R2), the prefix P1 is known to
+ denote the same object as the prefix P2, and the subtypes denoted by the
+ ranges R1 and R2 statically match.
AARM Discussion: This is determined statically. If the name contains some dynamic
-portion other than a dereference or indexed_component, it is not "known to denote
-the same object". [We could also do slices here, although it doesn't seem
-likely enough to bother with.]
+portion other than a dereference, indexed_component, or slice, it is not "known
+to denote the same object". [We could also use the same rules for indexes for
+the bounds of slices that have explicit bounds, although it doesn't seem very
+likely to occur and the wording is messy.]
A name N1 is *known to denote a prefix of the same object* as another name N2 if
N2 is known to denote the same object as a subcomponent of the object denoted by N1.
AARM Reason: This ensures that names Prefix.Comp and Prefix are known to
denote the same object for the purposes of the rules below. This intentionally does
-not include dereferences.
+not include dereferences; we only want to worry about accesses to the same object,
+and a dereference changes the object in question. (There is nothing shared between
+an access value and the object it designates.)
A call C is legal only if:
* For each name N that is passed to some inner call (not including the call C
@@ -71,8 +77,8 @@
other than the one containing N that is known to denote the same object as N.all;
* for each name N that is passed as the actual parameter to a formal in out or out
- parameter that is not of a by-reference type, there is no other name in the
- actual parameters corresponding to formal in out or out parameters of the call
+ parameter that is of an elementary type, there is no other name in the actual
+ parameters corresponding to formal in out or out parameters of the call
other than the one containing N that is known to denote the same object or is
known to denote a prefix of the same object.
@@ -85,10 +91,24 @@
in any case, is not portable to another implementation (or even another
-The second bullet does not check for uses of the prefix that are not dereferences,
-as that is the access type, and we cannot know any uses of that type actually do
-a dereference. Only dereferences of the access value expose the application to order
+The second bullet does not check for uses of the prefix, since the access type
+and the designated object are not the same, and "known to denote the same
+prefix" does not include dereferences anyway.
+Note that these rules as a group make a symmetrical set of rules, in that either
+name can designate an object that is the prefix of the other. If the name N is
+a prefix of some other name in the call, these rules will trigger because that
+prefix would necessarily be known to designate the same object. (Nothing in these
+rules require the full other name to match; any part can match.) OTOH, we need
+explicit wording if some prefix of N matches some other name in the call.
+These rules do not require checks for most in out parameters in the top-level
+call C, as the rules about evaluation of calls prevent problems. Similarly,
+we do not need checks for short circuit operations. The rules about arbitrary
+order (see 1.1.4) allow evaluating parameters and writing parameters back in
+an arbitrary order, but not interleaving of evaluating parameters of one call
+with writing parameters back from another - that would not correspond to any
+allowed sequential order.
End AARM Reason.
AARM Ramification: Note that first two bullets cannot fail for a procedure or entry
@@ -580,12 +600,16 @@
calls but not preventing the same problem for procedures would be bizarre.
-A better solution would be to create rules that only try to detect the "low-hanging
+Finally, A Proposed Solution
+A better solution is be to create rules that only try to detect the "low-hanging
fruit" - that is cases where there clearly is a problem. This would be preferable
anyway; it would reduce the frustration caused by the rules (compared to rules like
the accessibility rules, for which the checks generally have no effect except to
get in the way of what you need to do -- to the point that Ada provides an attribute
-to ignore them!). It would still be possible to cause problems, but at least
+to ignore them!). It would still be possible to cause problems, but at least
+obvious problems would be prevented, and most illegal calls would have obvious
Such rules would only reject calls where it is clear that parts of the same object
are involved. That eliminates the complications of private types (we won't look in
@@ -593,7 +617,7 @@
These are the rules proposed in the !wording section above.
-The proposed wording allow detects arrays indexed by the same value or object,
+The proposed wording detects arrays indexed by the same value or object,
dereferences of the same access value, as well as uses of the same object. It
does not try to detect other cases of problems.
@@ -603,6 +627,38 @@
Swap_Integer (Arr(I), Arr(J));
+The proposed wording only applies to calls. It specifically does not apply to
+short circuit operations, as the order of evaluation of those operations is
+language-defined. Thus it is not possible to cause an order dependence
+across the parts of a short-circuit form. For instance:
+ if F2(O1) = F6(O2, O3) and then F3(O1) = F3(O3) then
+does not have an order dependence; the calls to F2 and F6 have to be evaluated
+before the calls to F3. Thus the result will be False (O1.C = 2 /= O3.C = 3).
+Since "and then" is not a call, the proposed rules do not apply to it, and the
+calls to "=" making up the sub-expressions are checked separately. Whereas:
+ if F2(O1) = F6(O2, O3) and F3(O1) = F3(O3) then
+does have an order dependence, and the result of the expression could be either
+True or False. Since the evaluation of "and" is a call, the proposed rules
+apply to this expression and thus it is illegal.
+The proposed rules depend on the fact that while Ada allows parameters to be
+evaluated in an arbitrary order, it does not allow interleaving of part of the
+evaluations of those parameters. (See 1.1.4(18), 1.1.4(18.d) says that it is
+intended to allow programmers to depend on some side-effects.) Thus, each call
+evaluates its parameters and checks their subtypes (in some arbitrary order),
+executes the call, and does any copying back of parameters (in some arbitrary
+order) without part of any other call being evaluated in the middle.
+Of course, an implementation can reorder operations in any way it likes so
+long as the result one of those allowed by evaluation rules above. But a
+compiler cannot start evaluating other parameters before writing back the
+results of a call if the other parameters could depend on those results.
@@ -613,7 +669,8 @@
The problem is that adds a lot of complexity, and while many of the checks could
be eliminated, some probably would remain, adding overhead without much value.
-(After all, the program probably would work without the checks.)
+(After all, the program probably would work -- although not portably -- without
None of the proposed rules do anything about side-effects totally inside of
@@ -638,8 +695,6 @@
way), and thus would fill the role of strict functions more flexibly. But it would
still be too incompatible to ban dangerous side-effects in functions (although
separate tools or non-Ada operating modes could make such checks).
Questions? Ask the ACAA Technical Agent