A compound literal within a global lambda or block is still within
the body of a function for the purposes of computing its storage
duration and deciding whether its initializer must be constant.
There are a number of problems in our current treatment of compound
literals. C specifies that a compound literal yields an l-value
referring to an object with either static or automatic storage
duration, depending on where it was written; in the latter case,
the literal object has a lifetime tied to the enclosing scope (much
like an ObjC block), not the enclosing full-expression. To get these
semantics fully correct in our current design, we would need to
collect compound literals on the ExprWithCleanups, just like we do
with ObjC blocks; we would probably also want to identify literals
like we do with materialized temporaries. But it gets stranger;
GCC adds compound literals to C++ as an extension, but makes them
r-values, which are generally assumed to have temporary storage
duration. Ignoring destructor ordering, the difference only matters
if the object's address escapes the full-expression, which for an
r-value can only happen with reference binding (which extends
temporaries) or array-to-pointer decay (which does not). GCC then
attempts to lock down on array-to-pointer decay in ad hoc ways.
Arguably a far superior language solution for C++ (and perhaps even
array r-values in C, which can occur in other ways) would be to
propagate lifetime extension through array-to-pointer decay, so
that initializing a pointer object to a decayed r-value array
extends the lifetime of the complete object containing the array.
But this would be a major change in semantics which arguably ought
to be blessed by the committee(s).
Anyway, I'm not fixing any of that in this patch; I did try, but
it got out of hand.
Fixes rdar://28949016.
llvm-svn: 285643
2016-11-01 05:56:26 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -pedantic %s
2012-09-12 18:45:40 +08:00
// REQUIRES: LP64
2007-12-05 12:00:10 +08:00
struct foo { int a , b ; } ;
2008-07-08 00:46:50 +08:00
static struct foo t = ( struct foo ) { 0 , 0 } ;
2010-09-27 15:13:32 +08:00
static struct foo t1 = __builtin_choose_expr ( 0 , ( struct foo ) { 0 , 0 } , ( struct foo ) { 0 , 0 } ) ;
static struct foo t2 = { 0 , 0 } ;
2012-10-19 20:36:49 +08:00
static struct foo t3 = t2 ; // expected-error {{initializer element is not a compile-time constant}}
2010-09-27 15:13:32 +08:00
static int * p = ( int [ ] ) { 2 , 4 } ;
2009-05-16 19:45:48 +08:00
static int x = ( int ) { 1 } ;
2008-01-09 08:05:37 +08:00
2012-10-19 20:36:49 +08:00
static int * p2 = ( int [ ] ) { 2 , x } ; // expected-error {{initializer element is not a compile-time constant}}
static long * p3 = ( long [ ] ) { 2 , " x " } ; // expected-warning {{incompatible pointer to integer conversion initializing 'long' with an expression of type 'char [2]'}}
2008-01-10 04:58:06 +08:00
2012-10-19 20:36:49 +08:00
typedef struct { } cache_t ; // expected-warning{{empty struct is a GNU extension}}
static cache_t clo_I1_cache = ( ( cache_t ) { } ) ; // expected-warning{{use of GNU empty initializer extension}}
2008-07-08 00:46:50 +08:00
2008-01-15 02:19:28 +08:00
typedef struct Test { int a ; int b ; } Test ;
static Test * ll = & ( Test ) { 0 , 0 } ;
2007-12-05 12:00:10 +08:00
extern void fooFunc ( struct foo * pfoo ) ;
int main ( int argc , char * * argv ) {
2008-01-10 04:58:06 +08:00
int * l = ( int [ ] ) { x , * p , * p2 } ;
2007-12-05 12:00:10 +08:00
fooFunc ( & ( struct foo ) { 1 , 2 } ) ;
}
2009-01-20 03:26:10 +08:00
struct Incomplete ; // expected-note{{forward declaration of 'struct Incomplete'}}
2012-10-19 20:36:49 +08:00
struct Incomplete * I1 = & ( struct Incomplete ) { 1 , 2 , 3 } ; // expected-error {{variable has incomplete type}}
2008-05-20 13:22:08 +08:00
void IncompleteFunc ( unsigned x ) {
2012-10-19 20:36:49 +08:00
struct Incomplete * I2 = ( struct foo [ x ] ) { 1 , 2 , 3 } ; // expected-error {{variable-sized object may not be initialized}}
( void ) { 1 , 2 , 3 } ; // expected-error {{variable has incomplete type}}
( void ( void ) ) { 0 } ; // expected-error{{illegal initializer type 'void (void)'}}
2008-05-20 13:22:08 +08:00
}
2010-01-20 06:33:45 +08:00
// PR6080
int array [ ( sizeof ( int [ 3 ] ) = = sizeof ( ( int [ ] ) { 0 , 1 , 2 } ) ) ? 1 : - 1 ] ;
A compound literal within a global lambda or block is still within
the body of a function for the purposes of computing its storage
duration and deciding whether its initializer must be constant.
There are a number of problems in our current treatment of compound
literals. C specifies that a compound literal yields an l-value
referring to an object with either static or automatic storage
duration, depending on where it was written; in the latter case,
the literal object has a lifetime tied to the enclosing scope (much
like an ObjC block), not the enclosing full-expression. To get these
semantics fully correct in our current design, we would need to
collect compound literals on the ExprWithCleanups, just like we do
with ObjC blocks; we would probably also want to identify literals
like we do with materialized temporaries. But it gets stranger;
GCC adds compound literals to C++ as an extension, but makes them
r-values, which are generally assumed to have temporary storage
duration. Ignoring destructor ordering, the difference only matters
if the object's address escapes the full-expression, which for an
r-value can only happen with reference binding (which extends
temporaries) or array-to-pointer decay (which does not). GCC then
attempts to lock down on array-to-pointer decay in ad hoc ways.
Arguably a far superior language solution for C++ (and perhaps even
array r-values in C, which can occur in other ways) would be to
propagate lifetime extension through array-to-pointer decay, so
that initializing a pointer object to a decayed r-value array
extends the lifetime of the complete object containing the array.
But this would be a major change in semantics which arguably ought
to be blessed by the committee(s).
Anyway, I'm not fixing any of that in this patch; I did try, but
it got out of hand.
Fixes rdar://28949016.
llvm-svn: 285643
2016-11-01 05:56:26 +08:00
// rdar://28949016 - Constant restriction should not apply to compound literals in blocks
int ( ^ block ) ( int ) = ^ ( int i ) {
int * array = ( int [ ] ) { i , i + 2 , i + 4 } ;
return array [ i ] ;
} ;