@@ -793,7 +793,7 @@ struct_field_seq (void)
/* Return true if OPTS contain the option named STR. */
-static bool
+bool
opts_have (options_p opts, const char *str)
{
for (options_p opt = opts; opt; opt = opt->next)
@@ -1532,7 +1532,11 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM],
process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
&dummy2);
- for (f = t->u.s.fields; f; f = f->next)
+ if (t->u.s.base_class)
+ set_gc_used_type (t->u.s.base_class, level, param,
+ allow_undefined_types);
+
+ FOR_ALL_INHERITED_FIELDS(t, f)
{
int maybe_undef = 0;
int pass_param = 0;
@@ -2534,6 +2538,11 @@ output_mangled_typename (outf_p of, const_type_p t)
case TYPE_LANG_STRUCT:
case TYPE_USER_STRUCT:
{
+ /* For references to classes within an inheritance hierarchy,
+ only ever reference the ultimate base class, since only
+ it will have gt_ functions. */
+ while (t->u.s.base_class)
+ t = t->u.s.base_class;
const char *id_for_tag = filter_type_name (t->u.s.tag);
oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag),
id_for_tag);
@@ -2596,6 +2605,44 @@ output_escaped_param (struct walk_type_data *d, const char *param,
}
}
+const char *
+get_string_option (options_p opt, const char *key)
+{
+ for (; opt; opt = opt->next)
+ if (strcmp (opt->name, key) == 0)
+ return opt->info.string;
+ return NULL;
+}
+
+static void
+walk_subclasses (type_p base, struct walk_type_data *d)
+{
+ for (type_p sub = structures; sub != NULL; sub = sub->next)
+ {
+ if (sub->u.s.base_class == base)
+ {
+ const char *type_tag = get_string_option (sub->u.s.opt, "tag");
+ if (type_tag)
+ {
+ oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+ d->indent += 2;
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ d->indent += 2;
+ oprintf (d->of, "%*s%s *sub = static_cast <%s *> (x);\n",
+ d->indent, "", sub->u.s.tag, sub->u.s.tag);
+ const char *old_val = d->val;
+ d->val = "(*sub)";
+ walk_type (sub, d);
+ d->val = old_val;
+ d->indent -= 2;
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ oprintf (d->of, "%*sbreak;\n", d->indent, "");
+ d->indent -= 2;
+ }
+ walk_subclasses (sub, d);
+ }
+ }
+}
/* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
which is of type T. Write code to D->OF to constrain execution (at
@@ -2613,6 +2660,7 @@ walk_type (type_p t, struct walk_type_data *d)
{
const char *length = NULL;
const char *desc = NULL;
+ const char *type_tag = NULL;
int maybe_undef_p = 0;
int use_param_num = -1;
int use_params_p = 0;
@@ -2641,7 +2689,7 @@ walk_type (type_p t, struct walk_type_data *d)
else if (strcmp (oo->name, "dot") == 0)
;
else if (strcmp (oo->name, "tag") == 0)
- ;
+ type_tag = oo->info.string;
else if (strcmp (oo->name, "special") == 0)
;
else if (strcmp (oo->name, "skip") == 0)
@@ -2960,8 +3008,18 @@ walk_type (type_p t, struct walk_type_data *d)
d->indent += 2;
oprintf (d->of, "%*s{\n", d->indent, "");
}
+ else if (desc)
+ {
+ oprintf (d->of, "%*sswitch (", d->indent, "");
+ output_escaped_param (d, desc, "desc");
+ oprintf (d->of, ")\n");
+ d->indent += 2;
+ oprintf (d->of, "%*s{\n", d->indent, "");
+ oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+ d->indent += 2;
+ }
- for (f = t->u.s.fields; f; f = f->next)
+ FOR_ALL_INHERITED_FIELDS (t, f)
{
options_p oo;
int skip_p = 0;
@@ -2999,7 +3057,7 @@ walk_type (type_p t, struct walk_type_data *d)
}
endcounter = d->counter;
- for (f = t->u.s.fields; f; f = f->next)
+ FOR_ALL_INHERITED_FIELDS (t, f)
{
options_p oo;
const char *dot = ".";
@@ -3101,11 +3159,26 @@ walk_type (type_p t, struct walk_type_data *d)
oprintf (d->of, "%*sdefault:\n", d->indent, "");
oprintf (d->of, "%*s break;\n", d->indent, "");
}
+
+ if (desc && !union_p)
+ {
+ oprintf (d->of, "%*sbreak;\n", d->indent, "");
+ d->indent -= 2;
+ }
if (union_p)
{
oprintf (d->of, "%*s}\n", d->indent, "");
d->indent -= 2;
}
+ else if (desc)
+ {
+ /* Add cases to handle subclasses. */
+ walk_subclasses (t, d);
+
+ /* End of the switch statement */
+ oprintf (d->of, "%*s}\n", d->indent, "");
+ d->indent -= 2;
+ }
if (any_length_seen)
{
d->indent -= 2;
@@ -3451,6 +3524,11 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
options_p opt;
struct walk_type_data d;
+ /* Don't write fns for subclasses, only for the ultimate base class
+ within an inheritance hierarchy. */
+ if (s->u.s.base_class)
+ return;
+
memset (&d, 0, sizeof (d));
d.of = get_output_file_for_structure (s, param);
for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -3627,7 +3705,10 @@ write_types (outf_p output_header, type_p structures, type_p param_structs,
emitted afterwards. This is needed in plugin mode. */
oprintf (output_header, "/* Macros and declarations. */\n");
for (s = structures; s; s = s->next)
- if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+ /* Do not emit handlers for derived classes; we only ever deal with
+ the ultimate base class within an inheritance hierarchy. */
+ if ((s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+ && !s->u.s.base_class)
{
options_p opt;
@@ -3932,6 +4013,11 @@ write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param)
{
struct walk_type_data d;
+ /* Don't write fns for subclasses, only for the ultimate base class
+ within an inheritance hierarchy. */
+ if (s->u.s.base_class)
+ return;
+
memset (&d, 0, sizeof (d));
d.of = get_output_file_for_structure (s, param);
d.process_field = write_types_local_process_field;
@@ -4076,7 +4162,9 @@ write_local (outf_p output_header, type_p structures, type_p param_structs)
|| ((s)->gc_used == GC_MAYBE_POINTED_TO \
&& s->u.s.line.file != NULL) \
|| ((s)->gc_used == GC_USED \
- && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
+ && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \
+ || (s->u.s.base_class && opts_have (s->u.s.opt, "tag")))))
+
/* Might T contain any non-pointer elements? */
@@ -4360,6 +4448,8 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
if (!has_length && union_or_struct_p (tp))
{
+ while (tp->u.s.base_class)
+ tp = tp->u.s.base_class;
const char *id_for_tag = filter_type_name (tp->u.s.tag);
oprintf (f, " >_ggc_mx_%s,\n", id_for_tag);
if (emit_pch)
@@ -506,4 +506,12 @@ void dbgprint_count_type_at (const char *, int, const char *, type_p);
#define DBGPRINT_COUNT_TYPE(Msg,Ty) do{/*nodbgprint_count_type*/}while (0)
#endif /*ENABLE_CHECKING */
+#define FOR_ALL_INHERITED_FIELDS(TYPE, FIELD_VAR) \
+ for (type_p sub = (TYPE); sub; sub = sub->u.s.base_class) \
+ for (FIELD_VAR = sub->u.s.fields; FIELD_VAR; FIELD_VAR = FIELD_VAR->next)
+
+extern bool
+opts_have (options_p opts, const char *str);
+
+
#endif