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.  */
--------------

Reply via email to