Hi! As discussed in the PR, this is a verification ICE if a call stmt calls a same_body_alias (__comp_ctor) and IPA-CP decides to clone the ctor, it clones the function with the body (__base_ctor), but before the call stmts are updated, the checking fails because the clone isn't clone or former clone of the called function, but its alias.
Fixed by adjusting the verifier, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-02-10 Jakub Jelinek <ja...@redhat.com> PR middle-end/51929 * cgraphunit.c (verify_edge_corresponds_to_fndecl): If node is a same_body_alias, also test whether e->callee isn't a former or current clone of the decl this is a same body alias of. (verify_cgraph_node): Fix a typo in error message. * g++.dg/ipa/pr51929.C: New test. --- gcc/cgraphunit.c.jj 2012-02-03 13:31:41.000000000 +0100 +++ gcc/cgraphunit.c 2012-02-10 12:35:44.682099203 +0100 @@ -471,11 +471,17 @@ verify_edge_corresponds_to_fndecl (struc return false; node = cgraph_function_or_thunk_node (node, NULL); - if ((e->callee->former_clone_of != node->decl) + if ((e->callee->former_clone_of != node->decl + && (!node->same_body_alias + || e->callee->former_clone_of != node->thunk.alias)) /* IPA-CP sometimes redirect edge to clone and then back to the former - function. This ping-pong has to go, eventaully. */ + function. This ping-pong has to go, eventually. */ && (node != cgraph_function_or_thunk_node (e->callee, NULL)) - && !clone_of_p (node, e->callee)) + && !clone_of_p (node, e->callee) + /* If decl is a same body alias of some other decl, allow e->callee to be + a clone of a clone of that other decl too. */ + && (!node->same_body_alias + || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee))) return true; else return false; @@ -667,7 +673,7 @@ verify_cgraph_node (struct cgraph_node * for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) if (ref->use != IPA_REF_ALIAS) { - error ("Alias has non-alias refernece"); + error ("Alias has non-alias reference"); error_found = true; } else if (ref_found) --- gcc/testsuite/g++.dg/ipa/pr51929.C.jj 2012-02-10 12:36:55.792748549 +0100 +++ gcc/testsuite/g++.dg/ipa/pr51929.C 2012-02-09 19:42:10.000000000 +0100 @@ -0,0 +1,32 @@ +// PR middle-end/51929 +// { dg-do compile } +// { dg-options "-O -fno-guess-branch-probability -fipa-cp -fipa-cp-clone --param=max-inline-insns-single=25" } + +struct A +{ + A (A, unsigned); + A (const char *); + ~A () { a1 (a4 ()); } + void a1 (int); + unsigned a2 (); + char *a3 (); + int a4 (); +}; + +template <typename T> +struct B +{ + A b; + B (A x, int y = 1) : b (x.a3 (), x.a2 ()) { if (y & 1) b.a2 (); } +}; + +extern template struct B <char>; +A a1 ("foo"), a2 ("bar"); +B<char> b1 (a1), b2 (a2, 8); + +void +foo () +{ + A a3 ("baz"); + B<char> b3 (a1), b4 (a3); +} Jakub