CVS difference for ai12s/ai12-0378-1.txt
--- ai12s/ai12-0378-1.txt 2020/06/10 03:01:45 1.5
+++ ai12s/ai12-0378-1.txt 2020/07/03 01:39:51 1.6
@@ -1,5 +1,6 @@
-!standard 6.4.1(13/3) 20-06-08 AI12-0378-1/03
-!class Amendment 20-04-29
+!standard 6.4.1(13/3) 20-06-18 AI12-0378-1/04
+!standard 6.4.1(18/3)
+!class Binding Interpretation 20-06-18
!status work item 20-04-29
!status received 20-03-26
!priority Low
@@ -7,49 +8,104 @@
!subject View conversions and out parameters of access types revisited
!summary
-An actual of an out parameter that is a view conversion of an access type
-is not illegal if the types are not related, rather null is passed if the
-access value would violate any constraint, tag check, or accessibility
-check that applies to the formal. Predicates and null exclusions are always
-ignored for out parameters.
-
-!problem
-
-The legality rule that prevents view conversions of unrelated access types
-for out parameters is a compatibility problem in practice. When we implemented
-this in GNAT, a significant number of tests in our customer regression test
-suite failed to compile.
+An actual of an out parameter that is a view conversion of an access
+type is not illegal if the types are not related, rather null is passed
+if the access value could violate any (runtime) tag check or
+accessibility check that applies to the formal. Constraints, predicates,
+and null exclusions are always ignored for out parameters of an access
+type.
+
+!question
+
+The legality rule that prevents view conversions of unrelated access
+types for out parameters is a compatibility problem in practice. When we
+implemented this in GNAT, a significant number of tests in our customer
+regression test suite failed to compile. Should we handle such view
+conversions in a more compatible way? (Yes.)
-!proposal
+!recommendation
(See Summary.)
!wording
-Modify 6.4.1(13/3):
+Replace 6.4.1(13/3) with the following paragraphs:
+ * For an access type:
-[Author's Note: Broken into two bullets.]
+ * if the designated type of the actual is a class-wide type T'Class
+ and the designated type of the formal is neither an ancestor of T,
+ nor a class-wide type that covers T, then the formal parameter
+ is initialized to the null value of the formal type;
+
+
+ * if the actual is a stand-alone object of an anonymous access type,
+ and the accessibility level of the formal type is not library
+ level, then the formal parameter is initialized to the null value
+ of the formal type;
+
+ * if the call is within the body of an instance of a generic unit,
+ the actual or the formal type is descended from a generic formal
+ access type of the generic unit, and the actual and formal types
+ neither share an ancestor nor is the formal type accessibility at
+ library level, then the formal parameter is initialized to the null
+ value of the formal type;
+
+
+ * otherwise, the formal parameter is initialized to the value of the
+ actual parameter, without checking that the value satisfies any
+ constraint.
+
+ In all of the above cases, no check is performed for any predicate
+ or exclusion of the null value that might apply to the formal
+ type.
+
+ AARM Implementation Note: This rule means that any tag checks,
+ and accessibility checks can be assumed to pass for an out
+ parameter, but constraints, null exclusions, and predicates cannot
+ be assumed unless the compiler can prove that the object has been
+ previously written within the subprogram.
+
+Add after RM 6.4.1(18/3):
+
+ Implementation Permission
+
+ For an OUT parameter of an access type, if the representation of the
+ actual type and the formal type differ, and there are values of the
+ actual type that cannot be represented as values of the formal type,
+ the implementation may initialize the formal parameter with the null
+ value of the formal type.
+
+Add after AARM 6.4.1(18.i/3):
+
+ Inconsistencies with Ada 2012
+
+ Correction: Added rules so that value passed into an out parameter for access
+ types is well-defined in the case of a view conversion. Null will be passed in
+ for conversions that may have problematic accessibility or tags. If the
+ accessibility or tag check(s) would have passed, and the out parameter is
+ read before it is written, Constraint_Error may be raised by Ada 202x when
+ it would not have been in Ada 2012. Additionally, if the called subprogram
+ does not write the out parameter at all, the actual object will be
+ overwritten with null (and possibly raise Constraint_Error if the object is
+ null excluding), while the object would be unchanged in Ada 2012. Such cases
+ are thought to be rare, as most out parameters of access types are
+ overwritten before being read. In addition, at least one commonly used
+ Ada compiler already does passes null in these cases.
+
+Modify AARM 6.4.1(18.j/4): [to remove any mention of access types - there is
+no longer any compile-time incompatibility]
+
+ Corrigendum: Added rules to ensure that the value passed into a{n} out
+ parameter for {scalar}[elementary] types is well-defined in the case of
+ a view conversion. The new rules can be incompatible. For a view conversion
+ to an unrelated type with the Default_Value aspect specified, the
+ aspect is new in Ada 2012 so it should be unlikely to occur in
+ existing code.[ For a view conversion to an unrelated access type, the
+ incompatibility is possible as this could be written in Ada 95, but such
+ a view conversion is thought to be rare. In both cases, ]{D}eclaring and
+ passing a temporary rather than a view conversion will eliminate the problem.
-* For an access type, {
- * if the value is nonnull, satisfies any constraints of the formal,
- has an accessibility level no deeper than that of the type of the
- formal, and, if the designated type is tagged, the tag of the
- designated object identifies a type that is covered by the type of
- the formal, then the formal parameter is initialized from the value of
- the actual, without checking whether the value satisfies any
- predicate;
-
- * otherwise,} the formal parameter is initialized to the null value
- of the formal type, without checking that the value satisfies [any
- constraint,] any predicate[,] or any exclusion of the null value;
-
- {AARM Implementation Note: This rule means that any constraint
- checks, tag checks, and accessibility checks can be assumed to
- pass for an out parameter, but null exclusions and predicates
- cannot be assumed unless the compiler can prove that the object
- has been previously written within the subprogram.}
-
!discussion
It's fairly clear that we cannot have the original Legality Rule, as
@@ -68,11 +124,11 @@
An implementation could assume that all out parameters are unconstrained (and
thus making the discriminant checks on every use), thus defanging problem [A].
-This would not be problematic. However, the tag and accessibility checks are
-not normally done as usage sites, so assuming implementations will do the
-right thing would impose a substantial implementation burden for a very
-unusual case (but one that is not quite as pathological as we expected in
-AI12-0074-1).
+This would not be problematic, and is in fact the rule since Ada 83, so we
+don't make any change here. However, the tag and accessibility checks are not
+normally done at usage sites, so assuming implementations will do the right
+thing could impose a substantial implementation burden for a very unusual
+case (but one that is not quite as pathological as we expected in AI12-0074-1).
We created a test program to see what existing compilers do in these cases.
The test program is reproduced at the start of the !appendix. The test program
@@ -113,57 +169,48 @@
---
-These results suggest that having problematic cases use the GNAT rule of
-passing null would not be significantly incompatible in practice. We would
-only want to use such a rule in cases that are actually problems, in order
-that derivation works as expected (as noted in the preliminary parts of
-the test program), and so that explicit calls that are exactly like calls on
-inherited subprograms work the same way as the inherited call. Note that
-GNAT is the only compiler that passes null currently, other compilers
-implement the language as defined more closely.
+These results suggest that having certain problematic cases use the GNAT
+approach of passing null would not be significantly incompatible in
+practice, as these cases (tag-check or accessibility-level check issues)
+can already lead to problems in other Ada compilers. Note that GNAT is
+the only compiler that passes null currently; other compilers implement
+the language as defined more closely.
Note that an out parameter can always be null, even if the parameter is
declared with a null exclusion. Null exclusions are not checked when the
parameter is passed in, and null is passed when the actual is not
-convertable. An implementation should not assume that null exclusions of an
+convertible. An implementation should not assume that null exclusions of an
out parameter are enforced before the out parameter is written within the
subprogram.
-We could have required null to be passed for all out parameters of access
-types. That may have been a more sensible rule for a new language, but it
-would mean that changing an out parameter of a record type to an
-access-to-record type would also require changing the mode to "in out"
-if any discriminants or bounds need to be read. Presumably, that is why
-Ada initially made the choice it did. In any case, the runtime incompatiblity
-creating by generally making such a change would be intolerable, so it is
-much too late to contemplate that.
-
-The only other alternative to requiring null to be passed would be to declare
-that the value of an out parameter whose actual is a view conversion and whose
-value does not pass a membership test for the subtype of the parameter is
-abnormal. In that case, reading the value within the subprogram makes the
-program erroneous (while assigning it first is fine). This would work but it
-introduces erroneous execution where none is really needed (the passing null
-solution involves no erroneous execution).
+We could have required null to be passed for all out parameters of
+access types. That might have been a more sensible rule for a new
+language, but the runtime incompatibility creating by generally making
+such a change would be intolerable, so it is much too late to
+contemplate that.
+
+Note that there is a potential runtime incompatibility with passing
+null, in that in the absence of an assignment to the OUT parameter, the
+parameter will nevertheless be set to null, even if the tag and
+accessibility checks would have passed. We considered always performing
+the tag and accessibility checks, even on OUT parameters, but this was
+felt to introduce a "tripping hazard" where the supposedly irrelevant
+value of an OUT parameter prior to a call nevertheless could produce an
+exception at runtime under unusual circumstances. We considered passing
+in null only if a tag or accessibility check would have failed, but this
+made the runtime model harder to describe and to implement, for what are
+considered corner cases. We also considered a legality rule disallowing
+problematic cases, but we felt the potential incompatibilities would be
+worse.
---
-Note that we don't explicitly talk about converting between access types with
-different representations. We're expecting that an implementation with such
-representations will include them in conversion and membership checking in an
-appropriate manner. For instance, if one assumes that converting a bit pointer
-to a byte pointer raises an exception if the bit address is not an even byte,
-then so long as that is reflected in a membership test, all is well.
-
-It's true that there doesn't seem to be any justification within the language
-to raise an exception in such a case, but it seems nasty to simply destroy an
-access value if the target type cannot properly represent the address. (Note
-that a similar thing can happen on a segmented machine, such as the original
-8086.) One assumes that Ada implementations care enough about correctness to
-avoid user-beware cases. If they don't, it's not the language's job to try to
-fix them.
-[Author's note: We may want to add an AARM note somewhere in 4.6 to note this
-possibility, and possibly in 4.5.2 as well.]
+As far as converting between access types with different
+representations, we provide an implementation permission to pass null in
+such a case if it involves an OUT parameter. We don't provide any
+permission or suggestion related to normal conversions or IN OUT
+parameters in such a case. We presume implementations will do the
+(implementation-defined) "right thing" in such cases.
!ASIS
Questions? Ask the ACAA Technical Agent