------- Comment #6 from abel at gcc dot gnu dot org  2010-02-16 15:43 -------
How about the below patch?  It fixes all testcases for me.  I'm not sure
whether it makes sense to filter duplicate labels this late, but I don't know
how to do this earlier, as catches seem to be lowering independently of each
other.

diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 2cb334f..c18b807 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "function.h"
 #include "except.h"
+#include "pointer-set.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "tree-inline.h"
@@ -3063,6 +3064,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
        eh_catch c;
        edge_iterator ei;
        edge e;
+       struct pointer_set_t *seen_values = pointer_set_create ();

        /* Collect the labels for a switch.  Zero the post_landing_pad
           field becase we'll no longer have anything keeping these labels
@@ -3071,6 +3073,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)
        for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
          {
            tree tp_node, flt_node, lab = c->label;
+           bool have_label = false;

            c->label = NULL;
            tp_node = c->type_list;
@@ -3083,14 +3086,26 @@ lower_eh_dispatch (basic_block src, gimple stmt)
              }
            do
              {
-               tree t = build3 (CASE_LABEL_EXPR, void_type_node,
-                                TREE_VALUE (flt_node), NULL, lab);
-               VEC_safe_push (tree, heap, labels, t);
+               /* Filter out duplicate labels that arise when this handler 
+                  is shadowed by an earlier one.  When no labels are 
+                  attached to the handler anymore, we remove 
+                  the corresponding edge and then we delete unreachable 
+                  blocks at the end of this pass.  */
+               if (! pointer_set_contains (seen_values, TREE_VALUE
(flt_node)))
+                 {
+                   tree t = build3 (CASE_LABEL_EXPR, void_type_node,
+                                    TREE_VALUE (flt_node), NULL, lab);
+                   VEC_safe_push (tree, heap, labels, t);
+                   pointer_set_insert (seen_values, TREE_VALUE (flt_node));
+                   have_label = true;
+                 }

                tp_node = TREE_CHAIN (tp_node);
                flt_node = TREE_CHAIN (flt_node);
              }
            while (tp_node);
+           if (! have_label)
+             remove_edge (find_edge (src, label_to_block (lab)));
          }

        /* Clean up the edge flags.  */
@@ -3132,6 +3147,7 @@ lower_eh_dispatch (basic_block src, gimple stmt)

            VEC_free (tree, heap, labels);
          }
+       pointer_set_destroy (seen_values);
       }
       break;

@@ -3185,6 +3201,8 @@ execute_lower_eh_dispatch (void)
        }
     }

+  if (any_rewritten)
+    delete_unreachable_blocks ();
   return any_rewritten ? TODO_update_ssa_only_virtuals : 0;
 }



-- 

abel at gcc dot gnu dot org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |abel at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42859

Reply via email to