re PR c/4787 (Different anonymous variables declared but only one allocated when the initialization is the same)
* c-common.def (COMPOUND_LITERAL_EXPR): New. * c-common.c (c_expand_expr): Handle COMPOUND_LITERAL_EXPR. (c_staticp): New function. * c-common.h (COMPOUND_LITERAL_EXPR_DECL): New. (c_staticp): Declare. * c-typeck.c (default_function_array_conversion, build_unary_op): Don't handle CONSTRUCTOR specially. (lvalue_p, mark_addressable): Handle COMPOUND_LITERAL_EXPR. * c-decl.c (build_compound_literal): New function. * c-tree.h (build_compound_literal): Declare. * c-parse.in (primary): Use build_compound_literal. * c-lang.c (LANG_HOOKS_STATICP): Define. * objc/objc-lang.c (LANG_HOOKS_STATICP): Likewise. * doc/c-tree.texi: Document COMPOUND_LITERAL_EXPR. * doc/extend.texi: Update documentation of compound literals. Fixes PR c/4787. testsuite: * gcc.c-torture/execute/20000722-1.x, gcc.c-torture/execute/20010123-1.x: Remove. * gcc.c-torture/compile/init-3.c: Don't use a compound literal. * gcc.dg/c90-complit-1.c, gcc.dg/c99-complit-1.c, gcc.dg/c99-complit-2.c: New tests. From-SVN: r47629
This commit is contained in:
parent
d062a680ab
commit
db3acfa547
|
@ -1,3 +1,22 @@
|
|||
2001-12-04 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* c-common.def (COMPOUND_LITERAL_EXPR): New.
|
||||
* c-common.c (c_expand_expr): Handle COMPOUND_LITERAL_EXPR.
|
||||
(c_staticp): New function.
|
||||
* c-common.h (COMPOUND_LITERAL_EXPR_DECL): New.
|
||||
(c_staticp): Declare.
|
||||
* c-typeck.c (default_function_array_conversion, build_unary_op):
|
||||
Don't handle CONSTRUCTOR specially.
|
||||
(lvalue_p, mark_addressable): Handle COMPOUND_LITERAL_EXPR.
|
||||
* c-decl.c (build_compound_literal): New function.
|
||||
* c-tree.h (build_compound_literal): Declare.
|
||||
* c-parse.in (primary): Use build_compound_literal.
|
||||
* c-lang.c (LANG_HOOKS_STATICP): Define.
|
||||
* objc/objc-lang.c (LANG_HOOKS_STATICP): Likewise.
|
||||
* doc/c-tree.texi: Document COMPOUND_LITERAL_EXPR.
|
||||
* doc/extend.texi: Update documentation of compound literals.
|
||||
Fixes PR c/4787.
|
||||
|
||||
2001-12-04 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* langhooks.h (struct lang_hooks): Add staticp.
|
||||
|
|
|
@ -3432,6 +3432,15 @@ c_expand_expr (exp, target, tmode, modifier)
|
|||
}
|
||||
break;
|
||||
|
||||
case COMPOUND_LITERAL_EXPR:
|
||||
{
|
||||
/* Initialize the anonymous variable declared in the compound
|
||||
literal, then return the variable. */
|
||||
tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
|
||||
emit_local_var (decl);
|
||||
return expand_expr (decl, target, tmode, modifier);
|
||||
}
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
@ -3482,6 +3491,18 @@ c_unsafe_for_reeval (exp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Hook used by staticp to handle language-specific tree codes. */
|
||||
|
||||
int
|
||||
c_staticp (exp)
|
||||
tree exp;
|
||||
{
|
||||
if (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
|
||||
&& TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tree code classes. */
|
||||
|
||||
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
|
||||
|
|
|
@ -101,3 +101,9 @@ DEFTREECODE (CASE_LABEL, "case_label", 'e', 3)
|
|||
/* A STMT_EXPR represents a statement-expression. The
|
||||
STMT_EXPR_STMT is the statement given by the expression. */
|
||||
DEFTREECODE (STMT_EXPR, "stmt_expr", 'e', 1)
|
||||
|
||||
/* A COMPOUND_LITERAL_EXPR represents a C99 compound literal. The
|
||||
COMPOND_LITERAL_EXPR_DECL is the decl for the anonymous object
|
||||
represented by the COMPOUND_LITERAL; the DECL_INITIAL of that
|
||||
decl is the CONSTRUCTOR that initializes the compound literal. */
|
||||
DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", 'e', 1)
|
||||
|
|
|
@ -630,6 +630,10 @@ extern tree strip_array_types PARAMS ((tree));
|
|||
the given label statement. */
|
||||
#define LABEL_STMT_LABEL(NODE) TREE_OPERAND (LABEL_STMT_CHECK (NODE), 0)
|
||||
|
||||
/* COMPOUND_LITERAL_EXPR accessor. */
|
||||
#define COMPOUND_LITERAL_EXPR_DECL(NODE) \
|
||||
TREE_OPERAND (COMPOUND_LITERAL_EXPR_CHECK (NODE), 0)
|
||||
|
||||
/* Nonzero if this SCOPE_STMT is for the beginning of a scope. */
|
||||
#define SCOPE_BEGIN_P(NODE) \
|
||||
(TREE_LANG_FLAG_0 (SCOPE_STMT_CHECK (NODE)))
|
||||
|
@ -813,6 +817,8 @@ extern rtx c_expand_expr PARAMS ((tree, rtx, enum machine_mode,
|
|||
|
||||
extern int c_safe_from_p PARAMS ((rtx, tree));
|
||||
|
||||
extern int c_staticp PARAMS ((tree));
|
||||
|
||||
extern int c_unsafe_for_reeval PARAMS ((tree));
|
||||
|
||||
/* Information recorded about each file examined during compilation. */
|
||||
|
|
53
gcc/c-decl.c
53
gcc/c-decl.c
|
@ -3793,6 +3793,59 @@ clear_parm_order ()
|
|||
current_binding_level->parm_order = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Build a COMPOUND_LITERAL_EXPR. TYPE is the type given in the compound
|
||||
literal, which may be an incomplete array type completed by the
|
||||
initializer; INIT is a CONSTRUCTOR that initializes the compound
|
||||
literal. */
|
||||
|
||||
tree
|
||||
build_compound_literal (type, init)
|
||||
tree type;
|
||||
tree init;
|
||||
{
|
||||
/* We do not use start_decl here because we have a type, not a declarator;
|
||||
and do not use finish_decl because the decl should be stored inside
|
||||
the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */
|
||||
tree decl = build_decl (VAR_DECL, NULL_TREE, type);
|
||||
tree complit;
|
||||
DECL_EXTERNAL (decl) = 0;
|
||||
TREE_PUBLIC (decl) = 0;
|
||||
TREE_STATIC (decl) = (current_binding_level == global_binding_level);
|
||||
DECL_CONTEXT (decl) = current_function_decl;
|
||||
TREE_USED (decl) = 1;
|
||||
TREE_TYPE (decl) = type;
|
||||
store_init_value (decl, init);
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
|
||||
{
|
||||
int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
|
||||
if (failure)
|
||||
abort ();
|
||||
}
|
||||
|
||||
type = TREE_TYPE (decl);
|
||||
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
|
||||
return error_mark_node;
|
||||
|
||||
complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), decl);
|
||||
TREE_SIDE_EFFECTS (complit) = 1;
|
||||
|
||||
layout_decl (decl, 0);
|
||||
|
||||
if (TREE_STATIC (decl))
|
||||
{
|
||||
/* This decl needs a name for the assembler output. We also need
|
||||
a unique suffix to be added to the name, for which DECL_CONTEXT
|
||||
must be set. */
|
||||
DECL_NAME (decl) = get_identifier ("__compound_literal");
|
||||
DECL_CONTEXT (decl) = complit;
|
||||
rest_of_decl_compilation (decl, NULL, 1, 0);
|
||||
DECL_CONTEXT (decl) = NULL_TREE;
|
||||
}
|
||||
|
||||
return complit;
|
||||
}
|
||||
|
||||
/* Make TYPE a complete type based on INITIAL_VALUE.
|
||||
Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
|
||||
2 if there was no information (in which case assume 1 if DO_DEFAULT). */
|
||||
|
|
|
@ -56,6 +56,8 @@ static void c_post_options PARAMS ((void));
|
|||
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
|
||||
#undef LANG_HOOKS_SAFE_FROM_P
|
||||
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
|
||||
#undef LANG_HOOKS_STATICP
|
||||
#define LANG_HOOKS_STATICP c_staticp
|
||||
#undef LANG_HOOKS_PRINT_IDENTIFIER
|
||||
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
|
||||
#undef LANG_HOOKS_SET_YYDEBUG
|
||||
|
|
|
@ -627,29 +627,13 @@ primary:
|
|||
$2 = groktypename ($2);
|
||||
really_start_incremental_init ($2); }
|
||||
initlist_maybe_comma '}' %prec UNARY
|
||||
{ const char *name;
|
||||
tree result = pop_init_level (0);
|
||||
{ tree constructor = pop_init_level (0);
|
||||
tree type = $2;
|
||||
finish_init ();
|
||||
|
||||
if (pedantic && ! flag_isoc99)
|
||||
pedwarn ("ISO C89 forbids compound literals");
|
||||
if (TYPE_NAME (type) != 0)
|
||||
{
|
||||
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
|
||||
name = IDENTIFIER_POINTER (TYPE_NAME (type));
|
||||
else
|
||||
name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
|
||||
}
|
||||
else
|
||||
name = "";
|
||||
$$ = result;
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
|
||||
{
|
||||
int failure = complete_array_type (type, $$, 1);
|
||||
if (failure)
|
||||
abort ();
|
||||
}
|
||||
$$ = build_compound_literal (type, constructor);
|
||||
}
|
||||
| '(' expr ')'
|
||||
{ char class = TREE_CODE_CLASS (TREE_CODE ($2));
|
||||
|
|
|
@ -261,6 +261,7 @@ extern tree pop_init_level PARAMS ((int));
|
|||
extern void set_init_index PARAMS ((tree, tree));
|
||||
extern void set_init_label PARAMS ((tree));
|
||||
extern void process_init_element PARAMS ((tree));
|
||||
extern tree build_compound_literal PARAMS ((tree, tree));
|
||||
extern void pedwarn_c99 PARAMS ((const char *, ...))
|
||||
ATTRIBUTE_PRINTF_1;
|
||||
extern tree c_start_case PARAMS ((tree));
|
||||
|
|
|
@ -910,8 +910,7 @@ default_function_array_conversion (exp)
|
|||
}
|
||||
|
||||
lvalue_array_p = !not_lvalue && lvalue_p (exp);
|
||||
if (!flag_isoc99 && !lvalue_array_p
|
||||
&& !(TREE_CODE (exp) == CONSTRUCTOR && TREE_STATIC (exp)))
|
||||
if (!flag_isoc99 && !lvalue_array_p)
|
||||
{
|
||||
/* Before C99, non-lvalue arrays do not decay to pointers.
|
||||
Normally, using such an array would be invalid; but it can
|
||||
|
@ -3141,10 +3140,6 @@ build_unary_op (code, xarg, flag)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Allow the address of a constructor if all the elements
|
||||
are constant. */
|
||||
if (TREE_CODE (arg) == CONSTRUCTOR && TREE_CONSTANT (arg))
|
||||
;
|
||||
/* Anything not already handled and not a true memory reference
|
||||
or a non-lvalue array is an error. */
|
||||
else if (typecode != FUNCTION_TYPE && !flag
|
||||
|
@ -3256,6 +3251,7 @@ lvalue_p (ref)
|
|||
case COMPONENT_REF:
|
||||
return lvalue_p (TREE_OPERAND (ref, 0));
|
||||
|
||||
case COMPOUND_LITERAL_EXPR:
|
||||
case STRING_CST:
|
||||
return 1;
|
||||
|
||||
|
@ -3411,6 +3407,7 @@ mark_addressable (exp)
|
|||
x = TREE_OPERAND (x, 0);
|
||||
break;
|
||||
|
||||
case COMPOUND_LITERAL_EXPR:
|
||||
case CONSTRUCTOR:
|
||||
TREE_ADDRESSABLE (x) = 1;
|
||||
return 1;
|
||||
|
|
|
@ -1738,6 +1738,7 @@ This macro returns the attributes on the type @var{type}.
|
|||
@tindex COND_EXPR
|
||||
@tindex CALL_EXPR
|
||||
@tindex CONSTRUCTOR
|
||||
@tindex COMPOUND_LITERAL_EXPR
|
||||
@tindex STMT_EXPR
|
||||
@tindex BIND_EXPR
|
||||
@tindex LOOP_EXPR
|
||||
|
@ -2201,6 +2202,15 @@ next available array element.
|
|||
Conceptually, before any initialization is done, the entire area of
|
||||
storage is initialized to zero.
|
||||
|
||||
@item COMPOUND_LITERAL_EXPR
|
||||
@findex COMPOUND_LITERAL_EXPR_DECL
|
||||
These nodes represent ISO C99 compound literals. The
|
||||
@code{COMPOUND_LITERAL_EXPR_DECL} is an anonymous @code{VAR_DECL} for
|
||||
the unnamed object represented by the compound literal; the
|
||||
@code{DECL_INITIAL} of that @code{VAR_DECL} is a @code{CONSTRUCTOR}
|
||||
representing the brace-enclosed list of initializers in the compound
|
||||
literal.
|
||||
|
||||
@item SAVE_EXPR
|
||||
|
||||
A @code{SAVE_EXPR} represents an expression (possibly involving
|
||||
|
|
|
@ -1608,9 +1608,8 @@ foo (float f, float g)
|
|||
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. (GCC does not yet implement the full ISO C99 semantics
|
||||
for compound literals.) As an extension, GCC supports compound literals
|
||||
in C89 mode and in C++.
|
||||
the initializer; it is an lvalue. As an extension, GCC supports
|
||||
compound literals in C89 mode and in C++.
|
||||
|
||||
Usually, the specified type is a structure. Assume that
|
||||
@code{struct foo} and @code{structure} are declared as shown:
|
||||
|
@ -1638,28 +1637,14 @@ This is equivalent to writing the following:
|
|||
|
||||
You can also construct an array. If all the elements of the compound literal
|
||||
are (made up of) simple constant expressions, suitable for use in
|
||||
initializers, then the compound literal is an lvalue and can be coerced to a
|
||||
pointer to its first element, as shown here:
|
||||
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:
|
||||
|
||||
@example
|
||||
char **foo = (char *[]) @{ "x", "y", "z" @};
|
||||
@end example
|
||||
|
||||
Array compound literals whose elements are not simple constants are
|
||||
not very useful, because the compound literal is not an lvalue; ISO C99
|
||||
specifies that it is, being a temporary object with automatic storage
|
||||
duration associated with the enclosing block, but GCC does not yet
|
||||
implement this. There are currently only two valid ways to use it with
|
||||
GCC: to subscript it, or initialize
|
||||
an array variable with it. The former is probably slower than a
|
||||
@code{switch} statement, while the latter does the same thing an
|
||||
ordinary C initializer would do. Here is an example of
|
||||
subscripting an array compound literal:
|
||||
|
||||
@example
|
||||
output = ((int[]) @{ 2, x, 28 @}) [input];
|
||||
@end example
|
||||
|
||||
Compound literals for scalar types and union types are is
|
||||
also allowed, but then the compound literal is equivalent
|
||||
to a cast.
|
||||
|
|
|
@ -44,6 +44,8 @@ static void objc_post_options PARAMS ((void));
|
|||
#define LANG_HOOKS_DECODE_OPTION objc_decode_option
|
||||
#undef LANG_HOOKS_POST_OPTIONS
|
||||
#define LANG_HOOKS_POST_OPTIONS objc_post_options
|
||||
#undef LANG_HOOKS_STATICP
|
||||
#define LANG_HOOKS_STATICP c_staticp
|
||||
#undef LANG_HOOKS_PRINT_IDENTIFIER
|
||||
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
|
||||
#undef LANG_HOOKS_SET_YYDEBUG
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2001-12-04 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* gcc.c-torture/execute/20000722-1.x,
|
||||
gcc.c-torture/execute/20010123-1.x: Remove.
|
||||
* gcc.c-torture/compile/init-3.c: Don't use a compound literal.
|
||||
* gcc.dg/c90-complit-1.c, gcc.dg/c99-complit-1.c,
|
||||
gcc.dg/c99-complit-2.c: New tests.
|
||||
|
||||
2001-12-04 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* g++.dg/inherit/base1.C: New test.
|
||||
|
|
|
@ -6,6 +6,6 @@ struct something {
|
|||
};
|
||||
|
||||
struct something X = {
|
||||
foo: (struct empty) { },
|
||||
foo: { },
|
||||
bar: 1,
|
||||
};
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# Doesn't work. Hasn't worked ever, I think.
|
||||
set torture_execute_xfail "*-*-*"
|
||||
return 0
|
|
@ -1,2 +0,0 @@
|
|||
set torture_execute_xfail "*-*-*"
|
||||
return 0
|
|
@ -0,0 +1,20 @@
|
|||
/* Test for compound literals: in C99 only. */
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
|
||||
|
||||
struct s { int a; int b; };
|
||||
union u { int c; int d; };
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
(int) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "compound literal" "scalar" { target *-*-* } 12 } */
|
||||
(struct s) { 1, 2 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "compound literal" "struct" { target *-*-* } 14 } */
|
||||
(union u) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "compound literal" "union" { target *-*-* } 16 } */
|
||||
(int [1]) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "compound literal" "array" { target *-*-* } 18 } */
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/* Test for compound literals: in C99 only. Test for valid uses. */
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
struct s { int a; int b; };
|
||||
union u { int c; int d; };
|
||||
|
||||
int *i0a = &(int) { 0 };
|
||||
int *i0b = &(int) { 0 };
|
||||
int *i1a = &(int) { 1 };
|
||||
int *i1b = &(int) { 1 };
|
||||
const int *i0c = &(const int) { 0 };
|
||||
|
||||
struct s *s0 = &(struct s) { 1, 2 };
|
||||
struct s *s1 = &(struct s) { 1, 2 };
|
||||
const struct s *s2 = &(const struct s) { 1, 2 };
|
||||
|
||||
union u *u0 = &(union u) { 3 };
|
||||
union u *u1 = &(union u) { 3 };
|
||||
const union u *u2 = &(const union u) { 3 };
|
||||
|
||||
int *a0 = (int []) { 1, 2, 3 };
|
||||
const int *a1 = (const int []) { 1, 2, 3 };
|
||||
|
||||
char *p = (char []){ "foo" };
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (i0a == i0b || i0a == i0c || i0b == i0c)
|
||||
abort ();
|
||||
if (i1a == i1b)
|
||||
abort ();
|
||||
if (*i0a != 0 || *i0b != 0 || *i1a != 1 || *i1b != 1 || *i0c != 0)
|
||||
abort ();
|
||||
*i0a = 1;
|
||||
*i1a = 0;
|
||||
if (*i0a != 1 || *i0b != 0 || *i1a != 0 || *i1b != 1 || *i0c != 0)
|
||||
abort ();
|
||||
if (s0 == s1 || s1 == s2 || s2 == s0)
|
||||
abort ();
|
||||
if (s0->a != 1 || s0->b != 2 || s1->a != 1 || s1->b != 2
|
||||
|| s2->a != 1 || s2->b != 2)
|
||||
abort ();
|
||||
s0->a = 2;
|
||||
s1->b = 1;
|
||||
if (s0->a != 2 || s0->b != 2 || s1->a != 1 || s1->b != 1
|
||||
|| s2->a != 1 || s2->b != 2)
|
||||
abort ();
|
||||
if (u0 == u1 || u1 == u2 || u2 == u0)
|
||||
abort ();
|
||||
if (u0->c != 3 || u1->c != 3 || u2->c != 3)
|
||||
abort ();
|
||||
u0->d = 2;
|
||||
if (u0->d != 2 || u1->c != 3 || u2->c != 3)
|
||||
abort ();
|
||||
if (a0 == a1)
|
||||
abort ();
|
||||
if (a0[0] != 1 || a0[1] != 2 || a0[2] != 3
|
||||
|| a1[0] != 1 || a1[1] != 2 || a1[2] != 3)
|
||||
abort ();
|
||||
a0[0] = 3;
|
||||
if (a0[0] != 3 || a0[1] != 2 || a0[2] != 3
|
||||
|| a1[0] != 1 || a1[1] != 2 || a1[2] != 3)
|
||||
abort ();
|
||||
if (p[0] != 'f' || p[1] != 'o' || p[2] != 'o' || p[3] != 0)
|
||||
abort ();
|
||||
p[0] = 'g';
|
||||
if (p[0] != 'g' || p[1] != 'o' || p[2] != 'o' || p[3] != 0)
|
||||
abort ();
|
||||
if (sizeof((int []) { 1, 2 ,3 }) != 3 * sizeof(int))
|
||||
abort ();
|
||||
if (sizeof((int []) { [3] = 4 }) != 4 * sizeof(int))
|
||||
abort ();
|
||||
struct s *y;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
struct s *x = &(struct s) { 1, i };
|
||||
if (x->a != 1 || x->b != i)
|
||||
abort ();
|
||||
x->a++;
|
||||
x->b--;
|
||||
if (x->a != 2 || x->b != i - 1)
|
||||
abort ();
|
||||
if (i && y != x)
|
||||
abort ();
|
||||
y = x;
|
||||
}
|
||||
int *z;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int *x = (int []){ 0, i, i + 2, i - 3 };
|
||||
if (x[0] != 0 || x[1] != i || x[2] != i + 2 || x[3] != i - 3)
|
||||
abort ();
|
||||
x[0] = x[1];
|
||||
x[1] *= x[2];
|
||||
x[2] -= x[3];
|
||||
x[3] += 7;
|
||||
if (x[0] != i || x[1] != i * (i + 2) || x[2] != 5 || x[3] != i + 4)
|
||||
abort ();
|
||||
if (i && z != x)
|
||||
abort ();
|
||||
z = x;
|
||||
}
|
||||
(int) { 0 } = 1;
|
||||
(struct s) { 0, 1 }.a = 3;
|
||||
(union u) { 3 }.c = 4;
|
||||
(int []){ 1, 2 }[0] = 0;
|
||||
exit (0);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* Test for compound literals: in C99 only. Test for invalid uses. */
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
|
||||
|
||||
struct s { int a; int b; };
|
||||
union u { int c; int d; };
|
||||
|
||||
struct si;
|
||||
union ui;
|
||||
|
||||
void
|
||||
foo (int a)
|
||||
{
|
||||
/* The type name must not be incomplete (apart from arrays of unknown
|
||||
size), or a function type, or a VLA type. */
|
||||
(void) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "void type" { target *-*-* } 17 } */
|
||||
&(struct si) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "incomplete struct type" { target *-*-* } 19 } */
|
||||
&(union ui) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "incomplete union type" { target *-*-* } 21 } */
|
||||
(void (void)) { 0 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "function type" { target *-*-* } 23 } */
|
||||
(int [a]) { 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init|variable" "VLA type" { target *-*-* } 25 } */
|
||||
/* Initializers must not attempt to initialize outside the object
|
||||
declared. */
|
||||
(int [1]) { [1] = 2 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "value outside array" { target *-*-* } 29 } */
|
||||
(int [1]) { [-1] = 2 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "value outside array" { target *-*-* } 31 } */
|
||||
(int [1]) { 0, 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "value outside array" { target *-*-* } 33 } */
|
||||
}
|
||||
|
||||
int z;
|
||||
|
||||
/* Outside a function, initializers must be constant. */
|
||||
struct s *s0 = &(struct s) { 0, z }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "non-const" { target *-*-* } 40 } */
|
||||
int sz = sizeof((struct s) { 0, z }); /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "non-const" { target *-*-* } 42 } */
|
||||
|
||||
/* Compound literals aren't themselves constant expressions. */
|
||||
int x = (int) { 0 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "non-const" { target *-*-* } 46 } */
|
||||
|
||||
/* Nor are they suitable structure or union initializers
|
||||
outside a function. */
|
||||
struct s s1 = (struct s) { 0, 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "struct bad init" { target *-*-* } 51 } */
|
||||
union u u1 = (union u) { 0 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "union bad init" { target *-*-* } 53 } */
|
||||
|
||||
/* They aren't suitable for array initializers, either inside or outside
|
||||
a function. */
|
||||
int y[2] = (int [2]) { 0, 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "array bad init" { target *-*-* } 58 } */
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
struct s s2 = (struct s) { 0, 1 };
|
||||
union u u2 = (union u) { 0 };
|
||||
int z[2] = (int [2]) { 0, 1 }; /* { dg-bogus "warning" "warning in place of error" } */
|
||||
/* { dg-error "init" "array bad init" { target *-*-* } 66 } */
|
||||
}
|
Loading…
Reference in New Issue