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 debug info of nested inline functions


Hi Jason,

you may remember a patch I posted and over which we exchanged a few messages:
  first message: http://gcc.gnu.org/ml/gcc-patches/2010-07/msg02143.html
  last message: http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01289.html
I eventually dropped the ball and nothing was installed, although we had almost 
reached an agreement.

The problem is still present as of today on the mainline, so I think now is a 
good time to solve it once for all.  We were disagreeing on the last hunk of 
the latest revision of the patch:
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01286.html
and you suggested to iterate over DECL_CONTEXT instead of die_parent to find an 
appropriate parent in order to attach the DIE on the limbo list to.

I confirm that we need to iterate, as the immediate DECL_CONTEXT is an abtract 
instance for the testcase.  The attached patch implements this and generates 
exactly the same debug info for the testcase as the original patch.

Tested on x86_64-suse-linux, OK for the mainline?


2012-03-02  Eric Botcazou  <ebotcazou@adacore.com>

	* dwarf2out.c (gen_subprogram_die): Emit a definition of nested
	functions within an abstract instance of their parent.
	(gen_inlined_subroutine_die): Return if the origin is to be ignored.
	(function_possibly_abstracted_p): New static function.
	(process_scope_var): Do not emit concrete instances of abstracted
	nested functions from here.
	(gen_decl_die): Emit the abstract instance if the function is possibly
	abstracted and not only possibly inlined.
	(dwarf2out_finish): Skip an abtract parent instance and iterate over
	the context to find the first non-abstract parent instance to attach
	concrete instances on the limbo list to it.


-- 
Eric Botcazou
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 184668)
+++ dwarf2out.c	(working copy)
@@ -17173,7 +17173,13 @@ gen_subprogram_die (tree decl, dw_die_re
   dw_die_ref subr_die;
   tree outer_scope;
   dw_die_ref old_die = lookup_decl_die (decl);
-  int declaration = (current_function_decl != decl
+  /* Emit an abstract instance of nested functions within an abstract instance
+     of their parent.  */
+  int declaration = ((decl != current_function_decl
+		      && !(DECL_INITIAL (decl) != NULL_TREE
+			   && DECL_ABSTRACT (decl)
+			   && current_function_decl
+			   && DECL_ABSTRACT (current_function_decl)))
 		     || class_or_namespace_scope_p (context_die));
 
   premark_used_types ();
@@ -18198,6 +18204,8 @@ gen_inlined_subroutine_die (tree stmt, d
   gcc_assert (! BLOCK_ABSTRACT (stmt));
 
   decl = block_ultimate_origin (stmt);
+  if (DECL_IGNORED_P (decl))
+    return;
 
   /* Emit info for the abstract instance first, if we haven't yet.  We
      must emit this even if the block is abstract, otherwise when we
@@ -19158,8 +19166,25 @@ gen_block_die (tree stmt, dw_die_ref con
     decls_for_scope (stmt, context_die, depth);
 }
 
+/* Return true if an abstract instance of function DECL can be generated in
+   the debug information.  */
+
+static bool
+function_possibly_abstracted_p (tree decl)
+{
+  while (decl)
+    {
+      if (cgraph_function_possibly_inlined_p (decl))
+	return true;
+      decl = decl_function_context (decl);
+    }
+
+  return false;
+}
+
 /* Process variable DECL (or variable with origin ORIGIN) within
    block STMT and add it to CONTEXT_DIE.  */
+
 static void
 process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
 {
@@ -19177,8 +19202,15 @@ process_scope_var (tree stmt, tree decl,
   if (die != NULL && die->die_parent == NULL)
     add_child_die (context_die, die);
   else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
-    dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
+    dwarf2out_imported_module_or_decl_1 (decl_or_origin,
+					 DECL_NAME (decl_or_origin),
 					 stmt, context_die);
+  /* Do not emit concrete instances of abstracted nested functions without
+     actual instances.  */
+  else if (TREE_CODE (decl_or_origin) == FUNCTION_DECL
+	   && die
+	   && get_AT (die, DW_AT_inline))
+    ;
   else
     gen_decl_die (decl, origin, context_die);
 }
@@ -19525,11 +19557,11 @@ gen_decl_die (tree decl, tree origin, dw
 				     ? DECL_ORIGIN (origin)
 				     : DECL_ABSTRACT_ORIGIN (decl));
 
-      /* If we're emitting an out-of-line copy of an inline function,
+      /* If we're emitting an out-of-line copy of an abstracted function,
 	 emit info for the abstract instance and set up to refer to it.  */
-      else if (cgraph_function_possibly_inlined_p (decl)
-	       && ! DECL_ABSTRACT (decl)
-	       && ! class_or_namespace_scope_p (context_die)
+      else if (!DECL_ABSTRACT (decl)
+	       && function_possibly_abstracted_p (decl)
+	       && !class_or_namespace_scope_p (context_die)
 	       /* dwarf2out_abstract_function won't emit a die if this is just
 		  a declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
 		  that case, because that works only if we have a die.  */
@@ -22526,7 +22558,11 @@ dwarf2out_finish (const char *filename)
 	{
 	  dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
 
-	  if (origin && origin->die_parent)
+	  if (origin
+	      && origin->die_parent
+	      /* Skip an abtract parent instance.  */
+	      && !(origin->die_parent->die_tag == DW_TAG_subprogram
+		   && get_AT (origin->die_parent, DW_AT_inline)))
 	    add_child_die (origin->die_parent, die);
 	  else if (is_cu_die (die))
 	    ;
@@ -22545,16 +22581,22 @@ dwarf2out_finish (const char *filename)
 		 inlined and optimized out.  In that case we are lost and
 		 assign the empty child.  This should not be big issue as
 		 the function is likely unreachable too.  */
-	      tree context = NULL_TREE;
-
-	      gcc_assert (node->created_for);
+	      tree context = node->created_for;
+	      gcc_assert (context);
 
-	      if (DECL_P (node->created_for))
-		context = DECL_CONTEXT (node->created_for);
-	      else if (TYPE_P (node->created_for))
-		context = TYPE_CONTEXT (node->created_for);
+	      /* Find the first non-abstract parent instance.  */
+	      do {
+		if (DECL_P (context))
+		  context = DECL_CONTEXT (context);
+		else if (TYPE_P (context))
+		  context = TYPE_CONTEXT (context);
+		else
+		  context = NULL_TREE;
+		origin = get_context_die (context);
+	      } while (origin
+		       && origin->die_tag == DW_TAG_subprogram
+		       && get_AT (origin, DW_AT_inline));
 
-	      origin = get_context_die (context);
 	      add_child_die (origin, die);
 	    }
 	}

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