diff options
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/c-common.c | 21 | ||||
-rw-r--r-- | gcc/c-common.def | 6 | ||||
-rw-r--r-- | gcc/c-common.h | 6 | ||||
-rw-r--r-- | gcc/c-decl.c | 53 | ||||
-rw-r--r-- | gcc/c-lang.c | 2 | ||||
-rw-r--r-- | gcc/c-parse.in | 20 | ||||
-rw-r--r-- | gcc/c-tree.h | 1 | ||||
-rw-r--r-- | gcc/c-typeck.c | 9 | ||||
-rw-r--r-- | gcc/doc/c-tree.texi | 10 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 25 | ||||
-rw-r--r-- | gcc/objc/objc-lang.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/init-3.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20000722-1.x | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20010123-1.x | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c90-complit-1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c99-complit-1.c | 112 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c99-complit-2.c | 68 |
19 files changed, 339 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 22242e2274d..95ae31275af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,24 @@ 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. * langhooks-def.h (lhd_staticp, LANG_HOOKS_STATICP): New. (LANG_HOOKS_INITIALIZER): Add LANG_HOOKS_STATICP. diff --git a/gcc/c-common.c b/gcc/c-common.c index a7d005b04ed..f5fc0d348f5 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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, diff --git a/gcc/c-common.def b/gcc/c-common.def index 6ae0466f236..7840ce81610 100644 --- a/gcc/c-common.def +++ b/gcc/c-common.def @@ -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) diff --git a/gcc/c-common.h b/gcc/c-common.h index 1ce21a1769f..4ab415c1f1e 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -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. */ diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 34278546d97..b5597f98dad 100644 --- a/gcc/c-decl.c +++ b/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). */ diff --git a/gcc/c-lang.c b/gcc/c-lang.c index dceede52557..c2056c5b464 100644 --- a/gcc/c-lang.c +++ b/gcc/c-lang.c @@ -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 diff --git a/gcc/c-parse.in b/gcc/c-parse.in index fe57047ec9c..e0457b2af67 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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)); diff --git a/gcc/c-tree.h b/gcc/c-tree.h index e686ed4fd1b..a304b7ebff7 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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)); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index ff504dc1d05..297afad8ce8 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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; diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi index dd21ae6285b..3db3d7f10ff 100644 --- a/gcc/doc/c-tree.texi +++ b/gcc/doc/c-tree.texi @@ -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 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 781fa997add..cf275f1ecc9 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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. diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c index 33d2cde6ce3..7e2cae7bf00 100644 --- a/gcc/objc/objc-lang.c +++ b/gcc/objc/objc-lang.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 795c502821b..d22c31dc4bb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.c-torture/compile/init-3.c b/gcc/testsuite/gcc.c-torture/compile/init-3.c index d091168897b..be3d9b49679 100644 --- a/gcc/testsuite/gcc.c-torture/compile/init-3.c +++ b/gcc/testsuite/gcc.c-torture/compile/init-3.c @@ -6,6 +6,6 @@ struct something { }; struct something X = { - foo: (struct empty) { }, + foo: { }, bar: 1, }; diff --git a/gcc/testsuite/gcc.c-torture/execute/20000722-1.x b/gcc/testsuite/gcc.c-torture/execute/20000722-1.x deleted file mode 100644 index bbad3bb394a..00000000000 --- a/gcc/testsuite/gcc.c-torture/execute/20000722-1.x +++ /dev/null @@ -1,3 +0,0 @@ -# Doesn't work. Hasn't worked ever, I think. -set torture_execute_xfail "*-*-*" -return 0 diff --git a/gcc/testsuite/gcc.c-torture/execute/20010123-1.x b/gcc/testsuite/gcc.c-torture/execute/20010123-1.x deleted file mode 100644 index 2f397b96e51..00000000000 --- a/gcc/testsuite/gcc.c-torture/execute/20010123-1.x +++ /dev/null @@ -1,2 +0,0 @@ -set torture_execute_xfail "*-*-*" -return 0 diff --git a/gcc/testsuite/gcc.dg/c90-complit-1.c b/gcc/testsuite/gcc.dg/c90-complit-1.c new file mode 100644 index 00000000000..4cd910fa866 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c90-complit-1.c @@ -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 } */ +} diff --git a/gcc/testsuite/gcc.dg/c99-complit-1.c b/gcc/testsuite/gcc.dg/c99-complit-1.c new file mode 100644 index 00000000000..94e15db6d2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-complit-1.c @@ -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); +} diff --git a/gcc/testsuite/gcc.dg/c99-complit-2.c b/gcc/testsuite/gcc.dg/c99-complit-2.c new file mode 100644 index 00000000000..faf44b2376e --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-complit-2.c @@ -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 } */ +} |