CVS difference for ai05s/ai05-0234-1.txt
--- ai05s/ai05-0234-1.txt 2011/01/27 06:06:17 1.4
+++ ai05s/ai05-0234-1.txt 2011/02/08 08:21:06 1.5
@@ -1,4 +1,4 @@
-!standard 6.5(21/3) 10-11-18 AI05-0234-1/01
+!standard 6.5(21/3) 11-02-07 AI05-0234-1/02
!class binding interpretation 10-11-15
!status work item 10-11-15
!status received 10-10-31
@@ -66,106 +66,178 @@
!wording
-Modify 4.8(10.1/3) as (modified by AI05-0051-1) as follows:
+Insert after Static Semantics section of 3.10.2:
+ Dynamic Semantics
+ -----------------
+
+ At a given point in a program's execution, a given coextension is
+ a coextension of exactly one non-coextension object. This non-coextension
+ object is defined to be the "owner" of the coextension.
+
+ It is possible for the master and accessibility level of an object to
+ change in the following cases:
+ - When an aggregate or function call result is built in place
+ and one object "mutates into" another object as described in 7.6,
+ the two objects may have different masters and accessibility levels.
+ - When a return statement completes normally by returning from a function
+ and the function result object is not built in place,
+ the accessibility level of the return object changes to be
+ a level determined by the point of call as described above.
+ - When a coextension of one object becomes a coextension of
+ a different object as described above, the master and
+ accessibility level of the coextension become those of the
+ new owner.
+
+ Informally, the "ultimate master" of an object (or of an
+ access type associated with a coextension object), is the master
+ that the object will have eventually when all of these transformations
+ have occurred.
+
+ This is defined as follows:
+
+ If the result of a function call
+ or aggregate is built in place (see 7.6), the ultimate master
+ of the result object is that
+ of the object that the result object is used to initialize.
+
+ If the result object of a function call
+ is not built in place, the ultimate master
+ of the result object is the master
+ determined by the point of call (as described above).
+
+ In the case of a function call whose result is not built
+ in place, but for which coextension
+ ownership will be transferred (as described above),
+ the ultimate master of the coextensions
+ (if any) of the result object is that of the object to
+ which coextension ownership will be transferred;
+ this rule is applied recursively in the case where the
+ new owner is also such a function call result.
+
+ AARM note:
+ Informally, the ultimate master of
+ a coextension is that of its "ultimate owner".
+
+ In all other cases, the ultimate master of
+ a coextension is that of the coextension's owner.
+
+ The ultimate master of the access type of an
+ allocator that creates a coextension is that
+ of the coextension.
+
+ For any other entity whose master is defined,
+ the ultimate master of the entity is the same
+ as its master.
+
+The ultimate accessibility level of an entity
+is defined to be the accessibility level of its ultimate master.
+
+AARM note:
+ Despite the use of the future tense ("to which coextension
+ ownership will be transferred") and words like
+ "eventually" and "ultimate", implementers do not require
+ a crystal ball. An additional implicit parameter may be needed
+ in some cases in order to communicate information known at a
+ function's call site to the callee.
+
+ The terms "ultimate master" and "ultimate accessibility level" play
+ no role in the static semantics of the language. In particular, they
+ play no role in any accessibility-related legality rules. These terms
+ define properties of an object, not of a view of an object.
+
+Add at the end of the "Dynamic Semantics" section of 4.3.1:
+
+ If the type of the aggregate is discriminated and has
+ default expressions for its discriminants and has
+ one or more access discriminants for which the
+ aggregate provides an expression (as opposed to a
+ record_component_association with <>), then a check is
+ made that the accessibility level of the anonymous access type of
+ each such access discriminant, as determined by the expression provided
+ in the aggregate, is not deeper than the ultimate accessibility level
+ of the anonymous object created for the evaluation
+ of the aggregate. If this check fails, Program_Error is raised.
+
+ AARM note:
+ This check is guaranteed to pass in the (usual) case that
+ the aggregate's anonymous result object's accessibility
+ level matches its ultimate accessibility level.
+ An aggregate cannot contain a reference to something
+ shorter-lived than itself unless the aggregate object's
+ accessibility level changes, and such a pending change would
+ be reflected in the ultimate accessibility level of the object.
+ Note also that only a limited type may have a defaulted
+ access discriminant, so this rule has no effect unless the
+ type of the aggregate is limited.
+
+
+Modify 4.8(10.1/3) as (modified by AI05-0024-1 and AI05-0051-1) as
+follows:
+
For any allocator, if the designated type of the type of the
allocator is class-wide, then a check is made that the
accessibility level of the type determined by the
subtype_indication, or by the tag of the value of the
- qualified_expression, is not deeper than that of the type of the
- allocator. If the subtype determined by the subtype_indication or
- qualified_ expression {(or by the tag of the value of the qualified
+ qualified_expression, includes the elaboration {of the ultimate
+ master} of the type of the allocator. If the subtype determined by
+ the subtype_indication or
+ qualified_expression {(or by the tag of the value of the qualified
expression if the type of the qualified expression is class-wide)}
of the allocator has one or more access discriminants, then a
check is made that the accessibility level of the anonymous access
- type of each access discriminant is not deeper than that of the
- type of the allocator. Program_Error is raised if either such check
- fails.
+ type of each access discriminant is not deeper than [that]{the
+ ultimate accessibility level} of the type of the allocator.
+ Program_Error is raised if either such check fails.
-Replace 6.5(21/3) (as modified by AI05-0051-1) with:
+[Editor's note: Steve said he wanted other changes as well, but I can't figure
+out what they are supposed to be; he did not show them, rather describing
+what to change from some unknown baseline.]
- If any part (ignoring the values of bounds and discriminants) of the return
- object of a function (or a coextension thereof) has one or more access
- discriminants whose value is not constrained by the result subtype of the
- function, a check is made that the accessibility level of the anonymous
- access type of each access discriminant is not deeper than the level of the
- return object as determined by the point of call (see 3.10.2). If this check
- fails, Program_Error is raised.
+In 6.5(8) replace
-Add a (massive) AARM note after 6.5(21/3):
+ A check is made that the master of the type identified by the tag of the
+ result includes the elaboration of the master that elaborated the function
+ body.
- For a function with a classwide result type, the access values that
- need to be checked are determined by the tag of the return object.
- In order to implement this accessibility check in the case where
- the tag of the result is not known statically at the point of the
- return statement, an implementation may need to somehow
- associate with the tag of a specific tagged
- type an indication of whether the type has unconstrained access
- discriminants (explicit or inherited) or has any subcomponents
- with such discriminants. If an implementation is already maintaining
- a statically initialized descriptor of some kind for each specific
- tagged type, then an additional Boolean could be added to this
- descriptor.
-
- Note that the flag should only be queried in the case where any
- access discriminants which the result object might have would
- have subtypes with "bad" accessibility levels (as determined by
- the rules of 3.10.2 for determining the accessibility level of
- the type of an access discriminant in the expression or
- return_subtype_indication of a return statement).
-
- Thus, in a case like
-
- type Global is access T'Class;
- function F (Ptr : Global) return T'Class is
- begin
- return Ptr.all;
- end F;
-
- there is no need for a runtime accessibility check. The setting
- of the bit doesn't matter and there is no need to query it.
-
- On the other hand, given
-
- function F return T'Class is
- Local : T'Class := ... ;
- begin
- return Local;
- end F;
-
- In this case, a check would typically be required.
-
- The need for including subcomponents in this check is illustrated by
- the following example:
-
- X : aliased Integer;
-
- type Component_Type (Discrim : access Integer := X'Access)
- is limited null record;
-
- type Undiscriminated is record
- Fld : Component_Type;
- end record;
-
- function F return Undiscriminated is
- Local : aliaed Integer;
- begin
- return X : Untagged := (Fld => (Discrim => Local'Access)) do
- Foo;
- end return;
- -- raises Program_Error after calling Foo.
- end F;
+with
- Ramification:
- In the case where the tag of the result is not known statically
- at the point of the return statement and the runtime accessibility
- check is needed, discriminant values and array bounds
- play no role in performing this check. That is, array components are
- assumed to have non-zero length and components declared
- within variant parts are assumed to be present Thus, the check
- may be implemented simply by testing the aforementioned descriptor
- bit and conditionally raising Program_Error.
+ A check is made that the master of the type identified by the tag of the
+ result includes the elaboration of the ultimate master of the return object.
+
+====
+
+
+Modify 6.5(21) (as modified by AI05-0051) as follows:
+
+ If [any part of] the return object (or coextension
+ thereof) of a function has one or more [unconstrained] access
+ discriminants whose value is not constrained by the result subtype of
+ the function, a check is made that the accessibility level of the
+ anonymous access type of each access discriminant, as determined by
+ the expression or the return_subtype_indication of the function, is
+ not deeper than the [level of the return object as determined by the
+ point of call]{ultimate accessibility level of the
+ return object} (see 3.10.2). If this check fails, Program_Error is
+ raised.
+
+[Editor's note: Steve referenced 7.6 instead on 3.10.2 here. But that makes
+no sense, the "ultimate accessibility level" is defined in 3.10.2, so
+we reference there.]
+
+[Author's Note: The new 4.3.1 wording plugs the holes associated with
+defaulted access discriminants for limited types, thereby eliminating the
+need for the "any part of" wording in 6.5(21).]
+
+[Author's Note: AI05-0051's wording changes for this paragraph includes
+adding
+ "whose value is not constrained by the result subtype of the function" .
+What does this wording mean if the result subtype is
+Some_Constrained_Subtype'Class ? Like a zombie, AI05-0057 refuses to
+stay buried. [Editor's comment: The same thing that it means anywhere
+else -- which we can't agree on. I don't see anything different here.]]
+
!discussion
The language already specifies accessibility checks for access discriminants in
@@ -1736,3 +1808,60 @@
****************************************************************
+From: Steve Baird
+Sent: Monday, February 7, 2011 3:18 PM
+
+Here is a first cut at wording for this AI. [This is version /02 of
+the AI - Editor.]
+
+Thanks to Gary, Randy, and Bob for reviewing preliminary versions.
+
+Discussion:
+
+The following argument provides motivation for the proposed changes:
+
+ 1) We need some kind of accessibility checks to deal with the
+ "access discriminants with defaults" problem illustrated
+ in the AI (the example involving type Component_Type).
+
+ One could view this problem as a consequence of introducing
+ defaulted access discriminants for limited types. This introduces
+ the need to either check aggregates (the approach taken in
+ this version of the AI) or somehow check arbitrarily deeply nested
+ subcomponents at the point of a function return (the approach
+ taken by the previous version of this AI).
+
+ 2) We don't want to repeat checks at the point where an
+ object's accessibility level changes; we want to perform
+ the checks against the correct accessibility level in the
+ first place so that checks are performed while we still have
+ useful info about both entities whose accessibility levels
+ are being compared.
+
+ The AI lists the various scenarios where the accessibility level
+ of an object may change. One could imagine an approach where
+ additional checks are performed at these points. This seems like
+ a bad idea. The previous version of thie AI took this approach
+ and involved conservative checks associated with a
+ "has-subcomponents-with-defaulted-access-discriminants" flag in the
+ descriptor for a tagged type. The current approach is more precise;
+ cases which would would have failed overly conservative runtime
+ accessibility checks with the earlier approach will now succeed.
+
+ 3) This means that we have to know the "ultimate
+ accessibility level" of an aggregate result object
+ at the point where the discriminant value is given.
+
+ I think this is implementable using the approach outlined
+ in AI05-0051, but this needs to be confirmed. In particular,
+ we need to look at combinations such as a non-build-in-place
+ function call used to initialize an allocator where the
+ function result owns a coextension and the result subtype
+ of the function is class-wide with no discriminants.
+
+ 4) Having defined this notion for use with aggregates, we might as
+ well use it elsewhere (see above changes to 4.8 and 6.5)
+ even though the only holes that this fixes are related to coextensions
+ (and are therefore less important, at least to some folks).
+
+****************************************************************
Questions? Ask the ACAA Technical Agent