OSDN Git Service

Support namespaces in DWARF 2 output.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Dec 2003 20:31:05 +0000 (20:31 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Dec 2003 20:31:05 +0000 (20:31 +0000)
        * 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
gcc/dwarf2out.c

index 6ec2cdd..f1efa1c 100644 (file)
@@ -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
index 78c6bdf..9b064b7 100644 (file)
@@ -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))