From e040f9bd4b37dfffcb5197c0b6307313846d9e6b Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 22 Jul 2016 15:40:51 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 ++++ gcc/doc/extend.texi | 82 ++++++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7b5ed876ee..deeaac15b52 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2016-07-22 Martin Sebor + + PR c/71560 + * doc/extend.texi (Compound Literals): Correct and clarify. + (Cast to Union): Same. + 2016-07-22 Kelvin Nilsen * config/rs6000/rs6000.c (rs6000_option_override_internal): Add diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c5e7a0d5328..5c822657cfb 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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}. - -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++. +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, 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: -- 2.30.2