This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR debug/26754
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 13 May 2006 23:36:46 +0200
- Subject: [PATCH] Fix PR debug/26754
Hi,
Debug info generated by the 4.x series of compilers are wrong for variables
accessed from nested functions:
void foo(void)
{
int a = 0;
void bar(void)
{
a = 1;
}
bar ();
a = a + 1;
}
int main(void)
{
foo ();
}
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-suse-linux"...Using host libthread_db library
"/lib/tls/libthread_db.so.1".
(gdb) b t.c:11
Breakpoint 1 at 0x8048389: file t.c, line 11.
(gdb) run
Starting program: /home/eric/gnat/bugs/F318-004/t
Breakpoint 1, foo () at t.c:11
11 a = a + 1;
(gdb) p a
$1 = -12412
(gdb) next
12 }
(gdb) p a
$2 = -12412
This is of course a regression from the 3.x series of compilers. The culprit
is the nested functions lowering pass that puts these variables into the
"non-local frame structure" without telling anyone. Surprisingly enough,
there is already support code in mainline (get_nonlocal_debug_decl and
get_local_debug_decl) but it is effectively disabled.
Bootstrapped/regtested on i586-suse-linux. OK for mainline?
2006-05-13 Eric Botcazou <ebotcazou@adacore.com>
PR debug/26754
* gimplify.c (declare_regular_vars): New function.
* tree-gimple.h (declare_regular_vars): Declare it.
* tree-nested.c (get_local_debug_decl): Set DECL_IGNORED_P
on the original variable.
(finalize_nesting_tree_1): Declare debug_var_chain as regular
variables instead of temporary variables.
--
Eric Botcazou
Index: gimplify.c
===================================================================
--- gimplify.c (revision 113625)
+++ gimplify.c (working copy)
@@ -643,7 +643,7 @@ get_initialized_tmp_var (tree val, tree
return internal_get_tmp_var (val, pre_p, post_p, false);
}
-/* Declares all the variables in VARS in SCOPE. */
+/* Declares all nodes in VARS as temporary variables in SCOPE. */
void
declare_tmp_vars (tree vars, tree scope)
@@ -666,6 +666,45 @@ declare_tmp_vars (tree vars, tree scope)
}
}
+/* Declares all nodes in VARS as regular variables in SCOPE. */
+
+void
+declare_regular_vars (tree vars, tree scope)
+{
+ tree last = vars;
+ if (last)
+ {
+ tree temps, block;
+
+ /* C99 mode puts the default 'return 0;' for main outside the outer
+ braces. So drill down until we find an actual scope. */
+ while (TREE_CODE (scope) == COMPOUND_EXPR)
+ scope = TREE_OPERAND (scope, 0);
+
+ gcc_assert (TREE_CODE (scope) == BIND_EXPR);
+
+ block = BIND_EXPR_BLOCK (scope);
+ if (!block)
+ {
+ declare_tmp_vars (vars, scope);
+ return;
+ }
+
+ /* We need to attach the nodes both to the BIND_EXPR and to its
+ associated BLOCK for debugging purposes. The key point here
+ is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
+ is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
+ temps = nreverse (last);
+ if (BLOCK_VARS (block))
+ BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
+ else
+ {
+ BIND_EXPR_VARS (scope) = chainon (BIND_EXPR_VARS (scope), temps);
+ BLOCK_VARS (block) = temps;
+ }
+ }
+}
+
void
gimple_add_tmp_var (tree tmp)
{
Index: tree-gimple.h
===================================================================
--- tree-gimple.h (revision 113625)
+++ tree-gimple.h (working copy)
@@ -31,6 +31,7 @@ extern tree create_tmp_var (tree, const
extern tree get_initialized_tmp_var (tree, tree *, tree *);
extern tree get_formal_tmp_var (tree, tree *);
extern void declare_tmp_vars (tree, tree);
+extern void declare_regular_vars (tree, tree);
extern void annotate_all_with_locus (tree *, location_t);
Index: tree-nested.c
===================================================================
--- tree-nested.c (revision 113625)
+++ tree-nested.c (working copy)
@@ -1186,6 +1186,9 @@ get_local_debug_decl (struct nesting_inf
TREE_CHAIN (new_decl) = info->debug_var_chain;
info->debug_var_chain = new_decl;
+ /* Do not emit debug info twice. */
+ DECL_IGNORED_P (decl) = 1;
+
return new_decl;
}
@@ -1807,8 +1810,8 @@ finalize_nesting_tree_1 (struct nesting_
declare_tmp_vars (root->new_local_var_chain,
DECL_SAVED_TREE (root->context));
if (root->debug_var_chain)
- declare_tmp_vars (root->debug_var_chain,
- DECL_SAVED_TREE (root->context));
+ declare_regular_vars (root->debug_var_chain,
+ DECL_SAVED_TREE (root->context));
/* Dump the translated tree function. */
dump_function (TDI_nested, root->context);