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; + }