!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) @dinsa For each call, an implementation is free to follow or to ignore the recommendation expressed by the @fa. @dinst An implementation may allow a @fa Inline that has an argument which is a @fa denoting a @fa of the same @fa. !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? ****************************************************************