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:
parent
e8f8fdbb6c
commit
08553c06e0
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
|
@ -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];
|
Loading…
Reference in New Issue