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

Reply via email to