Version 1.3 of ais/ai-00309.txt

Unformatted version of ais/ai-00309.txt version 1.3
Other versions for file ais/ai-00309.txt

!standard 6.3.2 (06)          04-11-30 AI95-00309/02
!standard 6.3.2 (03)
!standard 10.1.5 (02)
!standard 10.1.5 (05)
!standard 10.1.5 (06)
!class binding interpretation 02-09-25
!status Amendment 200Y 04-11-30
!status ARG Approved 10-0-0 04-11-21
!status work item 04-04-26
!status received 02-09-17
!qualifier Error
!priority Low
!difficulty Medium
!subject Pragma Inline compatibility
!summary
Pragma Inline may refer to a subprogram_body without a subprogram_declaration.
!question
It seems that the standard makes a case illegal that was legal in Ada 83; however, the AARM doesn't include this in an "Incompatibilities With Ada 83" section, which leads me to believe that the incompatibility is unintentional and maybe should be fixed.
package Pak1 is ... end Pak1;
package body Pak1 is
procedure Proc1 is begin ... end Proc1; pragma Inline (Proc1); -- legal in Ada83, illegal in Ada95
end Pak1;
RM83 6.3.2(3) allows Inline at the place of any declarative item. For Ada 95, however, the standard says the pragma is a program unit pragma, which must denote a subprogram_declaration, which is not a subprogram_body. Was this incompatibility intentional? (No.)
!recommendation
(See wording.)
!wording
Add an implementation permission after 6.3.2(6):
An implementation may allow a pragma Inline that has an argument which is a direct_name denoting a subprogram_body of the same declarative_part.
AARM Note: We only need to allow this in declarative_parts, because a body is only allowed in another body, and these all have declarative_parts.
!discussion
The incompatibility does not appear to have been intentional, as it was not listed in the AARM as an incompatibility.
We add an implementation permission for pragma Inline only, because changing the definition of program unit pragmas would affect many other pragmas. Moreover, this use can be considered obsolescent, as Ada 95 allows the pragma to be given within the body to have the same effect.
!corrigendum 6.3.2(6)
Insert after the paragraph:
For each call, an implementation is free to follow or to ignore the recommendation expressed by the pragma.
the new paragraph:
An implementation may allow a pragma Inline that has an argument which is a direct_name denoting a subprogram_body of the same declarative_part.
!ACATS test
This is a permission, so no test is needed.
!appendix

!topic Pragma Inline issues
!reference RM95 6.3.2, 10.1.5; AARM95 6.3.2; RM83 6.3.2(3); AI83-00242
!from Adam Beneschan 09-16-02
!discussion

I have a couple of issues regarding Pragma Inline:

(1) It seems that RM95 makes a case illegal that was legal in Ada 83;
however, the AARM doesn't include this in an "Incompatibilities With
Ada 83" section, which leads me to believe that the incompatibility is
unintentional and maybe should be fixed.

    package Pak1 is
       ...
    end Pak1;

    package body Pak1 is

       procedure Proc1 is
       begin
          ...
       end Proc1;
       pragma Inline (Proc1);  -- legal in Ada83, illegal in Ada95

    end Pak1;

RM83 6.3.2(3) says about Pragma Inline: "If the pragma appears at the
place of a declarative item, each name must denote a subpropgram or a
generic subprogram declared by an earlier declarative item of the same
declarative part or package specification".  A "declarative item", as
defined in RM83 3.9(1-2), can be either a basic_declarative_item or a
later_declarative_item, and a subprogram body is a type of
later_declarative_item, so the pragma is legal.  AI83-00242 seems to
support the legality of this pragma placement; one of the examples in
this AI contains a nested subprogram body and a Pragma Inline that
follows the body.

In RM95, though, 6.3.2 says that Pragma Inline is a program unit
pragma, and 10.1.5(6) says that pragmas that occur "at a place of a
declaration other than the first" shall have an argument that denotes
a subprogram_declaration, generic_subprogram_declaration, or
generic_instantiation.  A subprogram body is not, syntactically, a
subprogram_declaration.  6.3 makes it clear that a subprogram body
that is not the completion of a subprogram_declaration does constitute
the initial declaration of the subprogram; however, the font used in
10.1.5(6) and the underscore in "subprogram_declaration" appear to
make it clear that the pragma must refer to an actual
subprogram_declaration that appears in the source and not just
anything that constitutes a subprogram declaration.

So it appears that the above example is legal in Ada 83 but not in Ada
95.


(2) In AARM95 6.3.2, under "Extensions to Ada 83" in AARM95, is the
note:

    A pragma Inline is allowed inside a subprogram_body if there is no
    corresponding subprogram_declaration.  This is for uniformity with
    other program unit pragmas.

This seems to imply that the Inline pragma would *not* be allowed
inside a subprogram body if there *is* a corresponding
subprogram_declaration.  However, I cannot find anything in 10.1.5
that disallows this.  10.1.5(2) says

     A name given as the argument of a program unit program

(*)  shall resolve to denote the declarations or renamings of one or
     more program units that occur immediately within the declarative
     region or compilation in which the pragma immediately occurs, or

(**) it shall resolve to denote the declaration of the immediately
     enclosing program unit (if any);

In this case:

    package Pak1 is
       procedure Proc2;
    end Pak1;

    package body Pak1 is

       procedure Proc2 is
          pragma Inline (Proc2);  -- legal?
       begin
          ...
       end Proc2;

    end Pak1;

the pragma doesn't satisfy the clause (*), but it does appear to
satisfy (**); and it certainly satisfies 10.1.5(5).

So what is the real rule?  Is an Inline pragma that denotes a
subprogram P allowed in the body of P (as the first declarative item)
if there was an earlier subprogram_declaration for P?

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

From: Robert Dewar
Sent: Tuesday, September 17, 2002  8:57 PM

To me it is obvious that a pragma Inline must refer to a separate spec, since
you need to know BEFORE you compile the body what the calling convention is.

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

From: Christoph Grein
Sent: Wednesday, September 18, 2002  2:45 AM

That's a convincing argument, and the RM shall say so.

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

From: Adam Beneschan
Sent: Wednesday, September 18, 2002  12:43 PM

Pragma Inline doesn't affect the calling convention, as far as I can
tell from 6.3.1.  Inlined subprograms aren't in the list of
subprograms whose default calling convention is Intrinsic, and thus
the convention would still be Ada (unless it's in a protected body).
This means, for example, that P'Access is legal even if Pragma Inline
has been applied to P.

I can think of a couple possible reasons why it might be desirable to
allow Pragma Inline in the body of a subprogram P that was declared in
the spec of package PK:

(1) An implementation could specify that such an Inline would be
    obeyed only on calls to P that occur in PK's body.

(2) If an implementation does not perform any code generation until
    link time, allowing Pragma Inline to be specified or not be
    specified in the subprogram body (depending on how large the body
    is) would be useful.

Nevertheless, I am not really arguing about whether this pragma should
or should not be allowed; I would be fine with disallowing the pragma
in this situation.  My main concerns are the apparent incompatibility
with Ada 83 and the ambiguity of the Ada 95 RM/AARM.

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

From: Pascal Leroy
Sent: Thursday, September 19, 2002  7:42 AM

> So it appears that the above example is legal in Ada 83 but not in Ada
> 95.

I agree that an unfriendly reading of the manual (well, of the fonts used by
the manual, really) might lead to the above conclusion, but that would be
absurd, because it would be a gratuitous incompatibility with Ada 83 and with
at least some Ada 95 compilers (I tried ours and GNAT, and they both allow the
above fragment).  And Dewar's Postulate states that the RM never says absurd
things.

AARM 10.1.5(6.a) makes it clear that the intent is that the above be legal.

I don't understand the discussion about conventions: the body declares Proc1
and then immediately freezes it, so the convention of Proc1 is known (and
happens to be Ada) when the body is compiled.  A pure one-pass compiler (if
such a thing existed) would only see the pragma after having generated the code
for the body of Proc1, but that's OK, it only means that recursive calls in the
body of Proc1 (if any) would not be inlined, which is probably a good policy
anyway.

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

From: Robert Dewar
Sent: Thursday, September 19, 2002  8:18 AM

I agree with this, my comment on conventions is indeed dubious.

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

From: Adam Beneschan
Sent: Thursday, September 19, 2002  10:20 AM

Pascal wrote:

> I agree that an unfriendly reading of the manual (well, of the fonts
> used by the manual, really) might lead to the above conclusion, but
> that would be absurd, because it would be a gratuitous
> incompatibility with Ada 83 and with at least some Ada 95 compilers
> (I tried ours and GNAT, and they both allow the above fragment).
> And Dewar's Postulate states that the RM never says absurd things.
>
> AARM 10.1.5(6.a) makes it clear that the intent is that the above be legal.

Now I'm totally lost: doesn't 10.1.5(6.a) say the exact opposite?

"If you want to denote a subprogram_body that is not a completion,
. . . you have to put the pragma inside."  I.e. you have to say

    procedure Proc1 is
        pragma Inline (Proc1);
    begin
        ...
    end Proc1;

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

From: Pascal Leroy
Sent: Thursday, September 19, 2002  10:43 AM

Yes, you're right of course, I must have read that sentence backwards.

I still believe that this is an unnecessary incompatibility and that it should
be fixed somehow.

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

From: Tucker Taft
Sent: Wednesday, September 18, 2002  1:15 PM

We noticed this problem as well, and
added a command line switch to allow "late"
pragma Inlines, but only on spec-less
bodies.  I believe Ada 83 was pretty clear
that the pragma had to refer to the declaration
of the subprogram, and only if it was
spec-less could that mean the body.

So I guess I agree this is an undocumented incompatibility,
and we could fix this by allowing a "late" pragma inline
(on spec-less bodies).  Of course there is no requirement
that any compiler act upon it, and we would probably
want to encourage users to use the approach where
the pragma inline comes before (most of) the body,
so implementations know "in time" to save away a
copy of the body.  Perhaps the "late" pragma
should be included only as an obsolescent feature.

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

From: Nick Roberts
Sent: Thursday, September 19, 2002  5:54 PM

My vote would simply be to change the rule so that pragma Inline
is illegal after the subprogram it applies to has been frozen.

If Inline were to be made a representation pragma (governing the
aspect of representation called "inline expansion"), then this
would be implied by 13.14 (19) anyway.

13.14 (14) should be amended to:

   * At the place where a callable entity is frozen, the entity's
     address, calling convention, and inline expansion are
     frozen, and each subtype of its profile is frozen. [etc.]

This may not yield strict forwards compatibility (from Ada 83),
but I think this solution has a certain simplicy.

I think it would be appropriate to freeze a subprogram's address
and calling convention along with its inline expansion.

Also, I think the following clause should be added after 13.14
(7):

   * Any procedure call statement causes freezing.

This is so that if, for example, we have:

   procedure P1 (...);

   procedure P2 (...) is
   begin
      ...
      P1(...);
      ...
   end;

we are sure that P1 gets frozen by the call to it in P2's body.

It may seem odd that a procedure should be frozen before its body
is declared, but freezing would affect only its address, calling
convention, and inline expansion (not its body). It would be
wrong to permit a pragma Inline (or pragma Convention) after the
above declarations, because it would be confusing for the reader
(and could be confusing for the compiler!).

If the compiler must emit machine code for the call to P1 before
it has established the actual address of P1's body (code), and it
doesn't have the assistance of a linker, it must do something
such as compiling a 'trampoline' for P1 (at its declaration).
This is a well-established technique.

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

From: Pascal Leroy
Sent: Friday, September 20, 2002  2:15 AM

First, let me comment on the proposed change to the freezing rules:

> Also, I think the following clause should be added after 13.14
> (7):
>
>    * Any procedure call statement causes freezing.
>
> This is so that if, for example, we have:
>
>    procedure P1 (...);
>
>    procedure P2 (...) is
>    begin
>       ...
>       P1(...);
>       ...
>    end;
>
> we are sure that P1 gets frozen by the call to it in P2's body.
> My vote would simply be to change the rule so that pragma Inline
> is illegal after the subprogram it applies to has been frozen.

This is already implied by the second sentence of 13.14(3), because a
procedure call can only occur in a body.  As for function calls, the rule is
in 13.14(8) (and it is carefully worded to deal with function calls
appearing in default expressions).

This is all necessary because the compiler needs to know the subprogram
calling convention, address, etc, to generate a call.  But it surely doesn't
need to know whether the subprogram is inlined or not, as pragma Inline is
only a recommendation, and it may not be obeyed for every call.

> If Inline were to be made a representation pragma (governing the
> aspect of representation called "inline expansion"), then this
> would be implied by 13.14 (19) anyway.
>
> This may not yield strict forwards compatibility (from Ada 83),
> but I think this solution has a certain simplicy.

Boy, that's a terrible idea!

Note that the ARG has actually moved in the other direction, turning some
representation attributes into operational attributes in order to make them
easier to use in some contexts (notably in relation with private types).

We don't introduce incompatibilities just for the fun of it or because it
makes the RM rules simpler/more aesthetical.  We have to keep in mind that
there is a large community of users out there who use that pragma, and the
suggested change would result in a considerable amount of pain for no
benefits at all (it wouldn't even make implementations simpler).

Even assuming that we are ready to forsake compatibility with Ada 83 (an
unwise choice in my opinion) the suggested change would introduce horrible
incompatibilities in Ada 95.  Consider the following example, which
illustrates a common idiom where people "hide" the pragmas Inline in the
private part of a package:

    with Gen;
    package Pak is
        type T is private;
        procedure Proc (X : T);
    private
        type T is ...;
        package Inst is new Gen (T, Proc);
        pragma Inline (Proc);
    end Pak;

The instantiation freezes T and Proc (13.14(5), 13.14(11)), so the pragma
would be illegal if it were a representation pragma.  To me, this is
absolutely unacceptable.

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

From: Nick Roberts
Sent: Friday, September 20, 2002  9:17 AM

>First, let me comment on the proposed change to the freezing rules:
>...
>This is already implied by the second sentence of 13.14(3),
>because a procedure call can only occur in a body.

I'm sorry, I missed that. However, what precisely, please, is a
"noninstance body", and where is it defined?

>[pragma Inline is] only a recommendation, and it may not be
>obeyed for every call.

True, but you want it to be in a position where it can be obeyed
(other impediments notwithstanding) as often as possible.

>Boy, that's a terrible idea!

It sounds like Pascal prefers the more complex solutions ;-)

>Note that the ARG has actually moved in the other direction,
>turning some representation attributes into operational
>attributes in order to make them easier to use in some contexts
>(notably in relation with private types).
>
>We don't introduce incompatibilities just for the fun of it or
>because it makes the RM rules simpler/more aesthetical.  We have
>to keep in mind that there is a large community of users out
>there who use that pragma, and the suggested change would result
>in a considerable amount of pain for no benefits at all (it
>wouldn't even make implementations simpler).

My suggestion was not made just for fun :-) but because it is
always a significant advantage to make the rules simpler and more
easily understood (by both programmer and compiler implementor),
always given, of course, that doing so doesn't cause some other
worse problem.

I am not convinced about the amount of pain my suggestion would
cause; I'm certainly not wishing to cause people pain! Robert
Dewar made a crystal clear case for the need for forward
compatibility, but the counter-argument is clearly that we must
avoid the danger of failing to make any improvements to the
language at all because we must retain 100% forward
compatibility.

>    with Gen;
>    package Pak is
>        type T is private;
>        procedure Proc (X : T);
>    private
>        type T is ...;
>        package Inst is new Gen (T, Proc);
>        pragma Inline (Proc);
>    end Pak;

Looking at this example, as far as I'm concerned it was always
wrong to put Inlines in the private part that applied to
subprograms in the visible part. But I suppose you're saying that
people have already done it and it's too late now. (Sigh)

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

From: Robert Dewar
Sent: Friday, September 20, 2002  8:15 PM

This sigh seems entirely inappropriate. Many people, including me, think
that it is not only OK, but desirable to put Inlines in the private part.
Whether something can be inlined is a functoin of the body, and is therefore
logically not part of the visible interface.

Not only have "people already done it" but it is an extensively used
style. We often use it, and so do many other Ada users.

Nick, if you don't like this style, don't use it, byut the suggestion
that this not be allowed is of course entirely off the wall. We are
not going to introduce incompatibilities because of random
gratutious dislikes :-)

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

From: Robert A. Duff
Sent: Friday, September 20, 2002  9:34 AM

> I'm sorry, I missed that. However, what precisely, please, is a
> "noninstance body", and where is it defined?

The term "body" is defined in 3.11(1/1).  (Note that the "/1" means you
have to look at the version with Corrigendum 1 included -- the term body
was not defined in the original Ada 95 standard (clearly a hole).)

Note also the rather subtle use of fonts to distinguish "body" from
"body".  ;-)

The term "noninstance body" just means a body that is not that of an
instance; I don't think it needs an explicit definition in the RM.
"Instance" is defined in 12.3(1,13).

By the way, both "body" and "instance" are in the index.
"Noninstance" is not.  ;-)

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

From: Christoph Grein
Sent: Monday, September 23, 2002  12:14 AM

I have both, the original and the one with Corrigendum 1, and there is no
3.11(1/1) and body is (and has always been) defined in 3.11(3). [There is only a
3.11(4/1) defining the new aspect_clause.]

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

From: Pascal Leroy
Sent: Monday, September 23, 2002  5:20 AM

Bob meant 3.11.1(1/1) (wonderful numbering scheme!).  3.11(3) defines
body-as-a-syntactic construct (sans-serif font), but 3.11.1(1/1) defines body
as a language entity (serif, italics).  The usage of fonts does matter here.

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

From: Robert A. Duff
Sent: Monday, September 23, 2002  8:50 AM

> Bob meant 3.11.1(1/1) (wonderful numbering scheme!).

Oops -- sorry.

>...3.11(3) defines
> body-as-a-syntactic construct (sans-serif font), but 3.11.1(1/1) defines body as
> a language entity (serif, italics).  The usage of fonts does matter here.

Indeed.  It's really odd that "body" is defined to be "body plus some
other stuff."

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

From: Robert Eachus
Sent: Monday, September 23, 2002  11:23 AM

Body is defined in 3.11.1(1/1).

However this misses the major point about this AI.  At best this AI
should be pathological with regard to pragma Inline.  (There should not
be any ACVC test resulting from the AI.)  Whether the clause located
after a subprogram body is legal or not, in-lining of the actual
subprogram is a decision made by the compiler, the pragma is just a
suggestion.

If the correct fix is to 10.1.5(2), which I think it is, then we have to
look at the effect of the change on all other library unit pragmas.
Pragma Elaborate_Body surely qualifies for the pathological label,
Elaborate and Elaborate_All are only allowed in a context clause.  Any
others?

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


Questions? Ask the ACAA Technical Agent