This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH]: Updated patch to output dwarf2 namespace debug info


The problem turned out to be that the abstract instance was being treated
as a declaration, so its body was not being emitted, so we couldn't find it
when we went looking.  The patch attached fixes this and also splits
classes into declaration/definition pairs.

Tested x86_64-pc-linux-gnu (with GDB testsuite as well).

Mark, this is a new feature, but it's one that the library folks have been
clamoring for for at least a couple of years (which is how long this patch
has been in development).  May I put this in for 3.4?

2003-12-08  Jason Merrill <jason@redhat.com>
	    Daniel Berlin  <dberlin@dberlin.org>

	* 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.

*** dwarf2out.c.~1~	2003-12-01 18:16:10.000000000 -0500
--- dwarf2out.c	2003-12-08 11:37:20.000000000 -0500
*************** static void push_decl_scope (tree);
*** 3740,3746 ****
  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 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);
--- 3740,3746 ----
  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_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_tagged_type_instantiatio
*** 3778,3784 ****
--- 3778,3788 ----
  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);
*************** dwarf_tag_name (unsigned int tag)
*** 4034,4039 ****
--- 4038,4045 ----
        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:
*************** scope_die_for (tree t, dw_die_ref contex
*** 10020,10028 ****
  
    containing_scope = TYPE_CONTEXT (t);
  
!   /* Ignore namespaces for the moment.  */
    if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
!     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
--- 10026,10039 ----
  
    containing_scope = TYPE_CONTEXT (t);
  
!   /* Use the containing namespace if it was passed in (for a declaration).  */
    if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
!     {
!       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
*************** local_scope_p (dw_die_ref context_die)
*** 10072,10085 ****
    return 0;
  }
  
! /* Returns nonzero if CONTEXT_DIE is a class.  */
  
  static inline int
! class_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));
  }
  
  /* Many forms of DIEs require a "type description" attribute.  This
--- 10083,10098 ----
    return 0;
  }
  
! /* 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_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_namespace));
  }
  
  /* Many forms of DIEs require a "type description" attribute.  This
*************** gen_subprogram_die (tree decl, dw_die_re
*** 10599,10605 ****
    tree outer_scope;
    dw_die_ref old_die = lookup_decl_die (decl);
    int declaration = (current_function_decl != decl
! 		     || class_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
--- 10612,10618 ----
    tree outer_scope;
    dw_die_ref old_die = lookup_decl_die (decl);
    int declaration = (current_function_decl != decl
! 		     || 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
*************** gen_subprogram_die (tree decl, dw_die_re
*** 10608,10614 ****
       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))
      {
        origin = NULL;
        if (old_die)
--- 10621,10627 ----
       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_or_namespace_scope_p (context_die))
      {
        origin = NULL;
        if (old_die)
*************** gen_variable_die (tree decl, dw_die_ref 
*** 10873,10879 ****
  
    dw_die_ref old_die = lookup_decl_die (decl);
    int declaration = (DECL_EXTERNAL (decl)
! 		     || class_scope_p (context_die));
  
    if (origin != NULL)
      add_abstract_origin_attribute (var_die, origin);
--- 10886,10892 ----
  
    dw_die_ref old_die = lookup_decl_die (decl);
    int declaration = (DECL_EXTERNAL (decl)
! 		     || class_or_namespace_scope_p (context_die));
  
    if (origin != NULL)
      add_abstract_origin_attribute (var_die, origin);
*************** gen_variable_die (tree decl, dw_die_ref 
*** 10926,10932 ****
    if (declaration)
      add_AT_flag (var_die, DW_AT_declaration, 1);
  
!   if (class_scope_p (context_die) || DECL_ABSTRACT (decl))
      equate_decl_number_to_die (decl, var_die);
  
    if (! declaration && ! DECL_ABSTRACT (decl))
--- 10939,10945 ----
    if (declaration)
      add_AT_flag (var_die, DW_AT_declaration, 1);
  
!   if (class_or_namespace_scope_p (context_die) || DECL_ABSTRACT (decl))
      equate_decl_number_to_die (decl, var_die);
  
    if (! declaration && ! DECL_ABSTRACT (decl))
*************** gen_struct_or_union_type_die (tree type,
*** 11316,11327 ****
    int complete = (TYPE_SIZE (type)
  		  && (! TYPE_STUB_DECL (type)
  		      || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))));
  
    if (type_die && ! complete)
      return;
  
    if (TYPE_CONTEXT (type) != NULL_TREE
!       && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)))
      nested = 1;
  
    scope_die = scope_die_for (type, context_die);
--- 11329,11342 ----
    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))
! 	  || TREE_CODE (TYPE_CONTEXT (type)) == NAMESPACE_DECL))
      nested = 1;
  
    scope_die = scope_die_for (type, context_die);
*************** gen_struct_or_union_type_die (tree type,
*** 11345,11351 ****
  
    /* If this type has been completed, then give it a byte_size attribute and
       then give a list of members.  */
!   if (complete)
      {
        /* Prevent infinite recursion in cases where the type of some member of
  	 this type is expressed in terms of this type itself.  */
--- 11360,11366 ----
  
    /* If this type has been completed, then give it a byte_size attribute and
       then give a list of members.  */
!   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.  */
*************** gen_type_die (tree type, dw_die_ref cont
*** 11570,11576 ****
  	  need_pop = 1;
  	}
        else
! 	need_pop = 0;
  
        if (TREE_CODE (type) == ENUMERAL_TYPE)
  	gen_enumeration_type_die (type, context_die);
--- 11585,11594 ----
  	  need_pop = 1;
  	}
        else
! 	{
! 	  declare_in_namespace (type, context_die);
! 	  need_pop = 0;
! 	}
  
        if (TREE_CODE (type) == ENUMERAL_TYPE)
  	gen_enumeration_type_die (type, context_die);
*************** is_redundant_typedef (tree decl)
*** 11803,11808 ****
--- 11821,11918 ----
    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
*************** gen_decl_die (tree decl, dw_die_ref cont
*** 11838,11844 ****
  	 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)
  	       /* 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.  */
--- 11948,11954 ----
  	 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_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.  */
*************** gen_decl_die (tree decl, dw_die_ref cont
*** 11863,11868 ****
--- 11973,11981 ----
  	  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.  */
*************** gen_decl_die (tree decl, dw_die_ref cont
*** 11914,11919 ****
--- 12027,12035 ----
        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
*************** gen_decl_die (tree decl, dw_die_ref cont
*** 11942,11948 ****
        break;
  
      case NAMESPACE_DECL:
!       /* Ignore for now.  */
        break;
  
      default:
--- 12058,12064 ----
        break;
  
      case NAMESPACE_DECL:
!       gen_namespace_die (decl);
        break;
  
      default:
*************** dwarf2out_decl (tree decl)
*** 12065,12070 ****
--- 12181,12193 ----
  	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))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]