... an ICE is (almost) always a bug in the compiler.
You do not need the "(almost)" part, unless the machine on which
the compiler is being run is not working correctly (in which case
it becomes difficult to trust anything at all
).
decay func().arr to a pointer, successfully complete the translation,
and generate a sensible executable.
The problem here is that there is no really sensible answer.
According to others who should know, the expression "func().arr"
is *not* an lvalue in C89/C90, but *is* an lvalue in C99.
Since it is not an operand of the unary "&" or sizeof operators,
the array lvalue will become a pointer rvalue, so in C99 the
assignment appears to be legal but useless, and a warning would be
appropriate.
In C89/C90, however, this is the one unique case in which an array
is an "rvalue", and the whole thing appears to be an error with a
required diagnostic, or perhaps an error with no required diagnostic.
But writing:
int (*p)[N] = &(func().arr);
would definitely require a diagnostic, because unary & can only
be applied to lvalues.
The way I prefer to describe situations involving arrays uses
somewhat different terminology from that in the C standards. In
my notation, we have "objects" and "values", rather than "lvalues"
and "values". In other words, we eliminate the whole concept of
"lvalue" as basically flawed and confusing. (This escapes the
weirdness surrounding "modifiable" vs "non-modifiable" lvalues, in
particular.) But even here we have a problem. The value returned
by a function is definitely a "value", not an "object", yet in this
case the value is a structure.
Normally structures can only exist in "complete object" form. For
instance:
struct S a, b;
...
a = b;
Here "a" and "b" both name entire objects. While "b" is in a "value
context", so that b's value is copied to a, it is obvious "where
this value lives" -- in the object named by b -- and its lifetime
is equally obvious. If b contains an array member named "arr",
writing:
int *ptr = b.arr;
causes b to point to the first element of the array by the usual
application of what I call "The Rule" about arrays and pointers in
C. The lifetime of that array is the lifetime of b; its place in
storage is determined by b's place; and so on.
Function return values, however, have no defined storage location.
Normally this never even comes up: If functions could return
arrays, we would have to resolve the question of what it means to
write:
int g(void)[N];
int *x = g();
and the answer to that would clearly be the same as the answer to
what it means to write:
int *p = func().arr;
but since functions cannot return arrays -- the declaration of g()
above must draw a diagnostic -- the first situation never occurs.
Only in this one case, when a function returns a structure that
contains at least one array as a member, do we have to find an
answer.
Ultimately, I think there are two reasonable answers: forbid this
entirely -- make a claim that an array value, in this one case in
which it occurs, has no address and cannot be used in any way
(including to subscript it) -- or state that the value of an "array
value" is the value of the address of the first element of that
array, just as with an array object, so that the assignment to p
is valid and well-defined, and so that subscripting works in the
usual way. If the second answer is chosen (as I think it is in
C99), we must then define the lifetime of the object to which this
pointer points. I think that lifetime should be "until the next
sequence point", so that the assignment to p, while valid, is
useless and probably deserves a warning.
The folks defining C seem to have chosen both answers (at different
times in different standards).