This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Allow some VLA type names at file scope (PR 39581)


This patch fixes PR 39581, C code with type names for variable length
arrays used at file scope being rejected by language-independent code
although there appears to be no basis in C99 for such rejection.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

2009-04-26  Joseph Myers  <joseph@codesourcery.com>

	PR c/39581
	* c-decl.c (global_bindings_p): Return negative value.
	(c_variable_size): New.  Based on variable_size from
	stor-layout.c.
	(grokdeclarator): Call c_variable_size not variable_size.

testsuite:
2009-04-26  Joseph Myers  <joseph@codesourcery.com>

	PR c/39581
	* gcc.dg/c99-const-expr-14.c, gcc.dg/gnu99-const-expr-4.c,
	gcc.dg/vla-21.c: New tests.

Index: gcc/testsuite/gcc.dg/c99-const-expr-14.c
===================================================================
--- gcc/testsuite/gcc.dg/c99-const-expr-14.c	(revision 0)
+++ gcc/testsuite/gcc.dg/c99-const-expr-14.c	(revision 0)
@@ -0,0 +1,35 @@
+/* Test for constant expressions: cases involving VLAs, at file scope.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+/* It appears address constants may contain casts to variably modified
+   types.  Whether they should be permitted was discussed in
+   <http://groups.google.com/group/comp.std.c/msg/923eee5ab690fd98>
+   <LV7g2Vy3ARF$Ew9Q@romana.davros.org>; since static pointers to VLAs
+   are definitely permitted within functions and may be initialized
+   and such initialization involves implicit conversion to a variably
+   modified type, allowing explicit casts seems appropriate.  Thus,
+   GCC allows them as long as the "evaluated" size expressions do not
+   contain the various operators not permitted to be evaluated in a
+   constant expression, and as long as the result is genuinely
+   constant (meaning that pointer arithmetic using the size of the VLA
+   is generally not permitted).  */
+
+static int sa[100];
+
+volatile int nv;
+int m;
+int n;
+int f (int, int);
+
+static int (*a2)[] = (int (*)[n])sa;
+static int (*a8)[] = (int (*)[(m=n)])sa; /* { dg-error "constant" } */
+static int (*a9)[] = (int (*)[(m+=n)])sa; /* { dg-error "constant" } */
+static int (*a10)[] = (int (*)[f(m,n)])sa; /* { dg-error "constant" } */
+static int (*a11)[] = (int (*)[(m,n)])sa; /* { dg-error "constant" } */
+static int (*a12)[] = (int (*)[sizeof(int[n])])sa;
+static int (*a13)[] = (int (*)[sizeof(int[m++])])sa; /* { dg-error "constant" } */
+static int (*a15)[] = (int (*)[sizeof(*(int (*)[n])sa)])sa;
+static int (*a16)[] = (int (*)[sizeof(*(int (*)[m++])sa)])sa; /* { dg-error "constant" } */
+static int (*a17)[] = (int (*)[nv])sa;
Index: gcc/testsuite/gcc.dg/vla-21.c
===================================================================
--- gcc/testsuite/gcc.dg/vla-21.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vla-21.c	(revision 0)
@@ -0,0 +1,7 @@
+/* Type names for VLAs should be allowed outside functions if the size
+   is not evaluated.  PR 39581.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+int a;
+int b = sizeof (int (*)[a]);
Index: gcc/testsuite/gcc.dg/gnu99-const-expr-4.c
===================================================================
--- gcc/testsuite/gcc.dg/gnu99-const-expr-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/gnu99-const-expr-4.c	(revision 0)
@@ -0,0 +1,29 @@
+/* Test for constant expressions: cases involving VLAs and typeof, at
+   file scope.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -pedantic-errors" } */
+
+/* It appears address constants may contain casts to variably modified
+   types.  Whether they should be permitted was discussed in
+   <http://groups.google.com/group/comp.std.c/msg/923eee5ab690fd98>
+   <LV7g2Vy3ARF$Ew9Q@romana.davros.org>; since static pointers to VLAs
+   are definitely permitted within functions and may be initialized
+   and such initialization involves implicit conversion to a variably
+   modified type, allowing explicit casts seems appropriate.  Thus,
+   GCC allows them as long as the "evaluated" size expressions do not
+   contain the various operators not permitted to be evaluated in a
+   constant expression, and as long as the result is genuinely
+   constant (meaning that pointer arithmetic using the size of the VLA
+   is generally not permitted).  */
+
+static int sa[100];
+int m;
+int n;
+
+static int (*a1)[] = &sa;
+static int (*a2)[] = (__typeof__(int (*)[n]))sa;
+static int (*a4)[] = (__typeof__((int (*)[n])sa))sa;
+static int (*a5)[] = (__typeof__((int (*)[m++])sa))sa; /* { dg-error "constant" } */
+static int (*a6)[] = (__typeof__((int (*)[100])(int (*)[m++])sa))sa;
+static int (*a7)[] = (__typeof__((int (*)[n])sa + m++))sa; /* { dg-error "constant" } */
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 146800)
+++ gcc/c-decl.c	(working copy)
@@ -663,7 +663,9 @@ objc_mark_locals_volatile (void *enclosi
 int
 global_bindings_p (void)
 {
-  return current_scope == file_scope && !c_override_global_bindings_to_false;
+  return (current_scope == file_scope && !c_override_global_bindings_to_false
+	  ? -1
+	  : 0);
 }
 
 void
@@ -4015,6 +4017,34 @@ warn_variable_length_array (const char *
     }
 }
 
+/* Given a size SIZE that may not be a constant, return a SAVE_EXPR to
+   serve as the actual size-expression for a type or decl.  This is
+   like variable_size in stor-layout.c, but we make global_bindings_p
+   return negative to avoid calls to that function from outside the
+   front end resulting in errors at file scope, then call this version
+   instead from front-end code.  */
+
+static tree
+c_variable_size (tree size)
+{
+  tree save;
+
+  if (TREE_CONSTANT (size))
+    return size;
+
+  size = save_expr (size);
+
+  save = skip_simple_arithmetic (size);
+
+  if (cfun && cfun->dont_save_pending_sizes_p)
+    return size;
+
+  if (!global_bindings_p ())
+    put_pending_size (save);
+
+  return size;
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -4479,7 +4509,7 @@ grokdeclarator (const struct c_declarato
 		       MINUS_EXPR, which allows the -1 to get folded
 		       with the +1 that happens when building TYPE_SIZE.  */
 		    if (size_varies)
-		      size = variable_size (size);
+		      size = c_variable_size (size);
 		    if (this_size_varies && TREE_CODE (size) == INTEGER_CST)
 		      size = build2 (COMPOUND_EXPR, TREE_TYPE (size),
 				     integer_zero_node, size);

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]