This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]