diff options
Diffstat (limited to 'gcc/gengtype.c')
-rw-r--r-- | gcc/gengtype.c | 69 |
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. */ |