OSDN Git Service

Fix PR debug/41065
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 23 Sep 2009 16:07:13 +0000 (16:07 +0000)
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 23 Sep 2009 16:07:13 +0000 (16:07 +0000)
gcc/ChangeLog:
PR debug/41065
* function.h (types_used_by_vars_hash): Declare new hash table.
(types_used_by_vars_eq, types_used_by_var_decl_insert): Declare
equality and hash function for the hash table.
(types_used_by_cur_var_decl): Declare a new global chained list.
(types_used_by_var_decl_insert): Declare new function.
* function.c (types_used_by_vars_hash): Define the hashtable ...
(types_used_by_vars_eq, types_used_by_vars_do_hash): ... as well as
its equality and hash functions.
(hash_types_used_by_vars_entry): New hash helper.
(types_used_by_cur_var_decl): Define the global chained list.
(used_types_insert): Update the list of types used by the global
variable being parsed.
(types_used_by_var_decl_insert): Define new function.
* c-common.h (record_types_used_by_current_var_decl): Declare ...
* c-common.c (record_types_used_by_current_var_decl): ... new
function.
* c-decl.c (finish_decl): Record the types used by the global
variable declaration we've just parsed.
* dwarf2out.c (premark_used_types): Insert a new line between
comment and function.
(premark_used_types_helper): Fix comment.
(premark_types_used_by_global_vars_helper,
premark_types_used_by_global_vars): New functions.
(prune_unused_types): Do not prune types used by global variables.

gcc/cp/ChangeLog:
PR debug/41065
* decl.c (cp_finish_decl): Record the types used by the global
variable declaration we've just parsed.

gcc/testsuite/ChangeLog:
PR debug/41065
* gcc.dg/debug/dwarf2/global-used-types.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152085 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/dwarf2out.c
gcc/function.c
gcc/function.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c [new file with mode: 0644]

index 25c0c01..a9e1286 100644 (file)
@@ -9182,6 +9182,31 @@ is_typedef_decl (tree x)
           && DECL_ORIGINAL_TYPE (x) != NULL_TREE);
 }
 
+/* Record the types used by the current global variable declaration
+   being parsed, so that we can decide later to emit their debug info.
+   Those types are in types_used_by_cur_var_decl, and we are going to
+   store them in the types_used_by_vars_hash hash table.
+   DECL is the declaration of the global variable that has been parsed.  */
+
+void
+record_types_used_by_current_var_decl (tree decl)
+{
+  gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
+
+  if (types_used_by_cur_var_decl)
+    {
+      tree node;
+      for (node = types_used_by_cur_var_decl;
+          node;
+          node = TREE_CHAIN (node))
+      {
+       tree type = TREE_PURPOSE (node);
+       types_used_by_var_decl_insert (type, decl);
+      }
+      types_used_by_cur_var_decl = NULL;
+    }
+}
+
 /* The C and C++ parsers both use vectors to hold function arguments.
    For efficiency, we keep a cache of unused vectors.  This is the
    cache.  */
index 9b7905b..6a02e04 100644 (file)
@@ -1130,6 +1130,7 @@ extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 /* Not in c-omp.c; provided by the front end.  */
 extern bool c_omp_sharing_predetermined (tree);
 extern tree c_omp_remap_decl (tree, bool);
+extern void record_types_used_by_current_var_decl (tree);
 
 /* In order for the format checking to accept the C frontend
    diagnostic framework extensions, you must include this file before
index c44e35c..e237332 100644 (file)
@@ -4064,6 +4064,13 @@ finish_decl (tree decl, location_t init_loc, tree init,
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
+  if (TREE_CODE (decl) == VAR_DECL
+      && TREE_STATIC (decl)
+      && global_bindings_p ())
+    /* So decl is a global variable. Record the types it uses
+       so that we can decide later to emit debug info for them.  */
+    record_types_used_by_current_var_decl (decl);
+
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
   if (init != 0 && DECL_INITIAL (decl) == 0)
     init = 0;
index ae3045e..338e725 100644 (file)
@@ -1,3 +1,9 @@
+2009-09-23  Dodji Seketeli  <dodji@redhat.com>
+
+       PR debug/41065
+       * decl.c (cp_finish_decl): Record the types used by the global
+       variable declaration we've just parsed.
+
 2009-09-22  Dodji Seketeli  <dodji@redhat.com>
 
        * cp-lang.c (LANG_HOOKS_FUNCTION_PARAMETER_PACK_P,
index 614dbb0..407f734 100644 (file)
@@ -5801,6 +5801,15 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
         type.  */
       else if (TREE_CODE (type) == ARRAY_TYPE)
        layout_type (type);
+
+      if (!processing_template_decl
+         && TREE_STATIC (decl)
+         && !at_function_scope_p ()
+         && current_function_decl == NULL)
+       /* So decl is a global variable or a static member of a
+          non local class. Record the types it uses
+          so that we can decide later to emit debug info for them.  */
+       record_types_used_by_current_var_decl (decl);
     }
   else if (TREE_CODE (decl) == FIELD_DECL
           && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
index a2e91d4..b8a0434 100644 (file)
@@ -15649,10 +15649,11 @@ dwarf2out_abstract_function (tree decl)
 }
 
 /* Helper function of premark_used_types() which gets called through
-   htab_traverse_resize().
+   htab_traverse.
 
    Marks the DIE of a given type in *SLOT as perennial, so it never gets
    marked as unused by prune_unused_types.  */
+
 static int
 premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
 {
@@ -15666,7 +15667,42 @@ premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
   return 1;
 }
 
+/* Helper function of premark_types_used_by_global_vars which gets called
+   through htab_traverse.
+
+   Marks the DIE of a given type in *SLOT as perennial, so it never gets
+   marked as unused by prune_unused_types. The DIE of the type is marked
+   only if the global variable using the type will actually be emitted.  */
+
+static int
+premark_types_used_by_global_vars_helper (void **slot,
+                                         void *data ATTRIBUTE_UNUSED)
+{
+  struct types_used_by_vars_entry *entry;
+  dw_die_ref die;
+
+  entry = (struct types_used_by_vars_entry *) *slot;
+  gcc_assert (entry->type != NULL
+             && entry->var_decl != NULL);
+  die = lookup_type_die (entry->type);
+  if (die)
+    {
+      /* Ask cgraph if the global variable really is to be emitted.
+         If yes, then we'll keep the DIE of ENTRY->TYPE.  */
+      struct varpool_node *node = varpool_node (entry->var_decl);
+      if (node->needed)
+       {
+         die->die_perennial_p = 1;
+         /* Keep the parent DIEs as well.  */
+         while ((die = die->die_parent) && die->die_perennial_p == 0)
+           die->die_perennial_p = 1;
+       }
+    }
+  return 1;
+}
+
 /* Mark all members of used_types_hash as perennial.  */
+
 static void
 premark_used_types (void)
 {
@@ -15674,6 +15710,16 @@ premark_used_types (void)
     htab_traverse (cfun->used_types_hash, premark_used_types_helper, NULL);
 }
 
+/* Mark all members of types_used_by_vars_entry as perennial.  */
+
+static void
+premark_types_used_by_global_vars (void)
+{
+  if (types_used_by_vars_hash)
+    htab_traverse (types_used_by_vars_hash,
+                  premark_types_used_by_global_vars_helper, NULL);
+}
+
 /* Generate a DIE to represent a declared function (either file-scope or
    block-local).  */
 
@@ -18776,6 +18822,9 @@ prune_unused_types (void)
     verify_marks_clear (node->die);
 #endif /* ENABLE_ASSERT_CHECKING */
 
+  /* Mark types that are used in global variables.  */
+  premark_types_used_by_global_vars ();
+
   /* Set the mark on nodes that are actually used.  */
   prune_unused_types_walk (comp_unit_die);
   for (node = limbo_die_list; node; node = node->next)
index 6c9bea8..aaed57a 100644 (file)
@@ -130,6 +130,10 @@ static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
 static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
   htab_t epilogue_insn_hash;
 \f
+
+htab_t types_used_by_vars_hash = NULL;
+tree types_used_by_cur_var_decl = NULL;
+
 /* Forward declarations.  */
 
 static struct temp_slot *find_temp_slot_from_address (rtx);
@@ -5426,6 +5430,7 @@ rest_of_handle_check_leaf_regs (void)
 }
 
 /* Insert a TYPE into the used types hash table of CFUN.  */
+
 static void
 used_types_insert_helper (tree type, struct function *func)
 {
@@ -5450,7 +5455,81 @@ used_types_insert (tree t)
     t = TREE_TYPE (t);
   t = TYPE_MAIN_VARIANT (t);
   if (debug_info_level > DINFO_LEVEL_NONE)
-    used_types_insert_helper (t, cfun);
+    {
+      if (cfun)
+       used_types_insert_helper (t, cfun);
+      else
+       /* So this might be a type referenced by a global variable.
+          Record that type so that we can later decide to emit its debug
+          information.  */
+       types_used_by_cur_var_decl =
+         tree_cons (t, NULL, types_used_by_cur_var_decl);
+
+    }
+}
+
+/* Helper to Hash a struct types_used_by_vars_entry.  */
+
+static hashval_t
+hash_types_used_by_vars_entry (const struct types_used_by_vars_entry *entry)
+{
+  gcc_assert (entry && entry->var_decl && entry->type);
+
+  return iterative_hash_object (entry->type,
+                               iterative_hash_object (entry->var_decl, 0));
+}
+
+/* Hash function of the types_used_by_vars_entry hash table.  */
+
+hashval_t
+types_used_by_vars_do_hash (const void *x)
+{
+  const struct types_used_by_vars_entry *entry =
+    (const struct types_used_by_vars_entry *) x;
+
+  return hash_types_used_by_vars_entry (entry);
+}
+
+/*Equality function of the types_used_by_vars_entry hash table.  */
+
+int
+types_used_by_vars_eq (const void *x1, const void *x2)
+{
+  const struct types_used_by_vars_entry *e1 =
+    (const struct types_used_by_vars_entry *) x1;
+  const struct types_used_by_vars_entry *e2 =
+    (const struct types_used_by_vars_entry *)x2;
+
+  return (e1->var_decl == e2->var_decl && e1->type == e2->type);
+}
+
+/* Inserts an entry into the types_used_by_vars_hash hash table. */
+
+void
+types_used_by_var_decl_insert (tree type, tree var_decl)
+{
+  if (type != NULL && var_decl != NULL)
+    {
+      void **slot;
+      struct types_used_by_vars_entry e;
+      e.var_decl = var_decl;
+      e.type = type;
+      if (types_used_by_vars_hash == NULL)
+       types_used_by_vars_hash =
+         htab_create_ggc (37, types_used_by_vars_do_hash,
+                          types_used_by_vars_eq, NULL);
+      slot = htab_find_slot_with_hash (types_used_by_vars_hash, &e,
+                                      hash_types_used_by_vars_entry (&e), INSERT);
+      if (*slot == NULL)
+       {
+         struct types_used_by_vars_entry *entry;
+         entry = (struct types_used_by_vars_entry*) ggc_alloc
+                   (sizeof (struct types_used_by_vars_entry));
+         entry->type = type;
+         entry->var_decl = var_decl;
+         *slot = entry;
+       }
+    }
 }
 
 struct rtl_opt_pass pass_leaf_regs =
index 72aad00..4825d16 100644 (file)
@@ -622,6 +622,28 @@ extern int virtuals_instantiated;
 /* Nonzero if at least one trampoline has been created.  */
 extern int trampolines_created;
 
+struct GTY(()) types_used_by_vars_entry {
+  tree type;
+  tree var_decl;
+};
+
+/* Hash table making the relationship between a global variable
+   and the types it references in its initializer. The key of the
+   entry is a referenced type, and the value is the DECL of the global
+   variable. types_use_by_vars_do_hash and types_used_by_vars_eq below are
+   the hash and equality functions to use for this hash table.  */
+extern GTY((param_is (struct types_used_by_vars_entry))) htab_t
+  types_used_by_vars_hash;
+
+hashval_t types_used_by_vars_do_hash (const void*);
+int types_used_by_vars_eq (const void *, const void *);
+void types_used_by_var_decl_insert (tree type, tree var_decl);
+
+/* During parsing of a global variable, this linked list points to
+   the list of types referenced by the global variable.  */
+extern GTY(()) tree types_used_by_cur_var_decl;
+
+
 /* cfun shouldn't be set directly; use one of these functions instead.  */
 extern void set_cfun (struct function *new_cfun);
 extern void push_cfun (struct function *new_cfun);
index 5b611f7..5fa33fd 100644 (file)
@@ -1,3 +1,8 @@
+ 2009-09-23  Dodji Seketeli  <dodji@redhat.com>
+
+       PR debug/41065
+       * gcc.dg/debug/dwarf2/global-used-types.c: New test.
+
 2009-09-23  Andreas Schwab  <schwab@redhat.com>
 
        * lib/profopt.exp (profopt-get-options): Set tool_flags for
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C
new file mode 100644 (file)
index 0000000..bad08ed
--- /dev/null
@@ -0,0 +1,13 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-g -dA -fno-merge-debug-strings" }
+// { dg-do compile }
+// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumeration_type" 1 } }
+// { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumerator" 2 } }
+// { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+.*?DW_AT_name" 1 } }
+// { dg-final { scan-assembler-times "ascii \"b.0\"\[\t \]+.*?DW_AT_name" 1 } }
+
+struct foo
+{
+  enum { a, b };
+};
+char s[foo::b];
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c b/gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c
new file mode 100644 (file)
index 0000000..1c2d403
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ Contributed by Dodji Seketeli <dodji@redhat.com>
+ { dg-options "-g -dA -fno-merge-debug-strings" }
+ { dg-do compile }
+ { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumeration_type" 1 } }
+ { dg-final { scan-assembler-times "DIE \\(0x.*?\\) DW_TAG_enumerator" 2 } }
+ { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+.*?DW_AT_name" 1 } }
+ { dg-final { scan-assembler-times "ascii \"b.0\"\[\t \]+.*?DW_AT_name" 1 } }
+ */
+
+enum { a, b };
+
+int v = a;
+char s[b];