!standard 08.03 (16) 99-08-31 AI95-00041/09 !standard 08.03 (18) !standard 10.01.05 (02) !standard 10.01.05 (07) !standard 10.01.05 (09) !standard 12.03 (13) !standard 12.03 (14) !class binding interpretation 95-06-25 !status Corrigendum 2000 99-05-24 !status WG9 approved 96-12-07 !status ARG approved 12-0-0 96-10-07 !status ARG approved (subj. ed. rev., letter ballot was 12-0-0) 96-10-03 !status ARG-approved (9-0-0) 96-06-17; letter ballot pending !status received 95-06-25 !reference AI95-00199 !priority High !difficulty Hard !qualifier Clarification !subject Program unit pragmas in generic units !summary Program unit pragmas within a generic unit and applying to the generic unit itself do not apply to instances of the generic unit, unless a specific rule of the pragma specifies the contrary. The only language defined pragma with such a rule is pragma Inline. If the user wants a library unit pragma without such a rule to apply to an instance, then that pragma must be repeated explicitly for the instance. !question Do program unit pragmas and in particular library unit pragmas within a generic unit and referring to the generic unit apply to all instances of the generic unit ? Consider: generic generic ... ... package P is package Q is pragma Pure(P); pragma Pure; ... ... end P; end Q; package PI is new P(...); package QI is new Q(...); Does the pragma Pure apply to the respective instances PI and QI ? Since pragma Pure is a library unit pragma, are instantiations of P and Q illegal, if the resulting instances are not library units ? !recommendation Program unit pragmas within a generic unit and applying to the generic unit itself do not apply to instances of the generic unit, unless a specific semantic rule of the pragma specifies the contrary. A sentence to this effect should be appended to 10.1.5(2). If the user wants such a pragma to apply to an instance, then it must be repeated explicitly for the instance. A respective note to the user should be added to 10.1.5. ARM 12.3(14) should read ({...} indicates added text): "...except in the case of a name that denotes the generic_declaration or some declaration within the generic unit; {in the first case, the corresponding name in the instance then also denotes the current instance (see 8.6), in the second case} the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. ..." The anomaly of pragma INLINE applying to all instances is based on an explicit semantic rule of the pragma. (It may be regarded by implementers as an example of how implementation-defined pragmas for generic units may well be explicitly specified to apply to all instances.) !wording See recommendation. !discussion Part I: The individual program unit pragmas Some general observations: 1. If a pragma that applies to a generic unit were not to apply to all instances, the user would still have the option to specify such a pragma for each of the instances individually. This may be cumbersome, but no language functionality is lost. 2. If a pragma that applies to a generic unit were to apply to all instances automatically, the user would lose the capability of specifying a pragma that applies to the generic unit only. Note that the user does not have the option of placing the pragma outside the generic package and thereby escape a "current instance rule" (discussed later) selectively, since such placement is not allowed for pragmas on generic packages; ARM 10.1.5(4). Before discussing the language rules, we examine the pragma semantics for all program unit pragmas and discuss whether or not the pragma should apply to the generic unit only or to all its instances as well. Pragma Preelaborate: Consider the following example: with user_defined_function; generic ... package P is pragma Preelaborate; X: integer := user_defined_function; ... end P; The generic unit is legal, since its elaboration does not call the imported function. (The purpose of the pragma is merely to ensure that the elaboration of the generic body occurs prior to the elaboration of all non-preelaborated library units; i.e., to avoid the need for elaboration checks upon instantiations). Yet, if the pragma applies to the instances as well, they would all be illegal, since they are not preelaborable ! The semantics of pragma Preelaborate can been regarded as an expression of intent that the pragma not be automatically applicable to all instances. Otherwise the pragma should have enforced its restrictions on the nested declarations within the generic package to detect the above problem prior to any instantiation. If pragma Preelaborate applied to all instances, the user would no longer have the means to force preelaboration of the body of the generic unit (as shown in the example) without also imposing such preelaboration requirements on all instances and restricting the instantiations to library level. (The semantics of the pragma when applied to local instances is somewhat ill-defined.) We conclude that pragma Preelaborate should not automatically apply to all instances of the generic unit. Pragma Pure: Consider the following example: generic type T is private; package Q is pragma Pure(Q); type TN is new T; ... end Q; The user intention of pragma Pure in this package is to indicate that this generic unit can (but need not) be instantiated to yield a pure package. E.g.: type Acc is access TT; package Q_Acc is new Q(Acc); -- not a pure package package Q_Int is new Q(Integer); -- a pure package Pragma Pure(Q_Int); If the pragma were applicable to all instances, the package Q_Acc would be illegal. This would put the writer of reusable generic packages that satisfy the necessary conditions for pure instances into a serious dilemma: If the pragma Pure is inserted, the reusability is curtailed to pure instances only. If the pragma Pure is not inserted, reusability is curtailed, because instances can then not be pure, since the purity rules prohibit the necessary dependency on the generic unit. This reuse problem arises not only from the nature of the actual parameters of the instantiation, but also (and more importantly) from the context clauses of the instantiation, i.e., with P; -- P not pure package Q_Int2 is new Q(P.T); -- would be illegal irrespective -- of the nature of P.T and from any non-pure context of a local instantiation (if local instances were allowed at all, given that the pragma is a library unit pragma). Among others, any predefined or implementation-defined pure generic packages could not be instantiated in any non-pure context, which would be a quite devastating consequence. (A similar dilemma arises for all the other categorization pragmas when used (or not used) in reusable generic packages.) We conclude that pragma Pure definitely should not automatically apply to all instances of the generic unit. Pragmas Shared_Passive and Remote_Types: These pragmas impose the necessary restrictions to create a shared passive or a remote types library unit, respectively. As in the case of pragma Pure, such a pragma for a generic unit is a precondition for any instantiation to be so classified. However, unlike pragma Pure, it is not quite as obvious why instances should not be automatically in the respective category as well. In the case of shared passive packages there is a potential issue when an application may be required to execute in environments that may or may not support storage nodes. If an instantiation is shared passive then the library unit may only be assigned to a single partition. In environments that do not support storage nodes this may be unnecessarily restrictive since it is possible that a non-categorized instance can be replicated in different partitions without compromising execution (e.g., if there are no variables in the package specification since a typical use of shared passive packages may be to store constant data that are common to different partitions). In the case of remote types packages, one may wish to declare a type with subprograms that may be accessed both locally and remotely depending upon the instantiation. If the pragma applies to all instantiations then, when any declared access type within the package is referenced, it must be treated as containing a potentially remote access value. (This is particularly relevant, if the implementation uses wide pointers to represent remote access type values.) One might perhaps surmise that despite the above scenarios, user convenience might argue for automatically applying these pragmas to all instances. However, we observe that no semantic difficulties arise if this were not the case and that such implicit "inheritance" seems contrary to the principle that critical specifications should be explicit. The cited situations show that to a-priori preclude that reusable packages can be instantiated both in restricted and unrestricted contexts may be unwise. Pragma All_Calls_Remote, Remote_Call_Interface: It is not unreasonable for applications to develop generic packages that may be instantiated to provide both locally and remotely accessible subprograms. For example, consider the case of a partition that provides the same interface for both intra-partition and inter-partition clients. If an instantiation is always a remote interface package, then intra-partition clients will incur the cost of calling subprograms through a compiler generated stub. Additionally, a confirmation of the intent that this pragma should be explicitly specified is present in AARM E.2.3(15b) where it is stated "We considered making the public child of an RCI package implicitly RCI, but it seemed better to require an explicit pragma to avoid any confusion." It seems inconsistent to require an explicit pragma for a public child and not require an explicit pragma for an instantiation. We conclude that the pragma should be applicable to the generic unit only. Pragma Elaborate_Body: Pragma Elaborate_Body applied to generic library unit forces the elaboration of the body of the unit immediately after the elaboration of the generic declaration. In the case of instantiations, this effect of the pragma merely restates the existing rules on instance elaboration, ARM 12.3(20), so that this effect is the rule for instantiations in general. Hence, there is no need to make the pragma apply automatically to all instances, while it would be most detrimental to enforce as a secondary consequence that such instantiations yield only library units. We conclude that the pragma should be applicable to the generic unit only. Pragmas Elaborate and Elaborate_All: These pragmas are irrelevant for this discussion, as they refer to program units other than the (generic) unit in which they appear. (Consequently, the affected units are elaborated prior to the elaboration of the generic unit and, hence, its instances.) Pragmas Convention, Export, Import: These pragmas are irrelevant, since they cannot be applied to generic units. Pragma Inline: Pragma INLINE (historically) subscribes to the rule that it applies to all instances, when given for a generic subprogram. Its application to all instances relies on explicitly stated semantics of the pragma; ARM 6.3.2(5). This concludes the list of predefined program unit pragmas. We have seen that, in some cases, applicability of the pragma to all instances would be seriously detrimental. We have seen other cases, where applicability to all instances may be more convenient on occasion, but is neither absolutely necessary nor warrants a rule that a-priori precludes reusable generic units that can be instantiated in both restricted and unrestricted contexts. Part II: The Language Rules First, the relevant ARM paragraphs: (The elisions ".." omit text irrelevant for the question at hand.) 12.3(11) provides the general rule for checking legality rules in generic instantiations. The following discussion deals with these legality rules. 12.3(13) states: "The instance is a copy of the text of the template". 12.3(14) continues: "The interpretation of each construct within a generic declaration .. is determined using the overloading rules when that generic declaration .. is compiled. In an instance, the interpretation of each (copied) construct is the same, except in the case of a name that denotes the generic_declaration ..; the corresponding name in the instance then denotes the corresponding copy of the denoted declaration." 8.3(16,18) reaffirms this "current instance rule": "Each occurrence of a usage name denotes the declaration determined by its interpretation. It also denotes the view declared by its denoted declaration, except in the following cases: ... If a usage name appears within the declarative part of a generic_declaration .. and it denotes that same generic_declaration then it denotes the current instance of the generic unit (rather than the generic unit itself)." 10.1.5(2) states: "A name given as the argument of a program unit pragma ... shall resolve to denote the declaration of the immediately enclosing program unit (if any); the pragma applies to the denoted program unit. If there are no names given as arguments, the pragma applies to the immediately enclosing program unit." Finally, 10.1.5(7): "The name, if any, in a library unit pragma shall denote the declaration of a library unit." From 8.3(16) we conclude that a usage name denotes both the declaration AND the view declared by the denoted declaration. The "current instance rule" applies only to the view, not to the denoted declaration, which is always the declaration of the generic unit. Interpreting 10.1.5(7) literally in the context of 8.3(16), we can conclude that its restriction does not apply to the instance PI, since the denoted generic declaration is a library unit. (Note that 10.1.5(7) refers to the declaration, not to the declared program unit.) An instantiation at non-library level is therefore legal. However, 10.1.5(2) contradicts, at least in spirit, this interpretation, since it states "The pragma then applies to the denoted program unit" (which is the entity declared by the denoted declaration and hence subject to the "current instance rule"). (So, while the pragma would not prevent non-library instantiation, its effects would still apply to the current instance. This would create interesting questions, for example, for the semantics of a pragma Preelaborate applying to a locally declared instance.) Also, 12.3(14) confuses the issue further, as it states that the usage name denotes the copy of the denoted declaration (rather than the denoted declaration), thus leaning towards a uniform current instance rule. The situation is different for the instance QI (containing the pragma without arguments). Here, the current instance rule or denotation of a declaration by a name is irrelevant, since there is no name involved. We can only resort to 12.3(13,14), which regards the instance as a copy of the text of the template, where the interpretation of each (copied) construct is the same as in the template, while none of the exceptions stated in 12.3(14) applies to our case. Here, one might conclude that the pragma applies only to the generic unit, since "the interpretation stays the same" in an instance. On the other hand, we can read 10.1.5(2): "If there are no names given as arguments, the pragma applies to the immediately enclosing program unit.", combine this with the notion that the instance is a copy of the template, and conclude that the (copied) pragma applies to this copied enclosing program unit, i.e. the instance. (Irrespective of such literal reading of the standard, we note that surely the semantics of a pragma without argument should not differ from the semantics of the pragma naming the unit explicitly.) We note in passing that the wording of 12.3(14) refers, for our case, to "a copy of the generic_declaration". This concept is not used anywhere else. This copy cannot be the "instance", which is a package, not a generic package, and hence could not be declared by that copy. What semantics are associated with this copy ? Is it an implicit declaration ? Does it introduce a name ? One can surmise that an unfortunate abbreviation has taken place here that clouds the issue at hand by stating that the usage name not only denotes the generic_declaration and also the current instance (ARM 8.3(16,18)), but also this (rather undefined) copy of the generic_declaration. 12.3(14) should be expanded to read "...except in the case of a name that denotes the generic_declaration or some declaration within the generic unit; {in the first case, the corresponding name in the instance then also denotes the current instance (see 8.6), in the second case} the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. ..." The insertion merely reiterates 8.3(18), separating this case from the (correct) semantics of other usage names denoting nested declarations within the generic unit and instance, respectively. Program unit pragmas applied to generic subprograms are not affected by the current instance rule, since perforce they occur outside the generic unit; ARM 10.1.5(4). Hence, neither 12.3(13,14) nor 8.6(16,18) apply. Consequently, such pragmas can not be interpreted as applying to instances of such subprograms on the basis on instantiation and name interpretation rules. Note, however, that pragma INLINE (historically) subscribes to the rule that it applies to all instances, when given for a generic subprogram. Its application to all instances relies on explicitly stated semantics of the pragma; ARM 6.3.2(5). This creates a quite different situation from applicability of pragmas to instances due to general name interpretation rules. This short exegesis of the ARM shows that there is no clear answer found in the ARM to the questions at hand. In interpreting the standard, we therefore can take three different routes: 1. confirm the "current instance rule", i.e., the pragma applies to all instances. 2. confirm the rule that the pragma applies only to the generic unit itself. 3. define the most appropriate rule for each pragma. In any case, the effect of the pragma without argument should be the same as the pragma with argument, as the former is surely intended as a shorthand for the latter. Alternative 1: "pragmas in generic units apply to instances": Arguably, it would contribute to conceptual unity, if the "current instance rule" were uniformly applied to all usage names of a generic unit. This would avoid the very fine distinction between the declaration denoted by a usage name and the view declared by the denoted declaration. It would also avoid the difference in pragma effects compared to the INLINE pragma, even though these effects are achieved through two completely independent language rules (name interpretation vs. explicitly specified pragma semantics). However, such a rule also implies that generic units containing library unit pragmas cannot be instantiated other than as library units. (If local instantiations were legal, at least the semantics of pragma Preelaborate requiring elaboration of the unit prior to all non-preelaborated library units of the partition would be impossible to obey for such instances). The rule would further imply that instantiations violating the pragma are always illegal. Some aggravatingly undesirable consequences have been shown in the discussion of the individual pragmas. Finally, if the main objective were to create uniformity for pragmas applicable to generic packages and generic subprograms, an additional general rule would have to be added to the language that extends applicability of pragmas for generic subprograms to their instances. This in turn is completely unacceptable, since, for example, it would prohibit local instantiations of Unchecked_Conversion. Alternative 2: "pragmas in generic units do not apply to their instances" Here, the user disadvantages cited above do not exist, since pragmatic information about the instances is to be specified on a case-by-case basis. The only identifiable disadvantage from a user perspective is that the user has to replicate the pragmas for each instance to which they ought to apply, which may well be true for the use of most such generics. The rules for pragmas on generic subprograms already imply this alternative, so that no changes are required in that respect. The anomaly of pragma INLINE applying to instances as well is based on an explicit semantic rule of the pragma rather than a general rule of the language (and hence not really an anomaly, merely a potential surprise). From an implementation perspective, Alternative 2 is a minor problem for those implementations that subscribe to the expansion model for implementing generics. The "current instance rule" comes natural to such an expansion (due to its systematic replacement of bound names), while a rule that limits the effect of the pragma to the generic declaration only will require special processing. The usage aspects outlined above outweigh this minor complication for implementations. Alternative 3: Individual rules for each pragma We rejected this alternative to maintain some uniformity in the interpretation of pragmas. In the final analysis, alternative 2 appears to have the fewest disadvantages and presents a uniform general rule, while still allowing "overriding" special rules for individual pragmas, as in the case of pragma Inline. !corrigendum 10.01.05(2) @drepl Certain pragmas are defined to be @i. A name given as the argument of a program unit pragma shall resolve to denote the declarations or renamings of one or more program units that occur immediately within the declarative region or @fa in which the @fa immediately occurs, or it shall resolve to denote the declaration of the immediately enclosing program unit (if any); the @fa applies to the denoted program unit(s). If there are no names given as arguments, the @fa applies to the immediately enclosing program unit. @dby Certain pragmas are defined to be @i. A name given as the argument of a program unit pragma shall resolve to denote the declarations or renamings of one or more program units that occur immediately within the declarative region or @fa in which the @fa immediately occurs, or it shall resolve to denote the declaration of the immediately enclosing program unit (if any); the @fa applies to the denoted program unit(s). If there are no names given as arguments, the @fa applies to the immediately enclosing program unit. Program unit pragmas given within a generic unit and applying to the generic unit itself do not apply to instances of the generic unit, unless a specific semantic rule of the @fa specifies the contrary. !corrigendum 10.01.05(9) @dinsa An implementation may place restrictions on configuration pragmas, so long as it allows them when the environment contains no @fa other than those of the predefined environment. @dinst NOTE@hr To apply a program unit pragma to an instance, it must be specified for the instance. A program unit pragma in the generic unit usually does not apply to any instances. !corrigendum 12.03(14) @drepl The interpretation of each construct within a generic declaration or body is determined using the overloading rules when that generic declaration or body is compiled. In an instance, the interpretation of each (copied) construct is the same, except in the case of a name that denotes the @fa or some declaration within the generic unit; the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. The overloading rules do not apply in the instance. @dby The interpretation of each construct within a generic declaration or body is determined using the overloading rules when that generic declaration or body is compiled. In an instance, the interpretation of each (copied) construct is the same, except in the case of a name that denotes the @fa or some declaration within the generic unit; in the first case, the corresponding name in the instance then also denotes the current instance (see 8.6), in the second case the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. The overloading rules do not apply in the instance. !ACATS test Test(s) are needed. A C-Test should be constructed to check that Pure/Preelaborate in a generic do not prevent the generic from being instantiated in a nested location. A B-Test should be constructed to check that Pure/Preelaborate in a generic do not automatically make the instantiation Pure/Preelaboratable. For example, instantiate such a generic at library level, with into a Pure/Preelab unit, check that an error occurs. !appendix !section 12.3(14) !section 12.3(13) !section 10.1.5(3) !section 10.1.5(7) !subject Do library unit pragmas in generics apply to all instances ? !reference RM95-12.3(14);6.0 !reference RM95-12.3(13);6.0 !reference RM95-10.1.5(3);6.0 !reference RM95-10.1.5(7);6.0 !keywords library unit pragma !from Erhard Ploedereder 4-12-95 !reference as: 95-5122.a Erhard Ploedereder 95-4-11>> A three-part question: Part I: Library unit pragmas are legal only if they apply to library units - 10.1.5(7). If such a pragma is given within a generic package, the argument name necessarily denotes the generic package itself, which must be a library unit. The "current instance rule" of 12.3(14) implies that in an instantiation the name denotes the current instance; the pragma therefore applies to the current instance of the instantiation. It follows that generic units containing a library unit pragma can only be instantiated as library units; other instantiations are illegal due to 10.1.5(7). Is this a correct conclusion ? --------------------- Part II: The interpretation gets murkier, when asking the same question for library unit pragmas without argument name. In this case, 12.3(14) does not apply, when literally interpreted. Is 12.3(13) sufficient to come to the same conclusion, namely that the pragma applies to the current instance in an instantiation ? -------------------------------- Part III: Under the above interpretation, 10.1.5(3-6) makes it impossible to have a library pragma apply to a generic package only but not to its instances. Would this ever be necessary/desirable ? (Interestingly, the rules do not prevent this for generic subprograms.) Note: For some of the predefined library pragmas, 10.1.5(3-6) has its benefits: It prevents the inverse situation to the question above: no pragma for the generic unit, but pragmas for the instantiations. This would open a hole in the contract model: generic bodies would need to be rechecked upon instantiation. Example: Shared_Passive, due to E.2.1(9). **************************************************************** !section 12.3(14) !section 12.3(13) !section 10.1.5(3) !section 10.1.5(7) !subject Do library unit pragmas in generics apply to all instances ? !reference RM95-12.3(14);6.0 !reference RM95-12.3(13);6.0 !reference RM95-10.1.5(3);6.0 !reference RM95-10.1.5(7);6.0 !keywords library unit pragma !reference 95-5122.a Erhard Ploedereder 4-12-95 !from Tucker Taft 94-04-12 !reference as: 95-5124.a Tucker Taft 95-4-12>> !discussion > A three-part question: > > Part I: > > Library unit pragmas are legal only if they apply to library units - > 10.1.5(7). If such a pragma is given within a generic package, the argument > name necessarily denotes the generic package itself, which must be a library > unit. The "current instance rule" of 12.3(14) implies that in an > instantiation the name denotes the current instance; the pragma therefore > applies to the current instance of the instantiation. > > It follows that generic units containing a library unit pragma can > only be instantiated as library units; other instantiations are illegal > due to 10.1.5(7). > > Is this a correct conclusion ? No, that was not the intent. The legality rule requiring a library unit pragma to denote the declaration of a library unit is not intended to disallow a generic library unit with such a pragma to be instantiated as a nested unit. Some clarification may be appropriate, however, to be language-lawyerly... Paragraph 10.1.5(7) doesn't say a library unit pragma must denote a library unit, but rather that it must denote the *declaration* of a library unit. There is a subtle difference here (see 8.6(16-18)). When inside a generic, the name of the generic still denotes the *declaration* of the generic, though the *entity* it denotes is the current instance of the generic. This subtle language-lawyerly difference between what "declaration" is denoted vs. what "entity" is denoted is only important in a few places, but is definitely relevant when talking about current instance-related rules. In any case, it wouldn't hurt to be more explicit in 10.1.5(7) about generic library units. > Part II: > > The interpretation gets murkier, when asking the same question for library > unit pragmas without argument name. In this case, 12.3(14) does not apply, > when literally interpreted. Is 12.3(13) sufficient to come to the same > conclusion, namely that the pragma applies to the current instance in an > instantiation ? That was not the intent. In general, a library unit pragma that applies to a generic library unit does not necessarily apply to all instances of the generic unit. > Part III: > > Under the above interpretation, 10.1.5(3-6) makes it impossible to have a > library pragma apply to a generic package only but not to its > instances. Would this ever be necessary/desirable ? > (Interestingly, the rules do not prevent this for generic subprograms.) As indicated above, it was the intent that a library unit pragma only apply to the generic unit itself, not automatically to its instances. > Note: > For some of the predefined library pragmas, 10.1.5(3-6) has its benefits: It > prevents the inverse situation to the question above: no pragma for the > generic unit, but pragmas for the instantiations. This would open a hole in > the contract model: generic bodies would need to be rechecked upon > instantiation. Example: Shared_Passive, due to E.2.1(9). I don't follow. A Shared_Passive library unit may only depend on other Pure or Shared_Passive library units. Why is your suggested (but unintended) interpretation of 10.1.5(3-6) useful here? In any case, a library unit pragma should be reapplied to the instantiation of a generic unit if you want it to apply to the instance. -Tuck **************************************************************** !section 12.3(14) !section 12.3(13) !section 10.1.5(3) !section 10.1.5(7) !subject Do library unit pragmas in generics apply to all instances ? !reference RM95-12.3(14);6.0 !reference RM95-12.3(13);6.0 !reference RM95-10.1.5(3);6.0 !reference RM95-10.1.5(7);6.0 !keywords library unit pragma !reference 95-5122.a Erhard Ploedereder 4-12-95 !reference 95-5124.a Tucker Taft 95-4-12 !from Erhard Ploedereder !reference as: 95-5128.a Erhard Ploedereder 95-4-13>> !discussion I wrote: > Note: > For some of the predefined library pragmas, 10.1.5(3-6) has its benefits: It > prevents the inverse situation to the question above: no pragma for the > generic unit, but pragmas for the instantiations. This would open a hole in > the contract model: generic bodies would need to be rechecked upon > instantiation. Example: Shared_Passive, due to E.2.1(9). Tuck responded: > I don't follow. A Shared_Passive library unit may only depend on > nother Pure or Shared_Passive library units. Why is your suggested > (but unintended) interpretation of 10.1.5(3-6) useful here? Indeed, the note was incorrect as written. The "problem" I was worried about exists already (and is independent of the topic of this comment). Clearly, I can already have a generic unit without the XYZ Pragma and then apply the XYZ Pragma to instantiations. Assume further that the XYZ Pragma imposes restrictions on the contents of the unit body, as most of the predefined library unit pragmas do. The semantics of the predefined pragmas are carefully designed to prevent the need for reexamining the body of the generic unit by individually imposing the rule that units depended on must be at least as restrictive, in particular the generic unit itself that gets instantiated. However, this is not required as an inherent semantics of program unit pragmas. Consequently, an impl.-defined pragma need not have a similar semantic rule. In that case, the enforcement of the restriction requires reexamination of the body of the instantiation, which may determine the body to be illegal. I suppose this is an "implementor beware!" situation, rather than a language issue. **************************************************************** !section 08.03(16) !subject Program unit pragmas in generic units !reference AI95-00041 !reference RM95-08.03 (16) !reference RM95-08.03 (18) !reference RM95-10.01.05 (02) !reference RM95-10.01.05 (07) !reference RM95-12.03 (13) !reference RM95-12.03 (14) !reference RM95-E.2 !from Offer pazy 95-10-11 !reference as: 95-5326.a Offer Pazy 95-10-11>> !discussion I disagree with the recommendation suggested in this AI. First, from a general point of view. I think that the idea that a generic is not known to be OK until it is instantiated by its clients is flawed. What's the point of developing generics if you can't rely on the clean compilation until to point when users start to instantiate it. Also, if I understand (?!) the issue correctly, for implementation that do not use the macro-expansion approach, this will represent a major problem, since after a generic unit has been cleanly compiled, they rely on the contract model rules to check instantiations and not on recompiling the generic unit. But more specifically, I have a problem with applying the recommendation to the categorization pragmas which are the creation of the DS annex. I find it hard to believe that people will develop "general" generic units without dedicating them as RCI or SP packages. Such a categorization is built into the creation of the generic and into its contents. I don't think it is practical to think about somebody writing such a generic unit and letting its users (instantiators) later decide whether or not it should serve as an RCI, SP, or a normal package. This is not the way I envision people developing such generics. Again, it implies that the compiler will have to check all the corresponding rules upon each instantiation on a unit which may have long been developed and frozen in another program library. So to summarize, I recommend (at least in the case of categ pragmas) a rule which will say (and I thought it already clearly said that) that a categ pragma can be placed inside a generic unit (and it takes effect). Appling a categ pragma on the instance can only repeat that of the generic unit (i.e. be a no-op) and not change the categorization of the instance. Offer Pazy 31 Robinwood Ave. Boston, MA 02130 USA (617)522-5988 pazy@world.std.com **************************************************************** !section 10.1.5(02) !subject Program unit pragmas in generic units !reference AI95-00041 !reference RM95-10.1.5(2-7) !reference RM95-12.3(13-14) !from Tucker Taft 95-10-30 !reference 95-5373.e Tucker Taft 95-10-30>> !discussion The background on this AI seems to have an enormous amount of language-lawyerly discussion that seems somewhat beside the point. I don't believe that 12.3(13-14) were written with pragmas in mind, and we should just analyze pragmas on a case by case basis to determine what make the most sense. In any case, I believe it was never the intent that just because a generic library unit had a library unit pragma, then all instances of the generic must themselves be library units. This seems very inflexible. On my own quick perusal, I would recommend that as a *general* rule, *library* unit pragmas on a generic library unit apply to the generic *only*, and not automatically to its instances. On the other hand, program unit pragmas which are *not* library unit pragmas should, by default, apply to all instances. In both cases, this should just be a default rule, subject to overriding by rules which are specific to a particular pragma. I think these general rules make sense because when talking about program units inside a generic, there is not much of interest to say except in terms of instances. On the other hand, library unit pragmas are often talking about things which relate directly to library-unit-ness, and relate to "with" clauses, elaboration order, etc., and might not make sense when applied to particular instances (which in any case might not be library units). **************************************************************** !section 08.03(16) !subject AI-41 and "non-generic equivalents" !reference AI-00041 !reference RM95-08.03(16) !from Bob Duff !reference 96-5479.a Robert A Duff 96-4-12>> !discussion Erhard, I believe you're in charge of AI-41. While you're at it, you might want to take into account this message I got from Robert Dewar: > with Ada.Numerics.Generic_Elementary_Functions; > > package Ada.Numerics.Elementary_Functions is > new Ada.Numerics.Generic_Elementary_Functions (Float); > > according to our undertanding of the ARG decision, this unit does NOT > inherit the pragma Pure from the generic package. Therefore it is not > pure. But surely it is meant to be Pure. We propose adding a Pure > pragma to this and other similar packages. I agree with Robert that it is meant to be declared Pure. The above text does not appear in the RM -- there is no generic instantiation, but just a statement that Ada.Numerics.Elementary_Functions is a package that exports certain functions. A.5.1(9). From that, I think one can argue that it *is* declared Pure. Anyway, I think it's worth stating in the AI. There are various other "non-generic equivalents" in the RM that I suppose should be treated the same way. - Bob ****************************************************************