gengtype: Support explicit pointers in template arguments
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 May 2014 15:17:34 +0000 (15:17 +0000)
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 May 2014 15:17:34 +0000 (15:17 +0000)
gcc/
2014-05-13  David Malcolm  <dmalcolm@redhat.com>

* gengtype-parse.c (require3): Eliminate in favor of...
(require4): New.
(require_template_declaration): Update to support optional single *
on a type.

* gengtype.c (get_ultimate_base_class): Add a non-const overload.
(create_user_defined_type): Handle a single level of explicit
pointerness within template arguments.
(struct write_types_data): Add field "kind".
(filter_type_name): Handle "*" character.
(write_user_func_for_structure_ptr): Require a write_types_data
rather than just a prefix string, so that we can look up the kind
of the wtd and use it as an index into wrote_user_func_for_ptr,
ensuring that such functions are written at most once.  Support
subclasses by invoking the marking function of the ultimate base
class.
(write_user_func_for_structure_body): Require a write_types_data
rather than just a prefix string, so that we can pass this to
write_user_func_for_structure_ptr.
(write_func_for_structure): Likewise.
(ggc_wtd): Add initializer of new "kind" field.
(pch_wtd): Likewise.

* gengtype.h (enum write_types_kinds): New.
(struct type): Add field wrote_user_func_for_ptr to the "s"
union member.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@210379 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gengtype-parse.c
gcc/gengtype.c
gcc/gengtype.h

index 0561b7b..a8a538b 100644 (file)
@@ -1,3 +1,32 @@
+2014-05-13  David Malcolm  <dmalcolm@redhat.com>
+
+       * gengtype-parse.c (require3): Eliminate in favor of...
+       (require4): New.
+       (require_template_declaration): Update to support optional single *
+       on a type.
+
+       * gengtype.c (get_ultimate_base_class): Add a non-const overload.
+       (create_user_defined_type): Handle a single level of explicit
+       pointerness within template arguments.
+       (struct write_types_data): Add field "kind".
+       (filter_type_name): Handle "*" character.
+       (write_user_func_for_structure_ptr): Require a write_types_data
+       rather than just a prefix string, so that we can look up the kind
+       of the wtd and use it as an index into wrote_user_func_for_ptr,
+       ensuring that such functions are written at most once.  Support
+       subclasses by invoking the marking function of the ultimate base
+       class.
+       (write_user_func_for_structure_body): Require a write_types_data
+       rather than just a prefix string, so that we can pass this to
+       write_user_func_for_structure_ptr.
+       (write_func_for_structure): Likewise.
+       (ggc_wtd): Add initializer of new "kind" field.
+       (pch_wtd): Likewise.
+
+       * gengtype.h (enum write_types_kinds): New.
+       (struct type): Add field wrote_user_func_for_ptr to the "s"
+       union member.
+
 2014-05-13  Richard Sandiford  <r.sandiford@uk.ibm.com>
 
        * fold-const.c (optimize_bit_field_compare): Use wi:: operations
index 96f0476..0f11cec 100644 (file)
@@ -197,18 +197,19 @@ require2 (int t1, int t2)
   return v;
 }
 
-/* If the next token does not have one of the codes T1, T2 or T3, report a
+/* If the next token does not have one of the codes T1, T2, T3 or T4, report a
    parse error; otherwise return the token's value.  */
 static const char *
-require3 (int t1, int t2, int t3)
+require4 (int t1, int t2, int t3, int t4)
 {
   int u = token ();
   const char *v = advance ();
-  if (u != t1 && u != t2 && u != t3)
+  if (u != t1 && u != t2 && u != t3 && u != t4)
     {
-      parse_error ("expected %s, %s or %s, have %s",
+      parse_error ("expected %s, %s, %s or %s, have %s",
                   print_token (t1, 0), print_token (t2, 0),
-                  print_token (t3, 0), print_token (u, v));
+                  print_token (t3, 0), print_token (t4, 0),
+                  print_token (u, v));
       return 0;
     }
   return v;
@@ -245,7 +246,9 @@ string_seq (void)
 
 /* The caller has detected a template declaration that starts
    with TMPL_NAME.  Parse up to the closing '>'.  This recognizes
-   simple template declarations of the form ID<ID1,ID2,...,IDn>.
+   simple template declarations of the form ID<ID1,ID2,...,IDn>,
+   potentially with a single level of indirection e.g.
+     ID<ID1 *, ID2, ID3 *, ..., IDn>.
    It does not try to parse anything more sophisticated than that.
 
    Returns the template declaration string "ID<ID1,ID2,...,IDn>".  */
@@ -254,6 +257,7 @@ static const char *
 require_template_declaration (const char *tmpl_name)
 {
   char *str;
+  int num_indirections = 0;
 
   /* Recognize the opening '<'.  */
   require ('<');
@@ -294,9 +298,21 @@ require_template_declaration (const char *tmpl_name)
          depth -= 1;
          continue;
        }
-      const char *id = require3 (SCALAR, ID, ',');
+      const char *id = require4 (SCALAR, ID, '*', ',');
       if (id == NULL)
-       id = ",";
+       {
+         if (T.code == '*')
+           {
+             id = "*";
+             if (num_indirections++)
+               parse_error ("only one level of indirection is supported"
+                            " in template arguments");
+           }
+         else
+           id = ",";
+       }
+      else
+       num_indirections = 0;
       str = concat (str, id, (char *) 0);
     }
   return str;
index b6e1718..21da84b 100644 (file)
@@ -145,6 +145,14 @@ get_ultimate_base_class (const_type_p s)
     s = s->u.s.base_class;
   return s;
 }
+
+static type_p
+get_ultimate_base_class (type_p s)
+{
+  while (s->u.s.base_class)
+    s = s->u.s.base_class;
+  return s;
+}
 \f
 /* Input file handling. */
 
@@ -589,7 +597,7 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
       /* We only accept simple template declarations (see
         require_template_declaration), so we only need to parse a
         comma-separated list of strings, implicitly assumed to
-        be type names.  */
+        be type names, potentially with "*" characters.  */
       char *arg = open_bracket + 1;
       char *type_id = strtok (arg, ",>");
       pair_p fields = 0;
@@ -597,8 +605,28 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
        {
          /* Create a new field for every type found inside the template
             parameter list.  */
-         const char *field_name = xstrdup (type_id);
-         type_p arg_type = resolve_typedef (field_name, pos);
+
+         /* Support a single trailing "*" character.  */
+         const char *star = strchr (type_id, '*');
+         int is_ptr = (star != NULL);
+         size_t offset_to_star = star - type_id;
+         if (is_ptr)
+           offset_to_star = star - type_id;
+
+         char *field_name = xstrdup (type_id);
+
+         type_p arg_type;
+         if (is_ptr)
+           {
+             /* Strip off the first '*' character (and any subsequent text). */
+             *(field_name + offset_to_star) = '\0';
+
+             arg_type = find_structure (field_name, TYPE_STRUCT);
+             arg_type = create_pointer (arg_type);
+           }
+         else
+           arg_type = resolve_typedef (field_name, pos);
+
          fields = create_field_at (fields, arg_type, field_name, 0, pos);
          type_id = strtok (0, ",>");
        }
@@ -2461,6 +2489,7 @@ struct write_types_data
   const char *reorder_note_routine;
   const char *comment;
   int skip_hooks;              /* skip hook generation if non zero */
+  enum write_types_kinds kind;
 };
 
 static void output_escaped_param (struct walk_type_data *d,
@@ -2537,7 +2566,8 @@ filter_type_name (const char *type_name)
       size_t i;
       char *s = xstrdup (type_name);
       for (i = 0; i < strlen (s); i++)
-       if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ',')
+       if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ','
+           || s[i] == '*')
          s[i] = '_';
       return s;
     }
@@ -3501,10 +3531,10 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix)
 
 /* Write on OF a user-callable routine to act as an entry point for
    the marking routine for S, generated by write_func_for_structure.
-   PREFIX is the prefix to use to distinguish ggc and pch markers.  */
+   WTD distinguishes between ggc and pch markers.  */
 
 static void
-write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix)
+write_user_func_for_structure_ptr (outf_p of, type_p s, const write_types_data *wtd)
 {
   /* Parameterized structures are not supported in user markers. There
      is no way for the marker function to know which specific type
@@ -3534,13 +3564,23 @@ write_user_func_for_structure_ptr (outf_p of, type_p s, const char *prefix)
        break;
       }
 
+  DBGPRINTF ("write_user_func_for_structure_ptr: %s %s", s->u.s.tag,
+            wtd->prefix);
+
+  /* Only write the function once. */
+  if (s->u.s.wrote_user_func_for_ptr[wtd->kind])
+    return;
+  s->u.s.wrote_user_func_for_ptr[wtd->kind] = true;
+
   oprintf (of, "\nvoid\n");
-  oprintf (of, "gt_%sx (", prefix);
+  oprintf (of, "gt_%sx (", wtd->prefix);
   write_type_decl (of, s);
   oprintf (of, " *& x)\n");
   oprintf (of, "{\n");
   oprintf (of, "  if (x)\n    ");
-  write_marker_function_name (of, alias_of ? alias_of : s, prefix);
+  write_marker_function_name (of,
+                             alias_of ? alias_of : get_ultimate_base_class (s),
+                             wtd->prefix);
   oprintf (of, " ((void *) x);\n");
   oprintf (of, "}\n");
 }
@@ -3578,7 +3618,8 @@ write_user_func_for_structure_body (type_p s, const char *prefix,
    which just marks the fields of T.  */
 
 static void
-write_user_marking_functions (type_p s, const char *prefix,
+write_user_marking_functions (type_p s,
+                             const write_types_data *w,
                              struct walk_type_data *d)
 {
   gcc_assert (s->kind == TYPE_USER_STRUCT);
@@ -3590,10 +3631,10 @@ write_user_marking_functions (type_p s, const char *prefix,
        {
          type_p pointed_to_type = fld_type->u.p;
          if (union_or_struct_p (pointed_to_type))
-           write_user_func_for_structure_ptr (d->of, pointed_to_type, prefix);
+           write_user_func_for_structure_ptr (d->of, pointed_to_type, w);
        }
       else if (union_or_struct_p (fld_type))
-       write_user_func_for_structure_body (fld_type, prefix, d);
+       write_user_func_for_structure_body (fld_type, w->prefix, d);
     }
 }
 
@@ -3791,7 +3832,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
   oprintf (d.of, "}\n");
 
   if (orig_s->kind == TYPE_USER_STRUCT)
-    write_user_marking_functions (orig_s, wtd->prefix, &d);
+    write_user_marking_functions (orig_s, wtd, &d);
 }
 
 
@@ -3969,14 +4010,14 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
 static const struct write_types_data ggc_wtd = {
   "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL,
   "GC marker procedures.  ",
-  FALSE
+  FALSE, WTK_GGC
 };
 
 static const struct write_types_data pch_wtd = {
   "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object",
   "gt_pch_note_reorder",
   "PCH type-walking procedures.  ",
-  TRUE
+  TRUE, WTK_PCH
 };
 
 /* Write out the local pointer-walking routines.  */
index 345a545..6369001 100644 (file)
@@ -127,7 +127,15 @@ extern type_p structures;
 extern type_p param_structs;
 extern pair_p variables;
 
+/* An enum for distinguishing GGC vs PCH.  */
 
+enum write_types_kinds
+{
+  WTK_GGC,
+  WTK_PCH,
+
+  NUM_WTK
+};
 
 /* Discrimating kind of types we can understand.  */
 
@@ -302,6 +310,10 @@ struct type {
       type_p first_subclass;
       /* The next in that list.  */
       type_p next_sibling_class;
+
+      /* Have we already written ggc/pch user func for ptr to this?
+        (in write_user_func_for_structure_ptr).  */
+      bool wrote_user_func_for_ptr[NUM_WTK];
     } s;
 
     /* when TYPE_SCALAR: */