Version 1.1 of ai05s/ai05-0075-1.txt

Unformatted version of ai05s/ai05-0075-1.txt version 1.1
Other versions for file ai05s/ai05-0075-1.txt

!standard 4.8(5.2/2)          07-10-30 AI05-0075-1/01
!standard 4.8(10.1/2)
!standard 6.5(5.3/2)
!standard 6.5(5.6/2)
!standard 6.5(21/2)
!class binding interpretation 07-10-30
!status work item 07-10-30
!status received 07-10-30
!priority Medium
!difficulty Hard
!qualifier Omission
!subject More access discriminant checks needed
!summary
New checks to avoid dangling discriminants are performed.
!question
In the case where the result returned by a function has one or more access discriminants, should the runtime check of 6.5(21/2) be performed even if the function result type is class-wide and does not have the same discriminants as the function result? (Yes.)
Should similar checks be performed for class-wide allocators? (Yes.)
Should compile-time checks analogous to the existing checks of 4.8(5.2/2) and 6.5(5.6/2) also be performed? (Yes.)
!recommendation
Additional static and runtime checks are performed (see wording).
!wording
Append after 4.8(5.2/2)
This condition shall also hold if the designated subtype of the type of the allocator is class-wide and the type determined by the subtype_indication or qualified_expression of the allocator has one or more noninherited access discriminants.
Append after 4.8(10.1/2)
If the designated type of the type of the allocator is class-wide, then a check is made that either the type of the allocated object (that is, the type determined either by the subtype_indication or by the tag of the value of the qualified_expression) lacks noninherited access discriminants or 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 the check fails.
Append after 6.5(5.3/2) (as a new item in the same bulleted list):
- If the result subtype of the function is class-wide, the
accessibility level of the type of the subtype defined by the return_subtype_indication shall not be statically deeper than that of the master that elaborated the function body.
In 6.5(5.6/2) replace
- 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.
with two separate bulleted items
- If the result subtype of the function is class-wide, the
accessibility level of the type of the expression of the return statement (if any) 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. If the result subtype of the function is class-wide, this condition shall also hold if the type of the expression of the return statement (if any) or the type of the result_subtype_indication (if any) has one or more noninherited access discriminants.
Append after 6.5(21/2):
If the result type of the function is class-wide, then a check is made that either the (specific) type of the function result lacks noninherited access discriminants or that the accessibility level of the anonymous access type of each access discriminant is not deeper than that of the master that elaborated the function body. If the check fails, Program_Error is raised.
!discussion
A wording change in 6.5(21/2) seems to be needed; in the case of a class-wide result type, the specified check may need to be performed even if the result type of the function has no access discriminants.
Consider the following example:
declare type Root is tagged null record; type Ext (D : access Integer) is new Root with null record;
function F return Root'Class is Local_Var : aliased Integer;
function Local_Func return Ext is begin return (D => Local_Var'access); end Local_Func; begin return Local_Func; end F;
procedure Do_Something (X : access Integer) is ... end; begin Do_Something (Ext (F).D); end;
If this test executes without raising any exception, then a dangling reference will be passed to Do_Something. It seems that the check described in 6.5(21/2) needs to be performed as part of returning from F, but the result subtype of F lacks unconstrained access discriminants.
This will introduce distributed overhead in the sense that a function which returns a classwide result may have to check for the possibility that its result has a "bad" access discriminant values even if there are no access discriminants anywhere in the program. For some implementations, this might involve querying a "has anonymous access discriminants" flag in the descriptor associated with a specific tagged type.
There is an analogous problem for allocators. Consider the following variation on the preceding example:
declare type Root is tagged null record; type Ext (D : access Integer) is new Root with null record;
type Ref is access Root'Class;
function F return Ref is Local_Var : aliased Integer;
function Local_Func return Ext is begin return (D => Local_Var'access); end Local_Func; begin return new Ext'(Local_Func); end F;
procedure Do_Something (X : access Integer) is ... end; begin Do_Something (Ext (F.all).D); end;
At a minimum, additional runtime checks are needed to cover these cases (see 4.8(10.1/2), 6.5(21/2)). Just adding runtime checks would be sloppy. Additional static checks are also needed (see 4.8(5.2/2) and 6.5(5.6/2)). So that's what's been done.
A couple of other changes that really should have gone into AI05-0032 are also included to handle static rejection of cases like
function Foo return T'Class is type Local_Extension is new T with null record; begin return X : Local_Extension; end Foo;
--!corrigendum 7.6.1(17.1/1)
!ACATS Test
ACATS B-Tests and C-Tests need to check the new rules.
!appendix

[The original question can be found in AI05-0051-1, from which this AI was split. - ED.]

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

Questions? Ask the ACAA Technical Agent