From PR 43936, -fcompare-debug failed with external declaration in function.
Created attachment 20518 [details] A testcase On Linux/x86-64, [hjl@gnu-6 stage2-gcc]$ ./xgcc -B./ -c -g -O2 -Wc++-compat -fno-common pr43942.i -fcompare-debug xgcc: pr43942.i: -fcompare-debug failure (length) [hjl@gnu-6 stage2-gcc]$
Reducing.
[hjl@gnu-6 stage2-gcc]$ cat x.i enum plugin_event { PLUGIN_GGC_START, PLUGIN_GGC_END }; extern int invoke_plugin_callbacks_full (int, void *); static __inline__ int invoke_plugin_callbacks (int event __attribute__ ((__unused__)), void *gcc_data __attribute__ ((__unused__))) { extern unsigned char flag_plugin_added; if (flag_plugin_added) return invoke_plugin_callbacks_full (event, gcc_data); return 3; } void ggc_collect (void) { invoke_plugin_callbacks (PLUGIN_GGC_START, ((void *)0)); invoke_plugin_callbacks (PLUGIN_GGC_END, ((void *)0)); } [hjl@gnu-6 stage2-gcc]$ ./xgcc -B./ -c -g -O2 x.i -fcompare-debug xgcc: x.i: -fcompare-debug failure (length) [hjl@gnu-6 stage2-gcc]$
It also failed with gcc 4.5.0.
Tail call optimization is disabled with -g.
-foptimize-sibling-calls is affected by external declaration in function.
Even more reduced testcase: invoke_plugin_callbacks (int event) { extern unsigned char flag_plugin_added; return invoke_plugin_callbacks_full (event); } ggc_collect (void) { invoke_plugin_callbacks (0); }
Tail call optimization doesn't handle # DEBUG event => 0 properly.
This patch --- diff --git a/gcc/tree.c b/gcc/tree.c index 8eeecff..0d79020 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -7937,7 +7937,8 @@ auto_var_in_fn_p (const_tree var, const_tree fn) { return (DECL_P (var) && DECL_CONTEXT (var) == fn && (((TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL) - && ! TREE_STATIC (var)) + && ! TREE_STATIC (var) + && ! TREE_PUBLIC (var)) || TREE_CODE (var) == LABEL_DECL || TREE_CODE (var) == RESULT_DECL)); } --- works for me.
That doesn't sound like the right fix. I'll look into this.
So, the first difference that happens is that with -g the extern var is removed from BLOCK_VARs, with -g it is kept there. This happens in remove_unused_scope_block_p. Next during inlining in remap_decls can_be_nonlocal decides the extern var can't be non-local (remapped_type for int is NULL at that point - int hasn't been remapped yet, so it returns false). This is something I don't understand at all - for variably_modified_type_p (TREE_TYPE (decl), id->src_fn) perhaps it makes sense, but aren't all other types just remapped to itself? Thus, remap_decls decides to remap_decl it (in -g case only) and that actually means the remapped var makes it into REFERENCED_VARS. One question is whether auto_var_in_fn_p should return true or false for DECL_EXTERNAL vars with DECL_CONTEXT being the FUNCTION_DECL. Apparently in many places in tree-inline.c this predicate is used to tell whether the decl should be remapped. So, either we need something like H.J.'s patch, but with && !DECL_EXTERNAL (var) (for VAR_DECL only), or e.g. tree-tailcall.c should add a && !DECL_EXTERNAL (var) or && !is_global_var (var) check.
Created attachment 20519 [details] patch1 Patch for tree-tailcall.c, only useful if the second patch isn't used.
Created attachment 20520 [details] patch2 Alternative patch for auto_var_in_fn_p
Created attachment 20521 [details] patch3 Patch to allow vars with non-vla types to be nonlocal if they weren't used and their type hasn't been remapped yet.
All the patches so far completely untested.
Another testcase --- char * bar (void) { extern char ext[]; return ext; } char * foo (void) { return bar (); } -- #2 0x0000000000cecc94 in can_be_nonlocal (decl=0x7ffff190b0a0, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:506 #3 0x0000000000cecd7f in remap_decls (decls=0x7ffff190b0a0, nonlocalized_list=0x7ffff18fb2e8, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:542 #4 0x0000000000ced348 in remap_block (block=0x7fffffffd808, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:603 #5 0x0000000000ced3c5 in remap_blocks (block=0x7ffff18fb058, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:624 #6 0x0000000000cf9255 in expand_call_inline (bb=0x7ffff18f5340, stmt=0x7ffff1952000, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:3742 #7 0x0000000000cf9b80 in gimple_expand_calls_inline (bb=0x7ffff18f5340, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:3926 #8 0x0000000000cfa1c9 in optimize_inline_calls (fn=0x7ffff18f6b00) at /export/gnu/import/git/gcc/gcc/tree-inline.c:4076 #9 0x0000000000cb3d07 in cgraph_early_inlining () at /export/gnu/import/git/gcc/gcc/ipa-inline.c:1696 ---Type <return> to continue, or q <return> to quit--- #10 0x00000000008c51de in execute_one_pass (pass=0x1781240) at /export/gnu/import/git/gcc/gcc/passes.c:1590 #11 0x00000000008c53d2 in execute_pass_list (pass=0x1781240) at /export/gnu/import/git/gcc/gcc/passes.c:1645 #12 0x00000000008c4531 in do_per_function_toporder ( callback=0x8c5391 <execute_pass_list>, data=0x16ba1e0) at /export/gnu/import/git/gcc/gcc/passes.c:1156 #13 0x00000000008c5e3e in execute_ipa_pass_list (pass=0x16ba060) at /export/gnu/import/git/gcc/gcc/passes.c:1925 #14 0x0000000000ca7b9d in ipa_passes () at /export/gnu/import/git/gcc/gcc/cgraphunit.c:1849 #15 0x0000000000ca7d0e in cgraph_optimize () at /export/gnu/import/git/gcc/gcc/cgraphunit.c:1910 #16 0x0000000000ca58e7 in cgraph_finalize_compilation_unit () at /export/gnu/import/git/gcc/gcc/cgraphunit.c:1166 #17 0x00000000004b6614 in c_write_global_declarations () at /export/gnu/import/git/gcc/gcc/c-decl.c:9552 #18 0x00000000009bef13 in compile_file () at /export/gnu/import/git/gcc/gcc/toplev.c:1065 #19 0x00000000009c1192 in do_compile () at /export/gnu/import/git/gcc/gcc/toplev.c:2424 #20 0x00000000009c1268 in toplev_main (argc=15, argv=0x7fffffffdf58) at /export/gnu/import/git/gcc/gcc/toplev.c:2466 ---Type <return> to continue, or q <return> to quit--- #21 0x00000000005733b0 in main (argc=15, argv=0x7fffffffdf58) at /export/gnu/import/git/gcc/gcc/main.c:35 #2 0x0000000000cecc94 in can_be_nonlocal (decl=0x7ffff190b0a0, id=0x7fffffffdba0) at /export/gnu/import/git/gcc/gcc/tree-inline.c:506 506 && !auto_var_in_fn_p (decl, id->src_fn)) (gdb) call debug_tree (decl) <var_decl 0x7ffff190b0a0 ext type <array_type 0x7ffff18f7540 type <integer_type 0x7ffff1a152a0 char public string-flag QI size <integer_cst 0x7ffff1a03758 constant 8> unit size <integer_cst 0x7ffff1a03780 constant 1> align 8 symtab 0 alias set -1 canonical type 0x7ffff1a152a0 precision 8 min <integer_cst 0x7ffff1a03708 -128> max <integer_cst 0x7ffff1a03820 127> pointer_to_this <pointer_type 0x7ffff1a2a930>> BLK align 8 symtab 0 alias set -1 canonical type 0x7ffff18f7540 pointer_to_this <pointer_type 0x7ffff18f75e8>> addressable public external common BLK defer-output file y.i line 4 col 15 align 8 context <function_decl 0x7ffff18f6a00 bar>> (gdb) I don't think auto_var_in_fn_p should return true.
(In reply to comment #13) > Created an attachment (id=20520) [edit] > patch2 > > Alternative patch for auto_var_in_fn_p > I think auto_var_in_fn_p should be fixed properly.
All patches bootstrapped/regtested on x86_64-linux and i686-linux, unfortunately patch3 had slightly negative impact on debuginfo quality (about 4000 variables in rtl checking cc1plus lost DW_AT_location attribute). So I've posted patch2 and for the time being am not proposing patch3.
Subject: Bug 43942 Author: jakub Date: Fri Apr 30 11:24:16 2010 New Revision: 158931 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158931 Log: PR debug/43942 * tree.c (auto_var_in_fn_p): Return false for DECL_EXTERNAL vars. * c-c++-common/pr43942.c: New test. Added: trunk/gcc/testsuite/c-c++-common/pr43942.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree.c
Subject: Bug 43942 Author: jakub Date: Fri Apr 30 11:30:52 2010 New Revision: 158932 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158932 Log: PR debug/43942 * tree.c (auto_var_in_fn_p): Return false for DECL_EXTERNAL vars. * c-c++-common/pr43942.c: New test. Added: branches/gcc-4_5-branch/gcc/testsuite/c-c++-common/pr43942.c Modified: branches/gcc-4_5-branch/gcc/ChangeLog branches/gcc-4_5-branch/gcc/testsuite/ChangeLog branches/gcc-4_5-branch/gcc/tree.c
Fixed.