aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2009-09-23 16:07:13 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2009-09-23 18:07:13 +0200
commitb646ba3f1c134c4fc22b000caff77725ccec1791 (patch)
tree716216bf133fc60984e49edb258a912ca31ba3e8 /gcc
parent4c6858252cf0b39482c1a436f6d9dcd7cc0a44f9 (diff)
downloadgcc-b646ba3f1c134c4fc22b000caff77725ccec1791.zip
gcc-b646ba3f1c134c4fc22b000caff77725ccec1791.tar.gz
gcc-b646ba3f1c134c4fc22b000caff77725ccec1791.tar.bz2
re PR debug/41065 (DW_TAG_enumeration_type+DW_TAG_enumerator is sometimes missing)
Fix PR debug/41065 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. From-SVN: r152085
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-common.c25
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/c-decl.c7
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/dwarf2out.c51
-rw-r--r--gcc/function.c81
-rw-r--r--gcc/function.h22
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C13
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c14
11 files changed, 232 insertions, 2 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 25c0c01..a9e1286 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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. */
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 9b7905b..6a02e04 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index c44e35c..e237332 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ae3045e..338e725 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 614dbb0..407f734 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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))
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index a2e91d4..b8a0434 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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)
diff --git a/gcc/function.c b/gcc/function.c
index 6c9bea8..aaed57a 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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;
+
+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 =
diff --git a/gcc/function.h b/gcc/function.h
index 72aad00..4825d16 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5b611f7..5fa33fd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..bad08ed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/global-used-types-1.C
@@ -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
index 0000000..1c2d403
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/global-used-types.c
@@ -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];