!standard 3.3.1(10) 10-10-22 AI05-0228-1/01 !standard 3.3.1(21) !class Amendment 10-10-22 !status work item 10-10-22 !status received 10-10-22 !priority Medium !difficulty Easy !subject Default initial values for types !summary (See proposal.) !problem The new predicate (see AI05-0153-1) and invariant (see AI05-0146-1) aspects provide unreliable results for objects that are not initialized. This can be prevented when a default initial value is provided. It is easy to provide a default initial value for record types, and access types have one defined by the language, but for other kinds of types, it is impossible. This seems bizarre, given that implementations have the capability of doing default initialization (as for record and access types). !proposal Add an aspect Default_Value, that can be used on all types. !wording Modify 3.3.1(10): For an object_declaration without an initialization expression, any initial values for the object or its subcomponents are determined by the implicit initial values defined for its nominal subtype{. If the subtype has the Default_Value aspect specified, the implicit initial value is the value of that aspect. Otherwise, the value is determined}[,] as follows: Modify 3.3.1(21): There is no implicit initial value for a scalar subtype{ unless the Default_Value aspect has been specified for the type}. In the absence of an explicit initialization{ or the explicit specification of the Default_Value aspect}, a newly created scalar object might have a value that does not belong to its subtype (see 13.9.1 and H.1). Add after 3.3.1(21): [Better place for this?] Static Semantics For a full type, the following language-defined aspect may be specified with an aspect_specification: Default_Value This aspect shall be specified by an expression, called an *default value expression*. Type_Invariant may be specified on a full_type_declaration. Name Resolution The expected type for a default value expression is the type defined by the full_type_declaration. Dynamic Semantics The default value expression is evaluated at the first freezing point of the type, and the result becomes the value of the aspect for the type. !discussion It is important that the default initial value be something that makes sense for the type. Simply initializing everything to zero is just as likely to cover bugs as eliminate them. However, if a type has a value specifically that means "Unknown" or "Undefined", it makes perfect sense to initialize all objects to that value. That would greatly reduce the chances of invalid objects of the type existing. !examples Providing a default initial value for an enumeration type with an unknown value: type Item_State is (Unknown, Fooey, Blarch, ...) with Default_Value => Unknown; Providing a default initial value for an access type with a null exclusion (in Ada 2005, any default initialized object of this type would raise Constraint_Error): type My_Access is not null access My_Rec with Default_Value => Unknown_Ptr; Unknown_Ptr : constant My_Access := new My_Rec'(Kind => Unknown); This is taking advantage of the deferred resolution of aspects. !ACATS test ACATS tests would be needed for this aspect. !appendix [Editor's note: This thread forked off of a discussion of predicates.] From: Robert Dewar Sent: Wednesday, October 13, 2010 11:21 AM > Well, yeah. We get a lot of support calls about uninit vars. > Too bad there's no language feature to prevent those bugs. All language features that "fix" uninitialized variables are evil. Requiring default initialization or providing default implicit initialization are particularly evil in my view. **************************************************************** From: Bob Duff Sent: Wednesday, October 13, 2010 12:33 PM > All language features that "fix" uninitialized variables are evil. I won't touch that with a barge pole. ;-) Anyway, it's irrelevant to my point, which is that uninit vars are a loophole in constraints, so the argument "predicates must be loophole-free, because constraints are" is bogus. >... Requiring default initialization or providing default implicit >initialization are particularly evil in my view. I certainly agree with that. Too bad JDI didn't (I'm talking about access types). **************************************************************** From: Tucker Taft Sent: Wednesday, October 13, 2010 1:01 PM >> ... Requiring default initialization or providing default implicit >> initialization are particularly evil in my view. > > I certainly agree with that. > > Too bad JDI didn't (I'm talking about access types). The default initial value of "null" for an access type seems OK, since you get an exception if you try to use it as though it had a usable non-null value. It is a default initial value of zero that is dangerous, since it is not distinguishable from a "true" initial value of zero. If there were a "null" value for all types, which corresponded roughly to a floating point signaling NaN, that would be fine in my view. You would get notified if you tried to do anything that presumed the object had an "intentional" initial value. **************************************************************** From: Randy Brukardt Sent: Wednesday, October 13, 2010 1:50 PM Right. The annoying thing is that Ada doesn't have a way to set a default initial value for scalar and array types, for those cases where there is an "obviously" bad value. For instance, many of my enumeration types have an value of "unknown" or something like that. It's purpose is exactly to provide a value for those cases where something has gone wrong or nothing has been calculated yet. Typically, it would be used (manually of course) as a default initial value for objects; it would be nice to be able to force all objects to start with that value rather than random garbage. Ada compilers clearly have the mechanism to deal with default initializations (because of access types and record components), so it is annoying that the programmer can't use that when it is appropriate. **************************************************************** From: Robert Dewar Sent: Wednesday, October 13, 2010 5:29 PM TW, on the IM 7040, there was a great instruction intended only for system diagnostics to set parity wrong on a specified word. WATFor fortran used this to initialize all uninitialized variables (under some option flag). And you got a parity error if you tried to load the value. BTW, I don't think it is worth spending too much time on different checking modes. Compilers will likely provide different checking modes anyway, whatever the standard says. **************************************************************** From: Robert Dewar Sent: Wednesday, October 13, 2010 5:27 PM >> It is a default initial value of zero that is dangerous, since it is >> not distinguishable from a "true" initial value of zero. If there >> were a "null" value for all types, which corresponded roughly to a >> floating point signaling NaN, that would be fine in my view. You >> would get notified if you tried to do anything that presumed the >> object had an "intentional" initial value. Big overhead in the array case having to check, and the trouble is that you MUST be able to have 32 tc integers, represented in the obvious way. It would be a menace if Ada insisted on stealing one value. > Ada > compilers clearly have the mechanism to deal with default > initializations (because of access types and record components), so it > is annoying that the programmer can't use that when it is appropriate. Good point, I think I will invent a pragma. In fact the obvious pragma to extend is pragma Initialize_Scalars; and allow the usage pragma Initialize_Scalars (local_type_NAME); 20 minutes work to allow this! **************************************************************** From: Randy Brukardt Sent: Wednesday, October 13, 2010 5:44 PM > >> It is a default initial value of zero that is dangerous, since it > >> is not distinguishable from a "true" initial value of zero. If > >> there were a "null" value for all types, which corresponded roughly > >> to a floating point signaling NaN, that would be fine in my view. > >> You would get notified if you tried to do anything that presumed > >> the object had an "intentional" initial value. > > Big overhead in the array case having to check, and the trouble is > that you MUST be able to have 32 tc integers, represented in the > obvious way. It would be a menace if Ada insisted on stealing one > value. I agree that it doesn't make sense to do it in all cases; it's just odd to not have the capability when it is useful. [That's Tucker's quote, BTW.] > > Ada > > compilers clearly have the mechanism to deal with default > > initializations (because of access types and record components), so > > it is annoying that the programmer can't use that when it is appropriate. > > Good point, I think I will invent a pragma. In fact the obvious pragma > to extend is > > pragma Initialize_Scalars; > > and allow the usage > > pragma Initialize_Scalars (local_type_NAME); > > 20 minutes work to allow this! At one point, someone suggested having an aspect for this purpose. That would look something like: type Item_State is (Unknown, Fooey, Blarch, ...) with Default_Initial_Value => Unknown; This seems like a good use for an aspect, given that it isn't something that ought to be dependent on the view of the type (or subtype, if we wanted to allow that). The (minor) advantage of the aspect over the pragma is that it allows the default value to be specified; that might be helpful if the "Unknown" value is not the first one in the enumeration. **************************************************************** From: Robert Dewar Sent: Wednesday, October 13, 2010 6:00 PM Well we could allow a default value for Initialize_Scalars or some other pragma. IS in GNAT is not always the lowest value, and can in fact be changed at link time or even execution time (the idea is to try different initial values and see if has an observable effect A disadvantage of an aspect if that is the only mechanism is that it is restricted to Ada 2012 mode. We have a lot of customers still stuck at Ada 95 (partly because of the high level of incompatibility between Ada 95 and Ada 2005). **************************************************************** From: Tucker Taft Sent: Wednesday, October 13, 2010 6:10 PM I believe we already discussed something along these lines in the recent ARG meeting. Didn't we invent an aspect spec like "with Default => blah"? Or am I dreaming that? **************************************************************** From: Randy Brukardt Sent: Wednesday, October 13, 2010 6:37 PM I think we invented it, but I don't think anyone took ownership of it and got it added to the agenda. As such, it is now too late (it wasn't included in the scope approved by WG 9), unless someone can figure out a reason why we need to add it for one of the existing AIs. **************************************************************** From: Robert Dewar Sent: Wednesday, October 13, 2010 6:47 PM Sounds good to me, I think I will implement the aspect and the corresponding pragma, so it really doesn't matter too much if it gets into the standard. It's a good idea! **************************************************************** From: Jean-Pierre Rosen Sent: Thursday, October 14, 2010 3:48 AM I was about to suggest an aspect too, but Randy shot first... > A disadvantage of an aspect if that is the only mechanism is that it > is restricted to Ada 2012 mode. We have a lot of customers still stuck > at Ada 95 (partly because of the high level of incompatibility between > Ada 95 and Ada 2005). OTOH, people will move to the new versions if the benefits balance the disagreements. Providing nice features in the most recent modes is a way to push them. **************************************************************** From: Robert Dewar Sent: Thursday, October 14, 2010 6:13 PM Well in fact in GNAT we systematically provide pragmas to match all aspects in any case, the way the internal implementation of aspects work is to translate to the corresponding pragma or attribute definition clause. So for example, we now have pragma predicate and pragma invariant in GNAT. We are more in the business of providing useful features to people than pushing them to use the latest version of Ada. As I say, the biggest barrier is the rather fierce upwards incompatibility of Ada 2005, this has resulted in a barrier for several large users (the issue with return of limited stuff). We have talked about a mode which would provide Ada 95 + all compatible features, but this is quite a bit of work. ****************************************************************