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);
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);
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:
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
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
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
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)
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);
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))
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);
/* 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. */
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);
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
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. */
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. */
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
break;
case NAMESPACE_DECL:
- /* Ignore for now. */
+ gen_namespace_die (decl);
break;
default:
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))