Hi, in PR 60419 we end up with a call graph node for a thunk that has no callee because symtab_remove_unreachable_nodes has determined its body is not needed although its declaration is still reachable (more details in comment 11 in bugzilla) and removal of callees is a part of the zombification process that such nodes undergo. Later on, the last stage of inlining that runs after that connects the thunk to the call graph and we segfault because we expect thunks to have a callee.
So we can either keep thunk targets alive or clear the thunk flag. Thunks and aliases are quite similar and symtab_remove_unreachable_nodes does clear the alias flag and the "in border" nodes are referred to but not output and thus just another symbol. Therefore I believe it is correct and much simpler to remove the thunk flag s well. Bootstrapped and tested on x86_64, I have also build Mozilla Firefox witht the patch (without LTO, partly on purpose, partly because again I'm having issues with LTO after updating FF). OK for trunk? There is the same issue on the 4.8 branch, but the patch does not apply, I'm in the process of preparing it. Thanks, Martin 2014-03-20 Martin Jambor <mjam...@suse.cz> PR ipa/60419 * ipa.c (symtab_remove_unreachable_nodes): Clear thunk flag of nodes in the border. testsuite/ * g++.dg/ipa/pr60419.C: New test. diff --git a/gcc/ipa.c b/gcc/ipa.c index 572dba1..164de0d 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -488,6 +488,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) node->definition = false; node->cpp_implicit_alias = false; node->alias = false; + node->thunk.thunk_p = false; node->weakref = false; if (!node->in_other_partition) node->local.local = false; diff --git a/gcc/testsuite/g++.dg/ipa/pr60419.C b/gcc/testsuite/g++.dg/ipa/pr60419.C new file mode 100644 index 0000000..84461f3 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr60419.C @@ -0,0 +1,80 @@ +// PR middle-end/60419 +// { dg-do compile } +// { dg-options "-O2" } + +struct C +{ +}; + +struct I : C +{ + I (); +}; + +struct J +{ + void foo (); + J (); + virtual void foo (int &, int); +}; + +template <class> +struct D +{ + virtual void foo (I &) const; + void bar () + { + I p; + foo (p); + } +}; + +struct K : J, public D<int> +{ +}; + +struct F +{ + K *operator->(); +}; + +struct N : public K +{ + void foo (int &, int); + I n; + void foo (I &) const {} +}; + +struct L : J +{ + F l; +}; + +struct M : F +{ + L *operator->(); +}; + +struct G +{ + G (); +}; + +M h; + +G::G () +try +{ + N f; + f.bar (); + throw; +} +catch (int) +{ +} + +void +baz () +{ + h->l->bar (); +}