PR c/71560 - union compound literal initializes wrong union field

gcc/ChangeLog:
	* doc/extend.texi (Compound Literals): Correct and clarify.
	(Cast to Union): Same.

From-SVN: r238651
This commit is contained in:
Martin Sebor 2016-07-22 15:40:51 +00:00 committed by Martin Sebor
parent 1610d41097
commit e040f9bd4b
2 changed files with 49 additions and 37 deletions

View File

@ -1,3 +1,9 @@
2016-07-22 Martin Sebor <msebor@redhat.com>
PR c/71560
* doc/extend.texi (Compound Literals): Correct and clarify.
(Cast to Union): Same.
2016-07-22 Kelvin Nilsen <kelvin@gcc.gnu.org>
* config/rs6000/rs6000.c (rs6000_option_override_internal): Add

View File

@ -1868,15 +1868,16 @@ foo (float f, float g)
@cindex compound literals
@c The GNU C name for what C99 calls compound literals was "constructor expressions".
ISO C99 supports compound literals. A compound literal looks like
a cast containing an initializer. Its value is an object of the
type specified in the cast, containing the elements specified in
the initializer; it is an lvalue. As an extension, GCC supports
compound literals in C90 mode and in C++, though the semantics are
somewhat different in C++.
A compound literal looks like a cast of a brace-enclosed aggregate
initializer list. Its value is an object of the type specified in
the cast, containing the elements specified in the initializer.
Unlike the result of a cast, a compound literal is an lvalue. ISO
C99 and later support compound literals. As an extension, GCC
supports compound literals also in C90 mode and in C++, although
as explained below, the C++ semantics are somewhat different.
Usually, the specified type is a structure. Assume that
@code{struct foo} and @code{structure} are declared as shown:
Usually, the specified type of a compound literal is a structure. Assume
that @code{struct foo} and @code{structure} are declared as shown:
@smallexample
struct foo @{int a; char b[2];@} structure;
@ -1901,7 +1902,7 @@ This is equivalent to writing the following:
You can also construct an array, though this is dangerous in C++, as
explained below. If all the elements of the compound literal are
(made up of) simple constant expressions, suitable for use in
(made up of) simple constant expressions suitable for use in
initializers of objects of static storage duration, then the compound
literal can be coerced to a pointer to its first element and used in
such an initializer, as shown here:
@ -1910,18 +1911,23 @@ such an initializer, as shown here:
char **foo = (char *[]) @{ "x", "y", "z" @};
@end smallexample
Compound literals for scalar types and union types are
also allowed, but then the compound literal is equivalent
to a cast.
Compound literals for scalar types and union types are also allowed. In
the following example the variable @code{i} is initialized to the value
@code{2}, the result of incrementing the unnamed object created by
the compound literal.
@smallexample
int i = ++(int) @{ 1 @};
@end smallexample
As a GNU extension, GCC allows initialization of objects with static storage
duration by compound literals (which is not possible in ISO C99, because
duration by compound literals (which is not possible in ISO C99 because
the initializer is not a constant).
It is handled as if the object is initialized only with the bracket
enclosed list if the types of the compound literal and the object match.
The initializer list of the compound literal must be constant.
It is handled as if the object were initialized only with the brace-enclosed
list if the types of the compound literal and the object match.
The elements of the compound literal must be constant.
If the object being initialized has array type of unknown size, the size is
determined by compound literal size.
determined by the size of the compound literal.
@smallexample
static struct foo x = (struct foo) @{1, 'a', 'b'@};
@ -1939,22 +1945,21 @@ static int z[] = @{1, 0, 0@};
In C, a compound literal designates an unnamed object with static or
automatic storage duration. In C++, a compound literal designates a
temporary object, which only lives until the end of its
full-expression. As a result, well-defined C code that takes the
address of a subobject of a compound literal can be undefined in C++,
so the C++ compiler rejects the conversion of a temporary array to a pointer.
For instance, if the array compound literal example above appeared
inside a function, any subsequent use of @samp{foo} in C++ has
undefined behavior because the lifetime of the array ends after the
declaration of @samp{foo}.
temporary object that only lives until the end of its full-expression.
As a result, well-defined C code that takes the address of a subobject
of a compound literal can be undefined in C++, so G++ rejects
the conversion of a temporary array to a pointer. For instance, if
the array compound literal example above appeared inside a function,
any subsequent use of @code{foo} in C++ would have undefined behavior
because the lifetime of the array ends after the declaration of @code{foo}.
As an optimization, the C++ compiler sometimes gives array compound
literals longer lifetimes: when the array either appears outside a
function or has const-qualified type. If @samp{foo} and its
initializer had elements of @samp{char *const} type rather than
@samp{char *}, or if @samp{foo} were a global variable, the array
would have static storage duration. But it is probably safest just to
avoid the use of array compound literals in code compiled as C++.
As an optimization, G++ sometimes gives array compound literals longer
lifetimes: when the array either appears outside a function or has
a @code{const}-qualified type. If @code{foo} and its initializer had
elements of type @code{char *const} rather than code{char *}, or if
@code{foo} were a global variable, the array would have static storage
duration. But it is probably safest just to avoid the use of array
compound literals in C++ code.
@node Designated Inits
@section Designated Initializers
@ -2145,11 +2150,12 @@ case 1...5:
@cindex cast to a union
@cindex union, casting to a
A cast to union type is similar to other casts, except that the type
specified is a union type. You can specify the type either with
@code{union @var{tag}} or with a typedef name. A cast to union is actually
a constructor, not a cast, and hence does not yield an lvalue like
normal casts. (@xref{Compound Literals}.)
A cast to union type looks similar to other casts, except that the type
specified is a union type. You can specify the type either with the
@code{union} keyword or with a @code{typedef} name that refers to
a union. A cast to a union actually creates a compound literal and
yields an lvalue, not an rvalue like true casts do.
(@xref{Compound Literals}.)
The types that may be cast to the union type are those of the members
of the union. Thus, given the following union and variables: