summaryrefslogtreecommitdiff
path: root/gcc/gengtype.c
diff options
context:
space:
mode:
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>2014-05-13 15:17:34 +0000
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>2014-05-13 15:17:34 +0000
commit782fb91549b1b0dd149e81db8a0f74276133f265 (patch)
tree8bffdaf2d5d6487778cb3b5ae5abfe405d0963d4 /gcc/gengtype.c
parentb988436fafc82cb15cabb125d8fd66839148c4f1 (diff)
downloadgcc-782fb91549b1b0dd149e81db8a0f74276133f265.tar.gz
gengtype: Support explicit pointers in template arguments
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
Diffstat (limited to 'gcc/gengtype.c')
-rw-r--r--gcc/gengtype.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b6e171822c8..21da84b77d9 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -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;
+}
/* 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. */