!standard 3.3(15) 21-05-20 AI12-0392-1/03 !standard 3.3(16) !standard 3.3(17) !standard 3.3(18) !standard 3.3(18.1/3) !standard 3.3(19/3) !standard 3.3(20) !standard 3.3(20.1/3) !standard 3.3(21/3) !standard 3.3(21.1/3) !standard 3.3(22) !standard 3.10.2(19.1/3) !standard 4.6(5/2) !class binding interpretation 20-09-03 !status Amendment 1-2012 20-09-09 !status WG9 Approved 22-06-22 !status ARG Approved 14-0-0 20-09-09 !status work item 20-09-03 !status received 20-07-23 !priority Low !difficulty Medium !qualifier Omission !subject Conditional expressions containing raise expressions !summary Interactions between raise expressions and both static accessibility checking and constancy rules are well defined. !question We need to know various properties of a raise_expression (is its accessibility level statically deeper than some other given level? does it denote a constant view of an object?) in order to implement various semantic checks. These issues can come up in plausible scenarios (as opposed to pathological corner cases) when raise_expressions occur within conditional expressions. Consider, for example, determining the legality of the following example Ptr : Some_Named_General_Access_To_Constant_Object_Type := Some_Tagged_Record_Type (case Foo is when Aaa => This_Obj, when Bbb => That_Obj, when others => (raise Program_Error)).Aliased_Component'Access; with respect to the accessibility rules. During the course of exploring these issues, a related problem with the definition of "view conversion" also came to light. Should these questions be answered? (Yes.) !recommendation (See Summary.) !wording Replace 3.3(15-22) with the following: Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent variables: - an object declared by an object_declaration without the reserved word constant; [AARM: keep the current 16.a-c TBH note as is] - a formal parameter of mode in out or out; - a generic formal object of mode in out; - a non-discriminant component of a variable; - a slice of a variable; - a loop parameter that is specified to be a variable for a generalized loop (see 5.5.2); - a dereference of an access-to-variable value; - a view conversion of a variable; - the return object declared by an extended_return_statement without the reserved word constant; - the current instance of a protected unit except within the body of a protected function of that protected unit, or within a function declared immediately within the body of the protected unit; - an attribute_reference where the attribute is defined to denote a variable (for example, the Storage_Pool attribute - see 13.11). AARM note: In particular, this implies that the following are not variables: - the result of evaluating a function call, an aggregate, a value conversion, a qualified expression, a conditional expression, a raise expression, or a parenthesized expression; - a target_name of an assignment_statement; - the index parameter of an iterated_component_association; - a choice parameter or entry index; This list of constructs that yield constant views is not exhaustive. Add after 3.10.2(19.1/3): The statically deeper relationship does not apply to the accessibility level of a raise_expression; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. Delete the words "whose operand is the name of an object" from the definition of "view conversion" in 4.6(5/2): A type_conversion [whose operand is the name of an object] is called a view conversion if both its target type and operand type are tagged, or if it appears in a call as an actual parameter of mode out or in out; other type_conversions are called value conversions. !discussion There have been problems in the past with the approach taken in 3.3 where we enumerate the list of constants rather than the variables (for example, it was never stated that a parenthesized expression yields a constant view). We address that problem here by instead enumerating the list of variables. When these issues were discussed, some thought that the "whose operand is the name of an object" wording in the definition of "view conversion" was only useless and confusing. Others pointed out how that wording is actively harmful because it introduces the possibility of a tagged value conversion for something like Proc (Some_Tagged(if Foo then Bar else raise Program_Error)); where we don't want the dynamic semantics of a value conversion in the case where Foo turns out (at run time) to be True. !corrigendum 3.3(15) @drepl Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent constants: @dby Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent variables: !corrigendum 3.3(16) @drepl @xbullet with the reserved word @b;> @dby @xbullet without the reserved word @b;> !standard 3.3(17) @drepl @xbullet;> @dby @xbullet or @b;> @xbullet;> !corrigendum 3.3(18) @drepl @xbullet @dby @xbullet @xbullet of a variable;> !standard 3.3(18.1/3) @drepl @xbullet @dby @xbullet !corrigendum 3.3(19/3) @drepl @xbullet @dby @xbullet !corrigendum 3.3(20) @drepl @xbullet @dby @xbullet !corrigendum 3.3(20.1/3) @drepl @xbullet with the reserved word @b;> @dby @xbullet without the reserved word @b;> !corrigendum 3.3(21/3) @ddel @xbullet or an @fa;> !corrigendum 3.3(21.1/3) @ddel @xbullet;> !corrigendum 3.3(21.2/3) @drepl @xbullet), the current instance of the enclosing protected unit;> @dby @xbullet !corrigendum 3.3(22) @drepl @xbullet, @fa, @fa, or view conversion of a constant.> @dby @xbullet where the attribute is defined to denote a variable (for example, the Storage_Pool attribute @endash see 13.11).> !corrigendum 3.10.2(19.1/3) @dinsa @xbullet @dinst @xbullet; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other.> !corrigendum 4.6(5/2) @drepl A @fa whose operand is the @fa of an object is called a @i if both its target type and operand type are tagged, or if it appears in a call as an actual parameter of mode @b or @b; other @fas are called @i. @dby A @fa is called a @i if both its target type and operand type are tagged, or if it appears in a call as an actual parameter of mode @b or @b; other @fas are called @i. !ASIS No ASIS effect. !ACATS test An ACATS C-Test is possible that a conditional expression is still considered a view conversion for tagged types. This would be a low-priority test as it is unlikely that an implementation would do anything else. An ACATS C-Test is possible that the presence of a raise expression does not cause an accessibility check to fail. This is of even lower priority as such a test necessarily would have to guess at what a compiler might do wrong (and it's likely that even an incorrect compiler would not reject many such cases). !appendix From: Steve Baird Sent: Thursday, July 23, 2020 1:39 PM Consider a declaration of the form Ptr : Some_Named_General_Access_Type := Some_Tagged_Record_Type (case Foo is when Aaa => This_Obj, when Bbb => That_Obj, when others => (raise Program_Error)).Aliased_Component'Access; 3.10.2 says Any static accessibility requirement that is imposed on an expression that has distributed accessibility (or on its type) is instead imposed on the dependent_expressions of the underlying conditional_expression. So we have to check that the accessibility level of This_Obj is not statically deeper than that of Some_Named_General_Access_Type. No problem there. Ditto for the accessibility level of That_Obj. Again, no problem. Now we come to the accessibility level of the raise expression. The RM says nothing about this. It seems that something needs to be done here. I recommend adding a rule immediately after 3.10.2(19.1/3): The statically deeper relationship does not apply to the accessibility level of a raise_expression; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. But let's suppose that Some_Named_General_Access_Type is an access-to-variable type. Suppose further that This_Obj and That_Obj are variables. Does our example violate the rule that if a 'Access attribute reference is of an access-to-variable type then the prefix of the attribute reference shall denote a variable? Perhaps a conditional expression, like a qualified expression, always yields a constant view. But the RM never says that (strictly speaking, it currently says the opposite - this issue is discussed below). Depending on the outcome of that question, perhaps the legality of this example hinges on whether a raise expression denotes a variable. In any case, it wouldn't hurt to have a well-defined answer to that question (although the urgency is low for determining the legality of a raise_expression as the Empty argument in an Aggregate aspect specification - the wording in 4.3.5 includes "shall denote a constant"). There are other related problems in this area. Section 3.3 contains a list that begins with The following (and no others) represent constants: So if a construct that names an object doesn't appear on that list, then it names a variable. There is no mention on that list of raise expressions (which is perhaps ok), conditional expressions, or parenthesized expressions. So these all name variables? That's not good. This is also tied up with the topic of AI12-0270-1 and the notion (which we are trying to move away from) of special rules for values that are not objects. For example, an attribute reference such as Some_Obj'Constrained is not on the list of constants, but nobody is going to argue that it should be legal as the target of an assignment statement. Ditto for things like results of membership tests and short circuit operators. This is because these things are values but not objects. Technically this is fine, but having this second category of non-variables may be confusing. It has been suggested that a better approach to constancy would be to reverse the polarity of the 3.3 list - list all of the kinds of variables, rather than listing the kinds of constants. This list would be shorter and more maintainable (because it changes less often). I recommend replacing 3.3(15-22) with the following: Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent variables: - an object declared by an object_declaration without the reserved word constant; [AARM: keep the current 16.a-c TBH note as is] - a formal parameter or generic formal object not of mode in; - a non-discriminant part of a variable (including a slice); - a dereference of an access-to-variable value; - a view conversion of a variable; - the return object declared by an extended_return_statement without the reserved word constant; - a loop parameter that is specified to be a variable for a generalized loop (see 5.5.2); - the current instance of a protected unit except within the body of a protected function of that protected unit, or within a function declared immediately within the body of that protected unit; - an attribute_reference where the attribute is defined to denote a variable (e.g., the Storage_Pool attribute - see 13.11); [In particular, this implies that the following are not variables: - the result of evaluating a function call, an aggregate, a value conversion, a qualified expression, a conditional expression, a raise expression, or a parenthesized expression; - a target_name of an assignment_statement; - the index parameter of an iterated_component_association; - a choice parameter or entry index; This list of constructs that yield constant views is not exhaustive.] Another minor point in this variable/constant wording cleanup shows up in the definition of "view conversion". The RM says: A type_conversion whose operand is the name of an object is called a view conversion if both its target type and operand type are tagged, or if it appears in a call as an actual parameter of mode out or in out; other type_conversions are called value conversions. It appears that the words "whose operand is the name of an object" have no useful effect on the language definition and only lead to confusion (e.g., trying to decide whether a raise expression is the name of an object in the same way that, for example, Some_String_Variable (-999) is the name of an object). Deleting that phrase might not warrant its own AI, but if we can include that as part of this AI then that seems to me like a (small) improvement. There may be other cases of definitional holes relating to raise expressions. For example, I haven't looked closely at whether a raise expression is never, always, or sometimes "known to be constrained". The answer to such a question would only matter in the case of a pathological corner case, perhaps something silly like X : T1 renames T2 (raise Program_Error).Discrim_Dependent_Component; Perhaps there are no definitional issues in this case, but my point is that if there are then they are less important than the issues discussed above. A conditional expression which has a raise expression as a dependent expression is a useful construct and definitional issues related to such a construct should be given higher priority than those that are only associated with pathologies. Opinions? **************************************************************** From: Tucker Taft Sent: Thursday, July 23, 2020 3:31 PM am in favor in general. See below for more specific comments. > ... > > I recommend replacing 3.3(15-22) with the following: > > Whether a view of an object is constant or variable is determined by > the definition of the view. The following (and no others) represent > variables: > > - an object declared by an object_declaration without the reserved > word constant; > > [AARM: keep the current 16.a-c TBH note as is] > > - a formal parameter or generic formal object not of mode in; I would suggest: - a formal parameter of mode in out or out; - generic formal object of mode in out; Somehow "not of mode in" seems unnecessarily convoluted, even though it is admittedly shorter, and since we are already in a list, no need to combine items. > - a non-discriminant part of a variable (including a slice); Again, this seems unnecessarily obscure. How about: - a non-discriminant component of a variable; - a slice of a variable; > - a dereference of an access-to-variable value; > > - a view conversion of a variable; > > - the return object declared by an extended_return_statement without > the reserved word constant; > > - a loop parameter that is specified to be a variable for a > generalized loop (see 5.5.2); > > - the current instance of a protected unit except within the body > of a protected function of that protected unit, or within a > function declared immediately within the body of that protected > unit; I think you could simply say "the protected unit" rather than "that protected unit." > - an attribute_reference where the attribute is defined to > denote a variable (e.g., the Storage_Pool attribute - see 13.11); Naughty, naughty. "e.g." is verboten. "(for example, ...)" > [In particular, this implies that the following are not variables: > - the result of evaluating a function call, an aggregate, > a value conversion, a qualified expression, a conditional > expression, a raise expression, or a parenthesized expression; > - a target_name of an assignment_statement; > - the index parameter of an iterated_component_association; > - a choice parameter or entry index; This list of constructs that > yield constant views is not exhaustive.] This should be an AARM note, in my view. ... > Opinions? See above. **************************************************************** From: Steve Baird Sent: Thursday, July 23, 2020 4:40 PM Every one of your suggested changes looks good to me. **************************************************************** From: Randy Brukardt Sent: Thursday, July 23, 2020 5:54 PM > It appears that the words "whose operand is the name of an object" > have no useful effect on the language definition and only lead to > confusion (e.g., trying to decide whether a raise expression is the name > of an object in the same way that, for example, > Some_String_Variable (-999) > is the name of an object). > > Deleting that phrase might not warrant its own AI, but if we can > include that as part of this AI then that seems to me like a (small) > improvement. I view this as more than a "small improvement". It seems necessary so that conditional expressions and raise expressions are treated consistently for tagged types -- we really don't want value conversions for (visible) tagged types as that could change the tag of the result. For instance, in something like: Proc (Some_Tagged(if Foo then Bar else raise Program_Error)); We would want the tag of the (in) parameter to be that of Bar inside of Proc, not Some_Tagged. Impementation-wise, making this a value conversion would also require making a copy of the object to (possibly) change the tag -- one couldn't just pass the address of the Bar object. I don't think we want to get into that sort of nonsense. **************************************************************** From: Steve Baird Sent: Monday, August 31, 2020 5:57 PM Here is an AI for this one, pretty much just writing up as a binding interpretation what has already been discussed. [This is version /01 of the AI - Editor. **************************************************************** From: Brad Moore Sent: Saturday, September 5, 2020 11:58 AM Minor editorial comment: Discussion, second paragraph "When discussion of these issues" => "{During}[When] the duscussion of these issues{,}" or "When [disucssion of]{discussing} these issues{,}" **************************************************************** From: Randy Brukardt Sent: Wednesday, September 9, 2020 4:17 PM I wonder what "duscussion" and "disucssion" mean. ;-) It should be noted that the posted AI says: "When these issues were discussed, some thought..." since your editor corrects obvious grammar mistakes in AIs when he notices them, usually before posting. He adds enough typos on his own (many of the ones seen during meetings) to leave any stand that can easily be eliminated at the source. **************************************************************** [From WG 9 review issue #103] 3.3 (17.1/5) {a} generic formal object.... This was processed as an Editorial Review change. ****************************************************************