* 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.
From-SVN: r70477
+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
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,
/* 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;
}
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);
}
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;
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)
{
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;
}
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