> I notice that D.7 seems to suggest that if the nested function is not
> inlinable and shared between all instances of the containing function
> that we put a normal (non-abstract/concrete) instance of the nested
> function inside the abstract function for the containing function.  But
> I agree that it's cleaner your way: put an abstract instance there
> instead so that the abstract instance of the containing function is all
> abstract.

Hum, yes, D.7 even tends to show that what GCC currently generates is as 
expected.  The problem arises when the containing function is itself inlined 
into the nested function: in this case, we have the cycle in the debug info:

  |->  AI (containing) -> OL (nested) -> CI (containing) --|
  |                                                        |
  ------------------DW_AT_abstract_origin ------------------

that is problematic for GDB, and Joel said at the time that there was no easy 
way to break the recursion in GDB.

AI: Abstract Instance
OL: Out-of-Line
CI: Concrete Instance

But if you think the patch is nevertheless reasonable, then let's go ahead.

> > +  /* Emit an abstract instance of nested functions within an abstract
> > instance +     of their parent.  */
> > +  int declaration = ((decl != current_function_decl
> > +                 && !(DECL_INITIAL (decl) != NULL_TREE
> > +                      && DECL_ABSTRACT (decl)
> > +                      && current_function_decl
> > +                      && DECL_ABSTRACT (current_function_decl)))
> >
> >                  || class_or_namespace_scope_p (context_die));
>
> Hmm, why isn't current_function_decl == decl when we're trying to emit
> the abstract instance of a nested function?

Because it is emitted when the first instance of the parent function is seen, 
and in this case current_function_decl == parent_decl.

> > +  /* Do not emit concrete instances of abstracted nested functions
> > without +     actual instances.  */
> > +  else if (TREE_CODE (decl_or_origin) == FUNCTION_DECL
> > +      && die
> > +      && get_AT (die, DW_AT_inline))
> > +    ;
>
> Should "without actual instances" be something like "within concrete
> instances of containing functions"?

Yes, that's probably clearer.

> > -     if (origin && origin->die_parent)
> > +     if (origin
> > +         && origin->die_parent
> > +         /* Skip an abtract parent instance.  */
> > +         && !(origin->die_parent->die_tag == DW_TAG_subprogram
> > +              && get_AT (origin->die_parent, DW_AT_inline)))
> >         add_child_die (origin->die_parent, die);
>
> What if the immediate parent is a DW_TAG_lexical_block or some other
> thing nested inside an abstract subprogram?

Indeed, there was a loop in the last revised version of the original thread:
  http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01286.html

Not clear why I dropped it...

> In my earlier comments I seem to have been wrong about the behavior of
> gen_subprogram_die; now I see that if there is an abstract instance the
> concrete out-of-line instance is not associated with the decl number.
> So I guess your earlier limbo handling code was fine apart from the
> lexical_block issue above.

So the above last revised version is OK with you, modulo the comment in 
process_scope_var?

-- 
Eric Botcazou

Reply via email to