summaryrefslogtreecommitdiff
path: root/gcc/tree-eh.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-04-25 17:24:28 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-04-25 17:24:28 +0000
commitb4ba5e9d1d9992c366874e0f4c5449d2f15e7b07 (patch)
tree3e4dfc8934383c983170f17940177f54350abc6f /gcc/tree-eh.c
parent6da398b341726847a8297d6ce3803a25d2dfc3c9 (diff)
downloadgcc-b4ba5e9d1d9992c366874e0f4c5449d2f15e7b07.tar.gz
* tree-cfg.c (tree_duplicate_bb): Duplicate EH region too.
* except.c: Include diagnostic.h (dump_eh_tree, verify_eh_tree): New functions. * except.h (verify_eh_tree, dump_eh_tree, verify_eh_edges): Declare. * tree-cfg.c (tree_verify_flow_info): verify eh edges. (dump_function_to_file): dump eh tree. * tree-eh.c (mark_eh_edge): New function. (mark_eh_edge_found_error): New static variable. (verify_eh_edges): New function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@98724 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r--gcc/tree-eh.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 90f90611d01..e21b5c51a5b 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -1746,6 +1746,97 @@ make_eh_edges (tree stmt)
foreach_reachable_handler (region_nr, is_resx, make_eh_edge, stmt);
}
+static bool mark_eh_edge_found_error;
+
+/* Mark edge make_eh_edge would create for given region by setting it aux
+ field, output error if something goes wrong. */
+static void
+mark_eh_edge (struct eh_region *region, void *data)
+{
+ tree stmt, lab;
+ basic_block src, dst;
+ edge e;
+
+ stmt = data;
+ lab = get_eh_region_tree_label (region);
+
+ src = bb_for_stmt (stmt);
+ dst = label_to_block (lab);
+
+ e = find_edge (src, dst);
+ if (!e)
+ {
+ error ("EH edge %i->%i is missing %i %i.", src->index, dst->index, src, dst);
+ mark_eh_edge_found_error = true;
+ }
+ else if (!(e->flags & EDGE_EH))
+ {
+ error ("EH edge %i->%i miss EH flag.", src->index, dst->index);
+ mark_eh_edge_found_error = true;
+ }
+ else if (e->aux)
+ {
+ /* ??? might not be mistake. */
+ error ("EH edge %i->%i has duplicated regions.", src->index, dst->index);
+ mark_eh_edge_found_error = true;
+ }
+ else
+ e->aux = (void *)1;
+}
+
+/* Verify that BB containing stmt as last stmt has precisely the edges
+ make_eh_edges would create. */
+bool
+verify_eh_edges (tree stmt)
+{
+ int region_nr;
+ bool is_resx;
+ basic_block bb = bb_for_stmt (stmt);
+ edge_iterator ei;
+ edge e;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ gcc_assert (!e->aux);
+ mark_eh_edge_found_error = false;
+ if (TREE_CODE (stmt) == RESX_EXPR)
+ {
+ region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0));
+ is_resx = true;
+ }
+ else
+ {
+ region_nr = lookup_stmt_eh_region (stmt);
+ if (region_nr < 0)
+ {
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & EDGE_EH)
+ {
+ error ("BB %i can not throw but has EH edges", bb->index);
+ return true;
+ }
+ return false;
+ }
+ if (!tree_could_throw_p (stmt))
+ {
+ error ("BB %i last statement has incorrectly set region", bb->index);
+ return true;
+ }
+ is_resx = false;
+ }
+
+ foreach_reachable_handler (region_nr, is_resx, mark_eh_edge, stmt);
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ if ((e->flags & EDGE_EH) && !e->aux)
+ {
+ error ("Unnecesary EH edge %i->%i", bb->index, e->dest->index);
+ mark_eh_edge_found_error = true;
+ return true;
+ }
+ e->aux = NULL;
+ }
+ return mark_eh_edge_found_error;
+}
/* Return true if the expr can trap, as in dereferencing an invalid pointer