> 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