There is a bug in gengtype's handling of types marked with GTY((user))
which can lead to gtype-desc.c containing broken test-and-mark functions
that fail to call the user-provided traversal functions, leading to
segfaults.
If the type is first encountered as an incomplete type declaration:
struct foo;
find_structure records the name of the type, setting its
kind to TYPE_STRUCT (not TYPE_USER_STRUCT).
Later, when the complete type is seen (with its GTY((user)) marking):
struct GTY((user)) foo
{
};
create_user_defined_type calls:
type_p ty = find_structure (type_name, TYPE_USER_STRUCT);
but the name is already found, erroneously of kind TYPE_STRUCT.
Since the parser treats it as a user struct, no attempt is made to
parse the fields.
Later, when write_func_for_structure writes out the marking function
for the type, this conditional:
if (orig_s->kind != TYPE_USER_STRUCT)
fails to treat the type as a "user" type, instead walking an empty
list of fields.
Hence it write out bogus marking functions into gtype-desc.c (with
analogous effects on PCH):
void
gt_ggc_mx_foo (void *x_p)
{
struct foo * const x = (struct foo *)x_p;
if (ggc_test_and_set_mark (x))
{
}
}
This code compiles and runs - until GC (or PCH) happens, when it
erroneously collects any objects that are only referenced by
affected types.
Note the erroneously empty body - the above should have read:
void
gt_ggc_mx_foo (void *x_p)
{
struct foo * const x = (struct foo *)x_p;
if (ggc_test_and_set_mark (x))
{
gt_ggc_mx (x);
}
}
i.e. with a call to the user-provided gt_ggc_mx function, otherwise
none of the references to affected GTY((user)) types are followed,
and only a subset of the reference graph is walked.
This patch fixes the "kind" of the type handled within
create_user_defined_type to ensure it is treated as a "user" type,
fixing the generated gtype-desc.c code.
Successfully bootstrapped and regrtested on x86_64-unknown-linux-gnu.
* gengtype.c (create_user_defined_type): Ensure that the kind
is set to TYPE_USER_STRUCT, fixing a bug seen when an incomplete
declaration is seen before the GTY((user)) marking.
---
gcc/gengtype.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 2085496..9c12752 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -559,6 +559,12 @@ type_p
create_user_defined_type (const char *type_name, struct fileloc *pos)
{
type_p ty = find_structure (type_name, TYPE_USER_STRUCT);
+
+ /* We might have already seen an incomplete decl of the given type,
+ in which case we won't have yet seen a GTY((user)), and the type will
+ only have kind "TYPE_STRUCT". Mark it as a user struct. */
+ ty->kind = TYPE_USER_STRUCT;
+
ty->u.s.line = *pos;
ty->u.s.bitmap = get_lang_bitmap (pos->file);
do_typedef (type_name, ty, pos);
--
1.7.11.7