!standard 3.2.3(01) 05-11-15 AI95-00416/12 !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(10) !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 9.3(02) !standard 9.3(03) !standard 13.11(25) !standard 13.11.1(3) !standard 13.11.2(9) !standard 13.11.2(10) !standard 13.11.2(17) !class amendment 05-02-07 !status Amendment 200Y 05-03-16 !status ARG Approved 8-0-1 05-04-18 !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] {of} 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 to directly initialize part of an object is that of the object being initialized from the execution of the called function result. The accessibility level of the result of a function call that is renamed in whole or in part is that of the innermost master of the object_renaming_declaration. Otherwise, the accessibility level of the result of a function call is that of the innermost master of the function call. 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, then 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: * The accessibility level of the anonymous access type of an access discriminant in the subtype_indication or qualified_expression of an allocator, or in the expression or return_subtype_indication of a return statement 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 innermost master of 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 3.10.2(16): In the above rules, the operand of a view conversion, parenthesized expression or qualified_expression is considered to be used in a context if the view conversion, parenthesized expression or qualified_expression itself is used in that context. 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). Move the text added to 4.8(7) by AI95-00344 to after 4.8(10), and modify it 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 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 subtype of the function is class-wide, the accessibility level of the type of the expression of the return statement 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 expression of the simple_return_statement or the return_subtype_indication, 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 the paragraph inserted before 6.5(6) by AI95-00318: 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 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 expression of the simple_return_statement or the return_subtype_indication, 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 the return_subtype_indication or evaluating the expression of a return statement that applies to the function body, 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; ] the execution of [an accept_statement, a block_statement, or a simple_statement] {a statement}; or the evaluation of an expression{, name,} or range that is not part of an enclosing expression, {name,} range, or... 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, or a coextension of one of these} [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 or coextensions 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 or coextensions 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 or coextensions 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 or coextensions 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 or coextensions 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 (or coextensions) are treated similarly to an object created by an allocator. The "whole" object is initialized, and then all of the task parts (including the coextensions) 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. Drop the changes to paragraphs 9.3(2) and 9.3(3) added by AI-162. Change the first bullet added by the replacement of 13.11(25) in AI-230 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. Change 13.11.2(10) as follows: 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 the paragraph added after 13.11.2(17) by AI-162. !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 expression of a simple return 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) @drepl An operation @i @i if it yields a value of type @i, if it has an operand whose expected type (see 8.6) is @i, or if it has an access parameter (see 6.1) designating @i. A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a @i of the type. The @i of a type are the predefined operations of the type, plus any user-defined primitive subprograms. @dby An operation @i @i if it yields a value of type @i, if it has an operand whose expected type (see 8.6) is @i, or if it has an access parameter or access result type (see 6.1) designating @i. A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a @i of the type. The @i of a type are the predefined operations of the type, plus any user-defined primitive subprograms. !corrigendum 3.3(10) @drepl @xbullet (or the equivalent operator invocation @emdash see 6.6);> @dby @xbullet (or the equivalent operator invocation @emdash see 6.6);> !corrigendum 3.7(27) @drepl An @fa is elaborated when the value of a corresponding access discriminant is defined, either by evaluation of its @fa or by elaboration of a @fa. The elaboration of an @fa 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). @dby For an access discriminant, its @fa is elaborated when the value of the access discriminant is defined: by evaluation of its @fa, by elaboration of a @fa, 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 is a call whose @fa or @fa denotes the declaration of a primitive subprogram of a tagged type, that is, a dispatching operation. A @i in a call on a dispatching operation of a tagged type @i is one whose corresponding formal parameter is of type @i or is of an anonymous access type with designated type @i; the corresponding formal parameter is called a @i. 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, then the call has a @i -- the context of the call can control the dispatching. @dby A @i is a call whose @fa or @fa denotes the declaration of a dispatching operation. A @i in a call on a dispatching operation of a tagged type @i is one whose corresponding formal parameter is of type @i or is of an anonymous access type with designated type @i; the corresponding formal parameter is called a @i. 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, then the call has a @i -- the context of the call can control the dispatching. Similarly, if the call is to a function with access result type designating @i, then the call has a @i, and the context can similarly control dispatching. !corrigendum 3.9.2(04) @drepl @xbullet or expression is @i if it is of a specific tagged type and, if it is a call with a controlling result, it has at least one statically tagged controlling operand; > @dby @xbullet or expression is @i if it is of a specific tagged type and, if it is a call with a controlling result or controlling access result, it has at least one statically tagged controlling operand;> !corrigendum 3.9.2(05) @drepl @xbullet or expression is @i if it is of a class-wide type, or it is a call with a controlling result and at least one dynamically tagged controlling operand;> @dby @xbullet or expression is @i if it is of a class-wide type, or it is a call with a controlling result or controlling access result and at least one dynamically tagged controlling operand;> !corrigendum 3.9.2(06) @drepl @xbullet or expression is @i if it is a call with a controlling result, all of whose controlling operands (if any) are tag indeterminate.> @dby @xbullet or expression is @i if it is a call with a controlling result or controlling access result, all of whose controlling operands (if any) are tag indeterminate.> !corrigendum 3.9.2(11) @drepl The @fa 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 @fa. @dby The @fa for a controlling formal parameter of a dispatching operation shall be tag indeterminate. If a dispatching operation is defined by a @fa 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) @drepl @xbullet, then its controlling tag value is determined by the controlling tag value of this enclosing call;> @dby @xbullet, then its controlling tag value is determined by the controlling tag value of this enclosing call;> @xbullet whose target is of a class-wide type, then its controlling tag value is determined by the target;> !corrigendum 3.10.2(07) @drepl @xbullet @dby @xbullet !corrigendum 3.10.2(09) @drepl @xbullet @dby @xbullet, or parenthesized expression, is the same as that of the operand.> !corrigendum 3.10.2(10) @drepl @xbullet @dby @xbullet. Otherwise, the accessibility level of the result of a function call is that of the innermost master of the function call.> @xbullet !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) @drepl @xbullet @dby @xbullet of an @fa is the same as that of the renamed view.> @xbullet or @fa of an @fa, or in the @fa or @fa of a return statement is determined as follows:> @xinbull in a @fa, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);> @xinbull where the value of the discriminant is determined by a @fa in the @fa, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);> @xinbull !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) @drepl @xbullet is the same as that of the access type.> @dby @xbullet is the same as that of the access type, except for an @fa of an anonymous access type that defines the value of an access parameter or an access discriminant. For an @fa defining the value of an access parameter, the accessibility level is that of the innermost master of the call. For one defining an access discriminant, the accessibility level is determined as follows:> @xinbull used to define the constraint in a @fa, the level of the @fa;> @xinbull used to define the constraint in a @fa, the level of the enclosing type;> @xinbull used to define the discriminant of an object, the level of the object.> @xindent 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).> !corrigendum 3.10.2(16) @dinsa @xbullet @dinst In the above rules, the operand of a view conversion, parenthesized expression or @fa is considered to be used in a context if the view conversion, parenthesized expression or @fa itself is used in that context. !corrigendum 04.08(05) @dinsa If the type of the @fa is an access-to-constant type, the @fa shall be an initialized allocator. If the designated type is limited, the @fa shall be an uninitialized allocator. @dinst If the designated subtype of the type of the @fa has one or more unconstrained access discriminants, then the accessibility level of the anonymous access type of each access discriminant, as determined by the @fa or @fa of the @fa, shall not be statically deeper than that of the type of the @fa (see 3.10.2). !corrigendum 04.08(10) !comment This includes the AI-344 change. @dinsa @xbullet of the @fa; any per-object constraints on subcomponents are elaborated (see 3.8) and any implicit initial values for the subcomponents of the object are obtained as determined by the @fa and assigned to the corresponding subcomponents. A check is made that the value of the object belongs to the designated subtype. Constraint_Error is raised if this check fails. This check and the initialization of the object are performed in an arbitrary order.> @dinst For any @fa, if the designated type of the type of the @fa is class-wide, then a check is made that the accessibility level of the type determined by the @fa, or by the tag of the value of the @fa, is not deeper than that of the type of the @fa. If the designated subtype of the @fa 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. Program_Error is raised if either such check fails. !corrigendum 6.5(05) @drepl A function body shall contain at least one @fa that applies to the function body, unless the function contains @fas. A @fa shall include a return expression if and only if it applies to a function body. @dby A function body shall contain at least one @fa that applies to the function body, unless the function contains @fas. A @fa shall include an @fa if and only if it applies to a function body. An @fa shall apply to a function body. If the result subtype of a function is defined by a @fa, the @fa of an @fa that applies to the function body shall be a @fa. The type of the @fa shall be the result type of the function. If the result subtype of the function is constrained, then the subtype defined by the @fa 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 @fa shall be a definite subtype, or there shall be an @nt{expression}. If the result subtype of the function is defined by an @fa, the @fa shall be an @fa. The subtype defined by the @fa 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 result subtype of the function is limited, then the @fa shall be an @fa, a function call (or equivalent use of an operator), or a @fa or parenthesized expression whose operand is one of these. If the result subtype of the function is class-wide, the accessibility level of the type of the @fa of the return statement 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 @fa of the @fa or the @fa, shall not be statically deeper than that of the master that elaborated the function body. @i<@s8> Within an @fa, the @i is declared with the given identifier, with the nominal subtype defined by the @fa. !corrigendum 6.5(06) @drepl For the execution of a @fa, the @fa (if any) is first evaluated and converted to the result subtype. @dby For the execution of an @fa, the @fa or @fa is elaborated. This creates the nominal subtype of the return object. If there is an @fa, it is evaluated and converted to the nominal subtype (which might raise Constraint_Error @emdash 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 @fa, if any, is then executed. For the execution of a @fa, the @fa (if any) is first evaluated and converted to the result subtype to become the value of the anonymous @i. 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) @dinsa The exception Program_Error is raised if this check fails. @dby 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 @fa of the @fa or the @fa, 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) @dinsa Finally, a transfer of control is performed which completes the execution of the construct to which the @fa applies, and returns to the caller. @dinst @i<@s8> 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 (after abandoning the execution of the function body) if, while elaborating the @fa or evaluating the @fa of a return statement that applies to the function body, it is determined that the value of the result will violate the constraint of this object's subtype. !corrigendum 7.6.1(03) @drepl After execution of a construct or entity is complete, it is @i, 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 @i: the execution of a @fa, a @fa, a @fa, an @fa, or an @fa. A master is finalized after it is complete, and before it is left. @dby After execution of a construct or entity is complete, it is @i, 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 @i: the execution of a body other than a @fa; the execution of a @fa; or the evaluation of an @fa, @fa, or @fa that is not part of an enclosing @fa, @fa, @fa, or @fa. A master is finalized after it is complete, and before it is left. !corrigendum 7.6.1(09) @drepl @xbullets.> @dby @xbullets;> @xbullet !corrigendum 9.2(02) @drepl A task object (which represents one task) can be created either as part of the elaboration of an @fa occurring immediately within some declarative region, or as part of the evaluation of an @fa. All tasks created by the elaboration of @fas of a single declarative region (including subcomponents of the declared objects) are activated together. Similarly, all tasks created by the evaluation of a single @fa are activated together. The activation of a task is associated with the innermost @fa or @fa that is responsible for its creation. @dby A task object (which represents one task) can be a part of a stand-alone object, of an object created by an @fa, or of an anonymous object of a limited type, or a coextension of one of these. All tasks that are part or coextensions of any of the stand-alone objects created by the elaboration of @fas (or @fas of formal objects of mode @b) of a single declarative region are activated together. All tasks that are part or coextensions of a single object that is not a stand-alone object are activated together. !corrigendum 9.2(03) @drepl For tasks created by the elaboration of @fas of a given declarative region, the activations are initiated within the context of the @fa (and its associated @fas if any @emdash see 11.2), just prior to executing the statements of the @fa<_sequence>. For a package without an explicit body or an explicit @fa, an implicit body or an implicit @fa is assumed, as defined in 7.2. @dby For the tasks of a given declarative region, the activations are initiated within the context of the @fa (and its associated @fas if any @emdash see 11.2), just prior to executing the statements of the @fa. For a package without an explicit body or an explicit @fa, an implicit body or an implicit @fa is assumed, as defined in 7.2. !corrigendum 9.2(04) @drepl For tasks created by the evaluation of an @fa, the activations are initiated as the last step of evaluating the @fa, after completing any initialization for the object created by the @fa, and prior to returning the new access value. @dby For tasks that are part or coextensions 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 or coextensions of the object created by the evaluation of an @fa, the activations are initiated as the last step of evaluating the @fa, prior to returning the new access value. For tasks that are part or coextensions of an object that is the result of a function call, the activations are not initiated until after the function returns. !corrigendum 13.11(25) @drepl A storage pool for an anonymous access type should be created at the point of an allocator for the type, and be reclaimed when the designated object becomes inaccessible. @dby The storage pool used for an @fa of an anonymous access type should be determined as follows: @xbullet is defining a coextension (see 3.10.2) of an object being created by an outer @fa, then the storage pool used for the outer @fa should also be used for the coextension;> @xbullet, and be reclaimed when the allocated object becomes inaccessible.> !corrigendum 13.11.1(3) @drepl Denotes the maximum value for Size_In_Storage_Elements that will be requested via Allocate for an access type whose designated subtype is S. The value of this attribute is of type @i. @dby Denotes the maximum value for Size_In_Storage_Elements that will be requested via Allocate for an access type whose designated subtype is S. For a type with access discriminants, if the implementation allocates space for a coextension in the same pool as that of the object having the access discriminant, then this accounts for any calls on Allocate that could be performed to provide space for such coextensions. The value of this attribute is of type @i. !corrigendum 13.11.2(9) @drepl @xhang<@xterm<3.>Free(X), when X is not equal to @b first performs finalization, as described in 7.6. It then deallocates the storage occupied by the object designated by X. If the storage pool is a user-defined object, then the storage is deallocated by calling Deallocate, passing @i'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. @dby @xhang<@xterm<3.>Free(X), when X is not equal to @b first performs finalization of the object designated by X (and any coextensions of the object @emdash 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 @i'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. !corrigendum 13.11.2(10) @drepl After Free(X), the object designated by X, and any subcomponents thereof, no longer exist; their storage can be reused for other purposes. @dby 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. !comment !corrigendum 13.11.2(17) !comment This just removes the change made by AI-00416. It is removed !comment there, and nothing need be done here. !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. ;-) *************************************************************