From 52ffd86eb62d0320ccf64138e5d7d37ab7a6f7c5 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 18 May 2006 18:22:12 +0000 Subject: [PATCH] Fix up vla, vm and [*] sematics. PR c/18740 PR c/7948 PR c/25802 * c-tree.h (struct c_arg_info): Add had_vla_unspec. (c_vla_unspec_p): Add. (c_vla_type_p): Add. * c-decl.c (struct c_scope): Add had_vla_unspec. (build_array_declarator): Add support for [*]. (grokdeclarator): Likewise. (grokparms): Likewise. (get_parm_info): Likewise. * c-objc-common.c (c_vla_unspec_p): Likewise. * c-objc-common.h (LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P): Likewise. * c-parser.c (c_parser_typeof_specifier): Evaluate arguments to typeof when argument is a variably modified type not inside sizeof or alignof. (c_parser_direct_declarator_inner): Propagate errors. (c_parser_sizeof_expression): Add support for [*]. * c-typeck.c (c_vla_type_p): Add. (composite_type): Add support for vla compositing. (comptypes_internal): Add support for vla compatibility. (c_expr_sizeof_expr): Evaluate vla arguments. * tree.c (variably_modified_type_p): Update comment for [*]. testsuite: * gcc.dg/c90-arraydecl-1.c: Update for vla, vm [*] fixups. * gcc.dg/vla-4.c: Add. * gcc.dg/vla-5.c: Add. * gcc.dg/vla-6.c: Add. From-SVN: r113888 --- gcc/ChangeLog | 27 ++++++++ gcc/c-decl.c | 87 +++++++++++++++++++++----- gcc/c-objc-common.c | 8 +++ gcc/c-objc-common.h | 3 + gcc/c-parser.c | 17 ++++- gcc/c-tree.h | 4 ++ gcc/c-typeck.c | 20 ++++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/c90-arraydecl-1.c | 13 ++-- gcc/testsuite/gcc.dg/vla-4.c | 48 ++++++++++++++ gcc/testsuite/gcc.dg/vla-5.c | 24 +++++++ gcc/testsuite/gcc.dg/vla-6.c | 26 ++++++++ gcc/tree.c | 8 +-- 13 files changed, 263 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/vla-4.c create mode 100644 gcc/testsuite/gcc.dg/vla-5.c create mode 100644 gcc/testsuite/gcc.dg/vla-6.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8465db33d04..3f95910f694 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2006-05-18 Mike Stump + + Fix up vla, vm and [*] sematics. + + PR c/18740 + PR c/7948 + PR c/25802 + * c-tree.h (struct c_arg_info): Add had_vla_unspec. + (c_vla_unspec_p): Add. + (c_vla_type_p): Add. + * c-decl.c (struct c_scope): Add had_vla_unspec. + (build_array_declarator): Add support for [*]. + (grokdeclarator): Likewise. + (grokparms): Likewise. + (get_parm_info): Likewise. + * c-objc-common.c (c_vla_unspec_p): Likewise. + * c-objc-common.h (LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P): Likewise. + * c-parser.c (c_parser_typeof_specifier): Evaluate arguments to + typeof when argument is a variably modified type not inside sizeof or alignof. + (c_parser_direct_declarator_inner): Propagate errors. + (c_parser_sizeof_expression): Add support for [*]. + * c-typeck.c (c_vla_type_p): Add. + (composite_type): Add support for vla compositing. + (comptypes_internal): Add support for vla compatibility. + (c_expr_sizeof_expr): Evaluate vla arguments. + * tree.c (variably_modified_type_p): Update comment for [*]. + 2006-05-18 Michael Matz PR target/27599 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index f4d33307bf2..ea1a8c41beb 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -331,6 +331,10 @@ struct c_scope GTY((chain_next ("%h.outer"))) declarations. */ BOOL_BITFIELD parm_flag : 1; + /* True if we saw [*] in this scope. Used to give an error messages + if these appears in a function definition. */ + BOOL_BITFIELD had_vla_unspec : 1; + /* True if we already complained about forward parameter decls in this scope. This prevents double warnings on foo (int a; int b; ...) */ @@ -3007,14 +3011,14 @@ quals_from_declspecs (const struct c_declspecs *specs) return quals; } -/* Construct an array declarator. EXPR is the expression inside [], or - NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied - to the pointer to which a parameter array is converted). STATIC_P is - true if "static" is inside the [], false otherwise. VLA_UNSPEC_P - is true if the array is [*], a VLA of unspecified length which is - nevertheless a complete type (not currently implemented by GCC), - false otherwise. The field for the contained declarator is left to be - filled in by set_array_declarator_inner. */ +/* Construct an array declarator. EXPR is the expression inside [], + or NULL_TREE. QUALS are the type qualifiers inside the [] (to be + applied to the pointer to which a parameter array is converted). + STATIC_P is true if "static" is inside the [], false otherwise. + VLA_UNSPEC_P is true if the array is [*], a VLA of unspecified + length which is nevertheless a complete type, false otherwise. The + field for the contained declarator is left to be filled in by + set_array_declarator_inner. */ struct c_declarator * build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, @@ -3046,7 +3050,16 @@ build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p, pedwarn ("ISO C90 does not support %<[*]%> array declarators"); } if (vla_unspec_p) - warning (0, "GCC does not yet properly implement %<[*]%> array declarators"); + { + if (!current_scope->parm_flag) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than function prototype scope"); + declarator->u.array.vla_unspec_p = false; + return NULL; + } + current_scope->had_vla_unspec = true; + } return declarator; } @@ -3858,20 +3871,21 @@ grokdeclarator (const struct c_declarator *declarator, int type_quals = TYPE_UNQUALIFIED; const char *name, *orig_name; tree typedef_type = 0; - int funcdef_flag = 0; + bool funcdef_flag = false; bool funcdef_syntax = false; int size_varies = 0; tree decl_attr = declspecs->decl_attr; int array_ptr_quals = TYPE_UNQUALIFIED; tree array_ptr_attrs = NULL_TREE; int array_parm_static = 0; + bool array_parm_vla_unspec_p = false; tree returned_attrs = NULL_TREE; bool bitfield = width != NULL; tree element_type; struct c_arg_info *arg_info = 0; if (decl_context == FUNCDEF) - funcdef_flag = 1, decl_context = NORMAL; + funcdef_flag = true, decl_context = NORMAL; /* Look inside a declarator for the name being declared and get it as a string, for an error message. */ @@ -4137,7 +4151,8 @@ grokdeclarator (const struct c_declarator *declarator, array_ptr_quals = declarator->u.array.quals; array_ptr_attrs = declarator->u.array.attrs; array_parm_static = declarator->u.array.static_p; - + array_parm_vla_unspec_p = declarator->u.array.vla_unspec_p; + declarator = declarator->declarator; /* Check for some types that there cannot be arrays of. */ @@ -4262,6 +4277,20 @@ grokdeclarator (const struct c_declarator *declarator, identical to GCC's zero-length array extension. */ itype = build_range_type (sizetype, size_zero_node, NULL_TREE); } + else if (decl_context == PARM) + { + if (array_parm_vla_unspec_p) + { + if (! orig_name) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than a declaration"); + } + + itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + size_varies = 1; + } + } /* Complain about arrays of incomplete types. */ if (!COMPLETE_TYPE_P (type)) @@ -4275,7 +4304,7 @@ grokdeclarator (const struct c_declarator *declarator, if (type != error_mark_node) { if (size_varies) - C_TYPE_VARIABLE_SIZE (type) = 1; + C_TYPE_VARIABLE_SIZE (type) = 1; /* The GCC extension for zero-length arrays differs from ISO flexible array members in that sizeof yields @@ -4285,6 +4314,12 @@ grokdeclarator (const struct c_declarator *declarator, TYPE_SIZE (type) = bitsize_zero_node; TYPE_SIZE_UNIT (type) = size_zero_node; } + if (array_parm_vla_unspec_p) + { + /* The type is complete. C99 6.7.5.2p4 */ + TYPE_SIZE (type) = bitsize_zero_node; + TYPE_SIZE_UNIT (type) = size_zero_node; + } } if (decl_context != PARM @@ -4472,6 +4507,13 @@ grokdeclarator (const struct c_declarator *declarator, return type; } + if (pedantic && decl_context == FIELD + && variably_modified_type_p (type, NULL_TREE)) + { + /* C99 6.7.2.1p8 */ + pedwarn ("a member of a structure or union cannot have a variably modified type"); + } + /* Aside from typedefs and type names (handle above), `void' at top level (not within pointer) is allowed only in public variables. @@ -4737,6 +4779,13 @@ grokdeclarator (const struct c_declarator *declarator, } } + if (storage_class == csc_extern + && variably_modified_type_p (type, NULL_TREE)) + { + /* C99 6.7.5.2p2 */ + error ("object with variably modified type must have no linkage"); + } + /* Record `register' declaration for warnings on & and in case doing stupid register allocation. */ @@ -4778,7 +4827,7 @@ grokdeclarator (const struct c_declarator *declarator, } /* Decode the parameter-list info for a function type or function definition. - The argument is the value returned by `get_parm_info' (or made in parse.y + The argument is the value returned by `get_parm_info' (or made in c-parse.c if there is an identifier list instead of a parameter decl list). These two functions are separate because when a function returns or receives functions then each is called multiple times but the order @@ -4796,6 +4845,13 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) { tree arg_types = arg_info->types; + if (funcdef_flag && arg_info->had_vla_unspec) + { + /* A function definition isn't function prototype scope C99 6.2.1p4. */ + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than function prototype scope"); + } + if (arg_types == 0 && !funcdef_flag && !in_system_header) warning (OPT_Wstrict_prototypes, "function declaration isn%'t a prototype"); @@ -4892,6 +4948,7 @@ get_parm_info (bool ellipsis) arg_info->tags = 0; arg_info->types = 0; arg_info->others = 0; + arg_info->had_vla_unspec = current_scope->had_vla_unspec; /* The bindings in this scope must not get put into a block. We will take care of deleting the binding nodes. */ @@ -5541,7 +5598,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) /* If we're inside a function proper, i.e. not file-scope and not still parsing parameters, then arrange for the size of a variable sized type to be bound now. */ - if (cur_stmt_list && variably_modified_type_p (t, NULL)) + if (cur_stmt_list && variably_modified_type_p (t, NULL_TREE)) add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t))); return t; diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c index 8fcee7330f4..facaeafd82e 100644 --- a/gcc/c-objc-common.c +++ b/gcc/c-objc-common.c @@ -257,3 +257,11 @@ c_types_compatible_p (tree x, tree y) { return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y)); } + +/* Determine if the type is a vla type for the backend. */ + +bool +c_vla_unspec_p (tree x, tree fn ATTRIBUTE_UNUSED) +{ + return c_vla_type_p (x); +} diff --git a/gcc/c-objc-common.h b/gcc/c-objc-common.h index 136445ca68e..49f9ce428b1 100644 --- a/gcc/c-objc-common.h +++ b/gcc/c-objc-common.h @@ -137,4 +137,7 @@ extern void c_initialize_diagnostics (diagnostic_context *); #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING #define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing +#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P +#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p + #endif /* GCC_C_OBJC_COMMON */ diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 8f6cafda284..5a67653d892 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -2148,6 +2148,7 @@ c_parser_typeof_specifier (c_parser *parser) } else { + bool was_vm; struct c_expr expr = c_parser_expression (parser); skip_evaluation--; in_typeof--; @@ -2155,7 +2156,13 @@ c_parser_typeof_specifier (c_parser *parser) && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) error ("% applied to a bit-field"); ret.spec = TREE_TYPE (expr.value); - pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE)); + was_vm = variably_modified_type_p (ret.spec, NULL_TREE); + /* This should be returned with the type so that when the type + is evaluated, this can be evaluated. For now, we avoid + evaluation when the context might. */ + if (!skip_evaluation && was_vm) + c_finish_expr_stmt (expr.value); + pop_maybe_used (was_vm); } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return ret; @@ -2451,6 +2458,8 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, } declarator = build_array_declarator (dimen, quals_attrs, static_seen, star_seen); + if (declarator == NULL) + return NULL; inner = set_array_declarator_inner (declarator, inner, !id_present); return c_parser_direct_declarator_inner (parser, id_present, inner); } @@ -4868,6 +4877,12 @@ c_parser_sizeof_expression (c_parser *parser) /* sizeof ( type-name ). */ skip_evaluation--; in_sizeof--; + if (type_name->declarator->kind == cdk_array + && type_name->declarator->u.array.vla_unspec_p) + { + /* C99 6.7.5.2p4 */ + error ("%<[*]%> not allowed in other than a declaration"); + } return c_expr_sizeof_type (type_name); } else diff --git a/gcc/c-tree.h b/gcc/c-tree.h index f67c4d20796..9b24daa79f5 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -309,6 +309,8 @@ struct c_arg_info { /* A list of non-parameter decls (notably enumeration constants) defined with the parameters. */ tree others; + /* True when these arguments had [*]. */ + BOOL_BITFIELD had_vla_unspec : 1; }; /* A declarator. */ @@ -506,6 +508,7 @@ extern bool c_missing_noreturn_ok_p (tree); extern tree c_objc_common_truthvalue_conversion (tree expr); extern bool c_warn_unused_global_decl (tree); extern void c_initialize_diagnostics (diagnostic_context *); +extern bool c_vla_unspec_p (tree x, tree fn); #define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \ c_build_qualified_type ((TYPE), \ @@ -524,6 +527,7 @@ extern struct c_label_context_vm *label_context_stack_vm; extern tree require_complete_type (tree); extern int same_translation_unit_p (tree, tree); extern int comptypes (tree, tree); +extern bool c_vla_type_p (tree); extern bool c_mark_addressable (tree); extern void c_incomplete_type_error (tree, tree); extern tree c_type_promotes_to (tree); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 2152920be5f..4cf50acecbc 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -253,6 +253,17 @@ qualify_type (tree type, tree like) return c_build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUALS (like)); } + +/* Return true iff the given tree T is a variable length array. */ + +bool +c_vla_type_p (tree t) +{ + if (TREE_CODE (t) == ARRAY_TYPE + && C_TYPE_VARIABLE_SIZE (t)) + return true; + return false; +} /* Return the composite type of two compatible types. @@ -330,6 +341,8 @@ composite_type (tree t1, tree t2) d2_variable = (!d2_zero && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); + d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); /* Save space: see if the result is identical to one of the args. */ if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1) @@ -834,6 +847,8 @@ comptypes_internal (tree type1, tree type2) d2_variable = (!d2_zero && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); + d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); + d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); if (d1_variable || d2_variable) break; @@ -2116,6 +2131,11 @@ c_expr_sizeof_expr (struct c_expr expr) { ret.value = c_sizeof (TREE_TYPE (expr.value)); ret.original_code = ERROR_MARK; + if (c_vla_type_p (TREE_TYPE (expr.value))) + { + /* sizeof is evaluated when given a vla (C99 6.5.3.4p2). */ + ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value); + } pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value))); } return ret; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e270f7a8791..8c1700f9c70 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2006-05-18 Mike Stump + + * gcc.dg/c90-arraydecl-1.c: Update for vla, vm [*] fixups. + * gcc.dg/vla-4.c: Add. + * gcc.dg/vla-5.c: Add. + * gcc.dg/vla-6.c: Add. + 2006-05-12 Stuart Hastings * testsuite/gcc.target/i386/20060512-1.c: New. diff --git a/gcc/testsuite/gcc.dg/c90-arraydecl-1.c b/gcc/testsuite/gcc.dg/c90-arraydecl-1.c index 47334b9123d..97dc1eee663 100644 --- a/gcc/testsuite/gcc.dg/c90-arraydecl-1.c +++ b/gcc/testsuite/gcc.dg/c90-arraydecl-1.c @@ -9,23 +9,22 @@ that we get just one error and no warnings. */ void foo0 (int a, int b[*]); /* { dg-error "ISO C90" "\[*\] not in C90" } */ -/* { dg-warning "implement" "\[*\] not implemented" { target *-*-* } 11 } */ void foo1 (int, int [*]); /* { dg-error "ISO C90" "\[*\] not in C90" } */ -/* { dg-warning "implement" "\[*\] not implemented" { target *-*-* } 13 } */ +/* { dg-error "allowed" "\'\[*\]\' not allowed in other than a declaration" { target *-*-* } 12 } */ /* Use of static and type qualifiers (not allowed with abstract declarators) is a C99 feature. */ void bar0 (int a[const]); /* { dg-bogus "warning" "warning in place of error" } */ -/* { dg-error "ISO C90" "\[quals\] not in C90" { target *-*-* } 19 } */ +/* { dg-error "ISO C90" "\[quals\] not in C90" { target *-*-* } 18 } */ void bar1 (int a[const 2]); /* { dg-bogus "warning" "warning in place of error" } */ -/* { dg-error "ISO C90" "\[quals expr\] not in C90" { target *-*-* } 21 } */ +/* { dg-error "ISO C90" "\[quals expr\] not in C90" { target *-*-* } 20 } */ void bar2 (int a[static 2]); /* { dg-bogus "warning" "warning in place of error" } */ -/* { dg-error "ISO C90" "\[static expr\] not in C90" { target *-*-* } 23 } */ +/* { dg-error "ISO C90" "\[static expr\] not in C90" { target *-*-* } 22 } */ void bar3 (int a[static const 2]); /* { dg-bogus "warning" "warning in place of error" } */ -/* { dg-error "ISO C90" "\[static quals expr\] not in C90" { target *-*-* } 25 } */ +/* { dg-error "ISO C90" "\[static quals expr\] not in C90" { target *-*-* } 24 } */ void bar4 (int a[const static 2]); /* { dg-bogus "warning" "warning in place of error" } */ -/* { dg-error "ISO C90" "\[quals static expr\] not in C90" { target *-*-* } 27 } */ +/* { dg-error "ISO C90" "\[quals static expr\] not in C90" { target *-*-* } 26 } */ /* Because [*] isn't properly implemented and so warns, we don't test here for [const *] yet. */ diff --git a/gcc/testsuite/gcc.dg/vla-4.c b/gcc/testsuite/gcc.dg/vla-4.c new file mode 100644 index 00000000000..7ffbfb31b8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-4.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-std=c99 -pedantic-errors" } */ +/* PR c/18740 */ + +static int i; + +int foo(int n) +{ + int (*t)[n]; + i = 0; + int j = 0; + char b[1][n+3]; /* Variable length array. */ + int d[3][n]; /* Variable length array. */ + sizeof (b[i++ + sizeof(j++)]); /* Outer sizeof is evaluated for vla, but not the inner one. */ + if (i != 1 || j != 0) + return 1; + __typeof__(b[i++]) c1; /* typeof is evauluated when given a vm */ + if (i != 2) + return 1; + __typeof__(t + (i++,0)) c2; /* typeof is evauluated when given a vm */ + if (i != 3) + return 1; + __typeof__(i + (i++,0)) c3; /* typeof is not evauluated when not given a vm */ + if (i != 3) + return 1; + sizeof (d[i++]); /* sizeof is evaluated for vla. */ + if (i != 4) + return 1; + __alignof__(__typeof__(t + (i++,0))); /* typeof is not evauluated when given a vm inside alignof*/ + if (i != 4) + return 1; + sizeof(__typeof__(t + (i++,0))); /* typeof is not evauluated when given a vm inside sizeof*/ + if (i != 4) + return 1; + return 0; +} + +int foo6(int a, int b[a][a], int (*c)[sizeof(*b)]) { + return sizeof (*c); +} + +int main() { + int b[10][10]; + int (*c)[sizeof(int)*10]; + if (foo6(10, b, c) != 10*sizeof(int)*sizeof(int)) + return 1; + return foo(10); +} diff --git a/gcc/testsuite/gcc.dg/vla-5.c b/gcc/testsuite/gcc.dg/vla-5.c new file mode 100644 index 00000000000..f5256c4c4a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-5.c @@ -0,0 +1,24 @@ +/* { dg-options "-std=c99 -pedantic-errors" } */ + +void foo1(int (*o)(int p[*])) { } + +void foo2(int o[*]); +void foo3(int o[4][*]); + +void foo4(int j, int a[j]); +void foo4(int, int a[*]); +void foo4(int, int a[]); +void foo4(int j, int a[j]) { +} + +int foo5(int a, int b[*][*], int c[static sizeof(*b)]); +int foo5(int a, int b[10][10], int c[400]) { + return sizeof (c); +} + +int foo6(int a, int b[*][*], int c[static sizeof(*b)]); +int foo6(int a, int b[a][a], int c[sizeof(*b)]) { + return sizeof (c); +} + +void foo7(__typeof__ (int (*)(int o[*])) i); diff --git a/gcc/testsuite/gcc.dg/vla-6.c b/gcc/testsuite/gcc.dg/vla-6.c new file mode 100644 index 00000000000..b7bdb31eeca --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-6.c @@ -0,0 +1,26 @@ +/* { dg-options "-std=c99 -pedantic-errors" } */ + +int a[*]; /* { dg-error "not allowed in other than function prototype scope" } */ +void foo1() { int a[*]; } /* { dg-error "not allowed in other than function prototype scope" } */ +void foo2() { int a[*]; } /* { dg-error "not allowed in other than function prototype scope" } */ +int foo3(int i)[*]; /* { dg-error "not allowed in other than function prototype scope" } */ +void foo4(int o[*][4]) { } /* { dg-error "not allowed in other than function prototype scope" } */ +void foo5(int o[4][*]) { } /* { dg-error "not allowed in other than function prototype scope" } */ + +/* [*] can't be used in a type that's not a declaration */ +void foo11(int x[sizeof(int (*)[*])]); /* { dg-error "not allowed in other than a declaration" } */ +void foo12(int [*]); /* { dg-error "not allowed in other than a declaration" } */ + +extern int n; +int B[100]; +void foo10(int m) { + typedef int (*vla)[m]; + struct tag { + vla x; /* { dg-error "a member of a structure or union cannot have a variably modified type" } */ + /* PR c/7948 */ + int (*y)[n]; /* { dg-error "a member of a structure or union cannot have a variably modified type" } */ + int z[n]; /* { dg-error "a member of a structure or union cannot have a variably modified type" } */ + }; + /* PR c/25802 */ + extern int (*r)[m]; /* { dg-error "variably modified type must have no linkage" } */ +} diff --git a/gcc/tree.c b/gcc/tree.c index 049ec093f8c..c369d604e47 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5629,11 +5629,7 @@ variably_modified_type_p (tree type, tree fn) if (type == error_mark_node) return false; - /* If TYPE itself has variable size, it is variably modified. - - We do not yet have a representation of the C99 '[*]' syntax. - When a representation is chosen, this function should be modified - to test for that case as well. */ + /* If TYPE itself has variable size, it is variably modified. */ RETURN_TRUE_IF_VAR (TYPE_SIZE (type)); RETURN_TRUE_IF_VAR (TYPE_SIZE_UNIT (type)); @@ -5673,7 +5669,7 @@ variably_modified_type_p (tree type, tree fn) case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - /* We can't see if any of the field are variably-modified by the + /* We can't see if any of the fields are variably-modified by the definition we normally use, since that would produce infinite recursion via pointers. */ /* This is variably modified if some field's type is. */