I'll entertain pointers to VLA/VM and [*] bugs for C, please send me
pointers to reports in bugzilla.
Thanks.
I know about http://gcc.gnu.org/PR25802
I also would like to know what people think the standard (c99) says
about:
void foo4(int o[*][4]) { }
void foo5(int o[4][*]) { }
void foo6(int (*o)(int p[*])) { }
Things I don't need reports for, are things fixed by the below patch.
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. */
--------------