[Bug c++/59255] [4.8/4.9 Regression] Segmentation fault with std::function and -fprofile-use
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59255 --- Comment #2 from mark at jarv dot in --- This is my first time trying to debug GCC, so please forgive me if this is obvious or unhelpful. I traced this in GDB and it seems that the segfault is because the FOR_EACH_EDGE loop at value-prof.c:1281 runs off the end of the icall_bb->succs vector without identifying an edge with the EDGE_EH flag set. I'm just guessing, but I think this means the icall_bb basic block has no edge to an exception handler. The code is expecting such an edge to exist so that it can be used by the direct call as well. Any suggestions on how to determine why the icall_bb has no exception handler successor? It also could throw, so it seems reasonable to expect that it would have an edge to an exception handler. Breakpoint 5, gimple_ic (icall_stmt=0x2f56f7b8, direct_call=0x2f4bcb90, prob=1, count=1, all=1) at ../../gcc-4.8.2/gcc/value-prof.c:1280 1280 add_stmt_to_eh_lp (dcall_stmt, lp_nr); (gdb) n 1281 FOR_EACH_EDGE (e_eh, ei, icall_bb->succs) (gdb) call debug_gimple_stmt(dcall_stmt) std::_Function_base::_Base_manager::_M_manager (_5, _4, 3); (gdb) p *icall_bb->succs $4 = { vecpfx_ = { alloc_ = 4, num_ = 1 }, vecdata_ = {0x2f588380} } (gdb) n 1282if (e_eh->flags & EDGE_EH) (gdb) p e_eh->flags $5 = 1 (gdb) n 1281 FOR_EACH_EDGE (e_eh, ei, icall_bb->succs) (gdb) n 1284 e = make_edge (dcall_bb, e_eh->dest, EDGE_EH); (gdb) p e_eh $6 = (edge) 0x0 (gdb) p stmt_could_throw_p(dcall_stmt) $7 = true (gdb) p stmt_could_throw_p(icall_stmt) $8 = true (gdb)
[Bug c++/59255] [4.8/4.9 Regression] Segmentation fault with std::function and -fprofile-use
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59255 --- Comment #3 from mark at jarv dot in --- I notice that lookup_stmt_eh_lp(icall_stmt) at value-prof.c:1272 returns -1. Elsewhere in the code (tree-eh.c:2208), I see "lp_nr <= 0" as a guard against further EH processing. At gimple-pretty-print.c:1881, I see that a negative lp_nr is pretty-printed as ("[MNT %d]", -lp_nr). Further searching around suggests that "MNT" might mean "must not throw". Notably, we're in a destructor in C++11 here, and I guess C++11 destructors are more often noexcept than in C++98. From http://stackoverflow.com/q/15721544/228142: '12.4/3: "A declaration of a destructor that does not have an exception-specification is implicitly considered to have the same exception-specification as an implicit declaration (15.4)." i.e. a destructor is only noexcept(true) if all the members and bases have a noexcept destructor.' Could the correct fix be as simple as: --- value-prof.c.orig2013-12-12 10:09:23.148929000 -0500 +++ value-prof.c2013-12-12 10:57:33.32998 -0500 @@ -1270,7 +1270,7 @@ gimple_ic (gimple icall_stmt, struct cgr /* Build an EH edge for the direct call if necessary. */ lp_nr = lookup_stmt_eh_lp (icall_stmt); - if (lp_nr != 0 + if (lp_nr > 0 && stmt_could_throw_p (dcall_stmt)) { edge e_eh, e; This certainly removes the ICE, but I don't know that I can vouch for its safety from the perspective of preserving correctness.
[Bug c++/59255] [4.8/4.9 Regression] Segmentation fault with std::function and -fprofile-use
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59255 --- Comment #4 from Mark Jarvin --- I think the other relevant text from the C++11 standard is available here: http://stackoverflow.com/q/13041715/228142 "An implicitly declared special member function (Clause 12) shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions." I guess I'm trying to build the case that it makes sense that icall_bb has no EH successor because it's a must-not-throw block, and it's a must-not-throw block in this specific case because it's a destructor with -std=c++11 and its members are (I'm guessing) all must-not-throw. The bug amounts to the code not correctly handling must-not-throw statements. If you buy that argument, I think there might be other places in GCC that aren't handling it either. For example, cfgexpand.c:2313 simply checks that lp_nr != 0. Likewise cgraph.c:1084, tree-cfg.c:4709, tree-eh.c:3029, maybe others.
[Bug c++/59255] [4.8/4.9 Regression] Segmentation fault with std::function and -fprofile-use
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59255 --- Comment #5 from Mark Jarvin --- Hmm... seems like it's already fixed in the trunk: http://gcc.gnu.org/viewcvs/gcc?view=revision&revision=201859 It doesn't seem to have been ported to 4.8. http://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_8-branch/gcc/value-prof.c?view=log