mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-14 06:50:27 +08:00
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. From-SVN: r210379
This commit is contained in:
parent
5c0f009c92
commit
9aa54cc915
@ -1,3 +1,32 @@
|
||||
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.
|
||||
|
||||
2014-05-13 Richard Sandiford <r.sandiford@uk.ibm.com>
|
||||
|
||||
* fold-const.c (optimize_bit_field_compare): Use wi:: operations
|
||||
|
@ -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<ID1,ID2,...,IDn>.
|
||||
simple template declarations of the form ID<ID1,ID2,...,IDn>,
|
||||
potentially with a single level of indirection e.g.
|
||||
ID<ID1 *, ID2, ID3 *, ..., IDn>.
|
||||
It does not try to parse anything more sophisticated than that.
|
||||
|
||||
Returns the template declaration string "ID<ID1,ID2,...,IDn>". */
|
||||
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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: */
|
||||
|
Loading…
x
Reference in New Issue
Block a user