From e89530cd2a6df48668a00f7c92582224da5e8872 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 8 Dec 2003 20:31:05 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74436 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 15 ++++++ gcc/dwarf2out.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 153 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6ec2cdd8ac8..f1efa1c7689 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2003-12-08 Jason Merrill + Daniel Berlin + + 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 * unwind-pe.h (read_uleb128): Fix handling of large values diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 78c6bdf0110..9b064b77cb0 100644 --- a/gcc/dwarf2out.c +++ b/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)) -- 2.11.4.GIT