diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6f8b592cbb0e7837e1020c6c46611c79ab0709da..bee756c8f5d95d846e7473d9c716d3a713572d0a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2003-08-14  Jan Hubicka  <jh@suse.cz>
+
+	* decl2.c (mark_member_pointers): Rename to...
+	(mark_member_pointers_and_eh_tinfos): ... this one; deal with eh tinfos
+	(lower_function): Update call.
+	* except.c (eh_type_info): Break out from ...
+	(build_eh_type): ... here; tinfo is already used.
+        (finish_eh_spec_block): Mark tinfos as used.
+        * semantics.c (finish_handler_params): Mark tinfo as used.
+	* cp-tree.h(eh_type_info): Declare.
+
 2003-08-15  Nathan Sidwell  <nathan@codesourcery.com>
 
 	* pt.c (instantiate_class_template): Set location before
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 934acb9934b13dfdfcd648949277ce2b87548137..eae862a33800f8c5180c877855cb951c54ed4931 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3829,6 +3829,7 @@ extern void mark_all_runtime_matches            (void);
 extern int nothrow_libfn_p			(tree);
 extern void check_handlers			(tree);
 extern void choose_personality_routine		(enum languages);
+extern tree eh_type_info			(tree);
 
 /* in expr.c */
 extern rtx cxx_expand_expr			(tree, rtx,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 54e627f5569fd43354c2aa434bd9d503f1d70cfd..eb32f49378d6a7277c343414b5bc1a77fe361985 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2562,12 +2562,49 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
 /* Callgraph code does not understand the member pointers.  Mark the methods
    referenced as used.  */
 static tree
-mark_member_pointers (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
-		      void *data ATTRIBUTE_UNUSED)
+mark_member_pointers_and_eh_handlers (tree *tp,
+				      int *walk_subtrees,
+		      		      void *data ATTRIBUTE_UNUSED)
 {
-  if (TREE_CODE (*tp) == PTRMEM_CST
-      && TYPE_PTRMEMFUNC_P (TREE_TYPE (*tp)))
-    cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1);
+  /* Avoid useless walking of complex type and declaration nodes.  */
+  if (TYPE_P (*tp) || DECL_P (*tp))
+    {
+      *walk_subtrees = 0;
+      return 0;
+    }
+  switch (TREE_CODE (*tp))
+    {
+    case PTRMEM_CST:
+      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (*tp)))
+	cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1);
+      break;
+
+    /* EH handlers will emit EH tables referencing typeinfo.  */
+    case HANDLER:
+      if (HANDLER_TYPE (*tp))
+	{
+	  tree tinfo = eh_type_info (HANDLER_TYPE (*tp));
+
+	  cgraph_varpool_mark_needed_node (cgraph_varpool_node (tinfo));
+	}
+      break;
+
+    case EH_SPEC_BLOCK:
+	{
+	  tree type;
+
+	  for (type = EH_SPEC_RAISES ((*tp)); type;
+	       type = TREE_CHAIN (type))
+	    {
+	       tree tinfo = eh_type_info (TREE_VALUE (type));
+
+	       cgraph_varpool_mark_needed_node (cgraph_varpool_node (tinfo));
+	    }
+	}
+      break;
+    default:
+      break;
+    }
   return 0;
 }
 
@@ -2576,7 +2613,8 @@ mark_member_pointers (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
 void
 lower_function (tree fn)
 {
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), mark_member_pointers,
+  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
+		  		mark_member_pointers_and_eh_handlers,
 				NULL);
 }
 
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 390f12c45514919198ae30a7088be6ddeb662530..1303919de370f7e15b24ecd2572c836c743a127f 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -115,11 +115,9 @@ prepare_eh_type (tree type)
   return type;
 }
 
-/* Build the address of a typeinfo decl for use in the runtime
-   matching field of the exception model.  */
-
-static tree
-build_eh_type_type (tree type)
+/* Return the type info for TYPE as used by EH machinery.  */
+tree
+eh_type_info (tree type)
 {
   tree exp;
 
@@ -131,12 +129,23 @@ build_eh_type_type (tree type)
   else
     exp = get_tinfo_decl (type);
 
-  mark_used (exp);
-  exp = build1 (ADDR_EXPR, ptr_type_node, exp);
-
   return exp;
 }
 
+/* Build the address of a typeinfo decl for use in the runtime
+   matching field of the exception model.  */
+
+static tree
+build_eh_type_type (tree type)
+{
+  tree exp = eh_type_info (type);
+
+  if (!exp)
+    return NULL;
+
+  return build1 (ADDR_EXPR, ptr_type_node, exp);
+}
+
 tree
 build_exc_ptr (void)
 {
@@ -470,8 +479,13 @@ finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
   for (raises = NULL_TREE;
        raw_raises && TREE_VALUE (raw_raises);
        raw_raises = TREE_CHAIN (raw_raises))
-    raises = tree_cons (NULL_TREE, prepare_eh_type (TREE_VALUE (raw_raises)),
-			raises);
+    {
+      tree type = prepare_eh_type (TREE_VALUE (raw_raises));
+      tree tinfo = eh_type_info (type);
+
+      mark_used (tinfo);
+      raises = tree_cons (NULL_TREE, type, raises);
+    }
 
   EH_SPEC_RAISES (eh_spec_block) = raises;
 }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 29d5dd7524b9d8ec5be4fa7ef9f79bdda6e935e6..932bb982816500568cdd333e681b56622a1b5085 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -956,6 +956,8 @@ finish_handler_parms (tree decl, tree handler)
     type = expand_start_catch_block (decl);
 
   HANDLER_TYPE (handler) = type;
+  if (type)
+    mark_used (eh_type_info (type));
 }
 
 /* Finish a handler, which may be given by HANDLER.  The BLOCKs are