Fix up vla, vm and [*] sematics.
authorMike Stump <mrs@apple.com>
Thu, 18 May 2006 18:22:12 +0000 (18:22 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Thu, 18 May 2006 18:22:12 +0000 (18:22 +0000)
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

13 files changed:
gcc/ChangeLog
gcc/c-decl.c
gcc/c-objc-common.c
gcc/c-objc-common.h
gcc/c-parser.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c90-arraydecl-1.c
gcc/testsuite/gcc.dg/vla-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vla-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vla-6.c [new file with mode: 0644]
gcc/tree.c

index 8465db33d04d902083c03d0bfb8ecab4c1e71412..3f95910f694daf205122478f91c5a3f291146623 100644 (file)
@@ -1,3 +1,30 @@
+2006-05-18  Mike Stump  <mrs@apple.com>
+
+       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  <matz@suse.de>
 
        PR target/27599
index f4d33307bf215bb54ec208518e77ca841beb5c24..ea1a8c41beb8fbe541fca43ccf129c3a3c960bbe 100644 (file)
@@ -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,
 }
 \f
 /* 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;
index 8fcee7330f481c6cb246e48e660f25cf55c64e31..facaeafd82e985672212ca27a8a792c04e91c69c 100644 (file)
@@ -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);
+}
index 136445ca68e82d287bd6d7ebd8dae67cca34e976..49f9ce428b164a173adf8975a5ba8e41108721f4 100644 (file)
@@ -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 */
index 8f6cafda28486e318771b8add1b198a4e4a4e8a0..5a67653d8926afecfcab8aa7f479f6696a9a683f 100644 (file)
@@ -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 ("%<typeof%> 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
index f67c4d20796aa9ee5c0247debb531e9952f2020b..9b24daa79f5fff13ab6d7dc2710d8c048f874efa 100644 (file)
@@ -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);
index 2152920be5fa490b089ed7c1bfc76a5ec6567185..4cf50acecbc947eb4166408e56caeec2e0ac5298 100644 (file)
@@ -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;
+}
 \f
 /* 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;
index e270f7a879117c6abfd7c99b27b3e341d77e9dd9..8c1700f9c701db706c5e7a3e1acf438168a6c7de 100644 (file)
@@ -1,3 +1,10 @@
+2006-05-18  Mike Stump  <mrs@apple.com>
+
+       * 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  <stuart@apple.com>
 
        * testsuite/gcc.target/i386/20060512-1.c: New.
index 47334b9123d6372caeedf7c51d178de0649d9e4f..97dc1eee663a1a133089f79600e308db56100d38 100644 (file)
@@ -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 (file)
index 0000000..7ffbfb3
--- /dev/null
@@ -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 (file)
index 0000000..f5256c4
--- /dev/null
@@ -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 (file)
index 0000000..b7bdb31
--- /dev/null
@@ -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" } */
+}
index 049ec093f8c36f899898f989b6adb728a3cc9144..c369d604e476face6b8533d497823a274cdf3f36 100644 (file)
@@ -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.  */