re PR c/52977 (internal compiler error: Segmentation fault with `-x c-header' or...
authorMichael Matz <matz@suse.de>
Thu, 19 Apr 2012 13:29:29 +0000 (13:29 +0000)
committerMichael Matz <matz@gcc.gnu.org>
Thu, 19 Apr 2012 13:29:29 +0000 (13:29 +0000)
PR middle-end/52977
* tree.h (VECTOR_CST_NELTS): Use part number of types again.
(struct tree_vector): Adjust GTY length.
* tree.c (make_vector_stat): Don't set VECTOR_CST_NELTS.

* gengtype.c (struct walk_type_data): Add in_record_p and loopcounter
members.
(walk_type, <TYPE_POINTER, TYPE_ARRAY>): Handle case where our
caller emitted the length calulation already.
(walk_type, <TYPE_UNION, TYPE_STRUCT>): Emit length calculations

From-SVN: r186593

gcc/ChangeLog
gcc/gengtype.c
gcc/tree.c
gcc/tree.h

index 0dca9338ff2d16e49c711cd99a14f483f12e3eb4..1f27b62ad68e0086c5a110197fbeada8e23731cf 100644 (file)
@@ -1,3 +1,17 @@
+2012-04-19  Michael Matz  <matz@suse.de>
+
+       PR middle-end/52977
+       * tree.h (VECTOR_CST_NELTS): Use part number of types again.
+       (struct tree_vector): Adjust GTY length.
+       * tree.c (make_vector_stat): Don't set VECTOR_CST_NELTS.
+
+       * gengtype.c (struct walk_type_data): Add in_record_p and loopcounter
+       members.
+       (walk_type, <TYPE_POINTER, TYPE_ARRAY>): Handle case where our
+       caller emitted the length calulation already.
+       (walk_type, <TYPE_UNION, TYPE_STRUCT>): Emit length calculations
+       before handling any of the fields for structs.
+
 2012-04-19  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/53031
index fa4539298148f437ecad42987884befac42c2235..abafaa9bc1236ba29abb62bac4b0a7fc542c346d 100644 (file)
@@ -2291,6 +2291,8 @@ struct walk_type_data
   const char *reorder_fn;
   bool needs_cast_p;
   bool fn_wants_lvalue;
+  bool in_record_p;
+  int loopcounter;
 };
 
 /* Print a mangled name representing T to OF.  */
@@ -2592,7 +2594,7 @@ walk_type (type_p t, struct walk_type_data *d)
          }
        else
          {
-           int loopcounter = d->counter++;
+           int loopcounter = d->loopcounter;
            const char *oldval = d->val;
            const char *oldprevval3 = d->prev_val[3];
            char *newval;
@@ -2602,7 +2604,10 @@ walk_type (type_p t, struct walk_type_data *d)
            oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
            oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent,
                     "", loopcounter, loopcounter);
-           output_escaped_param (d, length, "length");
+           if (!d->in_record_p)
+             output_escaped_param (d, length, "length");
+           else
+             oprintf (d->of, "l%d", loopcounter);
            oprintf (d->of, "); i%d++) {\n", loopcounter);
            d->indent += 2;
            d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
@@ -2624,7 +2629,7 @@ walk_type (type_p t, struct walk_type_data *d)
 
     case TYPE_ARRAY:
       {
-       int loopcounter = d->counter++;
+       int loopcounter;
        const char *oldval = d->val;
        char *newval;
 
@@ -2633,6 +2638,11 @@ walk_type (type_p t, struct walk_type_data *d)
        if (t->u.a.p->kind == TYPE_SCALAR)
          break;
 
+       if (length)
+         loopcounter = d->loopcounter;
+       else
+         loopcounter = d->counter++;
+
        /* When walking an array, compute the length and store it in a
           local variable before walking the array elements, instead of
           recomputing the length expression each time through the loop.
@@ -2643,13 +2653,16 @@ walk_type (type_p t, struct walk_type_data *d)
        oprintf (d->of, "%*s{\n", d->indent, "");
        d->indent += 2;
        oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
-       oprintf (d->of, "%*ssize_t l%d = (size_t)(",
-                d->indent, "", loopcounter);
-       if (length)
-         output_escaped_param (d, length, "length");
-       else
-         oprintf (d->of, "%s", t->u.a.len);
-       oprintf (d->of, ");\n");
+       if (!d->in_record_p || !length)
+         {
+           oprintf (d->of, "%*ssize_t l%d = (size_t)(",
+                    d->indent, "", loopcounter);
+           if (length)
+             output_escaped_param (d, length, "length");
+           else
+             oprintf (d->of, "%s", t->u.a.len);
+           oprintf (d->of, ");\n");
+         }
 
        oprintf (d->of, "%*sfor (i%d = 0; i%d != l%d; i%d++) {\n",
                 d->indent, "",
@@ -2678,6 +2691,9 @@ walk_type (type_p t, struct walk_type_data *d)
        const int union_p = t->kind == TYPE_UNION;
        int seen_default_p = 0;
        options_p o;
+       int lengths_seen = 0;
+       int endcounter;
+       bool any_length_seen = false;
 
        if (!t->u.s.line.file)
          error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag);
@@ -2713,6 +2729,45 @@ walk_type (type_p t, struct walk_type_data *d)
            d->indent += 2;
            oprintf (d->of, "%*s{\n", d->indent, "");
          }
+
+       for (f = t->u.s.fields; f; f = f->next)
+         {
+           options_p oo;
+           int skip_p = 0;
+           const char *fieldlength = NULL;
+
+           d->reorder_fn = NULL;
+           for (oo = f->opt; oo; oo = oo->next)
+             if (strcmp (oo->name, "skip") == 0)
+               skip_p = 1;
+             else if (strcmp (oo->name, "length") == 0
+                      && oo->kind == OPTION_STRING)
+               fieldlength = oo->info.string;
+
+           if (skip_p)
+             continue;
+           if (fieldlength)
+             {
+               lengths_seen++;
+               d->counter++;
+               if (!union_p)
+                 {
+                   if (!any_length_seen)
+                     {
+                       oprintf (d->of, "%*s{\n", d->indent, "");
+                       d->indent += 2;
+                     }
+                   any_length_seen = true;
+
+                   oprintf (d->of, "%*ssize_t l%d = (size_t)(",
+                            d->indent, "", d->counter - 1);
+                   output_escaped_param (d, fieldlength, "length");
+                   oprintf (d->of, ");\n");
+                 }
+             }
+         }
+       endcounter = d->counter;
+
        for (f = t->u.s.fields; f; f = f->next)
          {
            options_p oo;
@@ -2721,6 +2776,7 @@ walk_type (type_p t, struct walk_type_data *d)
            int skip_p = 0;
            int default_p = 0;
            int use_param_p = 0;
+           const char *fieldlength = NULL;
            char *newval;
 
            d->reorder_fn = NULL;
@@ -2741,6 +2797,9 @@ walk_type (type_p t, struct walk_type_data *d)
              else if (strncmp (oo->name, "use_param", 9) == 0
                       && (oo->name[9] == '\0' || ISDIGIT (oo->name[9])))
                use_param_p = 1;
+             else if (strcmp (oo->name, "length") == 0
+                      && oo->kind == OPTION_STRING)
+               fieldlength = oo->info.string;
 
            if (skip_p)
              continue;
@@ -2774,16 +2833,24 @@ walk_type (type_p t, struct walk_type_data *d)
                             "field `%s' is missing `tag' or `default' option",
                             f->name);
 
+           if (fieldlength)
+             {
+               d->loopcounter = endcounter - lengths_seen--;
+             }
+
            d->line = &f->line;
            d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name);
            d->opt = f->opt;
            d->used_length = false;
+           d->in_record_p = !union_p;
 
            if (union_p && use_param_p && d->param == NULL)
              oprintf (d->of, "%*sgcc_unreachable ();\n", d->indent, "");
            else
              walk_type (f->type, d);
 
+           d->in_record_p = false;
+
            free (newval);
 
            if (union_p)
@@ -2808,6 +2875,11 @@ walk_type (type_p t, struct walk_type_data *d)
            oprintf (d->of, "%*s}\n", d->indent, "");
            d->indent -= 2;
          }
+       if (any_length_seen)
+         {
+           d->indent -= 2;
+           oprintf (d->of, "%*s}\n", d->indent, "");
+         }
       }
       break;
 
index 7a71c245480d8955cdd734c2b5d5b84e017b5331..b0d52b2e0e9aa63f21a4deb7a24366b2c0202462 100644 (file)
@@ -1329,7 +1329,6 @@ make_vector_stat (unsigned len MEM_STAT_DECL)
 
   TREE_SET_CODE (t, VECTOR_CST);
   TREE_CONSTANT (t) = 1;
-  VECTOR_CST_NELTS (t) = len;
 
   return t;
 }
index 6bfc29eb15eb7d3ba71d1e702a92bfa7148c2df0..e719be2ed40772313f5210ca5c6b782996624799 100644 (file)
@@ -1534,14 +1534,13 @@ struct GTY(()) tree_complex {
 };
 
 /* In a VECTOR_CST node.  */
-#define VECTOR_CST_NELTS(NODE) (VECTOR_CST_CHECK (NODE)->vector.length)
+#define VECTOR_CST_NELTS(NODE) (TYPE_VECTOR_SUBPARTS (TREE_TYPE (NODE)))
 #define VECTOR_CST_ELTS(NODE) (VECTOR_CST_CHECK (NODE)->vector.elts)
 #define VECTOR_CST_ELT(NODE,IDX) (VECTOR_CST_CHECK (NODE)->vector.elts[IDX])
 
 struct GTY(()) tree_vector {
   struct tree_typed typed;
-  unsigned length;
-  tree GTY ((length ("%h.length"))) elts[1];
+  tree GTY ((length ("TYPE_VECTOR_SUBPARTS (TREE_TYPE ((tree)&%h))"))) elts[1];
 };
 \f
 #include "symtab.h"