diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0561b7b594e3..a8a538b59408 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +2014-05-13 David Malcolm + + * 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. + 2014-05-13 Richard Sandiford * fold-const.c (optimize_bit_field_compare): Use wi:: operations diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c index 96f04764c581..0f11cec7c413 100644 --- a/gcc/gengtype-parse.c +++ b/gcc/gengtype-parse.c @@ -197,18 +197,19 @@ require2 (int t1, int t2) return v; } -/* If the next token does not have one of the codes T1, T2 or T3, report a +/* If the next token does not have one of the codes T1, T2, T3 or T4, report a parse error; otherwise return the token's value. */ static const char * -require3 (int t1, int t2, int t3) +require4 (int t1, int t2, int t3, int t4) { int u = token (); const char *v = advance (); - if (u != t1 && u != t2 && u != t3) + if (u != t1 && u != t2 && u != t3 && u != t4) { - parse_error ("expected %s, %s or %s, have %s", + parse_error ("expected %s, %s, %s or %s, have %s", print_token (t1, 0), print_token (t2, 0), - print_token (t3, 0), print_token (u, v)); + print_token (t3, 0), print_token (t4, 0), + print_token (u, v)); return 0; } return v; @@ -245,7 +246,9 @@ string_seq (void) /* The caller has detected a template declaration that starts with TMPL_NAME. Parse up to the closing '>'. This recognizes - simple template declarations of the form ID. + simple template declarations of the form ID, + potentially with a single level of indirection e.g. + ID. It does not try to parse anything more sophisticated than that. Returns the template declaration string "ID". */ @@ -254,6 +257,7 @@ static const char * require_template_declaration (const char *tmpl_name) { char *str; + int num_indirections = 0; /* Recognize the opening '<'. */ require ('<'); @@ -294,9 +298,21 @@ require_template_declaration (const char *tmpl_name) depth -= 1; continue; } - const char *id = require3 (SCALAR, ID, ','); + const char *id = require4 (SCALAR, ID, '*', ','); if (id == NULL) - id = ","; + { + if (T.code == '*') + { + id = "*"; + if (num_indirections++) + parse_error ("only one level of indirection is supported" + " in template arguments"); + } + else + id = ","; + } + else + num_indirections = 0; str = concat (str, id, (char *) 0); } return str; diff --git a/gcc/gengtype.c b/gcc/gengtype.c index b6e171822c86..21da84b77d99 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. */ diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 345a545d294d..6369001e038c 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -127,7 +127,15 @@ extern type_p structures; extern type_p param_structs; extern pair_p variables; +/* An enum for distinguishing GGC vs PCH. */ +enum write_types_kinds +{ + WTK_GGC, + WTK_PCH, + + NUM_WTK +}; /* Discrimating kind of types we can understand. */ @@ -302,6 +310,10 @@ struct type { type_p first_subclass; /* The next in that list. */ type_p next_sibling_class; + + /* Have we already written ggc/pch user func for ptr to this? + (in write_user_func_for_structure_ptr). */ + bool wrote_user_func_for_ptr[NUM_WTK]; } s; /* when TYPE_SCALAR: */