CVS difference for ai05s/ai05-0142-4.txt

Differences between 1.8 and version 1.9
Log of other versions for file ai05s/ai05-0142-4.txt

--- ai05s/ai05-0142-4.txt	2010/04/29 06:27:42	1.8
+++ ai05s/ai05-0142-4.txt	2010/06/11 23:25:35	1.9
@@ -1,5 +1,6 @@
-!standard 3.10(9/2)                                  10-04-12  AI05-0142-4/06
+!standard 3.10(9/2)                                  10-06-11  AI05-0142-4/07
 !standard 3.10.2(13.1/2)
+!standard 3.10.2(19/2)
 !standard 6.1(15/2)
 !standard 6.1(23)
 !standard 6.2(3)
@@ -76,7 +77,18 @@
 on the proposed solution for AI-51; the return object then will have the correct
 level. - RLB]
 
+Add after 3.10.2(19/2): [This is a modification of a rule from AI05-0051-1, and replaces that rule.]
 
+   * Inside a return statement that applies to a function F, when
+     determining whether the accessibility level of an explicitly
+     aliased parameter of F is statically deeper than the level of the
+     return object of F, the level of the return object is presumed to
+     be the same as that of the level of the explicitly aliased
+     parameter; for statically comparing with the level of other
+     entities, the level of the return object of F is
+     presumed to be the same as that of the master that elaborated
+     the function body of F.
+
 Replace 6.1(15/2) by:
 
 parameter_specification ::=
@@ -141,10 +153,11 @@
 for each explicitly aliased parameter shall not be statically deeper than
 accessibility level of the master of the function result.
 
-[We could make this rule apply to all calls, since it can only fail for functions that
-initialize allocators, but that doesn't seem to add anything interesting. Note that we
-don't change the lifetime of anonymous objects or the accessibility of aliased parameters
-for procedures, so it would be somewhat weird to have this apply to procedures as well.]
+[Editor's note: We could have made this rule apply to all calls, since it can only fail for
+functions that initialize allocators, but that doesn't seem to add anything interesting. Note
+that we don't change the lifetime of anonymous objects or the accessibility of aliased
+parameters for procedures (since there is no return object to change the accessibility to),
+so it would be somewhat weird to have this apply to procedures as well.]
 
 AARM Discussion: Since explicitly aliased parameters are either tagged or required to be
 objects, there is always an object (possibly anonymous) to talk about. This is discussing
@@ -158,20 +171,19 @@
 in the initializer of an allocator; in all other cases this check will always pass.
 
 Add a new Dynamic Semantics rule after 6.4.1(15): (this would be a new, outer level, bullet)
-
-In a function call, for each explicitly aliased parameter, a
-check is made that the accessibility level of the master of the actual object is
-the same as or includes that of the master of the function result.
 
-AARM To Be Honest: We're talking about the "nominal" level of the actual object.
-If the actual object is a formal parameter of some function call F, we do not
-intend to require dynamic checks that depend on the master of the actual
-parameters to F, as that would cause nasty distributed overhead (all tagged and
-explicitly aliased parameters would have to carry accessibility levels).
+* In a function call, for each explicitly aliased parameter, a
+  check is made that the accessibility level of the master of the actual object is
+  not deeper than that of the master of the function result.
+
+AARM Ramification: If the actual object to a call C is a formal parameter of some
+function call F, no dynamic check against the master of the actual parameter of F is
+necessary. Any case which could fail the dynamic check is already statically illegal
+(either at the call site of F, or at the call site C). This is important, as
+it would require nasty distributed overhead to accurately know the dynamic accessibility
+of a formal parameter (all tagged and explicitly aliased parameters would have to carry
+accessibility levels).
 
-[Q: Is there a way to reword this to make the above clear?? Masters are usually
-a dynamic concept, but here we only want to use the master we know, not the actual
-master of the underlying object (which could be different).]
 
 Modify 7.6.1(13/3): [This wording was modified by AI05-0066-1]
 
@@ -210,7 +222,7 @@
 
 If an atomic object is passed as a parameter, then the [type of the] formal parameter shall
 either [be atomic]{have an atomic type} or allow pass by copy [(that is, not be a nonatomic
-by-reference type)]. 
+by-reference type)].
 
 AARM Reason: A formal parameter allows pass by copy if it is not aliased and it is of a type
 that allows pass by copy (that is, is not a by-reference type).
@@ -378,7 +390,7 @@
    if this check fails.
 
 AARM Notes: This check can only fail if the view is a formal parameter, in all other cases
-static matching will ensure that it is successful. 
+static matching will ensure that it is successful.
 
 This doesn't seem to save much wording nor allow many additional cases.
 
@@ -1465,15 +1477,15 @@
 
 > > > Otherwise, Accessor returns an object whose discriminant is an access
 > > > to =
-> > 
+> >
 > > "discriminant designates"
-> 
-> That can't be right, 3.10(1) says that "designates" is something that 
-> an access value does to an object. I don't mind using a better verb 
-> here, but one that has a defined meaning (and surely could be confused 
+>
+> That can't be right, 3.10(1) says that "designates" is something that
+> an access value does to an object. I don't mind using a better verb
+> here, but one that has a defined meaning (and surely could be confused
 > here, given that we're talking about access types) won't do.
-> 
-> We could say "an access that designates the element" (that's better 
+>
+> We could say "an access that designates the element" (that's better
 > than "to").
 
 I don't understand your objection.  It seems like "designates" is exactly
@@ -1494,7 +1506,7 @@
 From: Bob Duff
 Sent: Tuesday, May 19, 2009  6:03 PM
 
-> Your suggestion "discriminant designates an access to ..." does not 
+> Your suggestion "discriminant designates an access to ..." does not
 > make sense.
 
 I agree it makes no sense, but that's not my suggestion.  ;-) Sorry for being unclear.
@@ -1527,15 +1539,15 @@
 From: Randy Brukardt
 Sent: Wednesday, May 20, 2009  12:24 PM
 
-> but I think it's unnecessarily verbose -- we know it's an access 
-> value, because it's declared to be of an access type, just a few 
+> but I think it's unnecessarily verbose -- we know it's an access
+> value, because it's declared to be of an access type, just a few
 > paragraphs earlier.
 
 OK, but I disagree. I really want to emphasize that an access (not some sort of
 value) is being returned.
- 
+
 > I don't think we ever use the phrase "an access to" in the RM.
-> (If we called the silly things "pointers", like the rest of the world 
+> (If we called the silly things "pointers", like the rest of the world
 > does, wording would be easier!)
 
 I do realize that, which is why I did replace the "to" with "that designates".
@@ -1593,7 +1605,7 @@
 >       Randy's desire to relax the matching rules somewhat
 >       for explicitly aliased formal parameters of a
 >       discriminated type.
-> 
+>
 >       For 'Access, since there is no 'Constrained attribute
 >       for heap objects, we have to have tighter matching
 >       rules since you have to be able to decide whether
@@ -1652,16 +1664,16 @@
 Sent: Friday, May 22, 2009  2:12 PM
 
 > Well, it would allow something like:
-> 
+>
 >     type Rec (D : Natural := 100) is ...
-> 
+>
 >     Cobj : aliased Rec(10);
-> 
+>
 >     function Accessor (Param : aliased in out Rec; ...) return ...
-> 
+>
 >     := Accessor (Cobj);
-> 
-> as long as the body of Accessor does not use 'Access of the entire 
+>
+> as long as the body of Accessor does not use 'Access of the entire
 > parameter into an access-to-Rec.
 
 This would be legal even if we used the rules for 'Access, though I realize you would
@@ -1669,11 +1681,11 @@
 to explain and understand if we simply fall back on the availability of the 'Constrained
 attribute.
 
-> Actually, this seems pretty important, because the above is very 
-> similar to the form of the bounded containers. The actual objects have 
-> bounds, but of course the subprograms take unconstrained objects. (The 
-> difference is that the bounded containers, being tagged objects, don't 
-> allow defaulted discriminants. But surely I can imagine someone 
+> Actually, this seems pretty important, because the above is very
+> similar to the form of the bounded containers. The actual objects have
+> bounds, but of course the subprograms take unconstrained objects. (The
+> difference is that the bounded containers, being tagged objects, don't
+> allow defaulted discriminants. But surely I can imagine someone
 > building an untagged
 > container.)
 
@@ -1689,9 +1701,9 @@
 make one R.R. happier, that's fine with me!
 
 >     Acc : access Rec := Cobj'Access; -- Illegal.
-> 
-> (At least I hope the above is illegal, 'cause it would allow changing 
-> the discriminant of a constrained object!! Acc.all := (D => 20, ...) 
+>
+> (At least I hope the above is illegal, 'cause it would allow changing
+> the discriminant of a constrained object!! Acc.all := (D => 20, ...)
 > surely is
 > legal.)
 
@@ -1710,41 +1722,41 @@
 
 ...
 > > Well, it would allow something like:
-> > 
+> >
 > >     type Rec (D : Natural := 100) is ...
-> > 
+> >
 > >     Cobj : aliased Rec(10);
-> > 
+> >
 > >     function Accessor (Param : aliased in out Rec; ...) return ...
-> > 
+> >
 > >     := Accessor (Cobj);
-> > 
-> > as long as the body of Accessor does not use 'Access of the entire 
+> >
+> > as long as the body of Accessor does not use 'Access of the entire
 > > parameter into an access-to-Rec.
-> 
-> This would be legal even if we used the rules for 'Access, though I 
-> realize you would need convincing.  The relevant paragraph is 
-> 3.10.2(27.2).  But I agree it is simpler to explain and understand if 
+>
+> This would be legal even if we used the rules for 'Access, though I
+> realize you would need convincing.  The relevant paragraph is
+> 3.10.2(27.2).  But I agree it is simpler to explain and understand if
 > we simply fall back on the availability of the 'Constrained attribute.
 
 I obviously have had a brain meltdown, must be the sudden onset of summer (we seem
 to have skipped spring altogether). But now I wonder if 'Constrained would be helpful.
 
-> > Actually, this seems pretty important, because the above is very 
-> > similar to the form of the bounded containers. The actual objects 
-> > have bounds, but of course the subprograms take unconstrained 
-> > objects. (The difference is that the bounded containers, being 
-> > tagged objects, don't allow defaulted discriminants. But surely I 
+> > Actually, this seems pretty important, because the above is very
+> > similar to the form of the bounded containers. The actual objects
+> > have bounds, but of course the subprograms take unconstrained
+> > objects. (The difference is that the bounded containers, being
+> > tagged objects, don't allow defaulted discriminants. But surely I
 > > can imagine someone building an untagged container.)
-> 
+>
 > The only time "access Rec" doesn't allow "Cobj'Access"
-> is if there is a partial view of Rec that is constrained (that is, the 
-> partial view is simply "type Rec is private;", and the discriminants 
+> is if there is a partial view of Rec that is constrained (that is, the
+> partial view is simply "type Rec is private;", and the discriminants
 > are only visible in the private part).
-> We don't allow Cobj'Access in that case because the assumption is that 
-> all designated objects are unconstrained (to avoid privacy breaking).  
-> For a container either the discriminants would be visible, or clients 
-> could never declare constrained objects, so you would never bump into 
+> We don't allow Cobj'Access in that case because the assumption is that
+> all designated objects are unconstrained (to avoid privacy breaking).
+> For a container either the discriminants would be visible, or clients
+> could never declare constrained objects, so you would never bump into
 > the problem.
 
 Humm. In that case, 'Constrained is definitely *not* what we want. We want static matching
@@ -1768,30 +1780,30 @@
 I'll add some "alternative" discussion about potential runtime checks to avoid the static checks.
 
 > >     Acc : access Rec := Cobj'Access; -- Illegal.
-> > 
-> > (At least I hope the above is illegal, 'cause it would allow 
-> > changing the discriminant of a constrained object!! Acc.all := (D => 
+> >
+> > (At least I hope the above is illegal, 'cause it would allow
+> > changing the discriminant of a constrained object!! Acc.all := (D =>
 > > 20, ...) surely is legal.)
-> 
-> No it's not legal to change the discriminants through an access value, 
+>
+> No it's not legal to change the discriminants through an access value,
 > since in most cases, heap objects are constrained.
 
 Well, you have convinced me that the above is legal. <PEDANT> And it is *legal* to try to
 change the discriminants of a designated object: but it must raise Constraint_Error.</PENDANT>
 
-> In 2005 we added an exception for types whose partial view has no 
+> In 2005 we added an exception for types whose partial view has no
 > visible discriminant part -- those are presumed
-> *always* unconstrained in the heap, but of course only code that has 
-> visibility on the full type would even notice.  At least that is what 
+> *always* unconstrained in the heap, but of course only code that has
+> visibility on the full type would even notice.  At least that is what
 > 3.10.2(27.2) is *supposed* to be accomplishing.
-> Apparently at least in your case, it accomplished total obfuscation.  
-> Perhaps a note (if only in the AARM) might be useful on this 
+> Apparently at least in your case, it accomplished total obfuscation.
+> Perhaps a note (if only in the AARM) might be useful on this
 > paragraph.
 
 I think there is such a note in the vicinity. But of course I thought I remembered how this
 all works, rather than actually looking it up. Which doesn't always work out. :-) And what I
 did look up I read in the paper RM, so I didn't see the AARM notes.
- 
+
 ****************************************************************
 
 From: Christoph Grein
@@ -1816,8 +1828,9 @@
 
 end Safe_Pointers.On_Limited_Types;
 
-This was valid in Ada 95: Value was a return-by-reference function and returned a constant
-view. Ada 2005 removed the return-by-reference-types, so I have to replace Value by:
+This was valid in Ada 95: Value was a return-by-reference function and returned
+a constant view. Ada 2005 removed the return-by-reference-types, so I have to
+replace Value by:
 
   function Value (Pointer: Safe_Pointer) return access Object;
 
@@ -1825,7 +1838,7 @@
 
 If I understand the AI correctly, it would allow to define
 
-  type Accessor_Type (Element: not null access Object) is taged limited private;
+  type Accessor_Type (Element: not null access Object) is tagged limited private;
 
   function Accessor (Pointer: aliased in out Safe_Pointer) return Accessor_Type;
 
@@ -1833,8 +1846,9 @@
 
   X: Accessor_Type := Accessor (My_Pointer);
 
-where X.Element.all is a constant view of the object denoted by My_Pointer (a variable view
-if Limited is removed everywhere above), which would restore the safety of my safe pointers.
+where X.Element.all is a constant view of the object denoted by My_Pointer (a
+variable view if Limited is removed everywhere above), which would restore the
+safety of my safe pointers.
 
 How would I define the complete type and the body of Value?
 
@@ -1844,18 +1858,18 @@
 Sent: Monday, July 6, 2009  1:13 PM
 
 ...
-> where X.Element.all is a constant view of the object denoted by 
-> My_Pointer (a variable view if Limited is removed everywhere above), 
+> where X.Element.all is a constant view of the object denoted by
+> My_Pointer (a variable view if Limited is removed everywhere above),
 > which would restore the safety of my safe pointers.
 
-X.Element.all is always a variable view; if you wanted a constant view you would need to
-add "constant" to the discriminant declaration.
+X.Element.all is always a variable view; if you wanted a constant view you would
+need to add "constant" to the discriminant declaration.
 
 > How would I define the complete type and the body of Value?
 
-Well, I assume you mean the body of "Accessor" in your example (you'd probably call that
-Value). It depends of course on what's in your private part, since you didn't give that I
-can only guess.
+Well, I assume you mean the body of "Accessor" in your example (you'd probably
+call that Value). It depends of course on what's in your private part, since you
+didn't give that I can only guess.
 
 Assuming that the type Safe_Pointer is implemented as follows:
 
@@ -1878,35 +1892,38 @@
         return Pointer.Ptr;
     end Value;
 
-This is safe because of the accessibility checks. The Pointer parameter to Value will be
-required to live longer than the function result. Typically, the function result will have
-a very local lifetime. That means that it cannot be assigned to any other access type, so
-about all that can be done with it is to dereference it. If you do manage to use the value
-in a context (that's easier for "access Object" than for the discriminant case) where it
-lives a long time, the parameter has to live as long or longer, so it stays safe.
+This is safe because of the accessibility checks. The Pointer parameter to Value
+will be required to live longer than the function result. Typically, the
+function result will have a very local lifetime. That means that it cannot be
+assigned to any other access type, so about all that can be done with it is to
+dereference it. If you do manage to use the value in a context (that's easier
+for "access Object" than for the discriminant case) where it lives a long time,
+the parameter has to live as long or longer, so it stays safe.
 
-Note that you don't need "in out" here, because you aren't (ever) going to return part of
-the actual object. If your Safe_Pointer type could be defined:
+Note that you don't need "in out" here, because you aren't (ever) going to
+return part of the actual object. If your Safe_Pointer type could be defined:
     type Safe_Pointer is record
         Obj : aliased Object;
         Refs : Natural := 0;
         ...
-    end record;     
-then you would need "in out". (That can't happen in this case, but it can for the containers.)
+    end record;
+then you would need "in out". (That can't happen in this case, but it can for
+the containers.)
 
-Note that you'd probably want to declare Safe_Pointer "tagged" so that your users wouldn't
-have to declare every object as "aliased".
+Note that you'd probably want to declare Safe_Pointer "tagged" so that your
+users wouldn't have to declare every object as "aliased".
 
-For this definition, I'm assuming that there aren't any operations that can invalidate an
-existing Safe_Pointer object. If such operations exist (seems likely), then you would want
-a more complex scheme where you can keep track of the existence of the (raw) pointer:
+For this definition, I'm assuming that there aren't any operations that can
+invalidate an existing Safe_Pointer object. If such operations exist (seems
+likely), then you would want a more complex scheme where you can keep track of
+the existence of the (raw) pointer:
 
    type Accessor_Type (Element: not null access Object) is tagged limited private;
 
    function Value (Pointer: aliased in out Safe_Pointer) return Accessor_Type;
 
-For uses of Value, generally you would ignore the Accessor_Type object and just dereference
-the discriminant directly:
+For uses of Value, generally you would ignore the Accessor_Type object and just
+dereference the discriminant directly:
 
    ... Value (My_Ptr).Element.all ...
 
@@ -1919,8 +1936,8 @@
         ...
     end record;
 
-Accessor_Type would be defined as limited controlled so that you get an indication when
-the access ceases to exist:
+Accessor_Type would be defined as limited controlled so that you get an
+indication when the access ceases to exist:
 
    type Accessor_Type (Element: not null access Object) is new Ada.Finalization.Limited_Controlled with record
        My_Ptr : not null access Safe_Pointer; -- Default initialization will raise Constraint_Error.
@@ -1928,9 +1945,9 @@
 
    procedure Finalize (Object : in out Accessor_Type);
 
-We want a default-initialized object of Accessor_Type to raise an exception, as we only want
-Value to create one. We can't use the unknown discriminants
-(<>) trick here, as the whole point is the discriminant.
+We want a default-initialized object of Accessor_Type to raise an exception, as
+we only want Value to create one. We can't use the unknown discriminants (<>)
+trick here, as the whole point is the discriminant.
 
 And the bodies:
 
@@ -1945,18 +1962,356 @@
        Object.My_Ptr.Raw_Refs := Object.My_Ptr.Raw_Refs - 1;
 	    -- Will raise Constraint_Error if there is an underflow, that shouldn't be possible.
    end Finalize;
+
+Then, any operation that invalidates a Safe_Pointer object should first check
+that the Raw_Refs counter is equal to 0; if it is not, an exception should be
+raised instead. (The containers raise Program_Error for a "tampering" event.)
+
+This way, once someone creates an access value to access the actual object, the
+Safe_Pointer will be "locked" against modification until the access value is no
+longer accessible (that is, the locking will continue so long as the access
+value exists).
+
+Of course, there are a number of ways to circumvent this safety (using
+Unchecked_Deallocation, Unchecked_Access, or Unchecked_Conversion). But that is
+true for any Ada feature; one has to assume that the programmers are not
+intentionally shooting themselves in the foot. (Uncontrolled use of "Unchecked"
+anything is dangerous - that's why they're called "Unchecked", after all.)
+
+****************************************************************
+
+Summary of private mail on accessibility wording (April-June 2010)
+
+==============
+
+Randy Brukardt:
+
+I spent some time in the shower today thinking about this problem. I think I've
+concluded that the only problem was my note, but I might have missed something.
+Here's my analysis. (Now I've flip-flopped. Grrrr.)
+
+(1) We only need to worry about the dynamic check in cases where the static
+    check succeeds. If it fails, no one is ever going to run the code.
+
+(2) If we can prove that the dynamic check always has to succeed, it becomes
+    irrelevant.
+
+So the goal is to prove that the static check fails or the dynamic check always
+succeeds.
+
+The rules in question are for checking the accessibility of actuals passed to
+aliased parameters, checked at the call site. The case that I was worried about
+involves formal parameters passed in this circumstance. This necessarily has to
+happen in a body (in a specification, as in an aspect clause, the real actuals
+are available and they can be checked without extra overhead, so I don't much
+care). This would look something like:
+
+   function Func_A (R : aliased T) return S;
+
+   type Ptr_S is access all S;
+   P_S : Ptr_S;
+
+   function Func_B (P : aliased T; Q : T) return access S is
+       O1 : S := Func_A (P); -- OK (1A)
+       O2 : S := Func_A (Q); -- OK (1B)
+   begin
+       P_S := new S'(Func_A (P)); -- Statically illegal?? (2A)
+       P_S := new S'(Func_A (Q)); -- Statically illegal (2B)
+       if ... then
+           return P'access; -- OK (3A)
+       elsif ... then
+           return new S'(Func_A (P)); -- OK (3B)
+       else
+           return new S'(Func_A (Q)); -- Statically fails?? (3C)
+       end if;
+   end Func_B;
+
+These are most of the cases I can think of. I'm assuming AI-51 is adopted in the
+below. I'm also assuming that the static check uses the declared level of the
+formal parameters (other than anonymous access, which already uses the dynamic
+check, nothing new there). I didn't try to prove the latter, but I think it has
+to work that way currently, and we're not changing that.
+
+For local calls (the common case), like 1A and 1B, the static check will succeed
+because the formal parameters have the same level (or are outside of in the case
+of nesting and for aliased parameters of functions) the calls. The dynamic check
+will always succeed, as the objects that are passed have to live dynamically
+longer than the call (they were created before it). So no dynamic check is
+actually required.
+
+For allocators of outer (named) access types, we need to look at both cases
+separately as well. For a normal parameter (2B), the accessibility is that of
+the function. Thus, the static check has to fail (the access type has to have a
+longer lifetime than the parameter).
+
+For an aliased parameter, the accessibility level is defined to be the same as
+that of the function result. Because of AI-51, that level is dynamic. That means
+that we can't do a static check here (right?). We therefore would have to do a
+check based on the accessibility of the actual of the formal P, and that check
+could fail. This we don't want to have to do.
+
+However, what I intended here is that we would do a static check based on the
+formal level of the parameter (that is, the level of the function result, which
+is shallower than the function but deeper than everything else). That static
+check would necessarily fail (any named type that is outside of the function can
+be assumed to have a longer lifetime than the function call), so nothing dynamic
+would be necessary. How do we get the wording to reflect this?
+
+Anyway, moving on. Is there a way to force a dynamic check here even with the
+static rule I suggest above? That requires an access type with dynamic
+accessibility. If the type is declared in a generic unit, it technically has a
+dynamic check in the instance, but since the static check in the generic body
+would fail, the dynamic check is moot. Similarly for anonymous access
+components. Anonymous access parameters allocate at the call site which is the
+local case (and can't be allocated in the body, as the parameter is read-only),
+so there is no problem with them. I believe the same is true for stand-alone
+anonymous access objects. I think the access discriminant rules boil down to
+where the object is declared, so they end up being one of the other cases
+(including the return one, yet to discuss). So I don't think there is a problem
+here.
+
+
+For return statements, the level of the return object is dynamic. Since return
+objects have dynamic accessibility, there is not (usually??) a static check. For
+just returning an access to a parameter (3A, only legal for aliased parameters),
+there is no static check, but there needs to be no dynamic check either, since
+the accessibility levels are defined to be the same. The same is true for the
+function initializing an allocator of the function result using the aliased
+parameter (3B).
+
+OTOH, we don't know the result of the dynamic check for a function initializing
+an allocator of the function result using the normal parameter (3C). But here
+again we have a problem: we arguably should be using the level of the actual for
+the dynamic check. It would be better if the static check failed here (the
+formal parameter always having accessibility that is deeper than that of the
+function result, even though we don't know exactly what that is), but I don't
+think the statically deeper rules work in this case, as there is no defined
+static level for the function result. (Not completely sure, I don't understand
+AI-51 enough to be certain.)
+
+So the primary problem is to ensure that the static check is triggered (and
+fails) in these two cases (2A) and (3C), so that we never have to worry about
+the dynamic check (and thus incur no overhead).
+
+===============
+
+Tucker Taft:
+
+   Here is a slightly reworded version of the piece of AI-142 that I think you
+   are concerned about:
+
+Add after 6.4.1(15): [Dynamic Semantics] (this would be a new, outer level,
+bullet)
+
+* In a function call, for each explicitly aliased parameter, a check is made
+  that the accessibility level of the master of the actual object is not deeper
+  than that of the master of the function result.
+
+AARM To Be Honest: We're talking about the "nominal" level of the actual object.
+If the actual object is a formal parameter of some function call F, we do not
+intend to require dynamic checks that depend on the master of the actual
+parameters to F, as that would cause nasty distributed overhead (all tagged and
+explicitly aliased parameters would have to carry accessibility levels).
+
+[Q: Is there a way to reword this to make the above clear?? Masters are usually
+a dynamic concept, but here we only want to use the master we know, not the
+actual master of the underlying object (which could be different).]
+
+------------
+
+Your desire is to get rid of the "To Be Honest" I believe.
+You put it in because you want to be sure this is done efficiently, but I
+believe you now think that the expensive cases will either fail the static
+check, or always pass the dynamic check, so we don't need to explicitly allow
+any shortcuts in the dynamic check.
+
+I believe I agree with you.  I will try to explain myself using the following
+example, which you provided in one of your various e-mails:
+
+    function Func_A (R : aliased T) return S;
+
+    type Ptr_S is access all S;
+    P_S : Ptr_S;
+
+    function Func_B (P : aliased T; Q : T) return access S is
+        O1 : S := Func_A (P); -- OK (1A)
+        O2 : S := Func_A (Q); -- OK (1B)
+    begin
+        P_S := new S'(Func_A (P)); -- Statically illegal?? (2A)
+        P_S := new S'(Func_A (Q)); -- Statically illegal (2B)
+        if ... then
+            return P'access; -- OK (3A)
+        elsif ... then
+            return new S'(Func_A (P)); -- OK (3B)
+        else
+            return new S'(Func_A (Q)); -- Statically fails?? (3C)
+        end if;
+    end Func_B;
+
+----------------
+
+First of all, (3A) is illegal as written because P is of type T but we are
+returning access S.  But presuming P were of type S, then I agree this should
+pass both the static and dynamic checks, since that is pretty much the whole
+point of this AI!
+
+AI-51 requires the caller to pass in a dynamic accessibility level for functions
+with access results (or with result objects potentially having access
+discriminants). The rules of this AI make certain that any explicitly aliased
+parameters have dynamic accessibility no deeper than this passed-in value for
+the accessibility of the return object. (We may need to add a special case in
+the definition of "statically deeper than" to make sure the static check comes
+out right -- somewhere in the vicinity of 3.10.2(19) -- see below.)
+
+Now back to (2A).  Except for the special case of comparing against the level of
+the return object, explicitly aliased parameters are presumably considered
+equivalent to any other parameter as far as the static accessibility level, and
+hence are statically deeper than P_S. So I agree (2A) is just like (2B) as far
+as the static check, and both fail.
+
+We already talked about (3A) above.  (3B) is more complex. First of all I
+presume type S is build-in- place, and so we can't just copy the result of
+calling Func_A, at least not without worrying about access discriminants.  So we
+care what is the accessibility level of the return object of the call on Func_A.
+But by AI-51, we pass in the required accessibility level for the return object,
+and the level we pass in is that passed in to Func_B, and we know P's
+accessibility level is no deeper than that, so everything is fine as far as
+dynamic accessibility levels.
+
+What about static accessibility checks for (3B)?
+  From a static point of view, the level of the return from Func_B is that of
+  the master of Func_B, and ditto for Func_A, so we are fine since they have the
+  same master.  However, if Func_A were nested inside of Func_B, then this would
+  fail the static check.
+
+Now on to (3C).  In this one the call on Func_A fails the static check specified
+by this AI (added after 6.4.1(6), since the return object of the call on Func_A
+has a static level from the master of Func_A, and Q is clearly deeper than that.
+
+As indicated above, I do think we need to add something near 3.10.2(19).  Here
+is the addition from AI-51:
+
+Add after 3.10.2(19/2):
+
+     * For determining whether a level is statically deeper than the
+       level of the anonymous access type of an access result of a function,
+       when within a return statement that applies to the function, the
+       level determined by the point of call is presumed to be the same
+       as that of the level of the master that elaborated the function
+       body.
+
+I think we need to revise this to be something like:
+
+     * Inside a return statement that applies to a function
+       with an access result, when determining whether the
+       accessibility level of an explicitly aliased parameter
+       of the function is statically deeper than the level of the
+       anonymous access type of the access result, the level
+       determined by the point of call is presumed to be the same
+       as that of the level of the explicitly aliased parameter;
+       for statically comparing with the level of other entities,
+       the level determined by the point of call is presumed to
+       be the same as that of the master that elaborated the
+       function body.
+
+I think this may need to be generalized to include types that could have access
+discriminants (e.g. all class-wide types).
+
+===========
+
+Randy Brukardt:
+
+> Your desire is to get rid of the "To Be Honest" I believe.
+> You put it in because you want to be sure this is done efficiently,
+> but I believe you now think that the expensive cases will either fail
+> the static check, or always pass the dynamic check, so we don't need
+> to explicitly allow any shortcuts in the dynamic check.
+
+Right. So I think what I have to do is reword the To Be Honest into a
+Ramification, noting that the dynamic check cannot fail for a formal parameter
+unless the operation is statically illegal. Thus no overhead of dynamic checking
+is needed for aliased parameters.
+
+...
+> I think this may need to be generalized to include types that could
+> have access discriminants (e.g. all class-wide types).
+
+Not sure what you mean here. Are you saying that the part about "with an access
+result" should be dropped? That makes sense to me - I'm not sure why this is
+limited to access results, don't all return objects have the same effective
+level?? Sure, some don't have anything interesting that can be done, but so
+what?
+
+      * Inside a return statement that applies to a function F, when
+        determining whether the accessibility level of an explicitly
+        aliased parameter of F is statically deeper than the level of the
+        return object of F, the level of the return object is presumed to
+        be the same as that of the level of the explicitly aliased
+        parameter; for statically comparing with the level of other
+        entities, the level of the explicitly aliased parameter of F is
+        presumed to be the same as that of the master that elaborated
+        the function body of F.
+
+I dropped the "point of call" stuff because it doesn't seem to be helpful.
+
+Remind me: is the last part the same as normal parameters? That is, it would be
+weird if the static accessibility of a parameter differed when it was in a
+return statement or outside.
+
+Finally, if we can't talk about the level of the return object, then we ought to
+talk about the level of an access result or access discriminant. Then, if
+neither apply we drop into the "normal" case, which is fine.
+
+==========
+
+Tucker Taft:
+
+>       * Inside a return statement that applies to a function F, when
+>         determining whether the accessibility level of an explicitly
+>         aliased parameter of F is statically deeper than the level of the
+>         return object of F, the level of the return object is presumed to
+>         be the same as that of the level of the explicitly aliased
+>         parameter; for statically comparing with the level of other
+>         entities, the level of the explicitly aliased parameter of F is
+>         presumed to be the same as that of the master that elaborated
+>         the function body of F.
+
+Oops, you garbled this a bit.
+Should be:
+      ... for statically comparing with the level of
+      other entities, the level of the return object is
+      presumed to be the same as that of the master that
+      elaborated the function body of F.
+
+If we want to say something more about explicitly aliased parameters, we should
+say that "in other contexts, their level is the same as that of other
+parameters."
+
+> I dropped the "point of call" stuff because it doesn't seem to be helpful.
+
+OK.
+
+> Remind me: is the last part the same as normal parameters? That is, it
+> would be weird if the static accessibility of a parameter differed
+> when it was in a return statement or outside.
+
+It is only within a return statement that this special case exists, and only for
+explicitly aliased parameters.
+
+> Finally, if we can't talk about the level of the return object, then
+> we ought to talk about the level of an access result or access discriminant.
+> Then, if neither apply we drop into the "normal" case, which is fine.
+
+I think we can probably get away with the wording you propose, though probably
+this will be revised at least once more after Steve Baird et al get a chance to
+review it.
+
+===========
+
+Randy Brukardt:
 
-Then, any operation that invalidates a Safe_Pointer object should first check that the Raw_Refs counter
-is equal to 0; if it is not, an exception should be raised instead. (The containers raise Program_Error
-for a "tampering" event.)
-
-This way, once someone creates an access value to access the actual object, the Safe_Pointer will be
-"locked" against modification until the access value is no longer accessible (that is, the locking will
-continue so long as the access value exists).
-
-Of course, there are a number of ways to circumvent this safety (using Unchecked_Deallocation,
-Unchecked_Access, or Unchecked_Conversion). But that is true for any Ada feature; one has to assume
-that the programmers are not intentionally shooting themselves in the foot. (Uncontrolled use of
-"Unchecked" anything is dangerous - that's why they're called "Unchecked", after all.)
+I see, the wording was mainly about return objects, and not explicitly aliased
+parameters. I missed that originally (the wording order is a bit weird). But I
+think I'll leave it and let Steve and others pull it apart.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent