From 9acf766fe1b9fbdda3e7997f408912bfccfaf5fd Mon Sep 17 00:00:00 2001
From: Daniel Berlin <dberlin@dberlin.org>
Date: Thu, 6 Jan 2005 14:49:34 +0000
Subject: [PATCH] Fix PR middle-end/19286 Fix PR debug/19267

2005-01-05  Daniel Berlin  <dberlin@dberlin.org>

	Fix PR middle-end/19286
	Fix PR debug/19267
	* dwarf2out.c (gen_subprogram_die): If we've already tried to
	output this subprogram, simply ignore this attempt to do it again.
	(add_abstract_origin_attribute): Don't abort trying to add the abstract
	origin attribute if it's not possible.
	(gen_block_die): Don't ignore subblocks of "unused" blocks.
	(decls_for_scope): Ditto.
	* gimple-low.c (mark_blocks_with_used_subblocks): Remove.
	(mark_used_blocks): Don't call mark_blocks_with_used_subblocks.

From-SVN: r92991
---
 gcc/ChangeLog    | 13 +++++++++
 gcc/dwarf2out.c  | 73 +++++++++++++++++++++++++++---------------------
 gcc/gimple-low.c | 34 ++--------------------
 gcc/tree.h       |  3 +-
 4 files changed, 58 insertions(+), 65 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 43e651c84bf4..2cca2aeaf35b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2005-01-05  Daniel Berlin  <dberlin@dberlin.org>
+	
+	Fix PR middle-end/19286
+	Fix PR debug/19267
+	* dwarf2out.c (gen_subprogram_die): If we've already tried to
+	output this subprogram, simply ignore this attempt to do it again.
+	(add_abstract_origin_attribute): Don't abort trying to add the abstract
+	origin attribute if it's not possible.
+	(gen_block_die): Don't ignore subblocks of "unused" blocks.
+	(decls_for_scope): Ditto.
+	* gimple-low.c (mark_blocks_with_used_subblocks): Remove.
+	(mark_used_blocks): Don't call mark_blocks_with_used_subblocks.
+	
 2005-01-05  Richard Henderson  <rth@redhat.com>
 
 	PR target/11327
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 0ad5ce300465..7b8141153e58 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -10462,9 +10462,17 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
   else if (TYPE_P (origin))
     origin_die = lookup_type_die (origin);
 
-  gcc_assert (origin_die);
+  /* XXX: Functions that are never lowered don't always have correct block
+     trees (in the case of java, they simply have no block tree, in some other
+     languages).  For these functions, there is nothing we can really do to
+     output correct debug info for inlined functions in all cases.  Rather
+     than abort, we'll just produce deficient debug info now, in that we will
+     have variables without a proper abstract origin.  In the future, when all
+     functions are lowered, we should re-add a gcc_assert (origin_die)
+     here.  */
 
-  add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+  if (origin_die)
+      add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
 }
 
 /* We do not currently support the pure_virtual attribute.  */
@@ -11199,12 +11207,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 	     It seems reasonable to use AT_specification in this case.  */
 	  && !get_AT (old_die, DW_AT_inline))
 	{
-	  /* ??? This can happen if there is a bug in the program, for
-	     instance, if it has duplicate function definitions.  Ideally,
-	     we should detect this case and ignore it.  For now, if we have
-	     already reported an error, any error at all, then assume that
-	     we got here because of an input error, not a dwarf2 bug.  */
-	  gcc_assert (errorcount);
+	  /* Detect and ignore this case, where we are trying to output
+	     something we have already output.  */
 	  return;
 	}
 
@@ -12234,9 +12238,8 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
   tree decl;
   enum tree_code origin_code;
 
-  /* Ignore blocks never really used to make RTL.  */
-  if (stmt == NULL_TREE || !TREE_USED (stmt)
-      || (!TREE_ASM_WRITTEN (stmt) && !BLOCK_ABSTRACT (stmt)))
+  /* Ignore blocks that are NULL.  */
+  if (stmt == NULL_TREE)
     return;
 
   /* If the block is one fragment of a non-contiguous block, do not
@@ -12282,7 +12285,10 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
 	  if (debug_info_level > DINFO_LEVEL_TERSE)
 	    /* We are not in terse mode so *any* local declaration counts
 	       as being a "significant" one.  */
-	    must_output_die = (BLOCK_VARS (stmt) != NULL);
+	    must_output_die = (BLOCK_VARS (stmt) != NULL 
+			       && (TREE_USED (stmt) 
+				   || TREE_ASM_WRITTEN (stmt)
+				   || BLOCK_ABSTRACT (stmt)));
 	  else
 	    /* We are in terse mode, so only local (nested) function
 	       definitions count as "significant" local declarations.  */
@@ -12324,29 +12330,32 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
   tree decl;
   tree subblocks;
 
-  /* Ignore blocks never really used to make RTL.  */
-  if (stmt == NULL_TREE || ! TREE_USED (stmt))
+  /* Ignore NULL blocks.  */
+  if (stmt == NULL_TREE)
     return;
 
-  /* Output the DIEs to represent all of the data objects and typedefs
-     declared directly within this block but not within any nested
-     sub-blocks.  Also, nested function and tag DIEs have been
-     generated with a parent of NULL; fix that up now.  */
-  for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
+  if (TREE_USED (stmt))
     {
-      dw_die_ref die;
-
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-	die = lookup_decl_die (decl);
-      else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
-	die = lookup_type_die (TREE_TYPE (decl));
-      else
-	die = NULL;
-
-      if (die != NULL && die->die_parent == NULL)
-	add_child_die (context_die, die);
-      else
-	gen_decl_die (decl, context_die);
+      /* Output the DIEs to represent all of the data objects and typedefs
+	 declared directly within this block but not within any nested
+	 sub-blocks.  Also, nested function and tag DIEs have been
+	 generated with a parent of NULL; fix that up now.  */
+      for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
+	{
+	  dw_die_ref die;
+	  
+	  if (TREE_CODE (decl) == FUNCTION_DECL)
+	    die = lookup_decl_die (decl);
+	  else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
+	    die = lookup_type_die (TREE_TYPE (decl));
+	  else
+	    die = NULL;
+	  
+	  if (die != NULL && die->die_parent == NULL)
+	    add_child_die (context_die, die);
+	  else
+	    gen_decl_die (decl, context_die);
+	}
     }
 
   /* If we're at -g1, we're not interested in subblocks.  */
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index ee57d9beda0e..d86cc00307ec 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -541,7 +541,7 @@ struct tree_opt_pass pass_remove_useless_vars =
   0					/* letter */
 };
 
-/* Mark BLOCK used if it has a used variable in it, then recurse over it's
+/* Mark BLOCK used if it has a used variable in it, then recurse over its
    subblocks.  */
 
 static void
@@ -569,42 +569,12 @@ mark_blocks_with_used_vars (tree block)
     mark_blocks_with_used_vars (subblock);
 }
 
-/* Mark BLOCK used if any of it's subblocks have the USED bit set, or it's
-   abstract origin is used.  */
-
-static bool
-mark_blocks_with_used_subblocks (tree block)
-{
-  tree subblock;
- 
-  /* The block may have no variables, but still be used, if it's abstract
-     origin is used.  This occurs when we inline functions with no parameters
-     that call functions with no parameters or local vars (such as
-     dwarf2/dwarf-die7.c).  You end up with a block that has an abstract
-     origin, no variables, and nothing in the subblocks is used.  However, the
-     block is really used, because it's abstract origin was used.  */
-
-  if (BLOCK_ABSTRACT_ORIGIN (block))
-    {
-      if (TREE_USED (BLOCK_ABSTRACT_ORIGIN (block)))
-	TREE_USED (block) = true;
-    }
-
-  for (subblock = BLOCK_SUBBLOCKS (block);
-       subblock;
-       subblock = BLOCK_CHAIN (subblock))
-    TREE_USED (block) |= mark_blocks_with_used_subblocks (subblock);
-  return TREE_USED (block);
-}
-
 /* Mark the used attribute on blocks correctly.  */
   
 static void
 mark_used_blocks (void)
-{
-  
+{  
   mark_blocks_with_used_vars (DECL_INITIAL (current_function_decl));
-  mark_blocks_with_used_subblocks (DECL_INITIAL (current_function_decl));
 }
 
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 0858670609c7..4bdf2b32895c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -966,7 +966,8 @@ extern void tree_operand_check_failed (int, enum tree_code,
 /* Nonzero in a _DECL if the name is used in its scope.
    Nonzero in an expr node means inhibit warning if value is unused.
    In IDENTIFIER_NODEs, this means that some extern decl for this name
-   was used.  */
+   was used.  
+   In a BLOCK, this means that the block contains variables that are used.  */
 #define TREE_USED(NODE) ((NODE)->common.used_flag)
 
 /* In a FUNCTION_DECL, nonzero means a call to the function cannot throw