Version 1.3 of ai05s/ai05-0208-1.txt

Unformatted version of ai05s/ai05-0208-1.txt version 1.3
Other versions for file ai05s/ai05-0208-1.txt

!standard 3.10.1(2.4/2)          10-04-02 AI05-0208-1/03
!standard 3.10.1(2.6/2)
!class binding interpretation 10-02-22
!status Amendment 2012 10-04-02
!status ARG Approved 8-0-2 10-02-26
!status work item 10-02-22
!status received 10-02-16
!priority Medium
!difficulty Medium
!qualifier Omission
!subject Characteristics of incomplete views
!summary
An incomplete view declared by incomplete_type_declaration gets the characteristics of the completing type within the scope of the completing type.
!question
The following is legal in Ada 83:
package P is type List_Rec; type Name_List is access List_Rec; type List_Rec is record Name : String (1..50); Next : Name_List; end record; end P;
with P; package Q is Employees : P.Name_List; end Q;
with Q; with Text_IO; procedure Fire_Some_Employees (How_Many : Integer) is begin for I in 1 .. How_Many loop Text_IO.Put_Line (Q.Employees.Name & ": You're fired!"); Q.Employees := Q.Employees.Next; end loop; end Fire_Some_Employees;
However, the references to the components of Q.Employees are illegal by the rules of 3.10.1. The view of List_Rec is an incomplete view, so 3.10.1(2.2-5/2) apply to the dereferences of Q.Employees. Neither of the bullets apply (the dereferences are not within the scope of List_Rec's completion, and they are not within the scope of a "with P" clause [the "with P" on Q doesn't count, since the definition of the "scope of a with clause" is not transitive---10.1.2(5)]. Thus the dereferences are of an incomplete view, they are used as prefixes, and 3.10.1(10/2) makes that illegal.
Is this intended? (No.)
!recommendation
(See Summary.)
!wording
Modify 3.10.1(2.4/2):
* it occurs within the scope of a nonlimited_with_clause that mentions a library
package in whose visible part the completion of T is declared[.]{, or}
{* it occurs within the scope of T after the completion of T and T is an
incomplete view declared by an incomplete_type_declaration.}
AARM Discussion: Whether the designated type is an incomplete view (and thus whether this set of rules applies) is determined by the view of the type at the declaration of the access type; it does not change during the life of the type.
Modify 3.10.1(2.6/2):
Similarly, if a subtype_mark denotes a subtype_declaration defining a subtype of an incomplete view T, the subtype_mark denotes an incomplete view except under the same {three}[two] circumstances given above, in which case it denotes the full view of T.
!discussion
3.10.1(2.2/2) is talking about the view of the type at the point of the appropriate declaration. It doesn't depend on visibility or scope.
AI95-0326 makes it clear that was the intent, as that is necessary to avoid ripple effects for types imported by a limited with clause. Indeed, if scope applied to the view, the other bullets would just be repeating what was already true.
This is different than the model for partial views. This seems necessary given the differences in usage (partial views are about information hiding, while incomplete views are about limiting usage of types whose implementation is unknown).
However, no incompatibility with Ada 83/95 was intended. While it is not completely clear from either of those language standards that the example ought to work, it appears to work on all existing compilers. As such, we don't want it to stop working, and thus add wording to ensure that is the case.
!corrigendum 3.10.1(2.4/2)
Replace the paragraph:
by:
!corrigendum 3.10.1(2.6/2)
Replace the paragraph:
Similarly, if a subtype_mark denotes a subtype_declaration defining a subtype of an incomplete view T, the subtype_mark denotes an incomplete view except under the same two circumstances given above, in which case it denotes the full view of T.
by:
Similarly, if a subtype_mark denotes a subtype_declaration defining a subtype of an incomplete view T, the subtype_mark denotes an incomplete view except under the same three circumstances given above, in which case it denotes the full view of T.
!ACATS Test
It is likely that an existing ACATS C-Test covers examples like the one in the question. If not, one should be added.
!appendix

!topic What view of the type of an object?
!reference 7.3(15)
!from Adam Beneschan 10-02-16
!discussion

Getting the question of "what view of a type" correct is something I've
struggled with a number of times.  I've come to the conclusion that there's some
missing or confusing language in the RM.

Consider this:

   package P is
      type T1 is private;
      type T2 is private;
      procedure Proc;
   private
      type T1 is new integer;
      type T2 is record
         F1 : integer;
      end record;
   end P;

   with P;
   package Q is
      Var1 : P.T1;
      Var2 : P.T2;
   end Q;

   with Q;
   package body P is
      procedure Proc is
      begin
         Q.Var1 := 3;       -- LEGAL
         Q.Var2.F1 := 4;    -- LEGAL
      end Proc;
   end P;

What makes the assignment statements legal, I believe, is this sentence in
7.3(15):

   Moreover, within the scope of the declaration of the full view, the
   characteristics of the type are determined by the full view; in
   particular, within its scope, the full view determines the classes
   that include the type, which component, entries, and protected
   subprograms are visible, what attributes and other predefined
   operations are allowed, and whether the first subtype is static.

Thus, since the assignment statements are in the scope of the full view of T1
and T2, the characteristics of the full view are available---in particular that
T1 is an integer and T2 has an integer component F1.

My problem with this is that it seems to apply only to private types and private
extensions.  7.3(15) starts out by talking about partial views, and 7.3(4) says
that a partial view is created by private type or extension declaration.

What makes this legal?

   package P is
      type T1 is range -(2**31) .. 2**31-1;
   end P;

   with P;
   package Q is
      Var : P.T1;
   end Q;

   with Q;
   procedure R is
   begin
      Q.Var := 0;
   end R;

This is such a simple example that it seems absurd to question it---yet I can't
find the rule that makes this legal.  It seems that the same sentence of 7.3(15)
should be the one that applies.  (As was pointed out recently, the assignment
statement is in the scope of T1's declaration because the definition of "scope"
is recursive in applying to semantic dependents.  Also, all types have full
views.)  I can't find another sentence in the RM that applies (by looking up all
occurrences of the word "scope").  Yet the placement of this sentence makes it
appear that it applies only to types with a partial view, i.e. private types and
extensions.

I'm sure this is just a nitpick because every Ada programmer is going to get
this right.  I got confused by it, though, when trying to figure out what view
of a type was used in a "limited with" case:

   with P;
   package Q is
      Var : P.T1;
   end Q;

   limited with P;
   with Q;
   procedure R is
   begin
      Q.Var := 0;
   end R;

If P.T1 were used by name in R, it would be an incomplete type; yet the program
is allowed to know, for the assignment, about the characteristics of P.T1's full
view.  I think I got this figured out now, but it took some time to figure out
exactly what the rules said about this.

By the way, I found an interesting case that could be seen as anomalous---I
don't know.

    package P is
        type T is record
            F1 : Integer;
        end record;
    end P;

    limited with P;
    package Q1 is
        type Acc_1 is access P.T;
        A1 : Acc_1;
    end Q1;

    with P;
    package Q2 is
        type Acc_2 is access P.T;
        A2 : Acc_2;
        V1 : P.T;
    end Q2;

    with Q1;
    with Q2;              -- NOT REFERENCED, BUT MAKES A DIFFERENCE
    procedure R is
    begin
        Q1.A1.F1 := 3;    -- LEGAL
    end R;

As I understand it, the last assignment is legal, but would be illegal if "with
Q2" were removed---even though Q2 is not referenced anywhere in the procedure.
This is because "with Q2" causes the assignment statement to be in the scope of
the full view of T, because of the transitive dependence on P.  Correct?
Intended?  Another example of the ripple effects mentioned in AI-326?

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

From: Adam Beneschan
Sent: Tuesday, February 16, 2010  2:38 PM

> As I understand it, the last assignment is legal, but would be illegal
> if "with Q2" were removed---even though Q2 is not referenced anywhere
> in the procedure.

Scratch that---I misread the rules.  Sorry about that.

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

From: Adam Beneschan
Sent: Tuesday, February 16, 2010  3:06 PM

I hate to keep going back and forth on myself like this.  But now that I'm
rereading the rules again, I really don't have any idea what they are.

Do the rules in 3.10.1(2.2-2.5) apply to the assignment statement?
3.10.1(2.2) starts off, "Given an access type A whose designated type T is an
incomplete view..."  The first question is, an incomplete at what point?
Certainly, at the point where A is declared, its designated type is incomplete.
But I suspect that's not what it meant; I think it meant whether the view of T
is incomplete at the point of the assignment statement.

And here's where things get murky to me.  In the simple example that caused me
consternation:

    package P is
       type T1 is range -(2**31) .. 2**31-1;
    end P;

    with P;
    package Q is
       Var : P.T1;
    end Q;

    with Q;
    procedure R is
    begin
       Q.Var := 0;
    end R;

In the last assignment statement, the name T1 would not designate any view of
anything at that point, since it's not visible.  But if we were talking about
the "type of Q.Var", it would have to be the full view of T1.

The latter would have to be true here also (the only addition is the "limited
with"):

    package P is
       type T1 is range -(2**31) .. 2**31-1;
    end P;

    with P;
    package Q is
       Var : P.T1;
    end Q;

    with Q;
    limited with P;
    procedure R is
    begin
       Q.Var := 0;
    end R;

At the point of the last assignment statement, if we were to use the name P.T1,
it would refer to an incomplete view of the type; thus P.T1 could not be used
where an incomplete type was disallowed.  But when we're looking at the type of
Q.Var, again we need to be referring to the full view of T1 (actually the type
whose first subtype is T1). Certainly adding the "limited with" cannot make the
assignment illegal, if it's legal with no "with P" at all.

This means, to me, that the answer to the question "which view of T1 is used" at
this point in the program, is ambiguous.  The answer is one thing if we're
talking about what view the name T1 would refer to, and another thing if we're
talking about what view would we see if we were looking at an object of that
type.

This in turn means, to me, that the first part of 3.10.1(2.2) is
ambiguous:

   Given an access type A whose designated type T is an incomplete
   view, ...

What do we mean by "T is an incomplete view"?  Do we mean, would the name T
refer to an incomplete view?  (That doesn't make much sense since the name T may
not even be visible.)  Do we mean, was the view Q2.V1's type is a full viewof T
incomplete at the point that A was Q2.V1's type is a full viewdeclared?  Or, do
we mean, that if we were looking at an object of type T we would be using the
incomplete view (so that the characteristics of T are unavailable)?  If the last
is the case, then the legality of the last assignment statement:

    package P is
        type T is record
            F1 : Integer;
        end record;
    end P;

    limited with P;
    package Q1 is
        type Acc_1 is access P.T;
        A1 : Acc_1;
    end Q1;

    with P;
    package Q2 is
        type Acc_2 is access P.T;
        A2 : Acc_2;
        V1 : P.T;
    end Q2;

    with Q1;
    with Q2;
    procedure R is
    begin
        Q1.A1.F1 := 3;    -- LEGAL?
    end R;

*does* depend on whether "with Q2" is present; if "with Q2" is present, then
Q1.A1's designated type has to be a full view just like Q2.V1's type is a full
view.  And if it's a full view, then none of 3.10.1(2.2-2.5) apply since the
initial "Given..." condition doesn't apply.

If this is the correct interpretation, then I think this example from
AI-326 is wrong:

# package Q is
#     type T is ...;
#     Z : T;
# end Q;
#
# limited with Q;
# package P is
#     type Acc is access Q.T;
#     X : Acc;
# end P;
#
# with Q;
# package A is
#     package MyQ renames Q;
# end A;
#
# with P; with A;
# package R is
#     ... P.X.all ... -- Legal? (Depends.)
# end R;
#
# P.X.all is of an incomplete type.  It is not legal if used as a prefix or as
# the left-hand side of an assignment, but other uses are acceptable.  At any
# rate, the legality of the dereference does not depend on the "with Q" in A.

Are we sure P.X.all is of an incomplete type?  If the last interpretation is
correct, then P.X is of an access type whose designated type is *not*
incomplete, since the use of P.X is in the scope of the full declaration of T
(since R with's A and A with's Q), and therefore 3.10.1(2.2-2.5) apply.

My take on all this is that 3.10.1(2.2) is ambiguous and needs to be clarified.
I have no idea *what* the phrase "an access type A whose designated type T is an
incomplete view" means.

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

From: Randy Brukardt
Sent: Tuesday, February 16, 2010  7:13 PM

...
> This in turn means, to me, that the first part of 3.10.1(2.2) is
> ambiguous:
>
>    Given an access type A whose designated type T is an incomplete
>    view, ...
>
> What do we mean by "T is an incomplete view"?  Do we mean, would the
> name T refer to an incomplete view?  (That doesn't make much sense
> since the name T may not even be visible.)

No, of course not.

> Do we mean, was the view Q2.V1's type is a full viewof T incomplete at
> the point that A was Q2.V1's type is a full viewdeclared?

Hard to tell, because this sentence is so garbled.

> Or, do we mean, that if we were looking at an object of type T we
> would be using the incomplete view (so that the characteristics of T
> are unavailable)?

No.

For the purposes of 3.10.1(2.2/2), the view of the designated type is determined
when the access type is declared. (I'd say that's true for all purposes, but I
can't say that for 100% certain.) It never changes throughout the life of the
type; it remains an incomplete view no matter what withs are used. The rules
3.10.1(2.3-4/2) determines when the full view can be substituted; *that* depends
on visibility. Having both parts of the rule depend on visibility would be
madness.

Now that you know that, try your examples again and see if there is any
anomolies. (That surely could happen!)

As far as clarifying the wording, I have no idea how one could do that. It would
be hard to add wording to say "this doesn't depend on visibility or anything
that Adam's or Steve's imagination can dream up"!

The model here is that an incomplete view is always an incomplete view; just
that sometimes you can treat it as a full view. (And don't forget that the
completing view hides the incomplete view from all visibility within it's scope,
just to complicate things. But the incomplete view is still around, it's just
hidden.)

This is the basic model of views in Ada; there is nothing special here. The
special things happen when you want to act like that is not true (which is why
we have all of the junk about partial views gaining characteristics).

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

From: Adam Beneschan
Sent: Wednesday, February 17, 2010  11:08 AM

...
> > Do we mean, was the view Q2.V1's type is a full viewof T incomplete
> > at the point that A was Q2.V1's type is a full viewdeclared?
>
> Hard to tell, because this sentence is so garbled.

Man, you hit one wrong key in EMACS and everything goes kerflooey.

I think I meant to say "Do we mean, was the view of T incomplete at the point
that A was declared?"  And it sounds like your answer is "yes".

...
> For the purposes of 3.10.1(2.2/2), the view of the designated type is
> determined when the access type is declared. (I'd say that's true for
> all purposes, but I can't say that for 100% certain.) It never changes
> throughout the life of the type; it remains an incomplete view no
> matter what withs are used. The rules 3.10.1(2.3-4/2) determines when
> the full view can be substituted; *that* depends on visibility. Having
> both parts of the rule depend on visibility would be madness.
>
> Now that you know that, try your examples again and see if there is
> any anomolies. (That surely could happen!)

I'll try it, but my earlier impression was that if 3.10.1(2.2) means what you
say, then the Padua examples from AI-326 would work as written.

> As far as clarifying the wording, I have no idea how one could do
> that. It would be hard to add wording to say "this doesn't depend on
> visibility or anything that Adam's or Steve's imagination can dream up"!
>
> The model here is that an incomplete view is always an incomplete
> view; just that sometimes you can treat it as a full view. (And don't
> forget that the completing view hides the incomplete view from all
> visibility within it's scope, just to complicate things. But the
> incomplete view is still around, it's just hidden.)
>
> This is the basic model of views in Ada; there is nothing special
> here. The special things happen when you want to act like that is not
> true (which is why we have all of the junk about partial views gaining characteristics).

I suppose my thinking was something like this:  In the case

   package P is
      type T1 is private;
      procedure Proc;
   private
      type T1 is new integer;
   end P;

   with P;
   package Q is
      Var1 : P.T1;
   end Q;

   with Q;
   package body P is
      procedure Proc is
      begin
         Q.Var1 := 3;   -- (B)
      end Proc;
   end P;

the characteristics of T1 that we use at (B) are determined by the rules about
whether point (B) is in the scope of the full declaration of the type, not by
whether the declaration of Var1 was in the scope of the full declaration.  But
here:

    package P is
        type T2 is record
            F1 : Integer;
        end record;
    end P;

    limited with P;
    package Q1 is
        type Acc_1 is access P.T2;
        A1 : Acc_1;
    end Q1;

    with Q1;
    procedure R is
    begin
        Q1.A1.F1 := 3;  -- (C)
    end R;

the characteristics of T2 that we use at (C) are determined by whether the
declaration of Acc_1 was in the scope of the full declaration of T2, not by
whether (C) is in that scope.  So it seems there are two opposite ways of doing
things, and it's not intuitively clear why one example should work one way and
the other example should work the other way.  Your last sentence seems to imply
that the second example is how things work by default, and the first example is
an exception to the rule; but I don't see anything in the RM that explains this.
(3.1(7) doesn't seem to be any help at all.)  Unless there's other language
somewhere in the RM that I haven't found, this strikes me as one of those things
where "you just have to know how it works", which doesn't help me at all.

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

From: Adam Beneschan
Sent: Wednesday, February 17, 2010  11:45 AM

> Now that you know that, try your examples again and see if there is
> any anomolies. (That surely could happen!)

How about this (legal in Ada 83):

    package P is
       type List_Rec;
       type Name_List is access all List_Rec;
       type List_Rec is record
          Name : String (1..50);
          Next : Name_List;
       end record;
    end P;

    with P;
    package Q is
       Employees : P.Name_List;
    end Q;

    with Q;
    with Ada.Text_IO;
    procedure Fire_Some_Employees (How_Many : Integer) is
    begin
       for I in 1 .. How_Many loop
          Ada.Text_IO.Put_Line (Q.Employees.Name & ": You're fired!");
          Q.Employees := Q.Employees.Next;
       end loop;
    end Fire_Some_Employees;

If the view of the designated type (of Name_List) is determined at the point
where the access type Name_List is declared, then it's an incomplete view.  This
would mean that, according to 3.10.1(2.2/2), a dereference of a value of type
Name_List also has an incomplete view, unless one of the conditions in the next
two paragraphs is met. Fire_Some_Employees has two implicit dereferences of
Q.Employees, and they do not meet those two conditions: they are not within the
scope of List_Rec's completion, and they are not within the scope of a "with P"
clause (the "with P" on Q doesn't count, since the definition of the "scope of a
with clause" is not transitive---10.1.2(5)).

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

From: Adam Beneschan
Sent: Wednesday, February 17, 2010  11:49 AM

> How about this (legal in Ada 83):

Ummm, make that "legal in Ada 83 if you remove the word ALL from the access type
declaration", and say Text_IO instead of Ada.Text_IO.

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

From: Randy Brukardt
Sent: Thursday, February 18, 2010  12:09 AM

> If the view of the designated type (of Name_List) is determined at the
> point where the access type Name_List is declared, then it's an
> incomplete view.  This would mean that, according to 3.10.1(2.2/2), a
> dereference of a value of type Name_List also has an incomplete view,
> unless one of the conditions in the next two paragraphs is met.
> Fire_Some_Employees has two implicit dereferences of Q.Employees, and
> they do not meet those two conditions: they are not within the scope
> of List_Rec's completion, and they are not within the scope of a "with
> P" clause (the "with P"
> on Q doesn't count, since the definition of the "scope of a with
> clause" is not transitive---10.1.2(5)).

Since we're in pedantic mode, are you really sure this is legal in Ada 83? I
can't find anything in that standard that ever says what you can or cannot do
with an incomplete type (as opposed to its name). And of course, Ada 95 carried
over this sloppy wording, and screwed it up more such that this (and pretty much
everything else you might ever imagine doing with an incomplete type) is never
legal -- there isn't any defined connection between the incomplete type and its
completing type.

So clearly the situation has improved, only unusual cases are now pedantically
illegal. :-) And I do agree that this is currently illegal as the language is
written and intended.

Leaving pedantic mode for the moment, the question has to be whether this is
intended to work. I would have said "no", but it wouldn't surprise me that there
is an old ACVC requiring it to work. In that case, we need a fix to make it work
(and not bring AI95-00326 issues into play). Perhaps there is no clean model.

The best I can come up with would be to add an additional bullet after
3.10.1(2.4/2):

   * it occurs within the scope of T after the completion of T if T is an
     incomplete view declared by an incomplete_type_declaration, and the
     completion of T is declared immediately within the same declarative list as
     T.

This is really ugly, but I don't see any way for the above example to "work"
and for the limited with rules to work properly.

I should note that I was confused the other day about how partial views work. I
personally think that they *should have* worked similar to the way that
incomplete types are currently written -- but obviously it is way too late to
make that sort of change. OTOH, we definitely do not want the ripple effects
noted in the appendix of AI95-0326-1 to appear, so incomplete views *cannot*
work the same as partial views. In particular, the addition of a full with to
some other package must not change the legality of a dereference. That is,

package Q is
    type T is ...; -- Non-limited type.
end Q;

limited with Q;
package P is
    type Acc is access Q.T;
    X, Y : Acc;
    procedure Proc (Param : Q.T); -- Legal in Ada 2012 end P;

with Q;
package A is
end A;

with P; with A;
package R is
    procedure B;
end R;

package body R is
begin
    P.Proc (P.X.all);   -- OK.
    P.X.all := P.Y.all; -- Illegal.
end R;

We definitely don't want the legality of the assignment to depend on the unused
with in package A; removing an unused with is not supposed to change the
legality of some other package.

Anyway, do we really need the first example to work? If so, then we need to fix
something somewhere.

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

From: Adam Beneschan
Sent: Thursday, February 18, 2010  10:59 AM

...
> Since we're in pedantic mode, are you really sure this is legal in Ada
> 83?

You got me there.  I haven't tried to check RM83 carefully.  :)

...
> The best I can come up with would be to add an additional bullet after
> 3.10.1(2.4/2):
>
>    * it occurs within the scope of T after the completion of T if T is
> an incomplete view declared by an incomplete_type_declaration, and the
> completion of T is declared immediately within the same declarative
> list as T.
>
> This is really ugly, but I don't see any way for the above example to "work"
> and for the limited with rules to work properly.

Actually, I don't think it's that ugly.

For now, since I'm trying to figure out what rules to get the compiler to
follow, I'll assume that "view" in 3.10.1(2.2) means what you said in your
previous message and that there's some language to make things work in the sort
of example I just gave.

> I should note that I was confused the other day about how partial
> views work.
...
> Anyway, do we really need the first example to work? If so, then we
> need to fix something somewhere.

My take on this: (1) Partial views ("private" types) are all about information
hiding.  Package P wants to declare a type but not expose all characteristics of
the type to most users of the type; that way, the author of P is free to change
the implementation of the type without affecting anything.  So the language has
to be careful about defining which characteristics of the type are available and
where.

(2) The incomplete type used in my example has nothing to do with information
hiding.  It's there because that's the only syntax we provide(d) to allow data
structures to contain pointers to themselves, or two or more data structuers to
contain pointers to each other. (Anonymous access types in Ada 2005 provide an
alternative in some cases.)  So to my mind, there shouldn't be any question
about views, except for whatever restrictions are necessary between the
incomplete type and the completion (for freezing rules, etc.).  Other than that
small portion of the program, there's no reason for any other point to have to
deal with the incomplete view.  Thus, to me, it would make no sense for any
source that uses an object of type Name_List not to have access to all the
operations of type List_Rec.  So based on that, then yes, I think the first
example needs to work.

(I think the same could be said about incomplete types in a private part
completed in a body; in Ada 83, this should only affect the code "between" the
incomplete type and the completion, since no other source would be able to refer
to the type.  Ada 95 messed this up by adding child packages that were able to
refer to the incomplete type without having the completion available.)

I'm not sure which of these two models "limited with" fits into.  My initial
impression was that the main motivation was something like #2, but enhanced that
the two types that point to each other can be in different packages.  In other
words, there wouldn't be any need to enforce "information hiding", except for
whatever is necessary to avoid imposing huge burdens on implementations.

Anyway, I'll go ahead and make those assumptions about the language rules for
now, but I should also go back and read AI-326 and AI-217 more carefully to get
a feel for what the motivations behind the rules are, and then maybe I'll have
something to add.  But thanks for clarifying the intent of the current rules.  I
still would prefer to see more mathematically precise language in the RM about
views; I still don't think there's enough language in the RM to explain what
3.10.1(2.2) means without having someone "in the know" explain it to me.  But
it'll do for now.

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

From: Randy Brukardt
Sent: Thursday, February 18, 2010  11:24 AM

> Leaving pedantic mode for the moment, the question has to be whether
> this is intended to work. I would have said "no", but it wouldn't
> surprise me that there is an old ACVC requiring it to work. In that
> case, we need a fix to make it work (and not bring AI95-00326 issues
> into play). Perhaps there is no clean model.
>
> The best I can come up with would be to add an additional bullet after
> 3.10.1(2.4/2):
>
>   * it occurs within the scope of T after the completion of T if T is
> an incomplete view declared by an incomplete_type_declaration, and the
> completion of T is declared immediately within the same declarative
> list as T.

This seems to me necessary.  I agree that the current wording makes
the last example illegal, but I find the illegality surprising.
Clearly there was no notion of incomplete view in Ada83, and the intuitive
understanding was (at least for me) that once the completion has been analyzed
the incomplete declaration is hidden forever, and the full properties of the
type are available in the scope of the type.  3.10.1 (2.4/2)  was introduced to
make limited views work, and in the process affected "old-style" incomplete
declarations.  I think that the paragraph that Randy proposes is necessary.  I
would imagine that all implementations already assume the contents of this
paragraph.

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


Questions? Ask the ACAA Technical Agent