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] C++/DWARF : Add 'using' support



On Dec 11, 2003, at 10:31 PM, Jason Merrill wrote:


On Thu, 11 Dec 2003 18:01:05 -0800, Devang Patel <dpatel@apple.com> wrote:

!   debug_true_tree,		/* ignore_block */
--- 382,406 ----
!   debug_true_tree,		         /* ignore_block */

Don't reformat these lines.

I reformatted these lines so that all comments' start column is aligned properly.


! /* Returns the DIE for decl or aborts. */

  static dw_die_ref
! force_type_die (tree type)
  {
!   dw_die_ref type_die;

!   dwarf2out_decl (type);
!   type_die = lookup_decl_die (type);
!   if (!type_die)
      abort();

!   return type_die;
  }

This is obviously wrong.

Yes. This was caused by last minute beautification and my nightly test run caught it.


        /* Otherwise we're emitting the primary DIE for this decl.  */
!       else if (debug_info_level > DINFO_LEVEL_TERSE)
--- 11976,12005 ----
        /* Otherwise we're emitting the primary DIE for this decl.  */
!       else
! 	{
! 	  if (debug_info_level > DINFO_LEVEL_TERSE)

More gratuitous reformatting.

hmm.. I'll take care of this.



+       /* Setup namespace for the variable.  */
+       context_die = setup_namespace_context (decl, context_die);

This is probably left over from when you were working with Dan's patch. It
doesn't belong.

I need it for r1 in this case:


  namespace R
  {
    int r1 = 19;
  }

  using R::r1;
  namespace C
  {
    namespace D
    {
      void marker2 (void)
      {
        r1;
      }
    }
  }

+ if (tag == DBG_IMPORTED_GLOBAL_DECL
+ || tag == DBG_IMPORTED_DECL)
+ {
+ /* Check DECL_INITIAL for inlines. For example,
+ extern void foo():
+ ...
+ using ::foo;
+ More informative comment about DECL_INITIAL check for extern is
+ in dwarf2out_decl() in this source file. */
+ if (DECL_INITIAL (decl) == NULL_TREE)
+ return;
+ }

So you're throwing away a using-declaration which refers to a function
which doesn't happen to have been defined yet? That's wrong. We discussed
this--yes, dwarf2out_decl wouldn't normally emit a DIE for this function,
but if we want to use it we need to force it out.


I suppose you put this here because force_decl_die uses dwarf2out_decl, so
it would end up aborting rather than emit the die you're looking for. The
right thing to do is to fix force_decl_die to actually force out the die.

OK.


+ /* To emit DW_TAG_Imported_module or DW_TAG_Imported_decl, we need two DIEs.

No capital 'I' in these TAG names.

OK.


+ /* Use original type for TYPE_DECL. */

That seems wrong. If we're using a typedef, presumably we want the imported declaration to have the same name.

But in gen_typedef_die() we equate original type to die.



+       at_import_die = lookup_type_die (type);
+       if (!at_import_die)
+ 	  at_import_die = force_type_die (type);

This is redundant. Just call force_type_die.


+       at_import_die = lookup_decl_die (decl);
+       if (!at_import_die)

Likewise.

Because force_decl_type does not do lookup first. I'll update force_decl_type and force_type_die.


+ 	  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
+ 	    /* Inline function is still in defferend functions linst.
+ 	       We do not have any DIE to reference here. Ignore this
+ 	       using declaration for now.  This is FIXME.
+ 	
+ 	       extern __inline void foo (int a)
+ 	       { ... }
+ 	       namespace A
+ 	       {
+ 	         using ::foo;   <--- We are here.
+ 	       }
+ 	    */
+ 	    return;

We can certainly force out something for foo. Either a declaration or the
abstract instance.

Yes. I got lost in how we treat inlines so I left it as FIXME and I'm reading dwarf specs example again for more understanding.

+ /* Get the scope die for decl context. Use comp_unit_die for global module
+ or decl. If die is not found for non globals, force new die. */
+ if (tag == DBG_IMPORTED_GLOBAL_MODULE
+ || tag == DBG_IMPORTED_GLOBAL_DECL)
+ scope_die = comp_unit_die;

Lose the _GLOBAL_ variants. Instead, pass NULL_TREE for context if the using is at file scope.

I thought about that. Only reason for not pass NULL_TREE is to place context as created_for. But you suggest below to leave it null, so I'll pass NULL_TREE here.


+       scope_die = lookup_decl_die (context);
+       if (!scope_die)
+ 	scope_die = force_decl_die (context);

Again, just call force_decl_die.

OK.



+ /* OK, now we have DIEs for decl as well as scope. Emit imported die. */
+ if (tag == DBG_IMPORTED_GLOBAL_MODULE
+ || tag == DBG_IMPORTED_MODULE)
+ imported_die = new_die (DW_TAG_imported_module, scope_die, context);

Passing context as the "created for" argument seems odd here. decl seems
more appropriate, but still wrong. I'd just leave it null.

OK.


+ else if (tag == DBG_IMPORTED_GLOBAL_DECL
+ || tag == DBG_IMPORTED_DECL)
+ imported_die = new_die (DW_TAG_imported_declaration, scope_die, context);

Ditto.

OK.


! However we want to emit DIES to represent mere function declarations
! if they are namespace members. While generating DIEs for 'using' decls
! in C++ we may need to force out DIE for functions whose definition is
! not yet seen. At that point do not want to skip such functions.
! We check DECL_CONTEXT here for this purpose. */
! if (DECL_INITIAL (decl) == NULL_TREE && DECL_CONTEXT (decl) == NULL_TREE)
return;

This is still wrong. We still want to ignore declarations of namespace-scope functions which are not used. force_decl_die needs to override this somehow.

I'll update force_decl_die.


*************** cp_parser_qualified_namespace_specifier
*** 9181,9186 ****
--- 9182,9226 ----
    return cp_parser_namespace_name (parser);
  }

+ static void
+ cp_emit_debug_info_for_using (tree t);

The prototype goes at the top of the file. And this function belongs in
name-lookup.c.

OK.


+
+ /* Emit debugging information for using declarations and directives.
+ If input tree is overloaded fn then emit debug info for all
+ candidates. */
+
+ static void
+ cp_emit_debug_info_for_using (tree t)
+ {
+ enum dbg_module_or_decl tag;
+
+ tag = (current_namespace == global_namespace ?
+ DBG_IMPORTED_GLOBAL_DECL : DBG_IMPORTED_DECL);
+
+ if (really_overloaded_fn (t))
+ {
+ /* We have using Foo::bar and bar is overloaded.
+ Emit debug info. for all candidates. */
+ tree f;
+ for (f = t; f ; f = OVL_CHAIN (f))
+ (*debug_hooks->imported_module_or_decl) (OVL_FUNCTION (f),
+ current_namespace,
+ tag);
+ }
+ else
+ {
+ /* Do not trust really_overloaded_fn(). For example ...
+ void foo (int a) { ... }
+ namespace A { using ::foo; }
+ namespace B { using A::foo; }
+ */
+ if (TREE_CODE (t) == OVERLOAD)
+ t = OVL_FUNCTION (t);
+
+ (*debug_hooks->imported_module_or_decl) (t, current_namespace, tag);
+ }
+ }

You can avoid this if/else by always looping using OVL_CURRENT and OVL_NEXT.

*************** cp_parser_using_declaration (cp_parser*
*** 9260,9265 ****
--- 9300,9323 ----
  						identifier));
  	  /* Add it to the list of members in this class.  */
  	  finish_member_declaration (decl);
+
+ 	  /* Emit debug info.  */
+ 	  if (TREE_CODE (decl) == USING_DECL)
+ 	    {
+ 	      tree r;
+ 	      r = lookup_qualified_name (DECL_INITIAL(decl) ,identifier,
+ 					 false, false);
+ 	      if (r && TREE_CODE (r) != ERROR_MARK)
+ 		{
+ 		  r = BASELINK_FUNCTIONS (r);
+ 		  cp_emit_debug_info_for_using (r);
+ 		}
+ 	      else
+ 		{
+ 		  /* FIXME. Give up for now. Find another way to look up
+ 		     templates.  */
+ 		}
+ 	    }

This is badly broken. This section of code deals with class-scope usings,
and cp_emit_debug_info_for_using only handles namespace-scope usings. As
it should--we need to handle class- and function-scope usings while
emitting debug info for the relevant class or function.


--- 9334,9346 ----
  	    do_local_using_decl (decl);
  	  else
  	    do_toplevel_using_decl (decl);
+
+ 	  /* Emit debug info.  */
+ 	  cp_emit_debug_info_for_using (decl);
  	}

And here you're calling it for both function- and namespace-scope usings.
I think you want to move the call into do_toplevel_using_decl.

I'll look into it.


*************** cp_parser_using_directive (cp_parser* pa
*** 9315,9320 ****
--- 9378,9390 ----
    parse_using_directive (namespace_decl, attribs);
    /* Look for the final `;'.  */
    cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+
+   /* Emit debugging info.  */
+   tag = (current_namespace == global_namespace ?
+ 	 DBG_IMPORTED_GLOBAL_MODULE : DBG_IMPORTED_MODULE);
+   (*debug_hooks->imported_module_or_decl) (namespace_decl,
+ 					   current_namespace,
+ 					   tag);

And I'd push this call down, too, perhaps into do_using_directive. parser.c should avoid dealing with semantics as much as possible.

OK.


Thank you,
--
Devang


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