diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index fd80906..4c316a3 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -116,7 +116,6 @@ CXX_KEYWORD inline|public:|private:|protected:|template|operator|friend
     return IGNORABLE_CXX_KEYWORD;
 }
 "GTY"/{EOID}			{ return GTY_TOKEN; }
-"VEC"/{EOID}			{ return VEC_TOKEN; }
 "union"/{EOID}			{ return UNION; }
 "struct"/{EOID}			{ return STRUCT; }
 "class"/{EOID}			{ return STRUCT; }
@@ -163,7 +162,7 @@ CXX_KEYWORD inline|public:|private:|protected:|template|operator|friend
 }
 
 "..."				{ return ELLIPSIS; }
-[(){},*:<>;=%|+-]		{ return yytext[0]; }
+[(){},*:<>;=%|+\!\?\.-]		{ return yytext[0]; }
 
    /* ignore pp-directives */
 ^{HWS}"#"{HWS}[a-z_]+[^\n]*\n   {lexer_line.line++;}
diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index 5737a15..0b46661 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -76,7 +76,6 @@ static const char *const token_names[] = {
   "union",
   "struct",
   "enum",
-  "VEC",
   "...",
   "ptr_alias",
   "nested_ptr",
@@ -245,31 +244,12 @@ require_template_declaration (const char *tmpl_name)
 }
 
 
-/* typedef_name: either an ID, or VEC(x,y), or a template type
-   specification of the form ID<t1,t2,...,tn>.
-
-   FIXME cxx-conversion.  VEC(x,y) is currently translated to the
-   template 'vec_t<x>'.  This is to support the transition to C++ and
-   avoid re-writing all the 'VEC(x,y)' declarations in the code.  This
-   needs to be fixed when the branch is merged into trunk.  */
+/* typedef_name: either an ID, or a template type
+   specification of the form ID<t1,t2,...,tn>.  */
 
 static const char *
 typedef_name (void)
 {
-  if (token () == VEC_TOKEN)
-    {
-      const char *c1, *r;
-      advance ();
-      require ('(');
-      c1 = require2 (ID, SCALAR);
-      require (',');
-      require (ID);
-      require (')');
-      r = concat ("vec_t<", c1, ">", (char *) 0);
-      free (CONST_CAST (char *, c1));
-      return r;
-    }
-
   const char *id = require (ID);
   if (token () == '<')
     return require_template_declaration (id);
@@ -826,7 +806,6 @@ type (options_p *optsp, bool nested)
       return create_scalar_type (s);
 
     case ID:
-    case VEC_TOKEN:
       s = typedef_name ();
       return resolve_typedef (s, &lexer_line);
 
@@ -907,6 +886,7 @@ type (options_p *optsp, bool nested)
 		    fields = NULL;
 		    kind = TYPE_USER_STRUCT;
 		    consume_balanced ('{', '}');
+		    return create_user_defined_type (s, &lexer_line);
 		  }
 
 		return new_structure (s, kind, &lexer_line, fields, opts);
diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c
index e3317ec..8607ceb 100644
--- a/gcc/gengtype-state.c
+++ b/gcc/gengtype-state.c
@@ -52,6 +52,7 @@ type_lineloc (const_type_p ty)
     case TYPE_UNION:
     case TYPE_LANG_STRUCT:
     case TYPE_USER_STRUCT:
+    case TYPE_UNDEFINED:
       return CONST_CAST (struct fileloc*, &ty->u.s.line);
     case TYPE_PARAM_STRUCT:
       return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
@@ -770,6 +771,23 @@ write_state_string_type (type_p current)
     fatal ("Unexpected type in write_state_string_type");
 }
 
+/* Write an undefined type.  */
+static void
+write_state_undefined_type (type_p current)
+{
+  DBGPRINTF ("undefined type @ %p #%d '%s'", (void *) current,
+	     current->state_number, current->u.s.tag);
+  fprintf (state_file, "undefined ");
+  gcc_assert (current->gc_used == GC_UNUSED);
+  write_state_common_type_content (current);
+  if (current->u.s.tag != NULL)
+    write_state_a_string (current->u.s.tag);
+  else
+    fprintf (state_file, "nil");
+
+  write_state_fileloc (type_lineloc (current));
+}
+
 
 /* Common code to write structure like types.  */
 static void
@@ -963,6 +981,9 @@ write_state_type (type_p current)
 	{
 	case TYPE_NONE:
 	  gcc_unreachable ();
+	case TYPE_UNDEFINED:
+	  write_state_undefined_type (current);
+	  break;
 	case TYPE_STRUCT:
 	  write_state_struct_type (current);
 	  break;
@@ -1345,6 +1366,40 @@ read_state_lang_bitmap (lang_bitmap *bitmap)
 }
 
 
+/* Read an undefined type.  */
+static void
+read_state_undefined_type (type_p type)
+{
+  struct state_token_st *t0;
+
+  type->kind = TYPE_UNDEFINED;
+  read_state_common_type_content (type);
+  t0 = peek_state_token (0);
+  if (state_token_kind (t0) == STOK_STRING)
+    {
+      if (state_token_is_name (t0, "nil"))
+	{
+	  type->u.s.tag = NULL;
+	  DBGPRINTF ("read anonymous undefined type @%p #%d",
+		     (void *) type, type->state_number);
+	}
+      else
+	{
+	  type->u.s.tag = xstrdup (t0->stok_un.stok_string);
+	  DBGPRINTF ("read undefined type @%p #%d '%s'",
+		     (void *) type, type->state_number, type->u.s.tag);
+	}
+
+      next_state_tokens (1);
+      read_state_fileloc (&(type->u.s.line));
+    }
+  else
+    {
+      fatal_reading_state (t0, "Bad tag in undefined type");
+    }
+}
+
+
 /* Read a GTY-ed struct type.  */
 static void
 read_state_struct_type (type_p type)
@@ -1673,6 +1728,12 @@ read_state_type (type_p *current)
 	      next_state_tokens (1);
 	      read_state_string_type (current);
 	    }
+	  else if (state_token_is_name (t0, "undefined"))
+	    {
+	      *current = XCNEW (struct type);
+	      next_state_tokens (1);
+	      read_state_undefined_type (*current);
+	    }
 	  else if (state_token_is_name (t0, "struct"))
 	    {
 	      *current = XCNEW (struct type);
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b9fbd96..b3f73fe 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -171,13 +171,15 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
   int nb_types = 0, nb_scalar = 0, nb_string = 0;
   int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0;
   int nb_lang_struct = 0, nb_param_struct = 0;
-  int nb_user_struct = 0;
+  int nb_user_struct = 0, nb_undefined = 0;
   type_p p = NULL;
   for (p = t; p; p = p->next)
     {
       nb_types++;
       switch (p->kind)
 	{
+	case TYPE_UNDEFINED:
+	  nb_undefined++;
 	case TYPE_SCALAR:
 	  nb_scalar++;
 	  break;
@@ -205,7 +207,7 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
 	case TYPE_PARAM_STRUCT:
 	  nb_param_struct++;
 	  break;
-	default:
+	case TYPE_NONE:
 	  gcc_unreachable ();
 	}
     }
@@ -222,6 +224,8 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
 	     nb_lang_struct, nb_param_struct);
   if (nb_user_struct > 0)
     fprintf (stderr, "@@%%@@ %d user_structs\n", nb_user_struct);
+  if (nb_undefined > 0)
+    fprintf (stderr, "@@%%@@ %d undefined types\n", nb_undefined);
   fprintf (stderr, "\n");
 }
 #endif /* ENABLE_CHECKING */
@@ -553,7 +557,7 @@ do_scalar_typedef (const char *s, struct fileloc *pos)
 
 /* Define TYPE_NAME to be a user defined type at location POS.  */
 
-static type_p
+type_p
 create_user_defined_type (const char *type_name, struct fileloc *pos)
 {
   type_p ty = find_structure (type_name, TYPE_USER_STRUCT);
@@ -595,20 +599,58 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
 }
 
 
-/* Return the type previously defined for S.  Use POS to report errors.  */
+/* Given a typedef name S, return its associated type.  Return NULL if
+   S is not a registered type name.  */
 
-type_p
-resolve_typedef (const char *s, struct fileloc *pos)
+static type_p
+type_for_name (const char *s)
 {
   pair_p p;
   for (p = typedefs; p != NULL; p = p->next)
     if (strcmp (p->name, s) == 0)
       return p->type;
+  return NULL;
+}
+
+
+/* Create an undefined type with name S and location POS.  Return the
+   newly created type.  */
+
+static type_p
+create_undefined_type (const char *s, struct fileloc *pos)
+{
+  type_p ty = find_structure (s, TYPE_UNDEFINED);
+  ty->u.s.line = *pos;
+  ty->u.s.bitmap = get_lang_bitmap (pos->file);
+  do_typedef (s, ty, pos);
+  return ty;
+}
+
+
+/* Return the type previously defined for S.  Use POS to report errors.  */
 
-  /* If we did not find a typedef registered, assume this is a name
-     for a user-defined type which will need to provide its own
-     marking functions.  */
-  return create_user_defined_type (s, pos);
+type_p
+resolve_typedef (const char *s, struct fileloc *pos)
+{
+  bool is_template_instance = (strchr (s, '<') != NULL);
+  type_p p = type_for_name (s);
+
+  /* If we did not find a typedef registered, generate a TYPE_UNDEFINED
+     type for regular type identifiers.  If the type identifier S is a
+     template instantiation, however, we treat it as a user defined
+     type.
+
+     FIXME, this is actually a limitation in gengtype.  Supporting
+     template types and their instances would require keeping separate
+     track of the basic types definition and its instances.  This
+     essentially forces all template classes in GC to be marked
+     GTY((user)).  */
+  if (!p)
+    p = (is_template_instance)
+	? create_user_defined_type (s, pos)
+	: create_undefined_type (s, pos);
+
+  return p;
 }
 
 
@@ -707,7 +749,7 @@ find_structure (const char *name, enum typekind kind)
   type_p s;
   bool isunion = (kind == TYPE_UNION);
 
-  gcc_assert (union_or_struct_p (kind));
+  gcc_assert (kind == TYPE_UNDEFINED || union_or_struct_p (kind));
 
   for (s = structures; s != NULL; s = s->next)
     if (strcmp (name, s->u.s.tag) == 0 && UNION_P (s) == isunion)
@@ -1397,7 +1439,8 @@ adjust_field_type (type_p t, options_p opt)
 }
 
 
-static void set_gc_used_type (type_p, enum gc_used_enum, type_p *);
+static void set_gc_used_type (type_p, enum gc_used_enum, type_p *,
+			      bool = false);
 static void set_gc_used (pair_p);
 
 /* Handle OPT for set_gc_used_type.  */
@@ -1427,9 +1470,31 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
 }
 
 
-/* Set the gc_used field of T to LEVEL, and handle the types it references.  */
+/* Set the gc_used field of T to LEVEL, and handle the types it references.
+
+   If ALLOWED_UNDEFINED_TYPES is true, types of kind TYPE_UNDEFINED
+   are set to GC_UNUSED.  Otherwise, an error is emitted for
+   TYPE_UNDEFINED types.  This is used to support user-defined
+   template types with non-type arguments.
+
+   For instance, when we parse a template type with enum arguments
+   (e.g. MyType<AnotherType, EnumValue>), the parser created two
+   artificial fields for 'MyType', one for 'AnotherType', the other
+   one for 'EnumValue'.
+
+   At the time that we parse this type we don't know that 'EnumValue'
+   is really an enum value, so the parser creates a TYPE_UNDEFINED
+   type for it.  Since 'EnumValue' is never resolved to a known
+   structure, it will stay with TYPE_UNDEFINED.
+
+   Since 'MyType' is a TYPE_USER_STRUCT, we can simply ignore
+   'EnumValue'.  Generating marking code for it would cause
+   compilation failures since the marking routines assumes that
+   'EnumValue' is a type.  */
+
 static void
-set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
+set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM],
+		  bool allow_undefined_types)
 {
   if (t->gc_used >= level)
     return;
@@ -1445,6 +1510,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
 	pair_p f;
 	int dummy;
 	type_p dummy2;
+	bool allow_undefined_field_types = (t->kind == TYPE_USER_STRUCT);
 
 	process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
 			    &dummy2);
@@ -1472,11 +1538,21 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
 	    else if (skip)
 	      ;			/* target type is not used through this field */
 	    else
-	      set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
+	      set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL,
+				allow_undefined_field_types);
 	  }
 	break;
       }
 
+    case TYPE_UNDEFINED:
+      if (level > GC_UNUSED)
+	{
+	  if (!allow_undefined_types)
+	    error_at_line (&t->u.s.line, "undefined type `%s'", t->u.s.tag);
+	  t->gc_used = GC_UNUSED;
+	}
+      break;
+
     case TYPE_POINTER:
       set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
       break;
@@ -2397,7 +2473,7 @@ 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] == ':')
+	if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ',')
 	  s[i] = '_';
       return s;
     }
@@ -2417,6 +2493,7 @@ output_mangled_typename (outf_p of, const_type_p t)
     switch (t->kind)
       {
       case TYPE_NONE:
+      case TYPE_UNDEFINED:
 	gcc_unreachable ();
 	break;
       case TYPE_POINTER:
@@ -3042,7 +3119,8 @@ walk_type (type_p t, struct walk_type_data *d)
       d->process_field (t, d);
       break;
 
-    default:
+    case TYPE_NONE:
+    case TYPE_UNDEFINED:
       gcc_unreachable ();
     }
 }
@@ -3059,6 +3137,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d)
   switch (f->kind)
     {
     case TYPE_NONE:
+    case TYPE_UNDEFINED:
       gcc_unreachable ();
     case TYPE_POINTER:
       oprintf (d->of, "%*s%s (%s%s", d->indent, "",
@@ -3265,7 +3344,6 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix)
     gcc_unreachable ();
 }
 
-
 /* 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.  */
@@ -3429,6 +3507,10 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
   oprintf (d.of, " *)x_p;\n");
   if (chain_next != NULL)
     {
+      /* TYPE_USER_STRUCTs should not occur here.  These structures
+	 are completely handled by user code.  */
+      gcc_assert (orig_s->kind != TYPE_USER_STRUCT);
+
       oprintf (d.of, "  ");
       write_type_decl (d.of, s);
       oprintf (d.of, " * xlimit = x;\n");
@@ -3760,7 +3842,9 @@ write_types_local_user_process_field (type_p f, const struct walk_type_data *d)
     case TYPE_SCALAR:
       break;
 
-    default:
+    case TYPE_ARRAY:
+    case TYPE_NONE:
+    case TYPE_UNDEFINED:
       gcc_unreachable ();
     }
 }
@@ -3843,7 +3927,9 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d)
     case TYPE_SCALAR:
       break;
 
-    default:
+    case TYPE_ARRAY:
+    case TYPE_NONE:
+    case TYPE_UNDEFINED:
       gcc_unreachable ();
     }
 }
@@ -4063,6 +4149,9 @@ contains_scalar_p (type_p t)
       return 0;
     case TYPE_ARRAY:
       return contains_scalar_p (t->u.a.p);
+    case TYPE_USER_STRUCT:
+      /* User-marked structures will typically contain pointers.  */
+      return 0;
     default:
       /* Could also check for structures that have no non-pointer
          fields, but there aren't enough of those to worry about.  */
@@ -4313,8 +4402,9 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
       break;
 
     case TYPE_USER_STRUCT:
-      write_root (f, v, type->u.a.p, name, has_length, line, if_marked,
-		  emit_pch);
+      error_at_line (line, "`%s' must be a pointer type, because it is "
+	             "a GC root and its type is marked with GTY((user))",
+		     v->name);
       break;
 
     case TYPE_POINTER:
@@ -4384,7 +4474,11 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
     case TYPE_SCALAR:
       break;
 
-    default:
+    case TYPE_NONE:
+    case TYPE_UNDEFINED:
+    case TYPE_UNION:
+    case TYPE_LANG_STRUCT:
+    case TYPE_PARAM_STRUCT:
       error_at_line (line, "global `%s' is unimplemented type", name);
     }
 }
@@ -4880,7 +4974,9 @@ output_typename (outf_p of, const_type_p t)
 	output_typename (of, t->u.param_struct.stru);
 	break;
       }
-    default:
+    case TYPE_NONE:
+    case TYPE_UNDEFINED:
+    case TYPE_ARRAY:
       gcc_unreachable ();
     }
 }
@@ -4941,6 +5037,9 @@ dump_typekind (int indent, enum typekind kind)
     case TYPE_STRUCT:
       printf ("TYPE_STRUCT");
       break;
+    case TYPE_UNDEFINED:
+      printf ("TYPE_UNDEFINED");
+      break;
     case TYPE_USER_STRUCT:
       printf ("TYPE_USER_STRUCT");
       break;
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index e687e48..57a67fb 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -134,6 +134,9 @@ extern pair_p variables;
 
 enum typekind {
   TYPE_NONE=0,          /* Never used, so zeroed memory is invalid.  */
+  TYPE_UNDEFINED,	/* We have not yet seen a definition for this type.
+			   If a type is still undefined when generating code,
+			   an error will be generated.  */
   TYPE_SCALAR,          /* Scalar types like char.  */
   TYPE_STRING,          /* The string type.  */
   TYPE_STRUCT,          /* Type for GTY-ed structs.  */
@@ -423,6 +426,7 @@ extern type_p resolve_typedef (const char *s, struct fileloc *pos);
 extern type_p new_structure (const char *name, enum typekind kind,
 			     struct fileloc *pos, pair_p fields,
 			     options_p o);
+type_p create_user_defined_type (const char *, struct fileloc *);
 extern type_p find_structure (const char *s, enum typekind kind);
 extern type_p create_scalar_type (const char *name);
 extern type_p create_pointer (type_p t);
@@ -457,7 +461,6 @@ enum gty_token
   UNION,
   STRUCT,
   ENUM,
-  VEC_TOKEN,
   ELLIPSIS,
   PTR_ALIAS,
   NESTED_PTR,
