Doing diffs in .: --- ./c-decl.c.~1~ 2006-05-04 15:52:47.000000000 -0700 +++ ./c-decl.c 2006-05-05 19:34:04.000000000 -0700 @@ -3007,14 +3007,14 @@ quals_from_declspecs (const struct c_dec 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 +3046,15 @@ build_array_declarator (tree expr, struc 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.2p */ + error ("%<[*]%> not allowed in other than function prototype scope"); + declarator->u.array.vla_unspec_p = false; + return NULL; + } + } return declarator; } @@ -3858,20 +3866,21 @@ grokdeclarator (const struct c_declarato 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 +4146,8 @@ grokdeclarator (const struct c_declarato 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 +4272,14 @@ grokdeclarator (const struct c_declarato 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) + { + itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + size_varies = 1; + } + } /* Complain about arrays of incomplete types. */ if (!COMPLETE_TYPE_P (type)) @@ -4272,6 +4290,9 @@ grokdeclarator (const struct c_declarato else type = build_array_type (type, itype); + if (size_varies && pedantic && decl_context == FIELD) + error ("not an ordinary identifier, structure and unions are not ordinary"); + if (type != error_mark_node) { if (size_varies) @@ -4285,6 +4306,11 @@ grokdeclarator (const struct c_declarato 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; + } } if (decl_context != PARM @@ -4332,6 +4358,13 @@ grokdeclarator (const struct c_declarato error ("%qs declared as function returning an array", name); type = integer_type_node; } +#if 0 + if (funcdef_flag && current_scope->had_vla_unspec) + { + /* C99 6.7.5.2p3 */ + error ("%<[*]%> cannot be used in a function definition"); + } +#endif /* Construct the function type and go to the next inner layer of declarator. */ @@ -4411,6 +4444,7 @@ grokdeclarator (const struct c_declarato if (TREE_CODE (type) == ARRAY_TYPE && COMPLETE_TYPE_P (type) + && TYPE_SIZE_UNIT (type) && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST && TREE_OVERFLOW (TYPE_SIZE_UNIT (type))) { @@ -4507,6 +4541,7 @@ grokdeclarator (const struct c_declarato { /* Transfer const-ness of array into that of type pointed to. */ type = TREE_TYPE (type); + size_varies = C_TYPE_VARIABLE_SIZE (type); if (type_quals) type = c_build_qualified_type (type, type_quals); type = build_pointer_type (type); @@ -4516,8 +4551,6 @@ grokdeclarator (const struct c_declarato if (array_ptr_attrs != NULL_TREE) warning (OPT_Wattributes, "attributes in parameter array declarator ignored"); - - size_varies = 0; } else if (TREE_CODE (type) == FUNCTION_TYPE) { @@ -4737,6 +4770,14 @@ grokdeclarator (const struct c_declarato } } + if (pedantic + && 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 +4819,7 @@ grokdeclarator (const struct c_declarato } /* 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 --- ./c-objc-common.c.~1~ 2005-10-28 08:48:36.000000000 -0700 +++ ./c-objc-common.c 2006-05-05 13:24:43.000000000 -0700 @@ -257,3 +257,13 @@ c_types_compatible_p (tree x, tree y) { return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y)); } + +bool +c_vla_unspec_p (tree x, tree fn) +{ + if (TREE_CODE (x) == ARRAY_TYPE + && C_TYPE_VARIABLE_SIZE (x) + && TYPE_SIZE (x) == bitsize_zero_node) + return true; + return false; +} --- ./c-objc-common.h.~1~ 2006-01-27 14:56:07.000000000 -0800 +++ ./c-objc-common.h 2006-05-05 13:15:56.000000000 -0700 @@ -137,4 +137,7 @@ extern void c_initialize_diagnostics (di #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 */ --- ./c-parser.c.~1~ 2006-05-04 15:52:50.000000000 -0700 +++ ./c-parser.c 2006-05-04 19:02:29.000000000 -0700 @@ -2451,6 +2451,8 @@ c_parser_direct_declarator_inner (c_pars } 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); } --- ./c-tree.h.~1~ 2006-01-27 14:56:08.000000000 -0800 +++ ./c-tree.h 2006-05-05 13:22:09.000000000 -0700 @@ -506,6 +506,7 @@ extern bool c_missing_noreturn_ok_p (tre 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), \ --- ./testsuite/gcc.dg/array-star-1.c.~1~ 2006-05-04 15:54:57.000000000 -0700 +++ ./testsuite/gcc.dg/array-star-1.c 2006-05-06 14:24:32.000000000 -0700 @@ -1,4 +1,31 @@ -void foo1(int a[*]); -void foo1(int j, int a[j]) { +/* { dg-options "-std=c99 -pedantic-errors" } */ +/* PR gcc/25802 */ + +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" } */ + +/* ??? Are these three right? */ +void foo4(int o[*][4]) { } +void foo5(int o[4][*]) { } +void foo6(int (*o)(int p[*])) { } + +void foo7(int o[*]); +void foo8(int o[4][*]); + +void foo9(int j, int a[j]); +void foo9(int, int a[*]); +void foo9(int, int a[]); +void foo9(int j, int a[j]) { +} + +extern int n; +int B[100]; +void foo10(int m) { + struct tag { + int (*y)[n]; /* { dg-error "not an ordinary identifier" } */ + int z[n]; /* { dg-error "not an ordinary identifier" } */ + }; + extern int (*r)[m]; /* { dg-error "variably modified type must have no linkage" } */ } -void foo(int [*]) { } /* { dg-error "nope" } */ --- ./tree.c.~1~ 2006-05-04 15:52:45.000000000 -0700 +++ ./tree.c 2006-05-05 13:08:53.000000000 -0700 @@ -5629,11 +5629,7 @@ variably_modified_type_p (tree type, tre 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)); @@ -5674,7 +5670,7 @@ variably_modified_type_p (tree type, tre 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. */ --------------