This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix debuginfo for static vars in C++ ctors (PR debug/39372)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 6 Mar 2009 17:38:03 +0100
- Subject: [PATCH] Fix debuginfo for static vars in C++ ctors (PR debug/39372)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
In the testcase below we never emit DW_AT_location for the static variable
in ctor. In the abstract DIE we don't emit it because it is DECL_ABSTRACT
and in the ctor clone DIEs because the containing GIMPLE_BIND and its BLOCK
has been nuked during useless pass. After fixing this in tree-cfg.c it
still doesn't work, because the variable in BLOCK_NONLOCALIZED_VARS is still
DECL_ABSTRACT. This patch fixes it by emitting DW_AT_location in the
abstract DIE when its DECL_RTL has been set already, because the static
variable is the same between all the clones anyway.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
2009-03-06 Jakub Jelinek <jakub@redhat.com>
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.
--- gcc/dwarf2out.c.jj 2009-03-05 22:14:54.000000000 +0100
+++ gcc/dwarf2out.c 2009-03-06 10:40:09.000000000 +0100
@@ -5128,7 +5128,7 @@ static void add_byte_size_attribute (dw_
static void add_bit_offset_attribute (dw_die_ref, tree);
static void add_bit_size_attribute (dw_die_ref, tree);
static void add_prototyped_attribute (dw_die_ref, tree);
-static void add_abstract_origin_attribute (dw_die_ref, tree);
+static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
static void add_pure_or_virtual_attribute (dw_die_ref, tree);
static void add_src_coords_attributes (dw_die_ref, tree);
static void add_name_and_src_coords_attributes (dw_die_ref, tree);
@@ -12479,7 +12479,7 @@ add_prototyped_attribute (dw_die_ref die
by looking in either the type declaration or object declaration
equate table. */
-static inline void
+static inline dw_die_ref
add_abstract_origin_attribute (dw_die_ref die, tree origin)
{
dw_die_ref origin_die = NULL;
@@ -12517,7 +12517,8 @@ add_abstract_origin_attribute (dw_die_re
here. */
if (origin_die)
- add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ return origin_die;
}
/* We do not currently support the pure_virtual attribute. */
@@ -13885,6 +13886,7 @@ gen_variable_die (tree decl, tree origin
tree decl_or_origin = decl ? decl : origin;
dw_die_ref var_die;
dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
+ dw_die_ref origin_die;
int declaration = (DECL_EXTERNAL (decl_or_origin)
/* If DECL is COMDAT and has not actually been
emitted, we cannot take its address; there
@@ -14018,8 +14020,9 @@ gen_variable_die (tree decl, tree origin
var_die = new_die (DW_TAG_variable, context_die, decl);
+ origin_die = NULL;
if (origin != NULL)
- add_abstract_origin_attribute (var_die, origin);
+ origin_die = add_abstract_origin_attribute (var_die, origin);
/* Loop unrolling can create multiple blocks that refer to the same
static variable, so we must test for the DW_AT_declaration flag.
@@ -14082,7 +14085,17 @@ gen_variable_die (tree decl, tree origin
if (decl && (DECL_ABSTRACT (decl) || declaration))
equate_decl_number_to_die (decl, var_die);
- if (! declaration && ! DECL_ABSTRACT (decl_or_origin))
+ if (! declaration
+ && (! DECL_ABSTRACT (decl_or_origin)
+ /* Local static vars are shared between all clones/inlines,
+ so emit DW_AT_location on the abstract DIE if DECL_RTL is
+ already set. */
+ || (TREE_CODE (decl_or_origin) == VAR_DECL
+ && TREE_STATIC (decl_or_origin)
+ && DECL_RTL_SET_P (decl_or_origin)))
+ /* When abstract origin already has DW_AT_location attribute, no need
+ to add it again. */
+ && (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
{
if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
&& !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
--- gcc/tree-cfg.c.jj 2009-03-05 09:44:31.000000000 +0100
+++ gcc/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
{
--- gcc/testsuite/g++.dg/debug/dwarf2/static-local-var-in-ctor.C.jj 2009-03-06 10:33:57.000000000 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/static-local-var-in-ctor.C 2009-03-06 10:36:19.000000000 +0100
@@ -0,0 +1,37 @@
+// PR debug/39372
+// { dg-do compile }
+// { dg-options "-O0 -g -dA" }
+// { dg-final { scan-assembler "DW_OP_addr\[^\n\r\]*\[\n\r\]*\[^\n\r\]*staticvar1" } }
+// { dg-final { scan-assembler "DW_OP_addr\[^\n\r\]*\[\n\r\]*\[^\n\r\]*staticvar2" } }
+
+extern void f (int *);
+
+struct A
+{
+ A(int i);
+ void foo(int i);
+};
+
+A::A(int i)
+{
+ static int *staticvar1 = new int(i);
+ f (staticvar1);
+}
+
+void A::foo(int i)
+{
+ static int *staticvar2 = new int(i);
+ f (staticvar2);
+}
+
+void f (int *)
+{
+}
+
+int
+main (void)
+{
+ A a(42);
+ a.foo(42);
+ return 0;
+}
Jakub