Bug 43942 - [4.5/4.6 Regression] -fcompare-debug faulure with external declaration in function.
Summary: [4.5/4.6 Regression] -fcompare-debug faulure with external declaration in fun...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: 4.5.1
Assignee: Jakub Jelinek
URL:
Keywords: build, compare-debug-failure, wrong-code
Depends on:
Blocks:
 
Reported: 2010-04-29 17:55 UTC by H.J. Lu
Modified: 2022-01-18 23:30 UTC (History)
3 users (show)

See Also:
Host:
Target: i?86-*-*
Build:
Known to work:
Known to fail: 4.5.0 4.6.0
Last reconfirmed: 2010-04-29 19:23:46


Attachments
A testcase (129.92 KB, application/octet-stream)
2010-04-29 17:57 UTC, H.J. Lu
Details
patch1 (343 bytes, patch)
2010-04-29 20:40 UTC, Jakub Jelinek
Details | Diff
patch2 (328 bytes, patch)
2010-04-29 20:45 UTC, Jakub Jelinek
Details | Diff
patch3 (338 bytes, patch)
2010-04-29 20:46 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2010-04-29 17:55:31 UTC
From PR 43936, -fcompare-debug failed with external declaration in function.
Comment 1 H.J. Lu 2010-04-29 17:57:47 UTC
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]$
Comment 2 Andrew Pinski 2010-04-29 18:05:30 UTC
Reducing.
Comment 3 H.J. Lu 2010-04-29 18:16:31 UTC
[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]$ 
Comment 4 H.J. Lu 2010-04-29 18:18:26 UTC
It also failed with gcc 4.5.0.
Comment 5 H.J. Lu 2010-04-29 18:23:43 UTC
Tail call optimization is disabled with -g.
Comment 6 H.J. Lu 2010-04-29 18:26:45 UTC
-foptimize-sibling-calls is affected by external declaration in function.
Comment 7 Andrew Pinski 2010-04-29 18:27:20 UTC
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);
}
Comment 8 H.J. Lu 2010-04-29 18:44:59 UTC
Tail call optimization doesn't handle

# DEBUG event => 0

properly.
Comment 9 H.J. Lu 2010-04-29 19:16:57 UTC
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.
Comment 10 Jakub Jelinek 2010-04-29 19:23:46 UTC
That doesn't sound like the right fix.

I'll look into this.
Comment 11 Jakub Jelinek 2010-04-29 20:29:51 UTC
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.
Comment 12 Jakub Jelinek 2010-04-29 20:40:54 UTC
Created attachment 20519 [details]
patch1

Patch for tree-tailcall.c, only useful if the second patch isn't used.
Comment 13 Jakub Jelinek 2010-04-29 20:45:21 UTC
Created attachment 20520 [details]
patch2

Alternative patch for auto_var_in_fn_p
Comment 14 Jakub Jelinek 2010-04-29 20:46:20 UTC
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.
Comment 15 Jakub Jelinek 2010-04-29 20:46:52 UTC
All the patches so far completely untested.
Comment 16 H.J. Lu 2010-04-29 23:53:19 UTC
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.
Comment 17 H.J. Lu 2010-04-29 23:57:44 UTC
(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.
Comment 18 Jakub Jelinek 2010-04-30 10:24:10 UTC
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.
Comment 19 Jakub Jelinek 2010-04-30 11:24:40 UTC
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

Comment 20 Jakub Jelinek 2010-04-30 11:31:20 UTC
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

Comment 21 Richard Biener 2010-04-30 12:06:37 UTC
Fixed.