!standard 7.6(9.4/2) 08-05-21 AI05-0013-1/13 !standard 13.12(8) !standard D.7(3) !standard D.7(4/2) !standard D.7(10/2) !standard D.7(10.1/2) !standard D.7(10.2/2) !standard D.7(10.8/2) !class binding interpretation 06-04-10 !status Amendment 201Z 08-11-26 !status WG9 Approved 08-06-20 !status ARG Approved 7-1-1 08-02-08 !status work item 06-05-29 !status ARG Approved 11-0-1 06-11-18 !status work item 06-04-10 !status received 06-04-03 !priority Medium !difficulty Medium !qualifier Error !subject No_Nested_Finalization is difficult to enforce !summary Change the No_Nested_Finalization check to disallow allocators of nested access types which designate types that need finalization, and delete the coextension rule from the definition of "needs finalization". Class-wide types are defined to "need finalization". Correct the restrictions wording to avoid "shall" as these are definitions. Clarify when (if ever) restrictions are checked. !question 7.6(9.4) says that "A type is said to need finalization if ... it is a limited type that has an access discriminant whose designated type needs finalization." This rule was intended to support coextensions, which get finalized when the parent object gets finalized, and must therefore have been taken into account for computing the "needs finalization" properties. However: (1) Coextensions can exist for nonlimited types. Thus, the "limited" should be deleted from the wording. (2) This property cannot be computed at the freezing point of the type (which is the natural place to do so), as the designated type may not be frozen yet. Indeed, there is no place during the current compilation where it can be computed if the designated type is an incomplete one from a limited view - it will not be known until link-time if the complete type is controlled. This definition is used in No_Nested_Finalization; (2) implies link-time checking. Such checking would be very expensive to build, because every nested use of a type with an access discriminant would have to be recorded, along with its definition, and checks would have to be made if the actual complete type does in fact "need finalization". Is this intended? (No.) !recommendation (See summary.) !wording Replace 7.6(9.4/2) with: it is a class-wide type; or In 13.12(8), replace A pragma Restrictions is a configuration pragma; unless otherwise specified for a particular restriction, a partition shall obey the restriction if a pragma Restrictions applies to any compilation unit included in the partition. with A pragma Restrictions is a configuration pragma. If a pragma Restrictions applies to any compilation unit included in the partition, this may impose either (or both) of two kinds of requirements, as specified for the particular restriction: - A restriction may impose requirements on some or all of the units comprising the partition. Unless otherwise specified for a particular restriction, such a requirement applies to all of the units comprising the partition and is enforced via a post-compilation check. - A restriction may impose requirements on the runtime behavior of the program, as indicated by the specification of runtime behavior associated with a violation of the requirement. AARM Ramification: In this latter case, there is no post-compilation check needed for the requirement. Replace D.7(3) with: No task depends on a task other than the environment task of the partition. AARM Ramification: This disallows any function returning an object with a task part or coextension, even if called at the library level, as such a task would temporarily depend on a nested master (the master of the return statement), which is disallowed by this restriction. Replace D.7(4/2) with: No_Nested_Finalization Objects of a type that needs finalization (see 7.6) are declared only at library level. If an access type does not have library-level accessibility, then there are no allocators of the type where the type determined by the subtype_mark of the subtype_indication or qualified_expression needs finalization. Modify D.7(10/2) as follows: No_Dynamic_Attachment There is no {use of}[call to] any of the operations defined in package Interrupts (Is_Reserved, Is_Attached, Current_Handler, Attach_Handler, Exchange_Handler, Detach_Handler, and Reference). AARM Ramification: This includes 'Access and 'Address of these operations, as well as inherited versions of these operations. Replace D.7(10.1/2-10.2/2) with: No_Local_Protected_Objects Protected objects are declared only at library level. No_Local_Timing_Events Timing_Events are declared only at library level. Replace D.7(10.8/2) with: Simple_Barriers The Boolean expression in each entry barrier is either a static expression or a name that statically denotes a component of the enclosing protected object. !discussion Directly attempting to fix problem (2) leads into a rat-hole of bad or incompatible solutions. (If you are interested, version /01 of this AI contained an exhaustive list.) The key is to fix the uses of "needs finalization" to consider coextensions. There is only one use: restriction No_Nested_Finalization. The best way to do this for No_Nested_Finalization is to make the allocators, rather than the access types, illegal. At this point, the designated type must be frozen, so there is no problem knowing whether it "needs finalization". Note that the new rule uses the accessibility level of the access type of the allocator. This is needed to take coextensions into account; the accessibility level is determined by an extensive set of rules and we certainly don't want to duplicate those. While reviewing the "needs finalization" wording, it was pointed out that it is impossible to tell statically if a class-wide type includes a controlled part (because some future extension may include such a part, including one not yet written). As such, all class-wide types have to be treated as if they need finalization, and a sentence was added to that effect. During editorial review it was noted that the wording of D.7 is weird because it uses sometimes "shall" and sometimes "is". This is inconsistent. As this is static semantics (the actual check is defined in 13.12), all of these should use "is". That sometimes is confusing (it isn't clear on whom the restriction applies); it is best to word these in terms of what is *not* allowed. We are fixing all of the restrictions that use "shall", and some that need clearer wording. The most pervasive problem in the specification of restrictions is the failure to follow up on 13.12(8), which states that a restriction is subject to enforcement via a post-compilation check "unless otherwise specified for a particular restriction". There does not exist even one restriction to which this "unless otherwise specified" clause applies, even though many restrictions cannot be checked statically. The proposed new version of 13.12(8) is an attempt to address this issue. This change takes care of, for example, all of the restrictions defined in the "Dynamic Semantics" section of D.7 as well as No_Exceptions, No_Recursion, and No_Reentrancy. All of these have the property that "the runtime behavior associated with a violation of the requirement" is specified (even if it is only specified to be implementation dependent) and therefore no post-compilation check is called for. It is important to note that a given restriction may impose both kinds of requirements. For instance, the No_Exceptions restriction has this property. Statically, exception declarations and raise statements are disallowed. Dynamically, an execution which would normally raise an exception due to a failed runtime check becomes erroneous. Any proposed changes to 13.12(8) should be reviewed with this example in mind. Restriction No_Dynamic_Attachment talks about "calls". What about uses of the 'Access attribute, or uses of derived subprograms? Those need to be disallowed, too. Restriction No_Task_Hierarchy effectively requires that no function return a task or an object with a task part or coextension. That's because the task is initially created on the master of the return statement (before being moved to master of the call site), and that master violates the restriction. We have concluded that this behavior for the restriction is acceptable, as returning tasks in this way is complex, and this restriction is part of the Ravenscar profile. Moreover, having subtly different semantics for Ravenscar programs does not seem desirable. !corrigendum 7.6(9.4/2) @drepl @xbullet @dby @xbullet !corrigendum 13.12(8) @drepl A @fa Restrictions is a configuration pragma; unless otherwise specified for a particular restriction, a partition shall obey the restriction if a @fa Restrictions applies to any compilation unit included in the partition. @dby A @fa Restrictions is a configuration pragma. If a @fa Restrictions applies to any compilation unit included in the partition, this may impose either (or both) of two kinds of requirements, as specified for the particular restriction: @xbullet @xbullet !corrigendum D.7(3) @drepl @xindent @dby @xindent !corrigendum D.7(4/2) @drepl @xindent @dby @xindents of the type where the type determined by the @fa of the @fa or @fa needs finalization.> !corrigendum D.7(10/2) @drepl @xindent @dby @xindent !corrigendum D.7(10.1/2) @drepl @xindent @dby @xindent !corrigendum D.7(10.2/2) @drepl @xindent @dby @xindent !corrigendum D.7(10.8/2) @drepl @xindent @dby @xindent !ACATS test An ACATS B-Test should be created to test these cases. !appendix From: Pascal Leroy Date: Monday, April 3, 2006 8:04 AM 7.6(9.4) says that "A type is said to need finalization if ... it is a limited type that has an access discriminant whose designated type needs finalization." This rule was intended to support coextensions, which get finalized when the parent object gets finalized, and must therefore been taken into account for computing the "needs finalization" properties. However, there are two problems with this wording: 1 - The word "limited" should be erased because coextensions can exist for nonlimited types in Ada 2005. 2 - There is a nasty interaction with the freezing rules. I'd like to be able to compute the "needs finalization" property at the freezing point of the type that has the access discriminant, but at this point the type designated by the access discriminant may not be frozen yet (heck, it may not even be complete if it comes from a limited view). Comments? **************************************************************** From: Randy Brukardt Date: Monday, November 19, 2007 11:48 PM I've always been confused when reading D.7(3), even though I "know" the intent: All (nonenvironment) tasks depend directly on the environment task of the partition. This is supposed to imply some sort of check that makes programs that violates it illegal. But it always seems to me to be talking about some change in semantics instead (tasks, no matter where they are declared, depend directly on the environment task). [Indeed, we have a pragma with actions much like this in Annex H, so the idea isn't unique.] This was one of the reasons behind introducing "shall" here, which Tuck and Bob were so certain was incorrect. However, leaving the wording alone doesn't address the original problem that some of these restrictions are easy to misconstrue. (That's especially true as 13.12 never says anything about checking for violations of restrictions - it simply says that "a partition shall obey a restriction", and that can be accomplished in a number of ways, not all of which necessarily involve any checking.) It strikes me that the restrictions that make sense (mostly original ones) are written in the negative: "There are no ." *That* seems like a restriction. So I'm wondering if it would be better if restrictions like the above one were defined in terms of what is not allowed: No (nonenvironment) tasks depend directly on a task other than the environment task of the partition. Similar rewordings would be a good idea for D.7(10.1/2): No protected objects are declared other than at library level. and D.7(10.2/2): No Timing_Events are declared other that at library level. and D.7(10.8/2): No entry barrier has a Boolean expression that is neither a static Boolean expression nor a Boolean component of the enclosing protected object. This last wording is a bit of stretch. Note that these last three are the three new restrictions that use "shall", probably because they don't make much sense as restrictions without making it clear that a check is required (which is especially important for Ravenscar use). The first sentence of D.7(4/2) would need some change, too (this was the other place that had "shall" originally). No objects of a type that needs finalization (see 7.6) are declared other than at library level. There are no allocators where the type determined by the subtype_mark of the subtype_indication or qualified_expression needs finalization where the type of the allocator does not have library-level accessibility. Brickbats encouraged... **************************************************************** From: Tucker Taft Date: Tuesday, November 20, 2007 6:39 AM I see your point Randy. I still think adding "shall" to these definitions is a mistake, and believe we should remove it where it snuck in. On the other hand, adding some additional, admittedly redundant information every- where we define restrictions might help resolve the confusion. That is, get some "shall"s or at least references to the fundamental "checking" aspect of restrictions into the wording in the close neighborhood of the restriction definitions as a reminder to the user of the purpose of these definitions. **************************************************************** From: Tucker Taft Date: Tuesday, November 20, 2007 7:18 AM As far as using "no" in the wording, that does seem to help in some cases. Alternatively, we can rely on words like "each," "only," or "exclusively" to convey the "restrictive" intent, without having to reverse the sense of the sentence, and without having to use the word "shall." Hence: The only (nonenvironment) tasks are ones that depend directly on the environment task of the partition. Protected objects are declared exclusively at library level. Timing events are declared exclusively at library level. The Boolean expression in each entry barrier is either a static Boolean expression or a Boolean component of the enclosing protected object. One way to help stick to *definitional* wording (as opposed to slipping into "legality rule" wording) is to imagine each Restriction identifier as being placed in a phrase such as: A partition satisfies the "Simple_Barriers" restriction when: The Boolean expression in each entry barrier is either a static Boolean expression or a Boolean component of the enclosing protected object. **************************************************************** From: Robert A. Duff Date: Tuesday, November 20, 2007 7:48 AM > This was one of the reasons behind introducing "shall" here, which Tuck and > Bob were so certain was incorrect. Not quite incorrect -- just unnecessary. The current style is (mostly) to define the restrictions, and then have a single "shall" rule saying you have to obey. We could have chosen a style where each restriction says "If this restriction applies, then Thou Shalt [Not]..." But I don't see any reason to move to this other style -- if it ain't broke, don't fix it. Yeah, I know -- you think it IS broken. But to me, it's like many other things, e.g. static expressions. We define what they are, and then separately require their use. We don't say something like, "A static expression shall not contain a variable reference." > No (nonenvironment) tasks depend directly on a task other than the > environment task of the partition. I don't see how the negative helps. It's still a definition, rather than a "shall" rule. And it forces you into a double negative "No ... other than..." which is slightly less readable. **************************************************************** From: Robert A. Duff Date: Tuesday, November 20, 2007 7:54 AM > A partition satisfies the "Simple_Barriers" restriction when: ...which makes me think perhaps we should put something like that in the introductory paragraphs: The following restriction_identifiers are language defined; the following definitions define how each restriction may be satisfied. or: The following restriction_identifiers are language defined; a partitition satisfies the restriction as defined below. or: The following restriction_identifiers are language defined; a partitition is defined to satisfy the restriction under the conditions given below. Or something. **************************************************************** From: Randy Brukardt Date: Tuesday, November 20, 2007 2:08 PM > > This was one of the reasons behind introducing "shall" here, which Tuck and > > Bob were so certain was incorrect. > > Not quite incorrect -- just unnecessary. The current style is (mostly) to > define the restrictions, and then have a single "shall" rule > saying you have to obey. But that's the problem. What does it mean to "obey" a restriction? When the restriction is written as a negative (There are no delay_statements.) that's pretty clear. But when it is written positively, it isn't so clear. The only reason I know what is meant is because I've talked to you guys; I can't get there from the normative wording. Everytime I read D.7(3), I have to remember that it doesn't mean what it says, it means "No nested tasks". Why should that be? As I previously pointed out, I can think of at least two ways to obey "All (nonenvironment) tasks depend directly on the environment task of the partition." That kind of ambiguity is not good; we ought to use wording that makes it clear that task objects that violate this are illegal and not that some semantic change is intended. Sometimes its easy to get too close to some wording, and read what you know is meant rather than what it actually says. I think you're doing that here. > > No (nonenvironment) tasks depend directly on a task other than the > > environment task of the partition. > > I don't see how the negative helps. It's still a definition, rather than a > "shall" rule. And it forces you into a double negative "No ... other than..." > which is slightly less readable. Because it is more clear that it is intended that such tasks don't exist, rather than that there is some semantic change. (And other restrictions do make semantic changes, so we must be very clear.) It probably would be even clearer if it said something like: No object is created which creates a task that depends directly on a task other than the environment task of the partition. which makes it crystal clear that the real point of the Restriction is to ban the creation of certain kinds of objects. **************************************************************** From: Randy Brukardt Date: Tuesday, November 20, 2007 2:08 PM > > A partition satisfies the "Simple_Barriers" restriction when: > > ...which makes me think perhaps we should put something like that in the > introductory paragraphs: > > The following restriction_identifiers are language defined; > the following definitions define how each restriction may > be satisfied. > > or: > > The following restriction_identifiers are language defined; > a partitition satisfies the restriction as defined below. > > or: > > The following restriction_identifiers are language defined; > a partitition is defined to satisfy the restriction under the > conditions given below. > > Or something. Any such wording should use "obey", since "obey" is what the "shall" rule requires. No sense in continuing to confuse the issue by using "satisfy" here and "obey" there. **************************************************************** From: Tucker Taft Date: Tuesday, November 20, 2007 5:04 PM Good point. Hence, something like: The following restriction_identifiers are language defined; each definition given below specifies under what conditions the associated restriction is *obeyed*: **************************************************************** From: Robert A. Duff Date: Tuesday, November 20, 2007 5:12 PM I like it. **************************************************************** From: Ed Schonberg Date: Tuesday, November 20, 2007 2:41 PM > It probably would be even clearer if it said something like: > > No object is created which creates a task that depends > directly on a > task other than the > environment task of the partition. > > which makes it crystal clear that the real point of the Restriction > is to > ban the creation of certain kinds of objects. Why not describe it top-down: No task other than the environment task creates other tasks. **************************************************************** From: Robert A. Duff Date: Tuesday, November 20, 2007 4:38 PM > Why not describe it top-down: > > No task other than the environment task creates other tasks. That's not quite right. The issue is dependence, not creation. If we have: type A is access Some_Task_Type; at library level, then any task can do "new Some_Task_Type" of type A -- it doesn't matter who creates it, it still depends on the env task. **************************************************************** From: Ed Schonberg Date: Tuesday, November 20, 2007 4:49 PM Indeed. What about: tasks can only depend on the environment task of the partition I suppose we don't have to say anything special about the environment task itself. **************************************************************** From: Robert A. Duff Date: Tuesday, November 20, 2007 5:09 PM That works. Nitpick (which Tucker will appreciate ;-)): tasks can depend only on the environment task of the partition ^^^^^^^^^^^ I reversed these words. I'm the "only"-placement police, and I infected Tucker with this disease during Ada 9X. ;-) > I suppose we don't have to say anything special about the environment task > itself. Well, I think we have to, so: tasks, other than the env task itself, can depend only on the env task of the partition And while I'm at it, "of the partition" seems uselessly obvious, so: tasks, other than the env task itself, can depend only on the env task I'd drop the "can", but then Randy will kill me. ;-) **************************************************************** From: Randy Brukardt Date: Tuesday, November 20, 2007 11:48 PM ... > Indeed. What about: > tasks can only depend on the environment task of the partition > > I suppose we don't have to say anything special about the environment > task itself. But that's essentially the current wording, and it does not make it clear how that is accomplished (that is, that something is not allowed as opposed to just being a semantic change). We could of course use the original wording if we added an additional sentence to make it clear how it is enforced: "A partition obeys this restriction if no objects create tasks that violate the above." But I think it makes just as much sense to fold those into a single sentence, especially as we never say things like "violate the above". **************************************************************** From: Robert A. Duff Date: Tuesday, November 20, 2007 4:54 PM > Because it is more clear that it is intended that such tasks don't exist, > rather than that there is some semantic change. (And other restrictions do > make semantic changes, so we must be very clear.) I don't see how using negative wording fixes this possible misunderstanding. To me, "There are no tasks that don't depend on the env task" is exactly equivalent to "All tasks depend on the env task". (Of course, both need the "other than the env task itself" complication to muddy them up.) > It probably would be even clearer if it said something like: > > No object is created which creates a task that depends directly on a > task other than the > environment task of the partition. > > which makes it crystal clear that the real point of the Restriction is to > ban the creation of certain kinds of objects. I don't see how this prevents the possible confusion you're worried about. What if someone interprets the above to mean that the implementation should magically cause tasks to not depend on "a task other than..."? Having said all that, I must say: I think this issue is a storm in a coffee carafe (tempest in a teapot?), and I therefore have no strong objection to the negative wordings you suggested. I just don't think it's necessary. **************************************************************** From: Randy Brukardt Date: Friday, January 18, 2008 12:05 AM > Here are my AIs for Tampa. [This is AI05-0013-1/08 - ED]. Your proposed rewording of 13.12(8) has lost the "unless otherwise specified". There are restrictions (those in 13.12.1 in particular) that do not apply partition-wide. That needs to be reflected in this wording somehow. One of us forgot to change away from the rejected "shall" wording. I've done that, and made a few edits to the discussion. **************************************************************** From: Stephen W. Baird Date: Friday, January 18, 2008 12:03 PM > Your proposed rewording of 13.12(8) has lost the "unless otherwise > specified". There are restrictions (those in 13.12.1 in particular) that do > not apply partition-wide. That needs to be reflected in this wording > somehow. Good point. How about replacing - A restriction may impose requirements on the units comprising the partition which are enforced via a post-compilation check. with - A restriction may impose requirements on the units comprising the partition which are enforced via a post-compilation check unless otherwise specified for a particular restriction. ? **************************************************************** From: Randy Brukardt Date: Friday, January 18, 2008 1:38 PM I guess that would work, although my initial thought was that it was excepting from just being "enforced by a the post-compilation check" rather than both parts including the "the units comprising the partition" part. Not sure of a better way to put it, though. Maybe Tuck has an idea. **************************************************************** From: Stephen W. Baird Date: Monday, January 21, 2008 2:12 PM Good point. How about - A restriction may impose requirements on some or all of the units comprising the partition. Unless otherwise specified for a particular restriction, such a requirement applies to all of the units comprising the partition and is enforced via a post-compilation check. ? Note that, strictly speaking, both the current wording and the proposed wording allow a unit such as package Bad is pragma Restriction (No_Obsolescent_Features); subtype Reduced_Accuracy is Duration delta 1.0; end Bad; to successfully compile because the definition of the No_Obsolescent_Features restriction does not override the general rule that restrictions are enforced via Post-Compilation checks. I doubt this would occur in practice. If this implementation freedom is determined to be unacceptable (perhaps because it causes problems for test writers), then the problem should be addressed in 13.12.1. ****************************************************************