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. I've fixed the first problem by adding a direct call to (*debug_hooks->source_line) in assemble_thunk. This seems to work, but I'm not at all sure if it's the right way to fix it. Advice is appreciated. I've fixed the second problem by adding a check for cfun->cfg != NULL to guard the FOR_EACH_BB_REVERSE loop in final(). Do these changes look OK? -cary 2012-08-03 Cary Coutant <ccout...@google.com> * gcc/cgraphunit.c (assemble_thunk): Add source line info. * gcc/final.c (final): Check for non-null cfg pointer. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 89765b5..1558b4d 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1382,6 +1382,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); diff --git a/gcc/final.c b/gcc/final.c index 095d608..d22130f 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1863,11 +1863,12 @@ final (rtx first, FILE *file, int optimize_p) 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; - } + if (cfun->cfg != NULL) + 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. */