[PATCH] Fix infinite recursion in C front end during bad struct parsing. (ping)

Carlos O'Donell carlos@codesourcery.com
Wed Apr 19 19:07:00 GMT 2006


On Fri, Apr 14, 2006 at 07:59:13PM -0700, Mark Mitchell wrote:
> Carlos O'Donell wrote:
> > Ping?
> > 
> > http://gcc.gnu.org/ml/gcc-patches/2006-04/msg00161.html
> 
> This is OK, but I think we can make it a bit tidier.

The following patch seems to work just as effecitvely but we have tidied
up the implementation. The fallout is that "update_alignment_for_field"
and "place_union_field" are both more robust against ERROR_MARK.

Comments?

OK to checkin to mainline?
OK to checkin to 4.1?

No regressions on i686-pc-linux-gnu.

Cheers,
Carlos.
-- 
Carlos O'Donell
CodeSourcery
carlos@codesourcery.com
(650) 331-3385 x716

gcc/

2006-04-19  Carlos O'Donell  <carlos@codesourcery.com>
            Nathan Sidwell  <nathan@codesourcery.com>

	PR c/26774
	* stor-layou.c (update_alignment_for_field): Do not align
	ERROR_MARK nodes.
	(place_union_field): Place union field at the start of the union.
	(place_field): Move ERROR_MARK check later, and use the current
	allocation position to maintain monotonicity.

gcc/testsuite/

2006-04-19  Carlos O'Donell  <carlos@codesourcery.com>

	PR c/26774
	* gcc.dg/struct-parse-1.c: New test case.

Index: gcc/testsuite/gcc.dg/struct-parse-1.c
===================================================================
--- gcc/testsuite/gcc.dg/struct-parse-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/struct-parse-1.c	(revision 0)
@@ -0,0 +1,11 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc. */
+/* Contributed by Carlos O'Donell on 2006-03-31 */
+
+/* This code caused the C frontend to loop 
+   forever exhausting all system memory, or ICE */
+/* Origin: Carlos O'Donell <carlos@codesourcery.com> */
+
+/* { dg-options "-std=c99" } */
+struct s { int a; int b; struct t c; }; /* { dg-error "error: field 'c' has incomplete type" } */
+struct s d = { .b = 0 };
+
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	(revision 113057)
+++ gcc/stor-layout.c	(working copy)
@@ -663,6 +663,10 @@ update_alignment_for_field (record_layou
   bool user_align;
   bool is_bitfield;
 
+  /* Do not attempt to align an ERROR_MARK node */
+  if (TREE_CODE (type) == ERROR_MARK)
+    return 0;
+
   /* Lay out the field so we know what alignment it needs.  */
   layout_decl (field, known_align);
   desired_align = DECL_ALIGN (field);
@@ -775,6 +779,12 @@ place_union_field (record_layout_info rl
   DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
   SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
 
+  /* If this is an ERROR_MARK return *after* having set the 
+     field at the start of the union. This helps when parsing
+     invalid fields. */
+  if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
+    return;
+
   /* We assume the union's size will be a multiple of a byte so we don't
      bother with BITPOS.  */
   if (TREE_CODE (rli->t) == UNION_TYPE)
@@ -823,17 +833,6 @@ place_field (record_layout_info rli, tre
 
   gcc_assert (TREE_CODE (field) != ERROR_MARK);
 
-  if (TREE_CODE (type) == ERROR_MARK)
-    {
-      if (TREE_CODE (field) == FIELD_DECL)
-	{
-	  DECL_FIELD_OFFSET (field) = size_int (0);
-	  DECL_FIELD_BIT_OFFSET (field) = bitsize_int (0);
-	}
-      
-      return;
-    }
-  
   /* If FIELD is static, then treat it like a separate variable, not
      really like a structure field.  If it is a FUNCTION_DECL, it's a
      method.  In both cases, all we do is lay out the decl, and we do
@@ -858,6 +857,16 @@ place_field (record_layout_info rli, tre
       return;
     }
 
+  else if (TREE_CODE (type) == ERROR_MARK) 
+    {
+      /* Place this field at the current allocation position, so we
+	 maintain monotonicity.  */
+      DECL_FIELD_OFFSET (field) = rli->offset;
+      DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
+      SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
+      return;
+    }
+
   /* Work out the known alignment so far.  Note that A & (-A) is the
      value of the least-significant bit in A that is one.  */
   if (! integer_zerop (rli->bitpos))



More information about the Gcc-patches mailing list