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: r152077
This commit is contained in:
Dodji Seketeli 2009-09-23 14:58:58 +00:00 committed by Dodji Seketeli
parent e8f8fdbb6c
commit 08553c06e0
12 changed files with 260 additions and 2 deletions

View File

@ -1,3 +1,31 @@
2009-09-23 Dodji Seketeli <dodji@redhat.com>
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.
2009-09-23 Uros Bizjak <ubizjak@gmail.com>
PR c/39779

View File

@ -8407,4 +8407,29 @@ warn_for_sign_compare (location_t location,
}
}
/* 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;
}
}
#include "gt-c-common.h"

View File

@ -1032,6 +1032,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

View File

@ -3381,6 +3381,13 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
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;

View 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-18 Jason Merrill <jason@redhat.com>
* pt.c (get_pattern_parm): New.

View File

@ -5771,6 +5771,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))

View File

@ -13505,10 +13505,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)
{
@ -13522,7 +13523,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)
{
@ -13530,6 +13566,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). */
@ -16446,6 +16492,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)

View File

@ -132,6 +132,10 @@ static VEC(int,heap) *epilogue;
in this function. */
static VEC(int,heap) *sibcall_epilogue;
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);
@ -5372,6 +5376,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)
{
@ -5396,7 +5401,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 =

View File

@ -621,6 +621,28 @@ extern int virtuals_instantiated;
/* Nonzero if at least one trampoline has been created. */
extern int trampolines_created;
struct types_used_by_vars_entry GTY(()) {
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);

View 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 Uros Bizjak <ubizjak@gmail.com>
PR c/39779

View File

@ -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];

View File

@ -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];