Patchwork [v2,2/4] Parse base classes for GTY-marked types

login
register
mail settings
Submitter David Malcolm
Date Sept. 24, 2013, 5:49 p.m.
Message ID <1380044971-11810-3-git-send-email-dmalcolm@redhat.com>
Download mbox | patch
Permalink /patch/277554/
State New
Headers show

Comments

David Malcolm - Sept. 24, 2013, 5:49 p.m.
Extend gengtype (and gtype.state reading/writing) so that it is able to
parse base classes in simple cases, and only attempt to do it for
GTY-marked types.

	* gengtype-parse.c (require_without_advance): New.
	(type): For GTY-marked types that are not GTY((user)), parse any
	base classes, requiring them to be single-inheritance, and not
	be templates.  For non-GTY-marked types and GTY((user)),
	continue to skip over any C++ inheritance specification.
	* gengtype-state.c (state_writer::write_state_struct_type):
	Write base class of type (if any).
	(read_state_struct_type): Read base class of type (if any).
	* gengtype.c (new_structure): Add a "base_class" parameter.
	(create_optional_field_): Update for new parameter to
	new_structure.
	(adjust_field_rtx_def): Likewise.
	(adjust_field_tree_exp): Likewise.
	* gengtype.h (struct type): Add "base_class" field to the s
	union field.
	(new_structure): Add "base" parameter.
---
 gcc/gengtype-parse.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
 gcc/gengtype-state.c |  2 ++
 gcc/gengtype.c       | 15 ++++++++-------
 gcc/gengtype.h       |  4 +++-
 4 files changed, 58 insertions(+), 13 deletions(-)
Jeff Law - Oct. 15, 2013, 6:45 p.m.
On 09/24/13 11:49, David Malcolm wrote:
> Extend gengtype (and gtype.state reading/writing) so that it is able to
> parse base classes in simple cases, and only attempt to do it for
> GTY-marked types.
>
> 	* gengtype-parse.c (require_without_advance): New.
> 	(type): For GTY-marked types that are not GTY((user)), parse any
> 	base classes, requiring them to be single-inheritance, and not
> 	be templates.  For non-GTY-marked types and GTY((user)),
> 	continue to skip over any C++ inheritance specification.
> 	* gengtype-state.c (state_writer::write_state_struct_type):
> 	Write base class of type (if any).
> 	(read_state_struct_type): Read base class of type (if any).
> 	* gengtype.c (new_structure): Add a "base_class" parameter.
> 	(create_optional_field_): Update for new parameter to
> 	new_structure.
> 	(adjust_field_rtx_def): Likewise.
> 	(adjust_field_tree_exp): Likewise.
> 	* gengtype.h (struct type): Add "base_class" field to the s
> 	union field.
> 	(new_structure): Add "base" parameter.
This is OK.

jeff
David Malcolm - Oct. 24, 2013, 2:11 a.m.
On Tue, 2013-10-15 at 12:45 -0600, Jeff Law wrote:
> On 09/24/13 11:49, David Malcolm wrote:
> > Extend gengtype (and gtype.state reading/writing) so that it is able to
> > parse base classes in simple cases, and only attempt to do it for
> > GTY-marked types.
> >
> > 	* gengtype-parse.c (require_without_advance): New.
> > 	(type): For GTY-marked types that are not GTY((user)), parse any
> > 	base classes, requiring them to be single-inheritance, and not
> > 	be templates.  For non-GTY-marked types and GTY((user)),
> > 	continue to skip over any C++ inheritance specification.
> > 	* gengtype-state.c (state_writer::write_state_struct_type):
> > 	Write base class of type (if any).
> > 	(read_state_struct_type): Read base class of type (if any).
> > 	* gengtype.c (new_structure): Add a "base_class" parameter.
> > 	(create_optional_field_): Update for new parameter to
> > 	new_structure.
> > 	(adjust_field_rtx_def): Likewise.
> > 	(adjust_field_tree_exp): Likewise.
> > 	* gengtype.h (struct type): Add "base_class" field to the s
> > 	union field.
> > 	(new_structure): Add "base" parameter.
> This is OK.
Sorry about belated response.

I've now committed this to trunk as r204003, having doublechecked the
bootstrap and testsuites.

Thanks
Dave

Patch

diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index e5204c1..31d493a 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -165,6 +165,21 @@  require (int t)
   return v;
 }
 
+/* As per require, but do not advance.  */
+static const char *
+require_without_advance (int t)
+{
+  int u = token ();
+  const char *v = T.value;
+  if (u != t)
+    {
+      parse_error ("expected %s, have %s",
+		   print_token (t, 0), print_token (u, v));
+      return 0;
+    }
+  return v;
+}
+
 /* If the next token does not have one of the codes T1 or T2, report a
    parse error; otherwise return the token's value.  */
 static const char *
@@ -829,6 +844,7 @@  type (options_p *optsp, bool nested)
     case STRUCT:
     case UNION:
       {
+	type_p base_class = NULL;
 	options_p opts = 0;
 	/* GTY annotations follow attribute syntax
 	   GTY_BEFORE_ID is for union/struct declarations
@@ -868,16 +884,39 @@  type (options_p *optsp, bool nested)
 	    opts = gtymarker_opt ();
 	  }
 
+	bool is_user_gty = opts_have (opts, "user");
+
 	if (token () == ':')
 	  {
-	    /* Skip over C++ inheritance specification.  */
-	    while (token () != '{')
-	      advance ();
+	    if (is_gty && !is_user_gty)
+	      {
+		/* For GTY-marked types that are not "user", parse some C++
+		   inheritance specifications.
+		   We require single-inheritance from a non-template type.  */
+		advance ();
+		const char *basename = require (ID);
+		/* This may be either an access specifier, or the base name.  */
+		if (0 == strcmp (basename, "public")
+		    || 0 == strcmp (basename, "protected")
+		    || 0 == strcmp (basename, "private"))
+		  basename = require (ID);
+		base_class = find_structure (basename, TYPE_STRUCT);
+		if (!base_class)
+		  parse_error ("unrecognized base class: %s", basename);
+		require_without_advance ('{');
+	      }
+	    else
+	      {
+		/* For types lacking GTY-markings, skip over C++ inheritance
+		   specification (and thus avoid having to parse e.g. template
+		   types).  */
+		while (token () != '{')
+		  advance ();
+	      }
 	  }
 
 	if (is_gty)
 	  {
-	    bool is_user_gty = opts_have (opts, "user");
 	    if (token () == '{')
 	      {
 		pair_p fields;
@@ -900,7 +939,8 @@  type (options_p *optsp, bool nested)
 		    return create_user_defined_type (s, &lexer_line);
 		  }
 
-		return new_structure (s, kind, &lexer_line, fields, opts);
+		return new_structure (s, kind, &lexer_line, fields, opts,
+				      base_class);
 	      }
 	  }
 	else if (token () == '{')
diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c
index ba7948a..54e4287 100644
--- a/gcc/gengtype-state.c
+++ b/gcc/gengtype-state.c
@@ -957,6 +957,7 @@  state_writer::write_state_struct_type (type_p current)
 {
   write_state_struct_union_type (current, "struct");
   write_state_type (current->u.s.lang_struct);
+  write_state_type (current->u.s.base_class);
 }
 
 /* Write a GTY user-defined struct type.  */
@@ -1613,6 +1614,7 @@  read_state_struct_type (type_p type)
       read_state_options (&(type->u.s.opt));
       read_state_lang_bitmap (&(type->u.s.bitmap));
       read_state_type (&(type->u.s.lang_struct));
+      read_state_type (&(type->u.s.base_class));
     }
   else
     {
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index c3dffe8..a6dc221 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -674,7 +674,7 @@  resolve_typedef (const char *s, struct fileloc *pos)
 
 type_p
 new_structure (const char *name, enum typekind kind, struct fileloc *pos,
-	       pair_p fields, options_p o)
+	       pair_p fields, options_p o, type_p base_class)
 {
   type_p si;
   type_p s = NULL;
@@ -748,6 +748,7 @@  new_structure (const char *name, enum typekind kind, struct fileloc *pos,
   s->u.s.bitmap = bitmap;
   if (s->u.s.lang_struct)
     s->u.s.lang_struct->u.s.bitmap |= bitmap;
+  s->u.s.base_class = base_class;
 
   return s;
 }
@@ -976,7 +977,7 @@  create_optional_field_ (pair_p next, type_p type, const char *name,
     create_string_option (union_fields->opt, "tag", "1");
   union_type = 
     new_structure (xasprintf ("%s_%d", "fake_union", id++), TYPE_UNION,
-                   &lexer_line, union_fields, NULL);
+                   &lexer_line, union_fields, NULL, NULL);
 
   /* Create the field and give it the new fake union type.  Add a "desc"
      tag that specifies the condition under which the field is valid.  */
@@ -1167,7 +1168,7 @@  adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
 	    create_string_option (nodot, "tag", note_insn_name[c]);
       }
     note_union_tp = new_structure ("rtx_def_note_subunion", TYPE_UNION,
-				   &lexer_line, note_flds, NULL);
+				   &lexer_line, note_flds, NULL, NULL);
   }
   /* Create a type to represent the various forms of SYMBOL_REF_DATA.  */
   {
@@ -1177,7 +1178,7 @@  adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
     sym_flds = create_field (sym_flds, constant_tp, "rt_constant");
     sym_flds->opt = create_string_option (nodot, "tag", "1");
     symbol_union_tp = new_structure ("rtx_def_symbol_subunion", TYPE_UNION,
-				     &lexer_line, sym_flds, NULL);
+				     &lexer_line, sym_flds, NULL, NULL);
   }
   for (i = 0; i < NUM_RTX_CODE; i++)
     {
@@ -1319,7 +1320,7 @@  adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
 
       sname = xasprintf ("rtx_def_%s", rtx_name[i]);
       substruct = new_structure (sname, TYPE_STRUCT, &lexer_line, subfields,
-				 NULL);
+				 NULL, NULL);
 
       ftag = xstrdup (rtx_name[i]);
       for (nmindex = 0; nmindex < strlen (ftag); nmindex++)
@@ -1328,7 +1329,7 @@  adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
       flds->opt = create_string_option (nodot, "tag", ftag);
     }
   return new_structure ("rtx_def_subunion", TYPE_UNION, &lexer_line, flds,
-			nodot);
+			nodot, NULL);
 }
 
 /* Handle `special("tree_exp")'.  This is a special case for
@@ -1358,7 +1359,7 @@  adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED)
   flds->opt = create_string_option (flds->opt, "default", "");
 
   return new_structure ("tree_exp_subunion", TYPE_UNION, &lexer_line, flds,
-			nodot);
+			nodot, NULL);
 }
 
 /* Perform any special processing on a type T, about to become the type
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index f71ad97..06ebbed 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -291,6 +291,8 @@  struct type {
          field the original TYPE_LANG_STRUCT type.  This is a dirty
          trick, see the new_structure function for details.  */
       type_p lang_struct;
+
+      type_p base_class; /* the parent class, if any.  */
     } s;
 
     /* when TYPE_SCALAR: */
@@ -424,7 +426,7 @@  extern void do_scalar_typedef (const char *s, struct fileloc *pos);
 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);
+			     options_p o, type_p base);
 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);