mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-20 09:20:42 +08:00
Support namespaces in DWARF 2 output.
* dwarf2out.c (gen_namespace_die): New function. (force_namespace_die, setup_namespace_context): New fns. (declare_in_namespace): New fn. (gen_decl_die): Call declare_in_namespace. Handle namespaces. (dwarf2out_decl): Handle namespaces. (scope_die_for): Pass through a namespace scope. (class_scope_p): Rename to class_or_namespace_scope_p. (gen_subprogram_die, gen_variable_die): Adjust. (gen_struct_or_union_die): Always emit a declaration if context_die is a namespace. Co-Authored-By: Daniel Berlin <dberlin@dberlin.org> From-SVN: r74436
This commit is contained in:
parent
ed36980c22
commit
66c78aa97a
@ -1,3 +1,18 @@
|
||||
2003-12-08 Jason Merrill <jason@redhat.com>
|
||||
Daniel Berlin <dberlin@dberlin.org>
|
||||
|
||||
Support namespaces in DWARF 2 output.
|
||||
* dwarf2out.c (gen_namespace_die): New function.
|
||||
(force_namespace_die, setup_namespace_context): New fns.
|
||||
(declare_in_namespace): New fn.
|
||||
(gen_decl_die): Call declare_in_namespace. Handle namespaces.
|
||||
(dwarf2out_decl): Handle namespaces.
|
||||
(scope_die_for): Pass through a namespace scope.
|
||||
(class_scope_p): Rename to class_or_namespace_scope_p.
|
||||
(gen_subprogram_die, gen_variable_die): Adjust.
|
||||
(gen_struct_or_union_die): Always emit a declaration
|
||||
if context_die is a namespace.
|
||||
|
||||
2003-12-08 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* unwind-pe.h (read_uleb128): Fix handling of large values
|
||||
|
153
gcc/dwarf2out.c
153
gcc/dwarf2out.c
@ -3740,7 +3740,7 @@ static void push_decl_scope (tree);
|
||||
static void pop_decl_scope (void);
|
||||
static dw_die_ref scope_die_for (tree, dw_die_ref);
|
||||
static inline int local_scope_p (dw_die_ref);
|
||||
static inline int class_scope_p (dw_die_ref);
|
||||
static inline int class_or_namespace_scope_p (dw_die_ref);
|
||||
static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
|
||||
static const char *type_tag (tree);
|
||||
static tree member_declared_type (tree);
|
||||
@ -3778,7 +3778,11 @@ static void gen_tagged_type_instantiation_die (tree, dw_die_ref);
|
||||
static void gen_block_die (tree, dw_die_ref, int);
|
||||
static void decls_for_scope (tree, dw_die_ref, int);
|
||||
static int is_redundant_typedef (tree);
|
||||
static void gen_namespace_die (tree);
|
||||
static void gen_decl_die (tree, dw_die_ref);
|
||||
static dw_die_ref force_namespace_die (tree);
|
||||
static dw_die_ref setup_namespace_context (tree, dw_die_ref);
|
||||
static void declare_in_namespace (tree, dw_die_ref);
|
||||
static unsigned lookup_filename (const char *);
|
||||
static void init_file_table (void);
|
||||
static void retry_incomplete_types (void);
|
||||
@ -4034,6 +4038,8 @@ dwarf_tag_name (unsigned int tag)
|
||||
return "DW_TAG_namelist";
|
||||
case DW_TAG_namelist_item:
|
||||
return "DW_TAG_namelist_item";
|
||||
case DW_TAG_namespace:
|
||||
return "DW_TAG_namespace";
|
||||
case DW_TAG_packed_type:
|
||||
return "DW_TAG_packed_type";
|
||||
case DW_TAG_subprogram:
|
||||
@ -10020,9 +10026,14 @@ scope_die_for (tree t, dw_die_ref context_die)
|
||||
|
||||
containing_scope = TYPE_CONTEXT (t);
|
||||
|
||||
/* Ignore namespaces for the moment. */
|
||||
/* Use the containing namespace if it was passed in (for a declaration). */
|
||||
if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
|
||||
containing_scope = NULL_TREE;
|
||||
{
|
||||
if (context_die == lookup_decl_die (containing_scope))
|
||||
/* OK */;
|
||||
else
|
||||
containing_scope = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Ignore function type "scopes" from the C frontend. They mean that
|
||||
a tagged type is local to a parmlist of a function declarator, but
|
||||
@ -10072,14 +10083,16 @@ local_scope_p (dw_die_ref context_die)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns nonzero if CONTEXT_DIE is a class. */
|
||||
/* Returns nonzero if CONTEXT_DIE is a class or namespace, for deciding
|
||||
whether or not to treat a DIE in this context as a declaration. */
|
||||
|
||||
static inline int
|
||||
class_scope_p (dw_die_ref context_die)
|
||||
class_or_namespace_scope_p (dw_die_ref context_die)
|
||||
{
|
||||
return (context_die
|
||||
&& (context_die->die_tag == DW_TAG_structure_type
|
||||
|| context_die->die_tag == DW_TAG_union_type));
|
||||
|| context_die->die_tag == DW_TAG_union_type
|
||||
|| context_die->die_tag == DW_TAG_namespace));
|
||||
}
|
||||
|
||||
/* Many forms of DIEs require a "type description" attribute. This
|
||||
@ -10599,7 +10612,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
|
||||
tree outer_scope;
|
||||
dw_die_ref old_die = lookup_decl_die (decl);
|
||||
int declaration = (current_function_decl != decl
|
||||
|| class_scope_p (context_die));
|
||||
|| class_or_namespace_scope_p (context_die));
|
||||
|
||||
/* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we
|
||||
started to generate the abstract instance of an inline, decided to output
|
||||
@ -10608,7 +10621,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
|
||||
we'll get back to the abstract instance when done with the class. */
|
||||
|
||||
/* The class-scope declaration DIE must be the primary DIE. */
|
||||
if (origin && declaration && class_scope_p (context_die))
|
||||
if (origin && declaration && class_or_namespace_scope_p (context_die))
|
||||
{
|
||||
origin = NULL;
|
||||
if (old_die)
|
||||
@ -10873,7 +10886,7 @@ gen_variable_die (tree decl, dw_die_ref context_die)
|
||||
|
||||
dw_die_ref old_die = lookup_decl_die (decl);
|
||||
int declaration = (DECL_EXTERNAL (decl)
|
||||
|| class_scope_p (context_die));
|
||||
|| class_or_namespace_scope_p (context_die));
|
||||
|
||||
if (origin != NULL)
|
||||
add_abstract_origin_attribute (var_die, origin);
|
||||
@ -10926,7 +10939,7 @@ gen_variable_die (tree decl, dw_die_ref context_die)
|
||||
if (declaration)
|
||||
add_AT_flag (var_die, DW_AT_declaration, 1);
|
||||
|
||||
if (class_scope_p (context_die) || DECL_ABSTRACT (decl))
|
||||
if (class_or_namespace_scope_p (context_die) || DECL_ABSTRACT (decl))
|
||||
equate_decl_number_to_die (decl, var_die);
|
||||
|
||||
if (! declaration && ! DECL_ABSTRACT (decl))
|
||||
@ -11316,12 +11329,14 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
|
||||
int complete = (TYPE_SIZE (type)
|
||||
&& (! TYPE_STUB_DECL (type)
|
||||
|| ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))));
|
||||
int ns_decl = (context_die && context_die->die_tag == DW_TAG_namespace);
|
||||
|
||||
if (type_die && ! complete)
|
||||
return;
|
||||
|
||||
if (TYPE_CONTEXT (type) != NULL_TREE
|
||||
&& AGGREGATE_TYPE_P (TYPE_CONTEXT (type)))
|
||||
&& (AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
|
||||
|| TREE_CODE (TYPE_CONTEXT (type)) == NAMESPACE_DECL))
|
||||
nested = 1;
|
||||
|
||||
scope_die = scope_die_for (type, context_die);
|
||||
@ -11345,7 +11360,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die)
|
||||
|
||||
/* If this type has been completed, then give it a byte_size attribute and
|
||||
then give a list of members. */
|
||||
if (complete)
|
||||
if (complete && !ns_decl)
|
||||
{
|
||||
/* Prevent infinite recursion in cases where the type of some member of
|
||||
this type is expressed in terms of this type itself. */
|
||||
@ -11570,7 +11585,10 @@ gen_type_die (tree type, dw_die_ref context_die)
|
||||
need_pop = 1;
|
||||
}
|
||||
else
|
||||
need_pop = 0;
|
||||
{
|
||||
declare_in_namespace (type, context_die);
|
||||
need_pop = 0;
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) == ENUMERAL_TYPE)
|
||||
gen_enumeration_type_die (type, context_die);
|
||||
@ -11803,6 +11821,98 @@ is_redundant_typedef (tree decl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the DIE for namespace NS or aborts.
|
||||
|
||||
Note that namespaces don't really have a lexical context, so there's no
|
||||
need to pass in a context_die. They always go inside their containing
|
||||
namespace, or comp_unit_die if none. */
|
||||
|
||||
static dw_die_ref
|
||||
force_namespace_die (tree ns)
|
||||
{
|
||||
dw_die_ref ns_die;
|
||||
|
||||
dwarf2out_decl (ns);
|
||||
ns_die = lookup_decl_die (ns);
|
||||
if (!ns_die)
|
||||
abort();
|
||||
|
||||
return ns_die;
|
||||
}
|
||||
|
||||
/* Force out any required namespaces to be able to output DECL,
|
||||
and return the new context_die for it, if it's changed. */
|
||||
|
||||
static dw_die_ref
|
||||
setup_namespace_context (tree thing, dw_die_ref context_die)
|
||||
{
|
||||
tree context = DECL_P (thing) ? DECL_CONTEXT (thing) : TYPE_CONTEXT (thing);
|
||||
if (context && TREE_CODE (context) == NAMESPACE_DECL)
|
||||
/* Force out the namespace. */
|
||||
context_die = force_namespace_die (context);
|
||||
|
||||
return context_die;
|
||||
}
|
||||
|
||||
/* Emit a declaration DIE for THING (which is either a DECL or a tagged
|
||||
type) within its namespace, if appropriate.
|
||||
|
||||
For compatibility with older debuggers, namespace DIEs only contain
|
||||
declarations; all definitions are emitted at CU scope. */
|
||||
|
||||
static void
|
||||
declare_in_namespace (tree thing, dw_die_ref context_die)
|
||||
{
|
||||
dw_die_ref ns_context;
|
||||
|
||||
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
||||
return;
|
||||
|
||||
ns_context = setup_namespace_context (thing, context_die);
|
||||
|
||||
if (ns_context != context_die)
|
||||
{
|
||||
if (DECL_P (thing))
|
||||
gen_decl_die (thing, ns_context);
|
||||
else
|
||||
gen_type_die (thing, ns_context);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate a DIE for a namespace or namespace alias */
|
||||
|
||||
static void
|
||||
gen_namespace_die (tree decl)
|
||||
{
|
||||
dw_die_ref context_die = setup_namespace_context (decl, comp_unit_die);
|
||||
|
||||
/* Namespace aliases have a DECL_ABSTRACT_ORIGIN of the namespace
|
||||
they are an alias of.*/
|
||||
if (DECL_ABSTRACT_ORIGIN (decl) == NULL)
|
||||
{
|
||||
/* Output a real namespace */
|
||||
dw_die_ref namespace_die
|
||||
= new_die (DW_TAG_namespace, context_die, decl);
|
||||
add_name_and_src_coords_attributes (namespace_die, decl);
|
||||
equate_decl_number_to_die (decl, namespace_die);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Output a namespace alias */
|
||||
|
||||
/* Force out the namespace we are an alias of, if necessary */
|
||||
dw_die_ref origin_die
|
||||
= force_namespace_die (DECL_ABSTRACT_ORIGIN (decl));
|
||||
|
||||
/* Now create the namespace alias DIE. */
|
||||
dw_die_ref namespace_die
|
||||
= new_die (DW_TAG_imported_declaration, context_die, decl);
|
||||
add_name_and_src_coords_attributes (namespace_die, decl);
|
||||
add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
|
||||
equate_decl_number_to_die (decl, namespace_die);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate Dwarf debug information for a decl described by DECL. */
|
||||
|
||||
static void
|
||||
@ -11838,7 +11948,7 @@ gen_decl_die (tree decl, dw_die_ref context_die)
|
||||
emit info for the abstract instance and set up to refer to it. */
|
||||
else if (cgraph_function_possibly_inlined_p (decl)
|
||||
&& ! DECL_ABSTRACT (decl)
|
||||
&& ! class_scope_p (context_die)
|
||||
&& ! class_or_namespace_scope_p (context_die)
|
||||
/* dwarf2out_abstract_function won't emit a die if this is just
|
||||
a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in
|
||||
that case, because that works only if we have a die. */
|
||||
@ -11863,6 +11973,9 @@ gen_decl_die (tree decl, dw_die_ref context_die)
|
||||
origin = decl_class_context (decl);
|
||||
if (origin != NULL_TREE)
|
||||
gen_type_die_for_member (origin, decl, context_die);
|
||||
|
||||
/* And its containing namespace. */
|
||||
declare_in_namespace (decl, context_die);
|
||||
}
|
||||
|
||||
/* Now output a DIE to represent the function itself. */
|
||||
@ -11914,6 +12027,9 @@ gen_decl_die (tree decl, dw_die_ref context_die)
|
||||
if (origin != NULL_TREE)
|
||||
gen_type_die_for_member (origin, decl, context_die);
|
||||
|
||||
/* And its containing namespace. */
|
||||
declare_in_namespace (decl, context_die);
|
||||
|
||||
/* Now output the DIE to represent the data object itself. This gets
|
||||
complicated because of the possibility that the VAR_DECL really
|
||||
represents an inlined instance of a formal parameter for an inline
|
||||
@ -11942,7 +12058,7 @@ gen_decl_die (tree decl, dw_die_ref context_die)
|
||||
break;
|
||||
|
||||
case NAMESPACE_DECL:
|
||||
/* Ignore for now. */
|
||||
gen_namespace_die (decl);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -12065,6 +12181,13 @@ dwarf2out_decl (tree decl)
|
||||
return;
|
||||
break;
|
||||
|
||||
case NAMESPACE_DECL:
|
||||
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
||||
return;
|
||||
if (lookup_decl_die (decl) != NULL)
|
||||
return;
|
||||
break;
|
||||
|
||||
case TYPE_DECL:
|
||||
/* Don't emit stubs for types unless they are needed by other DIEs. */
|
||||
if (TYPE_DECL_SUPPRESS_DEBUG (decl))
|
||||
|
Loading…
x
Reference in New Issue
Block a user