!standard 10.2.1(11) 05-05-05 AI95-00403/03 !class binding interpretation 05-01-27 !status Amendment 200Y 05-03-17 !status WG9 Approved 06-06-09 !status ARG Approved 11-0-0 05-04-17 !status work item 05-01-27 !status received 05-01-27 !qualifier omission !subject Preelaboration checks and formal objects !summary For the purposes of determining whether a unit can be declared to be preelaborable, a generic formal object is nonstatic. !question In this example: (Pak2 is a library unit) generic x1: integer; package Pak2 is pragma Preelaborate; pragma Elaborate_Body; end Pak2; package body Pak2 is x2: integer := x1; end Pak2; Is this legal? (No.) It seems that the intent is that 10.2.1(10) makes this illegal, because it's possible to instantiate Pak2 with an actual for "x1" that would cause the declaration of x2 to perform an action that 10.2.1(6-7) makes nonpreelaborable. For instance, wou could instantiate Pak2 with an actual that contains a function call or the name of an object. !recommendation (See wording.) !wording Replace 10.2.1(10) by: A generic body is preelaborable only if elaboration of a corresponding instance body would not perform any such actions, presuming that: o the actual for each formal private type (or extension) declared within the formal part of the generic unit is a private type (or extension) that does not have preelaborable initialization; o the actual for each formal type is nonstatic; o the actual for each formal object is nonstatic; and o the actual for each formal subprogram is a user-defined subprogram. AARM Note: This is an "assume-the-worst" rule. The elaboration of a generic unit doesn't perform any of the actions listed above, because its sole effect is to establish that the generic can from now on be instantiated. So the elaboration of the generic itself is not the interesting part when it comes to preelaboration rules. The interesting part is what happens when you elaborate "any instantiation" of the generic. For instance, declaring an object of a limited formal private type might well start tasks, call functions, and do all sorts of non-preelaborable things. We prevent these situations by assuming that the actual parameters are as badly behaved as possible. !discussion 10.2.1(10) is intended to be an "assume-the-worst" rule. However, it explicitly requires assuming properties that have that effect for types and subprograms; objects aren't mentioned. Objects should be assumed to be non-static, because then 10.2.1(8) must apply. We must also specify that the private type used when assuming the worst doesn't have preelaborable initialization. !corrigendum 10.2.1(10) @drepl A generic body is preelaborable only if elaboration of a corresponding instance body would not perform any such actions, presuming that the actual for each formal private type (or extension) is a private type (or extension), and the actual for each formal subprogram is a user-defined subprogram. @dby A generic body is preelaborable only if elaboration of a corresponding instance body would not perform any such actions, presuming that: @xbullet @xbullet @xbullet @xbullet !ACATS Test Construct an ACATS B-Test to insure that generics of this form are not allowed to be preelaborable. !appendix !topic Preelaborable generics !reference RM95 10.2.1 !from Adam Beneschan 04-12-01 !discussion We've had a couple of questions regarding the use of Preelaborate on a library generic unit. Trying to find the answers to these questions seems to have led to confusion about what the RM means, so it was suggested that I ask Ada-Comment for clarification and perhaps suggest that the next version of the RM or AARM needs a note to clarify the meaning. I previously posted the first question on comp.lang.ada, and only got one response from someone who also wasn't sure what the RM said about this. Question 1: In this example: (Pak2 is a library unit) generic x1: integer; package Pak2 is pragma Preelaborate; pragma Elaborate_Body; end Pak2; package body Pak2 is x2: integer := x1; end Pak2; My reading is that 10.2.1(10) makes this illegal, because it's possible to instantiate Pak2 with an actual for "x1" that would cause the declaration of x2 to perform an action that 10.2.1(6-7) makes nonpreelaborable. (You could instantiate Pak2 with an actual that contains a function call or the name of an object, e.g.) Is my reading correct? Question 2: In this case, the object declaration is moved to the spec, so that 10.2.1(10) doesn't apply. generic x1: integer; package Pak2 is pragma Preelaborate; x2: integer := x1; end Pak2; Pak2 is a library unit. The Preelaborate on Pak2 makes it legal for other preelaborable units to "with" Pak2; but (Question 2A) does this Preelaborate have any effect on the legality of an instance of Pak2? Specifically, suppose Pak2 (1) is instantiated as a library-level instantiation New_Pak2, where there is *no* Preelaborate(New_Pak2) pragma; or (2) is instantiated inside another library unit that is not preelaborable. Question 2B: Is it legal to instantiate Pak2 with an actual for "x1" that contains a non-static function call or the name of an object? I think the answer to Question 2B is "yes" [in both cases], and the answer to Question 2A is "no"; but different people have come to different conclusions, so it would appear that the RM or AARM ought to be clearer about this. **************************************************************** From: Randy Brukardt Sent: Wednesday, December 1, 2004 6:16 PM I don't (off-hand) know the answer to Question 1, but Question 2 is exactly the question of AI-41, which was included in the corrigendum. Thus the answers are 2A) No, and 2B) Yes. Note that AI-41 changes wording in 10.1.5, and thus is discussed there; there isn't any mention of it in 10.2.1 because it applies to all program unit pragmas. (There's nothing special about Preelaborate this way.) I would expect that anyone that's confused hasn't read AI-41 or the Corrigendum, but perhaps I've missed something. **************************************************************** From: Adam Beneschan Sent: Wednesday, December 1, 2004 6:36 PM Yes, thanks; I wasn't aware of AI-41. I looked for the AI cross reference under section 10.2.1 and didn't find anything there, but I missed this one. I probably should have thought to look at 10.1.5. My fault. **************************************************************** From: Gary Dismukes Sent: Wednesday, December 1, 2004 7:08 PM > My reading is that 10.2.1(10) makes this illegal, because it's > possible to instantiate Pak2 with an actual for "x1" that would cause > the declaration of x2 to perform an action that 10.2.1(6-7) makes > nonpreelaborable. (You could instantiate Pak2 with an actual that > contains a function call or the name of an object, e.g.) > > Is my reading correct? That's the way I read it as well, that is, that it's intended to be an assume-the-worst rule. It does seem though that for completeness the wording of the rule should also say something about presuming that the actual for a formal 'in' object is a nonstatic object or some such, rather than just specifying the form of the actual for formal types and formal subprograms. **************************************************************** From: Tucker Taft Sent: Wednesday, December 1, 2004 9:37 PM I agree with Gary. **************************************************************** From: Edmond Schonberg Sent: Tuesday, May 2, 2006 9:30 AM B.3.2 (4) includes a pragma Preelaborate for this generic package, but its generic formal part includes a formal object. This runs afoul of the decision of AI-403: for the purposes of determining whether a unit can be declared to be preelaborable, a generic formal object is non-static. **************************************************************** From: Tucker Taft Sent: Tuesday, May 2, 2006 10:16 AM I am surprised that this would prevent the generic unit from being preelaborable. There is still a check that the instantiation satisfies the requirements for preelaboration. I wonder if this was the real intent of AI-403. **************************************************************** From: Tucker Taft Sent: Tuesday, May 2, 2006 10:27 AM I think you may have misinterpreted AI-403. What makes the example in AI-403 non-preelaborable is not the presence of the formal object, but rather the *use* of the formal object in the generic package *body* to initialize a package-level object. In other words, I believe that having a generic formal object in Interfaces.C.Pointer is fine. The pragma Preelaborate ensures that it doesn't get used in some inappropriate way in the body for Interfaces.C.Pointer. **************************************************************** From: Edmond Schonberg Sent: Tuesday, May 2, 2006 11:28 AM OK, thanks for clarification. ****************************************************************