!standard 3.5.9(8/2) 20-03-12 AI12-0367-1/02 !standard 3.5.10(2/1) !standard 13.1(9.1/5) !standard 13.14(10) !class binding interpretation 20-03-04 !status Amendment 1-2012 20-03-11 !status ARG Approved 14-0-0 20-03-11 !status work item 20-03-04 !status received 20-02-24 !priority Low !difficulty Easy !qualifier Omission !subject Glitches in aspect specifications !summary A Small has to be specified to be a positive value. An enumeration literal can appear in the specification of a Default_Value aspect. !question (1) The rules for specifying Small of a fixed point type require that the expression be static (3.5.10(2/1)) and less than the delta (3.5.9(8/2)). However, 0.0, -0.25, and -4596.0 are all less than any delta (since deltas are required to be positive by 3.5.9(7)), and are allowed by these rules. But these smalls are clearly nonsense. Should they be made illegal? (Yes.) (2) 13.1(9.1/5) (added by AI12-0181-1) says that a representation aspect specification cannot contain something that freezes the type itself. However, in type Kind is (Unknown, Raw, Bound, Solved) with Default_Value => Unknown; the use of the enumeration literal Unknown freezes Kind, so this specification is illegal. This means that any specification of Default_Value for an enumeration type is illegal (an attribute reference to 'Val would also be illegal for the same reason). That cannot be intended; is specifying Default_Value for an enumeration type legal? (Yes.) !recommendation (See Summary.) !wording (1) Modify 3.5.10(2/1): S'Small denotes the small of the type of S. The value of this attribute is of the type universal_real. Small may be specified for nonderived ordinary fixed point types via an attribute_definition_clause (see 13.3); the expression of such a clause shall be static {and positive}. (2) Modify 13.14(10): * At the place where an expression causes freezing, the type of the expression is frozen, unless the expression is an enumeration literal used {either} as a discrete_choice of the array_aggregate of an eumeration_representation_clause{ or as the aspect_definition of a specification for aspect Default_Value}. !discussion (1) Most of the rules for specifiable attributes require that the value is non-negative. It's inconsistent that this is missing here (we say "positive" here since a Small that equals 0.0 would give the same representation to all values). Note that compilers could (and presumably do) use the Implementation Permission of 3.5.9(10) to reject nonsense smalls as "not supported", but it's silly to have to use an Implementation Permission to reject nonsense. (2) We already had a special case to allow enumeration literals in enumeration representation clauses (the normal rules would have made any such clause illegal, which of course would have been silly). So we extend that special case to this case as well, these cases are essentially the same. There are other similar cases that we don't chose to fix: (1) Attributes of the type: type Kind is (Unknown, Raw, Bound, Solved) with Default_Value => Kind'Val(0); -- Illegal. and type Small is range 1 .. 5 with Default_Value => Small'Last; -- Illegal. (2) Typed constants of the type: type Small is range 1 .. 5 with Default_Value => Max; -- Illegal. Max : constant Small := 5; and type Kind is (Unknown, Raw, Bound, Solved) with Default_Value => Not_Set; -- Illegal. Not_Set : constant Kind := Unknown; Named numbers can be used in the numeric cases. Note that Default_Component_Value does not suffer from any of the versions of this problem, since the value is of a different type than the type being declared. !corrigendum 3.5.10(2/1) @drepl @xindent of the type of S. The value of this attribute is of the type @i. Small may be specified for nonderived ordinary fixed point types via an @fa (see 13.3); the expression of such a clause shall be static.> @dby @xindent of the type of S. The value of this attribute is of the type @i. Small may be specified for nonderived ordinary fixed point types via an @fa (see 13.3); the expression of such a clause shall be static and positive.> !corrigendum 13.14(10) @drepl @xbullet of the @fa of an @fa.> @dby @xbullet of the @fa of an @fa or as the @fa of a specification for aspect Default_Value.> !ASIS No ASIS effect. !ACATS test For (1), an ACATS B-Test could be constructed, but it seems to be of rather low value compared to other rules. Perhaps such a test case should be added to existing tests (both for attribute definition clauses and for aspect specifications). For (2), an ACATS B-Test should be constructed to check that the use of typed constants is not allowed in Default_Value expressions. An ACATS C-Test should check that enumeration literals are allowed (this is a very standard use, so it should occur as the part of some other test). !appendix From: Randy Brukardt Sent: Monday, February 24, 2020 9:10 PM I've been working on redoing the freezing code in Janus/Ada to support aspects. One of the aspect ACATS tests crashed the compiler by giving a negative value, so I've been adding some checks for the "nonnegative" part of the various specifiable attribute rules. (It was supposed to fall through to the "unsupported size" part of the code, but got an overflow before getting there. Not the best message anyway, so a redo.) Anyway, this led to the question of what rule (other than common sense) has this effect for ordinary fixed point types and specifying the Small attribute (or equivalent aspect). 3.5.10(2/1) requires the expression to be static and be of some real type. The typical wording about it needing to be nonnegative is missing here (really would want it positive anyway, but that's not said either). 3.5.9(8/2) requires that the small be no greater than the delta of the type. Nothing, however, seems to prevent Small from being specified as 0.0, -0.25, or -4596.0, all of which are less than any delta. (Note that 3.5.9(7) requires that delta expressions are positive.) 3.5.9(10) and 3.5.9(21) give implementation permissions to reject smalls that are "not supported" and not "powers of two". It seems uncomfortable to be required to use the "not supported" permission to reject clear nonsense, and inconsistent with the rules for other representation aspects as well as the rules for deltas. Thus, I suggest that we require specified Smalls to be positive (like deltas), probably by adding that to 3.5.10(2/1): S'Small denotes the small of the type of S. The value of this attribute is of the type universal_real. Small may be specified for nonderived ordinary fixed point types via an attribute_definition_clause (see 13.3); the expression of such a clause shall be static {and positive}. Since this is Ada 95 wording, we'll have to put it in an AI somewhere, probably the "presentation" AIs (since the impl perms don't allow these portably anyway). **************************************************************** From: Tucker Taft Sent: Monday, February 24, 2020 9:58 PM > ... > > Thus, I suggest that we require specified Smalls to be positive (like > deltas), probably by adding that to 3.5.10(2/1): > > S'Small denotes the small of the type of S. The value of this > attribute is of the type universal_real. Small may be specified for > nonderived ordinary fixed point types via an > attribute_definition_clause (see 13.3); the expression of such a clause > shall be static {and positive}. Looks good to me! > Since this is Ada 95 wording, we'll have to put it in an AI somewhere, > probably the "presentation" AIs (since the impl perms don't allow > these portably anyway). Makes sense. **************************************************************** From: Steve Baird Sent: Tuesday, February 25, 2020 2:23 PM >> S'Small denotes the small of the type of S. The value of this >> attribute is of the type universal_real. Small may be specified for >> nonderived ordinary fixed point types via an >> attribute_definition_clause (see 13.3); the expression of such a clause >> shall be static {and positive}. > Looks good to me! And to me. >> Since this is Ada 95 wording, we'll have to put it in an AI >> somewhere, probably the "presentation" AIs (since the impl perms >> don't allow these portably anyway). > > Makes sense. Agreed. **************************************************************** From: Randy Brukardt Sent: Wednesday, February 26, 2020 6:52 PM I was implementing 13.1(9.1/5) yesterday, and thinking about the (nonexistent) ACATS B-Test for Default_Value, and I think there is a problem with the existing set of rules with this aspect (and only this aspect, so far as I can tell). This explanation is long, but given we're talking about freezing there's not much choice. 13.1(9.1/5) says: An expression or name that freezes an entity shall not occur within an aspect_specification that specifies a representation or operational aspect of that entity. This was adopted to prevent nonsense like: type My_Int is range 1 .. 100 with Size => My_Int'Size; or similar versions involving subtypes of My_Int. Default_Value is a representation aspect by 3.5(56.2/3) (AARM 3.5(56.d/3) explains why. It makes sense in any case, since we need to know the default before generating any default-initialized objects). That means this rule applies to it. The expression is static by 3.5(56.3/3). We could have something like: type My_Int is range 1 .. 100 with Default_Value => 100; and that is obviously not a problem. But Ada is about naming things, so perhaps we wanted to say instead: type My_Int is range 1 .. 100 with Default_Value => Unknown; Unknown : constant My_Int := 100; This appears illegal to me. The type My_Int is frozen by the occurrence of the object declaration (13.14(6)), which causes the aspect(s) to be resolved, evaluated, and frozen (13.14(7.2/3)). The occurrence of "Unknown" is the name of an object, which causes freezing (13.14(8/4)), and specifically freezing of the subtype My_Int (13.14(11)), which triggers our friend 13.1(9.1/5). Note that the similar: type My_Int is range 1 .. 100 with Default_Value => End_Val; Start_Val : constant My_Int := 1; -- Freezes My_Int. End_Val : constant My_Int := 100; -- Too late. is illegal regardless, since Start_Val freezes the type, resolving the aspect - before End_Val is even declared, so the resolution must fail. So the case we're talking about is rather narrow in any case. We could have tried instead: type My_Int is range 1 .. 100 with Default_Value => My_Int'Last; This is exactly like the case that we were trying to prevent (reading attributes of the type we're freezing), so it's obviously illegal. That's annoying. However, there is a work-around for these examples (which happens to match the way I tend to write these declarations anyway): Max_Int : constant := 100; -- Named number type My_Int is range 1 .. Max_Int with Default_Value => Max_Int; So none of this is earth-shaking. But now for the coupe-de-grace: type Kind is (Unknown, Raw, Bound, Solved) with Default_Value => Unknown; The default value of Unknown is an implicit call to the function Unknown (various rules in 3.5.1), which freezes the profile of that function (13.14(8.1/3 & 10.1/4)), which freezes Kind (13.14(14/3)), which triggers 13.1(9.1/5). So this is illegal -- but that clearly triggers the Dewar rule (this is after all, one of the motivating cases for the feature). I don't have a good idea for reconciling this. The easiest fix would be to have a Notwithstanding rule that allowed enumeration literals (and presumably static constants) in Default_Value expressions, even though they are technically freezing. I don't see any implementation issue so long as the items are static (the representation details aren't used to determine the static value). I wouldn't want to allow attributes of the type (surely don't want to allow My_Int'Size here), although I suppose we could explicitly allow 'First and 'Last (which are necessarily static for an elementary *type*). Note that this problem seems to occur only with Default_Value, which is pretty much the only aspect that is attempting to use a value of the same type on which it is applied. (Even Default_Component_Size, which is otherwise similar, doesn't run into this problem.) Thus it is probably best to make whatever fix is decided only on Default_Value rather than generally. I'm thinking a Binding Interpretation will be needed for whatever we decide, since we clearly can't have the enumeration case illegal. Thoughts?? **************************************************************** From: Richard Wai Sent: Wednesday, February 26, 2020 7:16 PM Seems to me that just allowing that to be illegal (as per the existing rules) is the more consistent choice. In situations like this, I'd tend to think that being restricted to a named number is a fair restriction, I.e: type My_Int is range 1 .. 100 with Default_Value => Unknown; Unknown : constant := 100; I don't see how allowing an exception for this rule just so that you can set Default_Value to be a named object of that same type is something useful enough to justify that.. I think consistency is far more valuable. **************************************************************** From: Tucker Taft Sent: Wednesday, February 26, 2020 8:40 PM I would say we should not try to solve the problem with numeric types, since the named number solutions seems fine, but the enumeration literal issue seems to be more of a problem. We already have a special case for enumeration literals, so you can use them in an enumeration rep clause: 13.14(10): * At the place where an expression causes freezing, the type of the expression is frozen, unless the expression is an enumeration literal used as a discrete_choice of the array_aggregate of an enumeration_representation_clause. Seems like we could include the Default_Value usage as another special case here for enumeration literals. **************************************************************** From: Randy Brukardt Sent: Wednesday, February 26, 2020 9:35 PM > Seems to me that just allowing that to be illegal (as per the existing > rules) is the more consistent choice. That means that Default_Value can't be used for an enumeration type. *That* doesn't make sense. I don't care about the object case that much (even though it was the first thing I thought of), but not allowing this on enumerations at all is nonsense. **************************************************************** From: Randy Brukardt Sent: Wednesday, February 26, 2020 9:46 PM > Seems like we could include the Default_Value usage as another special > case here for enumeration literals. Yes, that would work. Didn't remember this exception to the usual rules! So we should just say: * At the place where an expression causes freezing, the type of the expression is frozen, unless the expression is an enumeration literal used as a discrete_choice of the array_aggregate of an eumeration_representation_clause{ or the aspect_definition of a specification for aspect Default_Value}. This is a very narrow exclusion to the usual rules, just enough to avoid nonsense. Guess I get to write this up. (This also lets me write ACATS tests for Default_Value, because we're not changing the rules.) **************************************************************** From: Richard Wai Sent: Wednesday, February 26, 2020 10:25 PM > > Seems to me that just allowing that to be illegal (as per the existing > > rules) is the more consistent choice. > > That means that Default_Value can't be used for an enumeration type. > *That* doesn't make sense. You got me there! **************************************************************** From: Tucker Taft Sent: Thursday, February 27, 2020 9:20 AM I presume it will be clear that "is an enumeration used as ..." applies to both phrases. This could be even clearer by saying: * At the place where an expression causes freezing, the type of the expression is frozen, unless the expression is an enumeration literal used {either} as a discrete_choice of the array_aggregate of an eumeration_representation_clause{ or as the <-- added "as" here aspect_definition of a specification for aspect Default_Value}. **************************************************************** From: Steve Baird Sent: Thursday, February 27, 2020 12:23 PM > * At the place where an expression causes freezing, the type of the > expression is frozen, unless the expression is an enumeration literal > used {either} as a discrete_choice of the array_aggregate of an > eumeration_representation_clause{ or as the aspect_definition of a   > <-- added "as" here specification for aspect Default_Value}. I like the extra clarity and agree that this is a good solution. This will allow something like type Enum is (Aaa, Bbb, Ccc) with Default_Value => Aaa; ... ...; for Enum use (Aaa => 123, Bbb => 456, Ccc => 789); but I don't see any problem with that. **************************************************************** From: Randy Brukardt Sent: Thursday, February 27, 2020 3:00 PM Fine by me. I originally had the "as" and took it out as redundant. Maybe I was right in the first place. :-) - Randy. **************************************************************** From: Tucker Taft Sent: Thursday, February 27, 2020 3:05 PM It all depends on where you insert the "either". I chose to insert it before the first "as" so you need another "as" after the "or". ****************************************************************