Bug 39372 - [4.3 Regression] Missing DW_AT_location for constructor static variable
Summary: [4.3 Regression] Missing DW_AT_location for constructor static variable
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: 4.4.7
Assignee: Jakub Jelinek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-03-05 00:11 UTC by Jan Kratochvil
Modified: 2012-03-13 13:10 UTC (History)
3 users (show)

See Also:
Host:
Target: x86_64-unknown-linux-gnu
Build:
Known to work: 4.1.2, 4.2.3, 4.4.0
Known to fail: 4.3.3
Last reconfirmed: 2009-03-05 10:54:03


Attachments
gcc44-pr39372.patch (1.78 KB, patch)
2009-03-06 09:46 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Kratochvil 2009-03-05 00:11:50 UTC
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;
}
Comment 1 Richard Biener 2009-03-05 10:39:33 UTC
It doesn't work with FSF 4.3.3 for me.
Comment 2 Jakub Jelinek 2009-03-05 10:54:03 UTC
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.
Comment 3 Jakub Jelinek 2009-03-05 11:14:16 UTC
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.
Comment 4 Jakub Jelinek 2009-03-05 15:02:02 UTC
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.
Comment 5 Jakub Jelinek 2009-03-06 09:46:23 UTC
Created attachment 17404 [details]
gcc44-pr39372.patch

Patch I'm going to bootstrap/regtest.
Comment 6 Jakub Jelinek 2009-03-06 22:49:52 UTC
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

Comment 7 Jakub Jelinek 2009-03-06 22:52:52 UTC
Fixed on the trunk so far.
Comment 8 Jakub Jelinek 2012-03-13 13:10:38 UTC
Fixed.