This patch is for the google/gcc-4_7 branch. It backports the following patch from trunk at r190190:
http://gcc.gnu.org/ml/gcc-patches/2012-08/msg00321.html GCC generates non-virtual thunks directly to assembly code, which causes a couple of problems. First, it doesn't add source location information to the thunk, so the thunk simply inherits the random location from the end of the function in front of it (the function it's a thunk for). In two different compilation units compiled with different options, this could result in two different locations for the same thunk, and gold will give a false positive ODR violation warning. Second, if you try to compile with -S -dA, GCC crashes in final(), where it's trying to build a mapping from insn to bb, because the function has no cfg, and FOR_EACH_BB_REVERSE tries to dereference cfun->cfg without checking for non-NULL. Bootstrapped and ran testsuite with no regressions. Google ref b/6891766. 2012-08-06 Cary Coutant <ccout...@google.com> gcc/ * cgraphunit.c (assemble_thunk): Add source line info. * final.c (final): Check for non-null cfg pointer. gcc/testsuite/ * g++.dg/debug/dwarf2/non-virtual-thunk.C: New test case. Index: gcc/final.c =================================================================== --- gcc/final.c (revision 190189) +++ gcc/final.c (working copy) @@ -1761,11 +1761,13 @@ final (rtx first, FILE *file, int optimi start_to_bb = XCNEWVEC (basic_block, bb_map_size); end_to_bb = XCNEWVEC (basic_block, bb_map_size); - FOR_EACH_BB_REVERSE (bb) - { - start_to_bb[INSN_UID (BB_HEAD (bb))] = bb; - end_to_bb[INSN_UID (BB_END (bb))] = bb; - } + /* There is no cfg for a thunk. */ + if (!cfun->is_thunk) + FOR_EACH_BB_REVERSE (bb) + { + start_to_bb[INSN_UID (BB_HEAD (bb))] = bb; + end_to_bb[INSN_UID (BB_END (bb))] = bb; + } } /* Output the insns. */ Index: gcc/cgraphunit.c =================================================================== --- gcc/cgraphunit.c (revision 190189) +++ gcc/cgraphunit.c (working copy) @@ -1799,6 +1799,10 @@ assemble_thunk (struct cgraph_node *node init_function_start (thunk_fndecl); cfun->is_thunk = 1; assemble_start_function (thunk_fndecl, fnname); + (*debug_hooks->source_line) (DECL_SOURCE_LINE (thunk_fndecl), + DECL_SOURCE_FILE (thunk_fndecl), + /* discriminator */ 0, + /* is_stmt */ 1); targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, fixed_offset, virtual_value, alias); Index: gcc/testsuite/g++.dg/debug/dwarf2/non-virtual-thunk.C =================================================================== --- gcc/testsuite/g++.dg/debug/dwarf2/non-virtual-thunk.C (revision 0) +++ gcc/testsuite/g++.dg/debug/dwarf2/non-virtual-thunk.C (revision 0) @@ -0,0 +1,39 @@ +// { dg-do compile } +// { dg-options "-g2 -dA" } + +// Verify that line number info is output for the non-virtual +// thunks for C::~C(). +// { dg-final { scan-assembler "thunk.C:30" } } + +class A +{ + public: + A(); + virtual ~A(); + private: + int i; +}; + +class B +{ + public: + B(); + virtual ~B(); + private: + int i; +}; + +class C : public A, public B +{ + public: + C(); + virtual ~C(); // line 30 +}; + +C::C() +{ +} + +C::~C() +{ +}