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]

Patch for bug 28504


This patch fixes bug 28504, an ICE-on-valid regression involving VLAs
in a nested parameter list.  The array size from the inner parameter
list would get pushed on the pending sizes list and then wrongly get
expanded inside the function, which such array sizes (at function
prototype scope) should be treated like [*].  I've arranged for the
pending sizes list gets saved in the arg_info structure, and only then
gets processed for the case of a function definition.  (There's an
existing testcase in the testsuite that makes sure that it does get
processed then: that cases such as void f(int n, int a[n++]){...} do
increment n on entry to the function.)

Ultimately we should cease using the pending sizes list altogether for
C as part of being more explicit about when array sizes are expanded,
but until then this should serve to fix this bug.  Bootstrapped with
no regressions on i686-pc-linux-gnu.  Applied to mainline.  Will apply
to 4.1 and 4.0 branches subject to testing there.

2006-09-08  Joseph S. Myers  <joseph@codesourcery.com>

	PR c/28504
	* c-tree.h (struct c_arg_info): Add pending_sizes.
	* c-parser.c (c_parser_parms_declarator,
	c_parser_parms_list_declarator): Initialize pending_sizes.
	* c-decl.c (get_parm_info): Initialize pending_sizes.
	(get_parm_info): Set pending_sizes.
	(grokdeclarator): Call put_pending_sizes for parameters for
	function definition only.

2006-09-08  Joseph S. Myers  <joseph@codesourcery.com>

	PR c/28504
	* gcc.dg/vla-10.c: New test.

diff -rupN GCC.orig/gcc/c-decl.c GCC/gcc/c-decl.c
--- GCC.orig/gcc/c-decl.c	2006-08-25 21:10:14.000000000 +0000
+++ GCC/gcc/c-decl.c	2006-09-08 20:58:57.000000000 +0000
@@ -4420,6 +4420,8 @@ grokdeclarator (const struct c_declarato
 	       inner layer of declarator.  */
 	    arg_info = declarator->u.arg_info;
 	    arg_types = grokparms (arg_info, really_funcdef);
+	    if (really_funcdef)
+	      put_pending_sizes (arg_info->pending_sizes);
 
 	    /* Type qualifiers before the return type of the function
 	       qualify the return type, not the function type.  */
@@ -4981,6 +4983,7 @@ get_parm_info (bool ellipsis)
   arg_info->tags = 0;
   arg_info->types = 0;
   arg_info->others = 0;
+  arg_info->pending_sizes = 0;
   arg_info->had_vla_unspec = current_scope->had_vla_unspec;
 
   /* The bindings in this scope must not get put into a block.
@@ -5136,6 +5139,7 @@ get_parm_info (bool ellipsis)
   arg_info->tags = tags;
   arg_info->types = types;
   arg_info->others = others;
+  arg_info->pending_sizes = get_pending_sizes ();
   return arg_info;
 }
 
diff -rupN GCC.orig/gcc/c-parser.c GCC/gcc/c-parser.c
--- GCC.orig/gcc/c-parser.c	2006-08-17 10:15:43.000000000 +0000
+++ GCC/gcc/c-parser.c	2006-09-08 20:58:57.000000000 +0000
@@ -2537,6 +2537,7 @@ c_parser_parms_declarator (c_parser *par
 	  ret->tags = 0;
 	  ret->types = list;
 	  ret->others = 0;
+	  ret->pending_sizes = 0;
 	  ret->had_vla_unspec = 0;
 	  c_parser_consume_token (parser);
 	  pop_scope ();
@@ -2579,6 +2580,7 @@ c_parser_parms_list_declarator (c_parser
       ret->tags = 0;
       ret->types = 0;
       ret->others = 0;
+      ret->pending_sizes = 0;
       ret->had_vla_unspec = 0;
       c_parser_consume_token (parser);
       return ret;
@@ -2589,6 +2591,7 @@ c_parser_parms_list_declarator (c_parser
       ret->parms = 0;
       ret->tags = 0;
       ret->others = 0;
+      ret->pending_sizes = 0;
       ret->had_vla_unspec = 0;
       /* Suppress -Wold-style-definition for this case.  */
       ret->types = error_mark_node;
@@ -2640,6 +2643,7 @@ c_parser_parms_list_declarator (c_parser
 	      ret->tags = 0;
 	      ret->types = 0;
 	      ret->others = 0;
+	      ret->pending_sizes = 0;
 	      ret->had_vla_unspec = 0;
 	      return ret;
 	    }
@@ -2666,6 +2670,7 @@ c_parser_parms_list_declarator (c_parser
 		  ret->tags = 0;
 		  ret->types = 0;
 		  ret->others = 0;
+		  ret->pending_sizes = 0;
 		  ret->had_vla_unspec = 0;
 		  return ret;
 		}
diff -rupN GCC.orig/gcc/c-tree.h GCC/gcc/c-tree.h
--- GCC.orig/gcc/c-tree.h	2006-05-20 11:32:56.000000000 +0000
+++ GCC/gcc/c-tree.h	2006-09-08 20:58:57.000000000 +0000
@@ -309,6 +309,11 @@ struct c_arg_info {
   /* A list of non-parameter decls (notably enumeration constants)
      defined with the parameters.  */
   tree others;
+  /* A list of VLA sizes from the parameters.  In a function
+     definition, these are used to ensure that side-effects in sizes
+     of arrays converted to pointers (such as a parameter int i[n++])
+     take place; otherwise, they are ignored.  */
+  tree pending_sizes;
   /* True when these arguments had [*].  */
   BOOL_BITFIELD had_vla_unspec : 1;
 };
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/vla-10.c GCC/gcc/testsuite/gcc.dg/vla-10.c
--- GCC.orig/gcc/testsuite/gcc.dg/vla-10.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/vla-10.c	2006-09-08 20:59:30.000000000 +0000
@@ -0,0 +1,7 @@
+/* ICE with VLA in nested parameter declaration: should be treated
+   like [*] instead of the size being expanded.  Bug 28504 from Volker
+   Reichelt <reichelt@gcc.gnu.org>.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void foo(void (*p)(int n, int x[n])) {}

-- 
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]