Version 1.8 of ai12s/ai12-0186-1.txt

Unformatted version of ai12s/ai12-0186-1.txt version 1.8
Other versions for file ai12s/ai12-0186-1.txt

!standard 13.14(15)          17-04-24 AI12-0186-1/06
!class binding interpretation 16-10-08
!status Amendment 1-2012 16-11-10
!status ARG Approved 7-0-2 16-10-09
!status work item 16-04-21
!status received 16-01-09
!priority Low
!difficulty Hard
!qualifier Clarification
!subject Profile freezing for the Access attribute
!summary
Using the access attribute does not freeze the profile of the associated access type (nor of the subprogram denoted by the prefix); that only happens upon a call of a value of the access type, use as a generic actual parameter of an instance, the occurrence of a body, or at the end of the declarative part.
!question
Consider:
procedure Proc (It : Blob); type Ptr is access procedure (It : Blob);
Link : Ptr := Proc'access;
The declaration freezes Ptr, and the expression freezes Proc, but NOT its profile. However, freezing an entity means (intuitively) that the entity is usable at that point. An access_to_subrogram with an unknown profile is certainly not usable yet.
13.14(15) says that any names in a full_type_declaration are frozen when the type is. Thus, in the above example, the declaration of Link freezes Ptr, and Ptr freezes Blob (because it is a name appearing in a full_type_declaration). This effectively freezes the profile, since everything in it is frozen.
However, a couple of ACATS tests fail when this interpretation is implemented. Is our compiler or the ACATS tests correct? (The ACATS tests.)
!recommendation
13.14 freezes profiles only in a few places:
* "General" freezing points like the occurrence of a body or the end of a declarative part. (At these places, everything is frozen.) - 13.14(3/5) and others.
* Calls to a function - 13.14(10.1/4) and 13.14(8.1/3).
* When a subprogram is used as an actual parameter to a generic instantation - 13.14(10.2/4).
A reference to an Access attribute was definitely not intended to be a place where the profile of a subprogram is frozen.
Unfortunately, the wording of 13.14(15) is somewhat unclear. The original intent was that "names" referred to object names and other names that appear within expressions, but not subtype_marks except those that were explicitly enumerated (parent subtype, component subtype, etc.). We agree the wording should be clarified.
!wording
Modify 13.14(15):
At the place where a subtype is frozen, its type is frozen. At the place where a type is frozen, any expressions or names within the full type definition cause freezing{, other than those that occur within an access_type_definition or an access_definition}; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well.
!discussion
The intent of 13.14(15) was that the only subtypes that were frozen as a side-effect of freezing a type were enumerated directly (parent subtype, component subtypes, etc.). But the term "name" is very general, and names appear within subtype_marks in particular. So we clarify that any names or expressions occurring within an access[_type]_definition do not cause freezing even if they appear within the full type definition of a type being frozen. Note that the designated subtype, and the designated profile, are frozen at a later point, as explained in 13.14(13) and 13.14(10.1/4) respectively.
One implication of this is that 'Access does not freeze the profile of the corresponding access-to-subprogram type. There clearly is some implementation impact from being able to use the Access attribute for a subprogram with an unfrozen profile. In particular, if a wrapper is needed, that will have to be deferred (at least) until the freezing point of the profile.
However, Ada 2012 already has similar requirements for incomplete types (which are never frozen, confirmed by AI12-0155-1). For a Taft-amendment type, the real profile of a subprogram may not be known until the body is compiled, long after the specification is compiled. For instance:
package P1 is type T is private; ... private type Taft; type T is access Taft; type Ptr is access procedure (It : Taft); -- Legal, even in Ada 95. package Inner is -- Make the operation non-primitive. procedure Proc (It : Taft); -- Legal in Ada 2012. end Inner; Link : Ptr := Inner.Proc'access; -- Legal. end P1;
So long as Link is called after the completion of Taft in the body, this is all legal. A compiler has to be able to generate Proc'Access without knowing anything about the representation of Taft. (If Taft is a tagged incomplete type, a child package could even call Link without knowing the exact representation of Taft.)
Since similar cases already exist, there doesn't seem to be any need to adopt an incompatible rule to have Proc'Access freeze the profile.
-----
We briefly were concerned that expressions in constraints of designated subtypes would not be handled by the revised wording. Specifically, consider:
package P is X : constant Integer; type A is access Rec(3*X); -- Elaborates X, must be frozen so it is illegal. private ... end P;
The new 13.14(15) wording does not freeze X in this case (X occurs in an access_type_definition). However, that doesn't matter, as 13.14(8) says that a nonstatic expression causes freezing where it occurs. Thus X is frozen by 13.14(11), as part of the type declaration, regardless of the wording of 13.14(15).
!corrigendum 13.14(15)
Replace the paragraph:
by:
!ASIS
No ASIS effect.
!ACATS test
A fairly low priority ACATS C-Test is needed to check examples like that in the question and discussion.
!appendix

From: Edmond Schonberg
Sent: Saturday, January  9, 2016  4:42 PM

A propos of which ... [split from a different e-mail thread]

we are having troubles implementing properly the old AI05-019.  The specific
example is the declaration for an object to subprogram:

       procedure Proc (It : Blob);
       type Ptr is access procedure (It : Blob);
       
       Link  : Ptr :=  Proc’access;

The declaration freezes Ptr, and the expression freezes Proc,  but NOT its
profile.  Now freezing an entity means (intuitively) that the entity is usable
at that point.  An access_to_subrogram with an unknown profile is certainly
not usable yet.  The GNAT backend has always assumed that when creating that
object the full profile is available (i.e. its parameter types are frozen) and
crashes or misbehaves if this is not the case.  Is this is a gap in the heart
of darkness (13.14) , or are we misleading AI0-019?  A couple of ACATS tests
trigger additional errors if subprogram profiles are frozen when an Access
reference attribute appears in an object declaration. 

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

From: Edmond Schonberg
Sent: Monday, January 11, 2016  9:41 AM

This may be so painfully obvious that people were too embarrassed to answer.
I would still like some comment or confirmation:

  does the declaration of Link freeze type Blob?

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

From: Tucker Taft
Sent: Monday, January 11, 2016  11:59 AM

Not according to 13.14.  The only things that freeze profiles are the "general"
freezing points, a function call, and a generic instantiation.  I believe the
freezing should be deferred until you make a call on a dereference of an object
of type Ptr.  In other words, when you make a function call, you freeze the
profile, whether it comes from a function declaration, or from an
access-to-function type.  Access-to-procedure profiles would only be frozen by
"general" freezing points, and presumably by generic instantiations.

Some sort of AI seems needed to clarify this!

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

From: Edmond Schonberg
Sent: Monday, January 11, 2016  12:23 PM

> Not according to 13.14.  The only things that freeze profiles are the
> "general" freezing points, a function call, and a generic instantiation.

and an object declaration (13.14 (6), That certainly freezes the type of the
object. Then 13.14 (16) states that all names in the type definition are
frozen. So I’m not convinced.

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

From: Gary Dismukes
Sent: Monday, January 11, 2016  1:07 PM

(Presumably you mean 13.14(15).)  The "names" referred to there don't
include things like subtype_marks, but refers to names in expressions.  Note
that component subtypes are called out separately in that rule.  So this
doesn't include parameter subtypes of a profile in the access-to-subprogram
type.

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

From: Edmond Schonberg
Sent: Monday, January 11, 2016  1:18 PM

> (Presumably you mean 13.14(15).)  The "names" referred to there don't 
> include things like subtype_marks, but refers to names in expressions.

Could be the intent, but I certainly cannot deduce it from the text. A name
is something that denotes an entity, and that certainly includes
subtype_marks. Why are they excluded by this paragraph?

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

From: Gary Dismukes
Sent: Monday, January 11, 2016  1:34 PM

Umm, so that subtypes in profiles wouldn't be frozen?  ;-)

Let's just say that I think it's the intent that those subtypes aren't frozen
by declaration of an object of the access type.  I believe that the
"expressions and names" of the rule refers to top-level syntactic instances of
those things, and the "name" of a subtype_mark is buried deeper and doesn't
count.  Perhaps the rule could be clearer (assuming that's the intent).  Let's
see what other think.

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

From: Tucker Taft
Sent: Monday, January 11, 2016  2:21 PM

I agree.  13.14(15) says:

   "At the place where a subtype is frozen, its type is frozen. At the place
   where a type is frozen, any expressions or names within the
   full_type_definition cause freezing; the first subtype, and any component
   subtypes, index subtypes, and parent subtype of the type are frozen as well.
   For a specific tagged type, the corresponding class-wide type is frozen as
   well. For a class-wide type, the corresponding specific type is frozen as
   well."

I believe the use of the term "name" is overly general here, and should not
include names that are subtype_marks.  Otherwise, the discussion about first
subtype, component subtypes, index subtypes, etc. would be largely redundant.
It should probably be "names that denote objects or subprograms" ...

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

From: Edmond Schonberg
Sent: Monday, January 11, 2016  2:34 PM

Let us say that as a justification,  “otherwise this other line would be
redundant” is not terribly compelling.  In any case we’ll have to rethink the
implementation of freezing for access_to_subprograms in GNAT.

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

From: Randy Brukardt
Sent: Thursday, April 21, 2016  7:04 PM

I'm trying to make sense of this discussion so I can create an AI.

I don't mind the "otherwise this line would be redundant" justification, as we
try hard to avoid redundant text in the Standard, and also try to mark
anything that is intentionally redundant.

But I can do better: AARM 13.14(15.b) says "Freezing an access type does not
freeze its designated subtype." If we used Ed's interpretation of 13.14(15),
there is no way that could be true, since there is always a "name" within the
subtype_mark of the designated type:

          type Ptr is access Blob;
          P : Ptr; -- Does not freeze Blob by 13.14(15.b)

Since Blob is not frozen here (to make the clear intent of 15.b True),
13.14(15) cannot be talking about the "name" within the "subtype_mark" Blob.
QED.

Tucker suggested trying to reword the rule to make it clearer that "name"
isn't talking about names in subtype_marks. Specifically:

> It should probably be "names that denote objects or subprograms" ...

I think his rewording is dangerous, as it potentially leaves a hole for other
kinds of entities (exceptions? named numbers? etc.)

I think we'd be better off with a To Be Honest note suggesting that the
"expressions or names within the full_type_declaration" is speaking
syntactically; we're not looking inside of other entities appearing in the
type declaration (like subtype_marks and subtype_indications). If it turns out
not to be right either, we at least won't have broken anything (AARM Notes can
always be ignored, and are much more easily fixed than RM wording.) This
wording has been around since (at least) Ada 9X version 3.0 (and a version of
the rule is in version 2.0 as well), and I don't remember anyone challenging
it before. Doesn't seem critical to change.

---

I've also been mulling the actual problem. It seems to me that it is related
(in a sense) to incomplete types (there's not much difference between an
unfrozen type and an incomplete type, which never is frozen). One can construct
a similar case with Taft-Amendment types:

    package P1 is
        type T is private;
        ...
    private
        type Taft is tagged;
        type T is access Taft;
        type Ptr is access procedure (It : Taft); -- Legal, even in Ada 95.
        package Inner is -- Make the operation non-primitive.
           procedure Proc (It : Taft); -- Legal in Ada 2012.
        end Inner;
        Link : Ptr := Proc'Access; -- Legal.
    end P1;

The declaration of Link doesn't violate any freezing rules, and it doesn't
violate any accessibility or conformance rules, so it must be legal. And one
could call it in a child package that has no knowledge of the type (even worse
than the freezing case).

An actual call will (outside of incomplete types) freeze the types of the
parameters, so one never has to generate a call without freezing. But one
might need to defer a wrapper until the end of the unit (or when the profile
is frozen; usually I find the former easier, but YMMV):

    package P2 is
       type Blob is range 0 .. 100;
       function Func (It : Blob) return Natural;
       type Ptr is access function (It : Blob) return Natural;
       Link : Ptr := Func'Access; -- Does not freeze the profile of Func, thus does not freeze Blob.
       for Blob'Size use 8; -- An evil rep. clause.
       Var : Natural := Link(10); -- Freezes the profile of Ptr, thus freezes Blob.
    end P2;

If Func'Access needs a wrapper of some sort, it can't be generated until the
profile is frozen, and that doesn't happen until Var is declared. The explicit
use of Func'Access just has to be a label of some sort. (I generally just do
deferred things at the end of the unit, as it doesn't matter where the actual
code lives, since it is accessed by the label anyway. Once you have to defer
it a little, it doesn't matter how much it gets deferred.)

---

Anyway, I've concluded that there isn't any real problem here, at least not
any NEW problem, so I'm going to write this up as a Ramification (with a To
Be Honest note) and you can throw bricks in Pisa.

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

From: Randy Brukardt
Sent: Thursday, April 21, 2016  8:08 PM

The proposed TBH uses Gary's explanation that "name" and "expression" in this
rule are talking about direct syntax and not about names or expressions that
happen to occur in other constructs that make up the full_type_declaration.
I'm happy to take credit for the AI if it is correct, but if there is
something wrong with Gary's explanation then that's all his idea. ;-) :-)

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

From: Tucker Taft
Sent: Thursday, April 21, 2016  9:59 PM

> ... Anyway, I've concluded that there isn't any real problem here, at 
> least not any NEW problem, so I'm going to write this up as a 
> Ramification (with a To Be Honest note) and you can throw bricks in Pisa.

In Pisa it might be more appropriate to drop them from the leaning tower and
see which lands first... ;-)

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

From: Tucker Taft
Sent: Tuesday, October 4, 2016  9:42 PM

Here is an update. [This is version /02 of the AI - Editor.]
It is surprising that paragraph 13.14(15) could have been
so misleading for so long, as far as what happens when you freeze an access
type.  The answer is that the names and expressions inside the
access[_type]_defininition do not cause freezing.  That only happens when the
designated subtype/profile is frozen.

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

From: Randy Brukardt
Sent: Wednesday, October 5, 2016  6:24 PM

Procedural: This AI is no longer a ramification if it changes normative
wording in the Standard. (Ramifications can only change notes, examples,
and the AARM.) It needs to be reclassified as a Binding Interpretation.

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

From: Tucker Taft
Sent: Wednesday, October 5, 2016  8:22 PM

Sorry. Forgot about that part. It might be considered a clarification I
suppose, though perhaps there is no such classification.

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

From: Randy Brukardt
Sent: Wednesday, October 5, 2016  8:55 PM

"Clarification" is one of the three sub-categories of Binding Interpretation.

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

From: Tucker Taft
Sent: Saturday, October 8, 2016  9:00 PM

I had to split out access-to-object and access-to-subprogram, and be careful
how I talked about the subtype_mark "used in specifying" the designated_subtype
(since in some cases it is part of a subtype_indication, and in others it is
used directly).

Hence,...

Modify 13.14(15) as follows:

   At the place where a subtype is frozen, its type is frozen. At the
   place where a type is frozen, any expressions or names within the full
   type definition cause freezing{, other than the name that is the
   subtype_mark used in specifying the designated subtype in an
   access-to-object type definition, or expressions or names that appear
   within the designated profile of an access-to-subprogram type definition};
   the first subtype, and any component subtypes, index subtypes, and parent
   subtype of the type are frozen as well. For a specific tagged type,
   the corresponding class-wide type is frozen as well. For a class-wide
   type, the corresponding specific type is frozen as well.


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


Questions? Ask the ACAA Technical Agent