Part 2 of the VEC C++ conversion.  This patch implements the gengtype
changes.

I extended gengtype to understand templated types.  These changes are
not as ugly as I thought they would be.  Gengtype has some hardwired
knowledge of VEC_*, which I renamed to vec_t.  I'm not even sure why
gengtype needs to care about vec_t in this way, but I was looking for
minimal changes, so I just did it.

The other change is more generic.  It allows gengtype to deal with
templated types.  There is a new function (filter_type_name) that
recognizes C++ special characters '<', '>' and ':'.  It turns them
into '_'.  This way, gengtype can generate a valid identifier for the
pre-processor.  It only does this in contexts where it needs a
pre-processor identifier.  For everything else, it emits the type
directly.  So, the functions emitted in gt-*.h files have proper
template type references.

2012-05-23   Diego Novillo  <dnovi...@google.com>

        * gengtype-lex.l (DEF_VEC_ALLOC_[IOP]/{EOID}): Remove.
        * gengtype-parse.c (token_names): Remove DEF_VEC_ALLOC_[IOP].
        (typedef_name): Emit vec_t<C1> instead of VEC_C1_C2.
        (def_vec_alloc): Remove.  Update all callers.
        * gengtype.c (filter_type_name): New.
        (output_mangled_typename): Call it.
        (write_func_for_structure): Likewise.
        (write_types): Likewise.
        (write_root): Likewise.
        (write_typed_alloc_def): Likewise.
        (note_def_vec): Emit vec_t<TYPE_NAME> instead of VEC_TYPE_NAME_base.
        (note_def_vec_alloc): Remove.
        * gengtype.h (note_def_vec_alloc): Remove.
        (DEFVEC_ALLOC): Remove token code.

diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index a71cce0..edfd4a1 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -100,10 +100,6 @@ EOID       [^[:alnum:]_]
   BEGIN(in_struct);
   return DEFVEC_I;
 }
-^{HWS}DEF_VEC_ALLOC_[IOP]/{EOID} {
-  BEGIN(in_struct);
-  return DEFVEC_ALLOC;
-}
 }
 
 <in_struct>{
diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index 89f14e8..4fc2b07 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -79,7 +79,6 @@ static const char *const token_names[] = {
   "VEC",
   "DEF_VEC_[OP]",
   "DEF_VEC_I",
-  "DEF_VEC_ALLOC_[IOP]",
   "...",
   "ptr_alias",
   "nested_ptr",
@@ -227,7 +226,7 @@ typedef_name (void)
       require (',');
       c2 = require (ID);
       require (')');
-      r = concat ("VEC_", c1, "_", c2, (char *) 0);
+      r = concat ("vec_t<", c1, ">", (char *) 0);
       free (CONST_CAST (char *, c1));
       free (CONST_CAST (char *, c2));
       return r;
@@ -916,31 +915,6 @@ def_vec (void)
     return;
 
   note_def_vec (type, is_scalar, &lexer_line);
-  note_def_vec_alloc (type, "none", &lexer_line);
-}
-
-/* Definition of an allocation strategy for a VEC structure:
-
-   'DEF_VEC_ALLOC_[IPO]' '(' id ',' id ')' ';'
-
-   For purposes of gengtype, this just declares a wrapper structure.  */
-static void
-def_vec_alloc (void)
-{
-  const char *type, *astrat;
-
-  require (DEFVEC_ALLOC);
-  require ('(');
-  type = require2 (ID, SCALAR);
-  require (',');
-  astrat = require (ID);
-  require (')');
-  require (';');
-
-  if (!type || !astrat)
-    return;
-
-  note_def_vec_alloc (type, astrat, &lexer_line);
 }
 
 /* Parse the file FNAME for GC-relevant declarations and definitions.
@@ -972,10 +946,6 @@ parse_file (const char *fname)
          def_vec ();
          break;
 
-       case DEFVEC_ALLOC:
-         def_vec_alloc ();
-         break;
-
        case EOF_TOKEN:
          goto eof;
 
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 814d9e0..82dca36 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -2295,6 +2295,34 @@ struct walk_type_data
   int loopcounter;
 };
 
+
+/* Given a string TYPE_NAME, representing a C++ typename, return a valid
+   pre-processor identifier to use in a #define directive.  This replaces
+   special characters used in C++ identifiers like '>', '<' and ':' with
+   '_'.
+
+   If no C++ special characters are found in TYPE_NAME, return
+   TYPE_NAME.  Otherwise, return a copy of TYPE_NAME with the special
+   characters replaced with '_'.  In this case, the caller is
+   responsible for freeing the allocated string.  */
+
+static const char *
+filter_type_name (const char *type_name)
+{
+  if (strchr (type_name, '<') || strchr (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] = '_';
+      return s;
+    }
+  else
+    return type_name;
+}
+
+
 /* Print a mangled name representing T to OF.  */
 
 static void
@@ -2321,8 +2349,13 @@ output_mangled_typename (outf_p of, const_type_p t)
       case TYPE_STRUCT:
       case TYPE_UNION:
       case TYPE_LANG_STRUCT:
-       oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag),
-                t->u.s.tag);
+       {
+         const char *id_for_tag = filter_type_name (t->u.s.tag);
+         oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag),
+                  id_for_tag);
+         if (id_for_tag != t->u.s.tag)
+           free (CONST_CAST(char *, id_for_tag));
+       }
        break;
       case TYPE_PARAM_STRUCT:
        {
@@ -3099,7 +3132,12 @@ write_func_for_structure (type_p orig_s, type_p s, 
type_p *param,
   oprintf (d.of, "\n");
   oprintf (d.of, "void\n");
   if (param == NULL)
-    oprintf (d.of, "gt_%sx_%s", wtd->prefix, orig_s->u.s.tag);
+    {
+      const char *id_for_tag = filter_type_name (orig_s->u.s.tag);
+      oprintf (d.of, "gt_%sx_%s", wtd->prefix, id_for_tag);
+      if (id_for_tag != orig_s->u.s.tag)
+       free (CONST_CAST(char *, id_for_tag));
+    }
   else
     {
       oprintf (d.of, "gt_%s_", wtd->prefix);
@@ -3230,16 +3268,19 @@ write_types (outf_p output_header, type_p structures, 
type_p param_structs,
     if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
       {
        options_p opt;
+       const char *s_id_for_tag;
 
        if (s->gc_used == GC_MAYBE_POINTED_TO && s->u.s.line.file == NULL)
          continue;
 
+       s_id_for_tag = filter_type_name (s->u.s.tag);
+
        oprintf (output_header, "#define gt_%s_", wtd->prefix);
        output_mangled_typename (output_header, s);
        oprintf (output_header, "(X) do { \\\n");
        oprintf (output_header,
                 "  if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix,
-                s->u.s.tag);
+                s_id_for_tag);
        oprintf (output_header, "  } while (0)\n");
 
        for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -3249,9 +3290,14 @@ write_types (outf_p output_header, type_p structures, 
type_p param_structs,
              const_type_p const t = (const_type_p) opt->info.type;
              if (t->kind == TYPE_STRUCT
                  || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT)
-               oprintf (output_header,
-                        "#define gt_%sx_%s gt_%sx_%s\n",
-                        wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag);
+               {
+                 const char *t_id_for_tag = filter_type_name (t->u.s.tag);
+                 oprintf (output_header,
+                          "#define gt_%sx_%s gt_%sx_%s\n",
+                          wtd->prefix, s->u.s.tag, wtd->prefix, t_id_for_tag);
+                 if (t_id_for_tag != t->u.s.tag)
+                   free (CONST_CAST(char *, t_id_for_tag));
+               }
              else
                error_at_line (&s->u.s.line,
                               "structure alias is not a structure");
@@ -3263,7 +3309,10 @@ write_types (outf_p output_header, type_p structures, 
type_p param_structs,
        /* Declare the marker procedure only once.  */
        oprintf (output_header,
                 "extern void gt_%sx_%s (void *);\n",
-                wtd->prefix, s->u.s.tag);
+                wtd->prefix, s_id_for_tag);
+
+       if (s_id_for_tag != s->u.s.tag)
+         free (CONST_CAST(char *, s_id_for_tag));
 
        if (s->u.s.line.file == NULL)
          {
@@ -3867,11 +3916,14 @@ write_root (outf_p f, pair_p v, type_p type, const char 
*name, int has_length,
 
        if (!has_length && UNION_OR_STRUCT_P (tp))
          {
-           oprintf (f, "    &gt_ggc_mx_%s,\n", tp->u.s.tag);
+           const char *id_for_tag = filter_type_name (tp->u.s.tag);
+           oprintf (f, "    &gt_ggc_mx_%s,\n", id_for_tag);
            if (emit_pch)
-             oprintf (f, "    &gt_pch_nx_%s", tp->u.s.tag);
+             oprintf (f, "    &gt_pch_nx_%s", id_for_tag);
            else
              oprintf (f, "    NULL");
+           if (id_for_tag != tp->u.s.tag)
+             free (CONST_CAST(char *, id_for_tag));
          }
        else if (!has_length && tp->kind == TYPE_PARAM_STRUCT)
          {
@@ -4270,7 +4322,7 @@ note_def_vec (const char *type_name, bool is_scalar, 
struct fileloc *pos)
   pair_p fields;
   type_p t;
   options_p o;
-  const char *name = concat ("VEC_", type_name, "_base", (char *) 0);
+  const char *name = concat ("vec_t<", type_name, ">", (char *) 0);
 
   if (is_scalar)
     {
@@ -4289,25 +4341,6 @@ note_def_vec (const char *type_name, bool is_scalar, 
struct fileloc *pos)
   do_typedef (name, new_structure (name, 0, pos, fields, 0), pos);
 }
 
-/* Record the definition of an allocation-specific VEC structure, as if
-   we had expanded the macros in vec.h:
-
-   typedef struct VEC_<type>_<astrat> {
-     VEC_<type>_base base;
-   } VEC_<type>_<astrat>;
-*/
-void
-note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos)
-{
-  const char *astratname = concat ("VEC_", type, "_", astrat, (char *) 0);
-  const char *basename = concat ("VEC_", type, "_base", (char *) 0);
-
-  pair_p field = create_field_at (0, resolve_typedef (basename, pos),
-                                 "base", 0, pos);
-
-  do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
-}
-
 /* Returns the specifier keyword for a string or union type S, empty string
    otherwise.  */
 
@@ -4355,8 +4388,10 @@ write_typed_alloc_def (outf_p f,
   bool two_args = variable_size && (quantity == vector);
   bool third_arg = ((zone == specific_zone)
                    && (variable_size || (quantity == vector)));
+  const char *type_name_as_id;
   gcc_assert (f != NULL);
-  oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name);
+  type_name_as_id = filter_type_name (type_name);
+  oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
   oprintf (f, "(%s%s%s%s%s) ",
           (variable_size ? "SIZE" : ""),
           (two_args ? ", " : ""),
@@ -4373,6 +4408,8 @@ write_typed_alloc_def (outf_p f,
   if (quantity == vector)
     oprintf (f, ", n");
   oprintf (f, " MEM_STAT_INFO)))\n");
+  if (type_name_as_id != type_name)
+    free (CONST_CAST(char *, type_name_as_id));
 }
 
 /* Writes a typed allocator definition into output F for a struct or
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 964cc31..cc489e0 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -422,8 +422,6 @@ extern void note_variable (const char *s, type_p t, 
options_p o,
                           struct fileloc *pos);
 extern void note_def_vec (const char *type_name, bool is_scalar,
                          struct fileloc *pos);
-extern void note_def_vec_alloc (const char *type, const char *astrat,
-                               struct fileloc *pos);
 
 /* Lexer and parser routines.  */
 extern int yylex (const char **yylval);
@@ -451,7 +449,6 @@ enum
     VEC_TOKEN,
     DEFVEC_OP,
     DEFVEC_I,
-    DEFVEC_ALLOC,
     ELLIPSIS,
     PTR_ALIAS,
     NESTED_PTR,

--
This patch is available for review at http://codereview.appspot.com/6236043

Reply via email to