Version 1.7 of ais/ai-00416.txt

Unformatted version of ais/ai-00416.txt version 1.7
Other versions for file ais/ai-00416.txt

!standard 3.2.3(01)          05-04-17 AI95-00416/06
!standard 3.3(10)
!standard 3.7(27)
!standard 3.9.2(02)
!standard 3.9.2(04)
!standard 3.9.2(05)
!standard 3.9.2(06)
!standard 3.9.2(11)
!standard 3.9.2(18)
!standard 3.10.2(07)
!standard 3.10.2(09)
!standard 3.10.2(10)
!standard 3.10.2(11)
!standard 3.10.2(12)
!standard 3.10.2(13)
!standard 3.10.2(14)
!standard 4.8(05)
!standard 4.8(07)
!standard 6.5(05)
!standard 6.5(06)
!standard 6.5(20)
!standard 6.5(22)
!standard 7.6.1(03)
!standard 7.6.1(09)
!standard 9.2(02)
!standard 9.2(03)
!standard 9.2(04)
!standard 13.11(25)
!standard 13.11.2(9)
!standard 13.11.2(17)
!class amendment 05-02-07
!status Amendment 200Y 05-03-16
!comment This AI is in the Amendment, but is not yet approved.
!status work item 05-02-07
!status received 05-02-07
!priority High
!difficulty Hard
!subject Access results, accessibility, and return statements
!summary
Dispatching on access result is supported, but nulls are allowed.
Tasks are activated after returning from a function that returns an object containing tasks.
Accessibility levels are defined both for the call site, and at the point of the return statement, which is important for objects with access discriminants and for objects of a class-wide type.
!problem
We have not fully specified the rules for functions with anonymous access type as a result type. In particular, how do they work with dispatching and what are the accessibility rules.
We have also not specified the details for result types with access discriminants, as these have special accessibility considerations.
In general, we need to specify the accessibility level of the "return object" given that it might be aliased, have access discriminants, be an object of an anonymous access type, etc.
We also need to specify some of the details of what happens if the return object has a controlled or task part.
!proposal
Dispatching on access result is possible. For example:
function Empty_Acc return access T;
function Similar(X : access T; Y : access T) return Boolean; ...
M : access T'Class := ... B : Boolean := Similar(M, Empty_Acc);
The tag of M.all determines which overriding of Empty_Acc is invoked. A call on a function with a controlling access result may be dereferenced and still be a dynamically tagged or tag indeterminate expression.
Defaults for controlling access parameters should be permitted, so long as they are functions with controlling access results.
---------------------
Caller does not pass in an accessibility level for return objects.
A return object has accessibility between the uplevels of the function and the return statement. Hence:
Ok for a return object to point to up-levels Ok for locals of return statement to point to return object Not Ok for locals outside return statement to point to return object Not Ok for up-levels to point to return object Not Ok for return object to point to locals
Function call has accessibility level of function declaration, so may not use a call on a local function to initialize an object in a longer-lived heap if it has an access discriminant or is of a class-wide type.
If access discriminants are initialized individually, then type conversion provides for the accessibility checks. However, if the access discriminants are not specified individually, but rather come from a named constrained subtype, or from an initializing object, then there is no type conversion involved, and hence we need an explicit rule for the needed accessibility check. This is relevant at a function return and at an allocator. At a function return, we can be returning a record aggregate (access discriminants given individually), an extension aggregate (access discriminants could come from ancestor part, either from an object or named constrained subtype, or from individual values specified after the "with"), a part of an existing object, a part of a function call (level based on level of function decl). At an allocator we have all of these possibilities, plus we have an unitialized allocator where the subtype_indication denotes a named constrained subtype, or an uninitialized allocator where the subtype_indication contains an explicit constraint (access discriminants specified individually).
---------------------
Tasks are not activated until outermost enclosing object fully and successfully initialized, and certainly not prior to return, since only caller knows extent of outermost enclosing object. A return object that is not successfully initialized, is finalized prior to exiting the return statement.
!wording
Change first sentence of 3.2.3(1):
An operation operates on a type T if it yields a value of type T, if it has an operand whose expected type (see 8.6) is T, or if it has an access parameter {or access result type} (see 6.1) designating T.
Change 3.3(10) as follows:
* {the return object created as} the result of evaluating a function_call (or the equivalent operator invocation - see 6.6);
Change 3.7(27) to:
For an access discriminant, its access_definition is elaborated when the value of the access discriminant is defined: by evaluation of its default_expression, by elaboration of a discriminant_constraint, or by an assignment that initializes the enclosing object.
Add to end of 3.9.2(2):
{Similarly, if the call is to a function with access result type designating T, then the call has a controlling access result, and the context can similarly control dispatching.}
Change 3.9.2(4):
... if it is a call with a controlling result {or controlling access result}, ...
Change 3.9.2(5):
... or it is a call with a controlling result {or controlling access result} and ...
Change 3.9.2(6):
... if it is a call with a controlling result {or controlling access result}, ...
Delete the second sentence of 3.9.2(11):
The default_expression for a controlling formal parameter of a dispatching operation shall be tag indeterminate. [A controlling formal parameter that is an access parameter shall not have a default_expression.]
Delete 3.9.2(11.b) (it explained the second sentence of 3.9.2(11)).
Change 3.9.2(18):
* If the call has a controlling result {or controlling access result} and is itself{, or designates,} a (possibly parenthesized or qualified) controlling operand of an enclosing call on a dispatching operation of a descendant of type T, then its controlling tag value is determined by the controlling tag value of this enclosing call;
Change the paragraph inserted by AI95-00196 after 3.9.2(18):
* If the call has a controlling result {or controlling access result} and {(possibly parenthesized, qualified, or dereferenced)} is the [(possibly parenthesized or qualified)] expression of an assignment_statement whose target is of a class-wide type, then its controlling tag value is determined by the target;
Add after 3.10(12):
AARM NOTE:
Note that we considered imposing a similar implicit null exclusion for controlling access results, but chose not to do that, because there is no Ada95 compatibility issue, and there is no automatic null check inherent in the use of a controlling access result. If a null check is necessary, it is because there is a dereference of the result, or because the value is passed to a null-excluding parameter. If there is no dereference of the result, a null return value is perfectly acceptable, and can be a useful indication of a particular status of the call.
Modify 3.10.2(7/2) as follows:
* An entity or view [created by a declaration] {defined by a declaration and created as part of its elaboration} has the same accessibility level as the innermost [enclosing] master that elaborates the declaration {(} other than the declaration itself{)} except in the cases of renaming and derived access types described below. A parameter of a master has the same accessibility level as the master.
AARM NOTE:
This rule defines the accessibility of all named access types, as well as the accessibility level of all anonymous access types other than those for access parameters and access discriminants. Special rules exist for the accessibility level of such anonymous types. Components, stand-alone objects, and function results whose (anonymous) type is defined by an access_definition have accessibility levels corresponding to named access types defined at the same point.
Ramification: {AI95-00230-01} Because accessibility level
is determined by where the access_definition is elaborated, for a type extension, the anonymous access types of components (other than access discriminants) inherited from the parent have the same accessibility as they did in the parent; those in the extension part have the accessibility determined by the scope where the type extension is declared. Similarly, the types of the non-discriminant access components of a derived untagged type have the same accessibility as they did in the parent.
Change 3.10.2(9) as follows:
* The accessibility level of a view conversion{, qualified expression, or parenthesized_expression,} is the same as that of the operand.
Replace 3.10.2(10) with:
* The accessibility level of the result of a function call that is used as a prefix of a name or as the actual parameter in a call is that of the immediately enclosing master. In other contexts, the accessibility level is that of the object being initialized from the function result.
Add after 3.10.2(10):
* Within a return statement, the accessibility level of the return object is that of the execution of the return statement. If the return statement completes normally by returning from the function, prior to leaving the function, the accessibility level of the return object changes to be a level determined by the point of call, as does the level of any coextensions (see below) of the return object.
AARM Note:
We define the accessibility level of the return object during the return statement to be that of the return statement itself so that the object may be designated by objects local to the return statement, but not by objects outside the return statement. In addition, the intent is that the return object gets finalized if the return statement ends without actually returning (for example, due to propagating an exception, or a goto). For a normal return, of course, no finalization is done before returning.
Delete the paragraph added by AI95-00385 after 3.10.2(11) (it is redundant).
Change 3.10.2(12) to be:
* For an access discriminant, the accessibility level of its anonymous access type is determined as follows:
+ For an access discriminant whose value is determined by a discriminant_association in a subtype_indication, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);
AARM NOTE: This deals with the following cases:
- Extension aggregate where ancestor part is a subtype_mark denoting a constrained subtype; - Uninitialized allocator where subtype_indication defines a constrained subtype; - Discriminant of object with a constrained nominal subtype, including constrained components, the result of calling a function with a constrained result subtype, the dereference of an access-to-constrained subtype, etc.
+ For an access discriminant of an object defined by an aggregate where the value of the discriminant is determined by a component_association in the aggregate, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);
+ For an access discriminant of any other object with an unconstrained nominal subtype, the accessibility level of the object.
AARM NOTE: In other words, if you know the value of the discriminant
from a discriminant constraint or an aggregate component association, then that determines the accessibility level; if you don't know it, then it is based on the object itself.
Delete 3.10.2(12.a/2) (it was moved up to be after paragraph 7/2).
Delete the second paragraph inserted by AI95-00318 after 3.10.2(13) (it is redundant).
Change 3.10.2(14):
* The accessibility level of an object created by an allocator is the same as that of the access type, except for an allocator of an anonymous access type that defines the value of an access parameter or an access discriminant. For an allocator defining the value of an access parameter, the accessibility level is that of the master immediately enclosing the call. For one defining an access discriminant, the accessibility level is determined as follows:
+ for an allocator used to define the constraint in a subtype_declaration, the level of the subtype_declaration;
+ for an allocator used to define the constraint in a component_definition, the level of the enclosing type;
+ for an allocator used to define the discriminant of an object, the level of the object.
In this last case, the allocated object is said to be a coextension of the object whose discriminant designates it, as well as of any object of which the discriminated object is itself a coextension or subcomponent. All coextensions of an object are finalized when the object is finalized (see 7.6.1).
AARM NOTE: The rules of access discriminants are such that when the space for an object with a coextension is reclaimed, the space for the coextensions can be reclaimed. Hence, there is implementation advice (see 13.11) that an object and its coextensions all be allocated from the same storage pool (or stack frame, in the case of a declared object).
Add after the paragraph inserted by AI95-00344 after 4.8(5):
If the designated subtype of the type of the allocator has one or more unconstrained access discriminants, then the accessibility level of the anonymous access type of each access discriminant, as determined by the subtype_indication or qualified_expression of the allocator, shall not be statically deeper than that of the type of the allocator (see 3.10.2).
Change 4.8(7) as amended by AI95-00344:
... is not deeper than that of the type of the allocator. {If the designated subtype of the allocator has one or more unconstrained 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 [this] {either such} check fails.
Add after the third paragraph inserted by AI95-00318 after 6.5(5):
If the result type is class-wide, the accessibility level of the type of the return_expression shall not be statically deeper than that of the master that elaborated the function body. If the result subtype has one or more unconstrained access discriminants, the accessibility level of the anonymous access type of each access discriminant, as determined by the return_subtype_indication or the return expression, shall not be statically deeper than that of the master that elaborated the function body.
AARM NOTE:
We know that if the result type is class wide, then there must be a return expression. Similarly, if the result subtype is unconstrained, then either the return_subtype_indication (if any) is constrained, or there must be a return expression.
Modify 6.5(5.5/2) as follows:
For the execution of an extended_return_statement, the subtype_indication or access_definition is elaborated. This creates the nominal subtype of the return object. If there is a return expression, it is evaluated and converted to the nominal subtype (which might raise Constraint_Error see 4.6){; the return object is created} and {the converted value} becomes the initial value of the return object; otherwise, the return object is {created and} initialized by default as for a stand-alone object of its nominal subtype (see 3.3.1). If the nominal subtype is indefinite, the return object is constrained by its initial value. The handled_sequence_of_statements, if any, is then executed.
AARM NOTE:
If the result type is controlled or has a controlled part, appropriate calls on Initialize or Adjust are performed prior to executing the handled_sequence_of_statements, except when the initial expression is an aggregate (which requires build-in-place with no call on Adjust).
If the return statement exits without resulting in a return (for example, due to an exception propagated from the return expression or the handled sequence of statements, or a goto out of the handled sequence of statements), the return object is finalized prior to leaving the return statement.
Add after 6.5(6):
If the return object has any parts that are tasks, the activation of those tasks does not occur until after the function returns (see 9.2).
AARM NOTE:
Only the caller can know when task activations should take place, as it depends on the context of the call. If the function is being used to initialize the component of some larger object, then that entire object must be initialized before any task activations. Even after the outer object is fully initialized, task activations are still postponed until the "begin" at the end of the declarative part if the function is being used to initialize part of a declared object.
Change the paragraph inserted by AI95-00318 after 6.5(20):
If the result type is class-wide, a check is made that the accessibility level of the type identified by the tag of the result is not deeper than that of the master that elaborated the function body. {If the result subtype has one or more unconstrained access discriminants, a check is made that the accessibility level of the anonymous access type of each access discriminant, as determined by the return_subtype_indication or return expression, is not deeper than that of the master that elaborated the function body.} If [this] {either} check fails, Program_Error is raised.
Add after 6.5(22/2):
Implementation Permission
If the result subtype of a function is unconstrained, and a call on the function is used, directly or indirectly, to provide the initial value of an object with a constrained nominal subtype, Constraint_Error may be raised at the point of the call (after abandoning the execution of the function body) if, while elaborating a return_subtype_indication or evaluating a return expression within the function, it is determined that the value of the result will violate the constraint of this object's subtype.
AARM NOTE: Without such a permission, it would be very difficult
to implement "build-in-place" semantics. Such an exception is not handleable within the function, because in the return-by-copy case, the constraint check to verify that the result satisfies the constraints of the object being initialized happens after the function returns, and we want the semantics to change as little as possible when switching between return-by-copy and build-in-place. This implies further that upon detecting such a situation, the implementation may need to simulate a goto to a point outside any local exception handlers prior to raising the exception.
Change 7.6.1(3) as amended by AI95-00162:
... except in the case of a master: the execution of a body other than a package_body; the elaboration of a declaration other than the declaration of a package {or of a type}; the execution of [an accept_statement, a block_statement, or a simple_statement] {a statement};
Add after 7.6.1(9):
* If the object has coextensions (see 3.10.2), each coextension is finalized after the object whose access discriminant designates it.
Change 9.2(2):
A task object (which represents one task) can be {a part of a stand-alone object, of an object created by an allocator, or of an anonymous object of a limited type} [created either as part of the elaboration of an object_declaration occurring immediately within some declarative region, or as part of the evaluation of an allocator]. All tasks {that are part of any of the stand-alone objects} created by the elaboration of object_declarations {(or generic_associations of formal objects of mode IN)} of a single declarative region [(including subcomponents of the declared objects)] are activated together. [Similarly, all tasks created by the evaluation of a single allocator are activated together. The activation of a task is associated with the innermost allocator or object_declaration that is responsible for its creation.] {All tasks that are part of a single object that is not a stand-alone object are activated together.}
Change 9.2(3):
For {the} tasks [created by the elaboration of object_declarations] of a given declarative region, the activations are initiated within the context of the handled_sequence_of_statements ...
Change 9.2(4):
{For tasks that are part of a single object that is not a stand-alone object, activations are initiated after completing any initialization of the outermost object enclosing these tasks, prior to performing any other operation on the outermost object. In particular, for} [For] tasks {that are part of the object} created by the evaluation of an allocator, the activations are initiated as the last step of evaluating the allocator, [after completing any initialization for the object created by the allocator, and] prior to returning the new access value. {For tasks that are part of an object that is the result of a function call, the activations are not initiated until after the function returns.}
AARM NOTE:
The intent is that "temporary" objects with task parts are treated similarly to an object created by an allocator. The "whole" object is initialized, and then all of the task parts are activated together. Each such "whole" object has its own task activation sequence, involving the activating task being suspended until all the new tasks complete their activation.
Change 13.11(25.1/2) as follows:
* If the allocator is [initializing an access discriminant of an object of a limited type, and the discriminant is itself a subcomponent] {defining a coextension (see 3.10.2)} of an object being created by an outer allocator, then the storage pool used for the outer allocator should also be used for the [allocator initializing the access discriminant] {coextension};
Change 13.11.2(9) as follows:
3. Free(X), when X is not equal to null first performs finalization {of
the object designated by X (and any coextensions of the object -- see 3.10.2)}, as described in 7.6{.1}. It then deallocates the storage occupied by the object designated by X {(and any coextensions)}. If the storage pool is a user-defined object, then the storage is deallocated by calling Deallocate, passing access_to_variable_subtype_name'Storage_Pool as the Pool parameter. Storage_Address is the value returned in the Storage_Address parameter of the corresponding Allocate call. Size_In_Storage_Elements and Alignment are the same values passed to the corresponding Allocate call. There is one exception: if the object being freed contains tasks, the object might not be deallocated.
After Free(X), the object designated by X, and any subcomponents {(and coextensions)} thereof, no longer exist; their storage can be reused for other purposes.
Delete 13.11.2(17.1/2).
!discussion
Our intent is to define the checks needed when an object with access discriminants is initialized by assignment as equivalent to converting each access discriminant to the type of the access discriminant of the target.
When a function call is used as a prefix (or as an actual parameter), such as for taking 'Access or selecting a component, it is considered a temporary object, and the accessibility level of an access discriminant subcomponent will have the level of the nearest enclosing master. On the other hand, if the function call is used as a "whole" to initialize an allocator, a declared object, or a return object, it takes on the accessibility level of the function declaration.
We want to preserve the model that an allocator (of an anonymous type) that is used to initialize an access discriminant results in an allocated object that has the same storage pool and lifetime as the object with the access discriminant. This should be true whether the enclosing object is limited or non-limited.
We have defined a new term, "coextension," to describe an object created by an allocator of an anonymous type that is being used to initialize an access discriminant of an "outer" object. An object and all its coextensions are allocated, initialized, finalized, and freed at the same point, as though the coextensions are components of the object.
For a limited function return, the caller has to control where the return object is built. If the result subtype is unconstrained, while the call is being used to initialize a constrained object, including a component, the space available to the object is bounded. To avoid overrunning this space, the caller must pass in some sort of implicit parameters which will allow the return statement to determine the limits on the space it may occupy. One possibility is to pass in the values for the discriminants, or perhaps to preeinitialize them in the space for the return object. There should be an implementation permission to allow raising Constraint_Error at the beginning of the return statement, prior to fully evaluating the return expression or executing the handled sequence of statements. Something analogous to a 'Constrained bit can be provided, to indicate whether the discriminant values are preinitialized.
-----------------
Our last discussion about access discriminants and allocators in Paris was a bit concerning, I'm sure. For what it's worth, I believe I have worked out all the problems, and the "joined at the hip" model will work for nonlimited types as well. Generally, the solution is to return more closely to the rule that an access discriminant always has the same level as the object it is a component of. I had broken that rule for objects returned by functions when referring to an access discriminant of a subcomponent of the result, and that was causing the trouble, I believe. Calling a function and then only using a part of the result is quite rare, and using a part that happens to have an access discriminant that is initialized from the enclosing object's access discriminant is well below the noise level.
Overall, the general rule becomes that as soon as you select a component of a function result, the function result is treated as a "temp", and it takes on a very local accessibility level, as do any access discriminants it has. E.g.:
X : T := func().component;
is not permitted if component has an access discriminant initialized from the enclosing object, because the call is a temp, and we are trying to initialize a longer-lasting object. Another way to think about it is that only when "build-in-place" is possible can the result of the function call be long-lived.
!example
(See umm, er...imagine one here. - ED)
!corrigendum 3.2.3(01)
Replace the paragraph:
An operation operates on a type T if it yields a value of type T, if it has an operand whose expected type (see 8.6) is T, or if it has an access parameter (see 6.1) designating T. A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a predefined operation of the type. The primitive operations of a type are the predefined operations of the type, plus any user-defined primitive subprograms.
by:
An operation operates on a type T if it yields a value of type T, if it has an operand whose expected type (see 8.6) is T, or if it has an access parameter or access result type (see 6.1) designating T. A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a predefined operation of the type. The primitive operations of a type are the predefined operations of the type, plus any user-defined primitive subprograms.
!corrigendum 3.7(27)
Replace the paragraph:
An access_definition is elaborated when the value of a corresponding access discriminant is defined, either by evaluation of its default_expression or by elaboration of a discriminant_constraint. The elaboration of an access_definition creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type (see 4.6).
by:
For an access discriminant, its access_definition is elaborated when the value of the access discriminant is defined: by evaluation of its default_expression, by elaboration of a discriminant_constraint, or by an assignment that initializes the enclosing object.
!corrigendum 3.9.2(02)
!comment This includes the wording change from AI-260-2.
@drepl A @i<call on a dispatching operation> is a call whose @fa<name> or @fa<prefix> denotes the declaration of a primitive subprogram of a tagged type, that is, a dispatching operation. A @i<controlling operand> in a call on a dispatching operation of a tagged type @i<T> is one whose corresponding formal parameter is of type @i<T> or is of an anonymous access type with designated type @i<T>; the corresponding formal parameter is called a @i<controlling formal parameter>. If the controlling formal parameter is an access parameter, the controlling operand is the object designated by the actual parameter, rather than the actual parameter itself. If the call is to a (primitive) function with result type @i<T>, then the call has a @i<controlling result> -- the context of the call can control the dispatching. @dby A @i<call on a dispatching operation> is a call whose @fa<name> or @fa<prefix> denotes the declaration of a dispatching operation. A @i<controlling operand> in a call on a dispatching operation of a tagged type @i<T> is one whose corresponding formal parameter is of type @i<T> or is of an anonymous access type with designated type @i<T>; the corresponding formal parameter is called a @i<controlling formal parameter>. If the controlling formal parameter is an access parameter, the controlling operand is the object designated by the actual parameter, rather than the actual parameter itself. If the call is to a (primitive) function with result type @i<T>, then the call has a @i<controlling result> -- the context of the call can control the dispatching. Similarly, if the call is to a function with access result type designating @i<T>, then the call has a @i<controlling access result>, and the context can similarly control dispatching.
!corrigendum 3.9.2(04)
Replace the paragraph:
by:
!corrigendum 3.9.2(05)
Replace the paragraph:
by:
!corrigendum 3.9.2(06)
Replace the paragraph:
by:
!corrigendum 3.9.2(11)
Replace the paragraph:
The default_expression for a controlling formal parameter of a dispatching operation shall be tag indeterminate. A controlling formal parameter that is an access parameter shall not have a default_expression.
by:
The default_expression for a controlling formal parameter of a dispatching operation shall be tag indeterminate.
If a dispatching operation is defined by a subprogram_renaming_declaration or the instantiation of a generic subprogram, any access parameter of the renamed subprogram or the generic subprogram that corresponds to a controlling access parameter of the dispatching operation, shall be null excluding.
!corrigendum 3.9.2(18)
Replace the paragraph:
by:
!corrigendum 3.10.2(09)
Replace the paragraph:
by:
!corrigendum 3.10.2(10)
Replace the paragraph:
by:
!comment !corrigendum 3.10.2(11)
!comment Since we want no change, we commented out the change in AI-385.
!comment @ddel This paragraph, added by AI95-00385, should be deleted.
!corrigendum 3.10.2(12)
Replace the paragraph:
by:
!corrigendum 3.10.2(13)
!comment A fake to force a conflict.
@ddel The second paragraph added by AI95-00318 should be deleted.
!corrigendum 3.10.2(14)
Replace the paragraph:
by:
!corrigendum 04.08(05)
Insert after the paragraph:
If the type of the allocator is an access-to-constant type, the allocator shall be an initialized allocator. If the designated type is limited, the allocator shall be an uninitialized allocator.
the new paragraph:
If the designated subtype of the type of the allocator has one or more unconstrained access discriminants, then the accessibility level of the anonymous access type of each access discriminant, as determined by the subtype_indication or qualified_expression of the allocator, shall not be statically deeper than that of the type of the allocator (see 3.10.2).
!corrigendum 04.08(07)
!comment This includes the AI-344 change.
@drepl For the evaluation of an @fa<allocator>, the elaboration of the @fa<subtype_indication> or the evaluation of the @fa<qualified_expression> is performed first. For the evaluation of an initialized allocator, an object of the designated type is created and the value of the @fa<qualified_expression> is converted to the designated subtype and assigned to the object. @dby For the evaluation of an @fa<allocator>, the elaboration of the @fa<subtype_indication> or the evaluation of the @fa<qualified_expression> is performed first. For the evaluation of an initialized allocator, an object of the designated type is created and the value of the @fa<qualified_expression> is converted to the designated subtype and assigned to the object. If the designated type of the type of the @fa<allocator> is class-wide, then a check is made that the accessibility level of the type identified by the tag of the value of the @fa<qualified_expression> is not deeper than that of the type of the @fa<allocator>. If the designated subtype of the @fa<allocator> has one or more unconstrained 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 @fa<allocator>. Program_Error is raised if either such check fails.
!corrigendum 6.5(05)
Replace the paragraph:
A function body shall contain at least one return_statement that applies to the function body, unless the function contains code_statements. A return_statement shall include a return expression if and only if it applies to a function body.
by:
A function body shall contain at least one return_statement that applies to the function body, unless the function contains code_statements. A simple_return_statement shall include a return expression if and only if it applies to a function body. An extended_return_statement shall apply to a function body.
If the result subtype of a function is defined by a subtype_mark, the return_subtype_indication of an extended_return_statement that applies to the function body shall be a subtype_indication. The type of the subtype_indication shall be the result type of the function. If the result subtype of the function is constrained, then the subtype defined by the subtype_indication shall also be constrained and shall statically match this result subtype. If the result subtype of the function is unconstrained, then the subtype defined by the subtype_indication shall be a definite subtype, or there shall be a return expression.
If the result subtype of the function is defined by an access_definition, the return_subtype_indication shall be an access_definition. The subtype defined by the access_definition shall statically match the result subtype of the function. The accessibility level of this anonymous access subtype is that of the result subtype.
If the type of the return expression is limited, then the return expression shall be an aggregate, a function call (or equivalent use of an operator), or a qualified_expression or parenthesized expression whose operand is one of these.
If the result type is class-wide, the accessibility level of the type of the return expression shall not be statically deeper than that of the master that elaborated the function body. If the result subtype has one or more unconstrained access discriminants, the accessibility level of the anonymous access type of each access discriminant, as determined by the return_subtype_indication or the return expression, shall not be statically deeper than that of the master that elaborated the function body.
Static Semantics
Within an extended_return_statement, the return object is declared with the given identifier, with nominal subtype defined by the return_subtype_indication.
!corrigendum 6.5(06)
Replace the paragraph:
For the execution of a return_statement, the expression (if any) is first evaluated and converted to the result subtype.
by:
For the execution of an extended_return_statement, the subtype_indication or access_definition is elaborated. This creates the nominal subtype of the return object. If there is a return expression, it is evaluated and converted to the nominal subtype (which might raise Constraint_Error -- see 4.6) and becomes the initial value of the return object; otherwise, the return object is initialized by default as for a stand-alone object of its nominal subtype (see 3.3.1). If the nominal subtype is indefinite, the return object is constrained by its initial value. The handled_sequence_of_statements, if any, is then executed.
For the execution of a simple_return_statement, the expression (if any) is first evaluated and converted to the result subtype to become the value of the anonymous return object.
If the return object has any parts that are tasks, the activation of those tasks does not occur until after the function returns (see 9.2).
!corrigendum 6.5(20)
Insert after the paragraph:
The exception Program_Error is raised if this check fails.
by:
If the result type is class-wide, a check is made that the accessibility level of the type identified by the tag of the result is not deeper than that of the master that elaborated the function body. If the result subtype has one or more unconstrained access discriminants, a check is made that the accessibility level of the anonymous access type of each access discriminant, as determined by the return_subtype_indication or return expression, is not deeper than that of the master that elaborated the function body. If either check fails, Program_Error is raised.
!corrigendum 6.5(22)
Insert after the paragraph:
Finally, a transfer of control is performed which completes the execution of the construct to which the return_statement applies, and returns to the caller.
the new paragraph:
Implementation Permission
If the result subtype of a function is unconstrained, and a call on the function is used to provide the initial value of an object with a constrained nominal subtype, Constraint_Error may be raised at the point of the call while elaborating a return_subtype_indication or evaluating a return expression within the function, if it is determined that the value of the result will violate the constraint of this object's subtype.
!corrigendum 7.6.1(03)
Replace the paragraph:
After execution of a construct or entity is complete, it is left, meaning that execution continues with the next action, as defined for the execution that is taking place. Leaving an execution happens immediately after its completion, except in the case of a master: the execution of a task_body, a block_statement, a subprogram_body, an entry_body, or an accept_statement. A master is finalized after it is complete, and before it is left.
by:
After execution of a construct or entity is complete, it is left, meaning that execution continues with the next action, as defined for the execution that is taking place. Leaving an execution happens immediately after its completion, except in the case of a master: the execution of a body other than a package_body; the elaboration of a declaration other than the declaration of a package or of a type; the execution of a statement; or the evaluation of an expression or range that is not part of an enclosing expression, range, or simple_statement. A master is finalized after it is complete, and before it is left.
!corrigendum 9.2(02)
Replace the paragraph:
A task object (which represents one task) can be created either as part of the elaboration of an object_declaration occurring immediately within some declarative region, or as part of the evaluation of an allocator. All tasks created by the elaboration of object_declarations of a single declarative region (including subcomponents of the declared objects) are activated together. Similarly, all tasks created by the evaluation of a single allocator are activated together. The activation of a task is associated with the innermost allocator or object_declaration that is responsible for its creation.
by:
A task object (which represents one task) can be a part of a stand-alone object, of an object created by an allocator, or of an anonymous object of a limited type. All tasks that are part of any of the stand-alone objects created by the elaboration of object_declarations (or generic_associations of formal objects of mode in) of a single declarative region are activated together. All tasks that are part of a single object that is not a stand-alone object are activated together.
!corrigendum 9.2(03)
Replace the paragraph:
For tasks created by the elaboration of object_declarations of a given declarative region, the activations are initiated within the context of the handled_sequence_of_statements (and its associated exception_handlers if any -- see 11.2), just prior to executing the statements of the _sequence. For a package without an explicit body or an explicit handled_sequence_of_statements, an implicit body or an implicit null_statement is assumed, as defined in 7.2.
by:
For the tasks of a given declarative region, the activations are initiated within the context of the handled_sequence_of_statements (and its associated exception_handlers if any -- see 11.2), just prior to executing the statements of the _sequence. For a package without an explicit body or an explicit handled_sequence_of_statements, an implicit body or an implicit null_statement is assumed, as defined in 7.2.
!corrigendum 9.2(04)
Replace the paragraph:
For tasks created by the evaluation of an allocator, the activations are initiated as the last step of evaluating the allocator, after completing any initialization for the object created by the allocator, and prior to returning the new access value.
by:
For tasks that are part of a single object that is not a stand-alone object, activations are initiated after completing any initialization of the outermost object enclosing these tasks, prior to performing any other operation on the outermost object. In particular, for tasks that are part of the object created by the evaluation of an allocator, the activations are initiated as the last step of evaluating the allocator, prior to returning the new access value. For tasks that are part of an object that is the result of a function call, the activations are not initiated until after the function returns.
!ACATS test
Create C-Tests to check that controlling access results dispatch properly.
!appendix

!topic Accessibility level--contradiction?
!reference RM05 3.10.2, 7.6.1
!from Adam Beneschan 05-02-09
!discussion

I'm trying to understand how accessibility levels work with the new
generalized anonymous access type stuff, and I'm running into some
difficulties.  If my understanding of the RM is correct (a dubious
assumption), it appears that the RM is saying something
self-contradictory.

Consider this example:

   procedure P1 is

      type Rec is record
         C1 : access Integer;
      end record;

   begin...end P1;

As I understand it, the elaboration of Rec is now considered to be a
master, which has an accessibility level.  The type Rec also has an
accessibility level (3.10.2(7)).  Of course, the execution of P1 is a
master that has an accessibility level.  I'll denote these as
Level(Elaboration-of-Rec), Level(Rec), and Level(P1), and use ">" to
mean "deeper than".

According to 3.10.2(7), an entity created by a declaration has the
same accessibility level as the innermost enclosing master other than
the declaration itself.  The type Rec is an entity.  It seems clear
that the innermost enclosing master for this type declaration is the
execution of P1.  Thus, Level(Rec) = Level(P1).

3.10.2(12/2) says, "The accessibility level of the anonymous access
type of a component is that of the master that elaborated its
access_definition. This is the same as the level of the type whose
definition encloses the access_definition except in the case of an
access discriminant....."  Thus, the level of the anonymous access
type "access Integer" is that of the master that elaborated this
access definition.  If we follow 3.8(16-17), we find that the
elaboration of Rec, which is a master, contains the elaboration of the
record_definition, which contains the elaboration of the
component_list, which contains the elaboration of the component_items
(including component_declarations), which contain the elaboration of
the component_definition, which is the access_definition in this case.
Thus, the master that elaborated the access definition is the
elaboration of Rec.  This means that, according to this paragraph, the
accessibility level of the elaboration of this master,
i.e. Level(Elaboration-of-Rec), is the same as the level of the type
whose definition encloses the access definition, i.e. Level(Rec).
[And the level of the anonymous access type is the same as both.]
Thus, we have Level(Elaboration-of-Rec) = Level(Rec).

Since we already established that Level(Rec) = Level(P1), this means
Level(Elaboration-of-Rec) = Level(P1).

3.10.2(6) says that the accessibility level of a master is deeper than
that of each dynamically enclosing master.  Since the execution of P1
dynamically encloses the elaboration of Rec, which is a master, we
therefore have Level(Elaboration-of-Rec) > Level(P1).

Something's wrong.

*************************************************************

From: Tucker Taft
Sent: Wednesday, February  9, 2005  7:54 PM

I think you are right.  3.10.2(7/2) says the following:

    An entity or view created by a declaration has the same
    accessibility level as the innermost enclosing master other
    than the declaration itself except in the cases of renaming
    and derived access types described below. A parameter of a
    master has the same accessibility level as the master.

and 7.6.1(3/2) says:

    ... a master: the execution of a body other than a package_body;
    the elaboration of a declaration other than the declaration of a
    package; the execution of an accept_statement, a block_statement,
    or a simple_statement; or the evaluation of an expression or range
    that is not part of an enclosing expression, range, or
    simple_statement.

Although "access_definition" is not a declaration,
"component_declaration" and "type_declaration" are
both declarations, and we really only want one
level there.  So 7.6.1 should probably exempt type
declarations as well as package declarations from
being masters.  I think that would solve the problem
you identify.  Like package declarations, type
declarations are essentially "see-through."  Of course
entities created as part of the creation of an *object* of
the type are another matter, and those are clearly related
to the accessibility of the object, not the
type declaration.

> Consider this example:
>
>    procedure P1 is
>
>       type Rec is record
>          C1 : access Integer;
>       end record;
>
>    begin...end P1;
 > ...

If we eliminate "Rec" as a master, then the master
of the anonymous access type created by the
elaboration of "C1" is now P1, rather than Rec.
Which is what we want.

*************************************************************

From: Tucker Taft
Sent: Thursday, February 17, 2005  3:17 AM

Our last discussion about access discriminants
and allocators in Paris was a bit concerning,
I'm sure.  For what it's worth, I believe I have
worked out all the problems, and the "joined at
the hip" model will work for nonlimited types
as well.  Generally, the solution is to return
more closely to the rule that an access discriminant
always has the same level as the object it is
a component of.  I had broken that rule for objects
returned by functions when referring to an
access discriminant of a subcomponent of the
result, and that was causing the trouble, I
believe.  Calling a function and then only using
a part of the result is quite rare, and using
a part that happens to have an access discriminant
that is initialized from the enclosing object's
access discriminant is well below the noise
level.

Overall, the general rule becomes that as soon
as you select a component of a function result,
the function result is treated as a "temp",
and it takes on a very local accessibility
level, as do any access discriminants it has.
E.g.:

     X : T := func().component;

is not permitted if component has an access
discrim. initialized from the enclosing object,
because the call is a temp, and we are
trying to initialize a longer-lasting
object.  Another way to think about it is
that only when "build-in-place" is possible
can the result of the function call be
long-lived.

I'll write all this up in the next version of
the AI.

So those who were concerned can breathe easier. ;-)

*************************************************************


Questions? Ask the ACAA Technical Agent