diff --git a/MAINTAINERS b/MAINTAINERS
index 508abe88cb572164ae4dd574512beb307939511a..cbbf126bb28cc304ac1a617c49f703218546541c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -372,6 +372,7 @@ Mark Shinwell					shinwell@codesourcery.com
 Franz Sirl					franz.sirl-kernel@lauterbach.com
 Michael Sokolov					msokolov@ivan.Harhan.ORG
 Richard Stallman				rms@gnu.org
+Basile Starynkevitch				basile@starynkevitch.net
 Graham Stott					graham.stott@btinternet.com
 Mike Stump					mrs@apple.com
 Jeff Sturm					jsturm@gcc.gnu.org
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index d997d1edc6dd1c3591604d7c65529de72775bd6b..ed677c61aa628e3f75e1da2f253b49637167e248 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 2002, 2003, 2004
+@c Copyright (C) 2002, 2003, 2004, 2007
 @c Free Software Foundation, Inc.
 @c This is part of the GCC manual.
 @c For copying conditions, see the file gcc.texi.
@@ -282,6 +282,16 @@ The routine @code{ggc_marked_p} can be used to determine if an element
 has been marked already; in fact, the usual case is to use
 @code{if_marked ("ggc_marked_p")}.
 
+@findex mark_hook
+@item mark_hook ("@var{hook-routine-name}")
+
+If provided for a structure or union type, the given
+@var{hook-routine-name} (between double-quotes) is the name of a
+routine called when the garbage collector has just marked the data as
+reachable. This routine should not change the data, or call any ggc
+routine. Its only argument is a pointer to the just marked (const)
+structure or union.
+
 @findex maybe_undef
 @item maybe_undef
 
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 1413d6fb4387b70c661590f8ec53b3c149eec343..f195dab2e1740c0f4b6cc1b7e3a63a87fe40f72d 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1382,6 +1382,7 @@ struct write_types_data
   const char *marker_routine;
   const char *reorder_note_routine;
   const char *comment;
+  int skip_hooks;		/* skip hook generation if non zero */
 };
 
 static void output_escaped_param (struct walk_type_data *d,
@@ -1549,6 +1550,8 @@ walk_type (type_p t, struct walk_type_data *d)
       use_params_p = 1;
     else if (strcmp (oo->name, "desc") == 0)
       desc = oo->info;
+    else if (strcmp (oo->name, "mark_hook") == 0)
+      ;
     else if (strcmp (oo->name, "nested_ptr") == 0)
       nested_ptr_d = (const struct nested_ptr_data *) oo->info;
     else if (strcmp (oo->name, "dot") == 0)
@@ -2039,6 +2042,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
   int i;
   const char *chain_next = NULL;
   const char *chain_prev = NULL;
+  const char *mark_hook_name = NULL;
   options_p opt;
   struct walk_type_data d;
 
@@ -2056,6 +2060,8 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
       chain_next = opt->info;
     else if (strcmp (opt->name, "chain_prev") == 0)
       chain_prev = opt->info;
+    else if (strcmp (opt->name, "mark_hook") == 0)
+      mark_hook_name = opt->info;
 
   if (chain_prev != NULL && chain_next == NULL)
     error_at_line (&s->u.s.line, "chain_prev without chain_next");
@@ -2111,10 +2117,17 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
 	  output_type_enum (d.of, orig_s);
 	}
       oprintf (d.of, "))\n");
+      if (mark_hook_name && !wtd->skip_hooks)
+	{
+	  oprintf (d.of, "    {\n");
+	  oprintf (d.of, "      %s (xlimit);\n   ", mark_hook_name);
+	}
       oprintf (d.of, "   xlimit = (");
       d.prev_val[2] = "*xlimit";
       output_escaped_param (&d, chain_next, "chain_next");
       oprintf (d.of, ");\n");
+      if (mark_hook_name && !wtd->skip_hooks)
+	oprintf (d.of, "    }\n");
       if (chain_prev != NULL)
 	{
 	  oprintf (d.of, "  if (x != xlimit)\n");
@@ -2142,7 +2155,10 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
       oprintf (d.of, "  while (x != xlimit)\n");
     }
   oprintf (d.of, "    {\n");
-
+  if (mark_hook_name && chain_next == NULL && !wtd->skip_hooks)
+    {
+      oprintf (d.of, "      %s (x);\n", mark_hook_name);
+    }
   d.prev_val[2] = "*x";
   d.indent = 6;
   walk_type (s, &d);
@@ -2258,14 +2274,16 @@ write_types (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.  "
+  "GC marker procedures.  ",
+  FALSE
 };
 
 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.  "
+  "PCH type-walking procedures.  ",
+  TRUE
 };
 
 /* Write out the local pointer-walking routines.  */