JTC1/SC22/WG14
N782
SC22/WG14 N782
Cleanup of aggregate initialization
Clive D.W. Feather
clive@demon.net
1997-10-20
Abstract
========
The compound literals proposal - N716 - innocently introduces an
inconsistency in aggregate initialization. No-one has given a rationale
for it, and this paper proposes that it be removed.
Following discussion at Menlo Park, other areas needing change to bring
them into line have been noted. These are the compound literals section
itself and the IEC 559 floating-point arithmetic annex.
Discussion
==========
Consider the following code:
struct s { int a; int b; };
int x = 1, y = 2;
struct s sx;
int main (void)
{
sx.a = 3; sx.b = 4;
{
int z = x; // Valid
struct s s1 = sx; // Valid
struct s s2 = (struct s) { x, y }; // Valid
struct s s3 = { x, y }; // Forbidden
/* ... */
}
}
There is no semantic difference between the declarations of s2 and s3,
yet the latter is forbidden by 6.5.7 paragraph 4:
All the expressions in an initializer for an object that has
static storage duration or in an initializer list for an object
that has aggregate or union type shall be constant expressions.
It has been suggested that the original constraint was to allow for
implementations where the dynamic initializer would have been a burden.
Since such implementations now have to cope with compound literals and
the declaration of s2, the restriction has outlived its usefulness.
Proposal
========
[References are to draft 11 pre 3.]
Change 6.3.2.6 paragraph 7 from:
Except that the initializers need not be constant expressions (when
the unnamed object has automatic storage duration), all the semantic
rules and constraints for initializer lists in 6.5.7 are applicable
to compound literals.[71] The order in which any side effects occur
among the initialization list expressions is unspecified.[72]
to:
| All the semantic rules and constraints for initializer lists in 6.5.8
| are applicable to compound literals.[71]
Delete footnote 72.
Change 6.5.8 paragraph 4 from:
All the expressions in an initializer for an object that has
static storage duration or in an initializer list for an object
that has aggregate or union type shall be constant expressions.
to:
All the expressions in an initializer for an object that has
| static storage duration shall be constant expressions.
Add a new paragraph to the end of subclause 6.5.8:
| The order in which any side effects occur among the initialization
| list expressions is unspecified.[*]
| [*] In particular, the evaluation order need not be the same as the
| order of subobject initialization.
Change F.7.4 paragraph 1 from:
An arithmetic constant expression of floating type, other than one in
an initializer for an object that has static storage duration or in an
initializer list for an object that has aggregate or union type, is
evaluated (as if) during execution. As execution-time evaluation, it
is affected by any operative modes and raises exceptions as required
by IEC 559 (provided the state for the FENV_ACCESS pragma is on).[283]
to:
An arithmetic constant expression of floating type, other than one in
| an initializer for an object that has static storage duration, is
evaluated (as if) during execution. As execution-time evaluation, it
is affected by any operative modes and raises exceptions as required
by IEC 559 (provided the state for the FENV_ACCESS pragma is on).[283]
In the example, change:
float w[] = { 0.0/0.0 }; /* does not raise an exception */
to:
float w[] = { 0.0/0.0 }; /* raises an exception */
and change the text paragraph from:
For the aggregate and static initializations, the division is done at
translation time, raising no (execution-time) exceptions. On the
other hand, for the two automatic scalar initializations the invalid
division occurs at execution time.
to:
| For the static initialization, the division is done at
translation time, raising no (execution-time) exceptions. On the
| other hand, for the three automatic initializations the invalid
division occurs at execution time.
Change F.7.5 paragraph 1 from:
All computation for automatic scalar initialization is done (as if)
at execution time. As execution-time evaluation, it is affected by
any operative modes and raises exceptions as required by IEC 559
(provided the state for the FENV_ACCESS pragma is on). All
computation for initialization of objects that have static storage
duration or that have aggregate or union type is done (as if) at
translation time.
to:
| All computation for automatic initialization is done (as if)
at execution time. As execution-time evaluation, it is affected by
any operative modes and raises exceptions as required by IEC 559
(provided the state for the FENV_ACCESS pragma is on). All
computation for initialization of objects that have static storage
| duration is done (as if) at translation time.
In the example, change:
float u[] = { 1.1e75 }; /* does not raise exceptions */
to:
float u[] = { 1.1e75 }; /* raises exceptions */
and change the text paragraph from:
The aggregate and static initializations of u and v raise no
(execution-time) exceptions because their computation is done at
translation time. The automatic initialization of w requires an
execution-time conversion to float of the wider value 1.1e75, which
raises exceptions. The automatic initializations of x and y entail
execution-time conversion; however, in some expression evaluation
methods, the conversions is not to a narrower format, in which case
no exception is raised.[284] The automatic initialization of z entails
execution-time conversion, but not to a narrower format, so no
exception is raised. Note that the conversions of the floating
constants 1.1e75 and 1.1e75f to their internal representations occur
at translation time in all cases.
to:
| The static initialization of v raises no
| (execution-time) exception because its computation is done at
| translation time. The automatic initializations of u and w require an
execution-time conversion to float of the wider value 1.1e75, which
raises exceptions. The automatic initializations of x and y entail
execution-time conversion; however, in some expression evaluation
methods, the conversions is not to a narrower format, in which case
no exception is raised.[284] The automatic initialization of z entails
execution-time conversion, but not to a narrower format, so no
exception is raised. Note that the conversions of the floating
constants 1.1e75 and 1.1e75f to their internal representations occur
at translation time in all cases.