Regression against g++-4.3 for g++-4.4 on the variable `problem': g++ (GCC) 4.4.0 20090303 (experimental): <1><54>: Abbrev Number: 8 (DW_TAG_subprogram) <55> DW_AT_specification: <0x33> <5a> DW_AT_inline : 0 (not inlined) <2><72>: Abbrev Number: 11 (DW_TAG_lexical_block) <3><73>: Abbrev Number: 12 (DW_TAG_variable) <74> DW_AT_name : (indirect string, offset: 0x14): problem <7a> DW_AT_type : <0x85> (DW_AT_location is not found by any abstract_origin or specificatione etc.) g++ (GCC) 4.4.0 20090219 (Red Hat 4.4.0-0.21): <1><54>: Abbrev Number: 8 (DW_TAG_subprogram) <55> DW_AT_specification: <0x33> <5a> DW_AT_inline : 0 (not inlined) <2><73>: Abbrev Number: 12 (DW_TAG_variable) <74> DW_AT_name : (indirect string, offset: 0x1a): problem <7a> DW_AT_type : <0x10b> it worked before - g++ (GCC) 4.3.2 20081105 (Red Hat 4.3.2-7): <1><85>: Abbrev Number: 10 (DW_TAG_subprogram) <86> DW_AT_specification: <0x33> <8b> DW_AT_inline : 0 (not inlined) <2><a3>: Abbrev Number: 13 (DW_TAG_variable) <a4> DW_AT_name : (indirect string, offset: 0x14): problem <aa> DW_AT_type : <0x7f> <ae> DW_AT_location : 9 byte block: 3 8 0 0 0 0 0 0 0 (DW_OP_addr: 8) ------------------------------------------------------------------------------- extern void f (int *); class A { public: A(int i); }; A::A(int i) { static int *problem = new int(i); f (problem); } void f (int *) { } int main (void) { A a(42); return 0; }
It doesn't work with FSF 4.3.3 for me.
But in FSF 4.1.2 and 4.2.3 I see: .uleb128 0xe # (DIE (0x161) DW_TAG_variable) .ascii "staticvar1\0" # DW_AT_name .byte 0x1 # DW_AT_decl_file (pr39372.C) .byte 0xb # DW_AT_decl_line .long 0xe2 # DW_AT_type .byte 0x9 # DW_AT_location .byte 0x3 # DW_OP_addr .quad _ZZN1AC1EiE10staticvar1 Looking into it.
Ah, the reason why it didn't fail with 4.1.x and older 4.2.x/4.3.x is PR27574. Before that change set_decl_abstract_flags saw error_mark_node DECL_INITIAL and so didn't dive into the blocks, now it does. Guess the right fix will be not mark TREE_STATIC VAR_DECLs in set_block_abstract_flags as abstract.
This is harder than I thought. My first attempt: --- integrate.c.xx2009-02-20 15:36:24.000000000 +0100 +++ integrate.c2009-03-05 15:46:23.000000000 +0100 @@ -173,7 +173,10 @@ set_block_abstract_flags (tree stmt, int for (local_decl = BLOCK_VARS (stmt); local_decl != NULL_TREE; local_decl = TREE_CHAIN (local_decl)) - set_decl_abstract_flags (local_decl, setting); + /* Don't mark local static variables, those are shared between all + inline/cloned copies. */ + if (TREE_CODE (local_decl) != VAR_DECL || !TREE_STATIC (local_decl)) + set_decl_abstract_flags (local_decl, setting); for (subblock = BLOCK_SUBBLOCKS (stmt); subblock != NULL_TREE; works well for this testcase, the abstract DIE has DW_AT_location attribute for the local variable and DIEs for the ctor clones don't have any DIEs for this variable. But it creates worse output for C: extern void f (int *); static inline __attribute__((always_inline)) void foo (void) { static int staticvar1[4]; f (staticvar1); } void bar (void) { foo (); } void baz (void) { foo (); foo (); } Before the patch the abstract fn DIE contains a DIE for the static variable without DW_AT_location and the spots that inline this fn has DIE for the static variable with DW_AT_abstract_origin and DW_AT_location (the same in all cases). After the patch the abstract fn DIE's static variable DIE contains DW_AT_location, the spots that inline this have DIE for the static variable without DW_AT_abstract_origin and again with DW_AT_location. I'd say either the abstract origin DIE shouldn't contain DW_AT_location, but then all spots that use it should contain DW_AT_abstract_origin and DW_AT_location, or the abstract origin DIE should contain DW_AT_location and the clones shouldn't contain the DIE at all. So, I've tried a different patch: --- tree-cfg.c.jj2 2009-03-05 09:44:31.000000000 +0100 +++ tree-cfg.c 2009-03-05 14:57:46.000000000 +0100 @@ -1799,11 +1799,11 @@ remove_useless_stmts_bind (gimple_stmt_i tree var = NULL_TREE; /* Even if there are no gimple_bind_vars, there might be other decls in BLOCK_VARS rendering the GIMPLE_BIND not useless. */ - if (block) + if (block && !BLOCK_NUM_NONLOCALIZED_VARS (block)) for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var)) if (TREE_CODE (var) == IMPORTED_DECL) break; - if (var) + if (var || (block && BLOCK_NUM_NONLOCALIZED_VARS (block))) gsi_next (gsi); else { which prevents removing GIMPLE_BINDs that contain BLOCK_NONLOCALIZED_VARS in its gimple_bind_block (tree-ssa-live.c BLOCK removal does the same thing). Unfortunately this doesn't solve the original bug, because the abstract FUNCTION_DECL in the C++ ctor clone case is marked DECL_ABSTRACT already by the C++ FE, so when dwarf2out_abstract_function is called on it, was_abstract is true and so everything is set to DECL_ABSTRACT, but not reset afterwards. This means the VAR_DECL in clone's BLOCK_NONLOCALIZED_VARS has DECL_ABSTRACT set and thus won't have DW_AT_location emitted.
Created attachment 17404 [details] gcc44-pr39372.patch Patch I'm going to bootstrap/regtest.
Subject: Bug 39372 Author: jakub Date: Fri Mar 6 22:49:39 2009 New Revision: 144682 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=144682 Log: PR debug/39372 * dwarf2out.c (add_abstract_origin_attribute): Return origin_die. (gen_variable_die): Emit DW_AT_location on abstract static variable's DIE, don't emit it if abstract origin already has it. * tree-cfg.c (remove_useless_stmts_bind): GIMPLE_BINDs with any BLOCK_NONLOCALIZED_VARS in its gimple_bind_block aren't useless. * g++.dg/debug/dwarf2/static-local-var-in-ctor.C: New test. Added: trunk/gcc/testsuite/g++.dg/debug/dwarf2/static-local-var-in-ctor.C Modified: trunk/gcc/ChangeLog trunk/gcc/dwarf2out.c trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-cfg.c
Fixed on the trunk so far.
Fixed.