This fixes PR53011 - EH cleanup needs to cater for loops now
(or avoid some transforms).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c       (revision 186523)
--- gcc/tree-eh.c       (working copy)
*************** cleanup_empty_eh_merge_phis (basic_block
*** 3916,3921 ****
--- 3916,3936 ----
    for (ei = ei_start (old_bb->preds); (e = ei_safe_edge (ei)); )
      if (e->flags & EDGE_EH)
        {
+       /* ???  CFG manipluation routines do not try to update loop
+          form on edge redirection.  Do so manually here for now.  */
+       /* If we redirect a loop entry or latch edge that will either create
+          a multiple entry loop or rotate the loop.  If the loops merge
+          we may have created a loop with multiple latches.
+          All of this isn't easily fixed thus cancel the affected loop
+          and mark the other loop as possibly having multiple latches.  */
+       if (current_loops
+           && e->dest == e->dest->loop_father->header)
+         {
+           e->dest->loop_father->header = NULL;
+           e->dest->loop_father->latch = NULL;
+           new_bb->loop_father->latch = NULL;
+           loops_state_set (LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+         }
        redirect_eh_edge_1 (e, new_bb, change_region);
        redirect_edge_succ (e, new_bb);
        flush_pending_stmts (e);
Index: gcc/testsuite/g++.dg/torture/pr53011.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr53011.C      (revision 0)
--- gcc/testsuite/g++.dg/torture/pr53011.C      (revision 0)
***************
*** 0 ****
--- 1,66 ----
+ // { dg-do compile }
+ 
+ extern "C" class WvFastString;
+ typedef WvFastString& WvStringParm;
+ struct WvFastString {
+   ~WvFastString();
+   operator char* () {}
+ };
+ class WvString : WvFastString {};
+ class WvAddr {};
+ class WvIPAddr : WvAddr {};
+ struct WvIPNet : WvIPAddr {
+   bool is_default() {}
+ };
+ template<class T, bool> struct WvTraits_Helper {
+   static void release(T *obj) {
+     delete obj;
+   }
+ };
+ template<class From> struct WvTraits {
+   static void release(From *obj) {
+     WvTraits_Helper<From, 0>::release(obj);
+   }
+ };
+ struct WvLink {
+   void   *data;
+   WvLink *next;
+   bool    autofree;
+   WvLink(bool, int) : autofree() {}
+   bool get_autofree() {}
+ 
+   void unlink() {
+     delete this;
+   }
+ };
+ struct WvListBase {
+   WvLink head, *tail;
+   WvListBase() : head(0, 0) {}
+ };
+ template<class T> struct WvList : WvListBase {
+   ~WvList() {
+     zap();
+   }
+ 
+   void zap(bool destroy = 1) {
+     while (head.next) unlink_after(&head, destroy);
+   }
+ 
+   void unlink_after(WvLink *after, bool destroy) {
+     WvLink *next = 0;
+     T *obj       = (destroy && next->get_autofree()) ? 
+                    static_cast<T*>(next->data) : 0;
+ 
+     if (tail) tail = after;
+     next->unlink();
+     WvTraits<T>::release(obj);
+   }
+ };
+ typedef WvList<WvString>WvStringListBase;
+ class WvStringList : WvStringListBase {};
+ class WvSubProc {
+   WvStringList last_args, env;
+ };
+ void addroute(WvIPNet& dest, WvStringParm table) {
+   if (dest.is_default() || (table != "default")) WvSubProc checkProc;
+ }

Reply via email to