This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
C++ debug info regression from destructor cleanups patch
- From: Daniel Jacobowitz <drow at mvista dot com>
- To: gcc-bugs at gcc dot gnu dot org
- Cc: Jason Merrill <jason at redhat dot com>, gdb at sources dot redhat dot com
- Date: Mon, 30 Dec 2002 13:19:44 -0500
- Subject: C++ debug info regression from destructor cleanups patch
Jason, your patch:
2001-12-13 Jason Merrill <jason@redhat.com>
* Make-lang.in (parse.h): Separate rule, just depend on parse.c.
Use cleanups to run base and member destructors.
* init.c (push_base_cleanups): New function, split out from...
(build_delete): ...here. Lose !TYPE_HAS_DESTRUCTOR code.
* decl.c (finish_destructor_body): Move vbase destruction code to
push_base_cleanups.
(begin_function_body, finish_function_body): New fns.
(finish_function): Move [cd]tor handling and call_poplevel to
finish_function_body.
(pushdecl): Skip the new level.
* semantics.c (genrtl_try_block): Don't call end_protect_partials.
(setup_vtbl_ptr): Call push_base_cleanups.
* method.c (synthesize_method): Call {begin,end}_function_body.
* pt.c (tsubst_expr): Handle COMPOUND_STMT_BODY_BLOCK.
* cp-tree.h: Declare new fns.
* parse.y (function_body, .begin_function_body): New nonterminals.
(fndef, pending_inline, function_try_block): Use function_body.
(ctor_initializer_opt, function_try_block): No longer has a value.
(base_init): Remove .set_base_init token.
(.set_base_init, compstmt_or_error): Remove.
* Make-lang.in (parse.c): Expect two fewer s/r conflicts.
caused a change in the GDB testsuite results which might indicate a bug. On
looking at it closer I'm not certain it's really avoidable, but I'd like a
second opinion. Consider this simple file (constructed by Michael Chastain):
===
int main ()
{
int i, j, k;
i = 101;
j = 102;
k = 103;
}
===
Before your patch, the debug info looks like:
<1><21>: Abbrev Number: 2 (DW_TAG_subprogram)
DW_AT_sibling : <60>
DW_AT_external : 1
DW_AT_name : (indirect string, offset: 0x1d): main
DW_AT_decl_file : 1
DW_AT_decl_line : 2
DW_AT_type : <60>
DW_AT_low_pc : 0 0
DW_AT_high_pc : 0x2c 44
DW_AT_frame_base : 1 byte block: 55 (DW_OP_reg5; )
<2><3b>: Abbrev Number: 3 (DW_TAG_variable)
DW_AT_name : i
DW_AT_decl_file : 1
DW_AT_decl_line : 3
DW_AT_type : <60>
DW_AT_location : 2 byte block: 91 7c (DW_OP_fbreg: -4; )
After:
<1><21>: Abbrev Number: 2 (DW_TAG_subprogram)
DW_AT_sibling : <6a>
DW_AT_external : 1
DW_AT_name : (indirect string, offset: 0x1d): main
DW_AT_decl_file : 1
DW_AT_decl_line : 2
DW_AT_type : <6a>
DW_AT_low_pc : 0 0
DW_AT_high_pc : 0x2c 44
DW_AT_frame_base : 1 byte block: 55 (DW_OP_reg5; )
<2><3b>: Abbrev Number: 3 (DW_TAG_lexical_block)
DW_AT_low_pc : 0x10 16
DW_AT_high_pc : 0x25 37
<3><44>: Abbrev Number: 4 (DW_TAG_variable)
DW_AT_name : i
DW_AT_decl_file : 1
DW_AT_decl_line : 3
DW_AT_type : <6a>
DW_AT_location : 2 byte block: 91 7c (DW_OP_fbreg: -4; )
i.e. we introduce a lexical block around the locals. The code added for the
implicit return is outside of this lexical block; it begins at 0x25. So GDB
single-steps through main, stops on the brace, and the user asks what the
locals are - and they're gone, even though the real lexical block containing
them (main itself) is still open.
This also shows the problem, without falling off main:
class C {
public:
~C ();
};
C::~C() { }
int main ()
{
C cc;
C dd;
return 0;
}
The actual calls to the destructor are inside the lexical block for the
second test, as is the moving to the return; only the final "leave; ret" is
outside it. So during execution of the prologue the function's locals have
vanished. Of course at this point their destructor has been called, and
they may not be valid any more. I'm more concerned about the first case.
Should we be emitting that lexical block in the debug info at all?
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer