Message ID | m3aa617omi.fsf@redhat.com |
---|---|
State | New |
Headers | show |
On Thu, Jan 05, 2012 at 11:47:49PM +0100, Dodji Seketeli wrote: > --- /dev/null > +++ b/gcc/testsuite/g++.dg/debug/dwarf2/nested-3.C > @@ -0,0 +1,34 @@ > +// Origin: PR debug/45682 > +// { dg-options "-g -gdwarf-4 -dA -fdebug-types-section" } > + > +namespace thread { > + class Executor {}; > +} > + > +thread::Executor *te; > + > +int > +main () > +{ > + return 0; > +} > + > +// We want to express the fact that the DIE for the definition of > +// 'Executor' is a child of the DIE for the namespace 'thread'. E.g, > +// we must have this outout: > +// .uleb128 0x2 # (DIE (0x25) DW_TAG_namespace) > +// .long .LASF0 # DW_AT_name: "thread" > +// # DW_AT_declaration > +// .uleb128 0x3 # (DIE (0x2a) DW_TAG_class_type) > +// .long .LASF1 # DW_AT_name: "Executor" > +// # DW_AT_declaration > +// .uleb128 0x4 # (DIE (0x2f) DW_TAG_class_type) > +// .byte 0x1 # DW_AT_byte_size > +// .byte 0x1 # DW_AT_decl_file (../../prtests/test-PR45682-2.cc) > +// .byte 0x2 # DW_AT_decl_line > +// .long 0x2a # DW_AT_specification > +// .byte 0 # end of children of DIE 0x25 > +// > +// Hence the scary regexp: > +// > +// { dg-final { scan-assembler "\[^\n\r\]*\\(DIE \\(0x(\[0-9a-f\]+)\\) DW_TAG_namespace\\)\[\n\r\]+\[^\n\r\]*DW_AT_name: \"thread\"\[\n\r\]+\[^\n\r\]*DW_AT_declaration\[\n\r\]+\[^\n\r\]*\\(DIE \\(0x(\[0-9a-f\]+)\\)\[^\n\r\]*DW_TAG_class_type\\)\[\n\r\]+\[^\n\r\]*DW_AT_name: \"Executor\"\[\n\r\]+\[^\n\r\]*DW_AT_declaration\[\n\r\]+\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_class_type\\)\[\n\r\]+(\[^\n\r\]*\[\n\r\]+)+\[^\n\r\]*0x\\2\[^\n\r\]*\[\n\r\]+\[^\n\r\]*end of children of DIE 0x\\1" } } Just a testcase comment, I bet this will surely fail on Darwin or other targets that aren't capable of merging string sections. So, you should add -fno-merge-debug-strings to dg-options and adjust the example and regexp for that, that way it will be the same on all targets. Jakub
> In the example of the patch below, the DIE for the definition of the > class 'Executor', when put in the type unit section is not put under > the DIE for the 'thread' namespace. Rather, it's put under the DIE > for the global namespace. I don't think this is the problem that PR 45682 is complaining about. Given the test case in your patch, the type unit looks like this: type_unit + namespace ("thread") + + L1: class_type ("Executor", declaration) + class_type (specification: L1) The definition DIE is *supposed* to appear at the outer level, with the specification DIE pointing to the declaration, which provides its context. This is the way it would have appeared in the comp unit DIE before splitting it out into a type unit. (And what it would look like with -fno-debug-types-section.) What PR 45682 is complaining about is that the skeleton DIE left behind for class Executor is not inside the namespace. That problem, however, is only visible with the full test case provided in the PR. There, the DIE structure in .debug_types is good, but the DIE structure in .debug_info is wrong: compile_unit + namespace ("thread") + class_type ("Executor", declaration) + + L1: subprogram ("CurrentExecutor", external) + ... + subprogram (specification: L1) + ... Here, the DIE for class_type Executor should be under the namespace DIE, but isn't. I don't think your patch fixes that problem. I think the real problem is that the skeleton declaration DIE for class Executor is being inserted under the wrong DIE -- probably in remove_child_or_replace_with_skeleton(). Thanks for looking at this, though! It's been on my TODO list for a while, but had dropped below the fold, and I'd forgotten about it. -cary
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 850eb55..96c247c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -3302,7 +3302,7 @@ static int should_move_die_to_comdat (dw_die_ref); static dw_die_ref clone_as_declaration (dw_die_ref); static dw_die_ref clone_die (dw_die_ref); static dw_die_ref clone_tree (dw_die_ref); -static void copy_declaration_context (dw_die_ref, dw_die_ref); +static dw_die_ref copy_declaration_context (dw_die_ref, dw_die_ref); static void generate_skeleton_ancestor_tree (skeleton_chain_node *); static void generate_skeleton_bottom_up (skeleton_chain_node *); static dw_die_ref generate_skeleton (dw_die_ref); @@ -7075,11 +7075,11 @@ clone_as_declaration (dw_die_ref die) AT_specification attribute, it also includes attributes and children attached to the specification. */ -static void +static dw_die_ref copy_declaration_context (dw_die_ref unit, dw_die_ref die) { dw_die_ref decl; - dw_die_ref new_decl; + dw_die_ref new_decl = NULL; decl = get_AT_ref (die, DW_AT_specification); if (decl == NULL) @@ -7118,6 +7118,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die) add_AT_specification (die, new_decl); } } + return new_decl ; } /* Generate the skeleton ancestor tree for the given NODE, then clone @@ -7247,7 +7248,7 @@ break_out_comdat_types (dw_die_ref die) next = (c == first ? NULL : c->die_sib); if (should_move_die_to_comdat (c)) { - dw_die_ref replacement; + dw_die_ref replacement, copied = NULL; comdat_type_node_ref type_node; /* Create a new type unit DIE as the root for the new tree, and @@ -7265,7 +7266,7 @@ break_out_comdat_types (dw_die_ref die) /* Copy the declaration context, attributes, and children of the declaration into the new compile unit DIE. */ - copy_declaration_context (unit, c); + copied = copy_declaration_context (unit, c); /* Remove this DIE from the main CU. */ replacement = remove_child_or_replace_with_skeleton (c, prev); @@ -7274,6 +7275,8 @@ break_out_comdat_types (dw_die_ref die) break_out_comdat_types (c); /* Add the DIE to the new compunit. */ + if (copied != NULL && copied->die_parent) + unit = copied->die_parent; add_child_die (unit, c); if (replacement != NULL) diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/nested-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/nested-3.C new file mode 100644 index 0000000..847afd7 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/nested-3.C @@ -0,0 +1,34 @@ +// Origin: PR debug/45682 +// { dg-options "-g -gdwarf-4 -dA -fdebug-types-section" } + +namespace thread { + class Executor {}; +} + +thread::Executor *te; + +int +main () +{ + return 0; +} + +// We want to express the fact that the DIE for the definition of +// 'Executor' is a child of the DIE for the namespace 'thread'. E.g, +// we must have this outout: +// .uleb128 0x2 # (DIE (0x25) DW_TAG_namespace) +// .long .LASF0 # DW_AT_name: "thread" +// # DW_AT_declaration +// .uleb128 0x3 # (DIE (0x2a) DW_TAG_class_type) +// .long .LASF1 # DW_AT_name: "Executor" +// # DW_AT_declaration +// .uleb128 0x4 # (DIE (0x2f) DW_TAG_class_type) +// .byte 0x1 # DW_AT_byte_size +// .byte 0x1 # DW_AT_decl_file (../../prtests/test-PR45682-2.cc) +// .byte 0x2 # DW_AT_decl_line +// .long 0x2a # DW_AT_specification +// .byte 0 # end of children of DIE 0x25 +// +// Hence the scary regexp: +// +// { dg-final { scan-assembler "\[^\n\r\]*\\(DIE \\(0x(\[0-9a-f\]+)\\) DW_TAG_namespace\\)\[\n\r\]+\[^\n\r\]*DW_AT_name: \"thread\"\[\n\r\]+\[^\n\r\]*DW_AT_declaration\[\n\r\]+\[^\n\r\]*\\(DIE \\(0x(\[0-9a-f\]+)\\)\[^\n\r\]*DW_TAG_class_type\\)\[\n\r\]+\[^\n\r\]*DW_AT_name: \"Executor\"\[\n\r\]+\[^\n\r\]*DW_AT_declaration\[\n\r\]+\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_class_type\\)\[\n\r\]+(\[^\n\r\]*\[\n\r\]+)+\[^\n\r\]*0x\\2\[^\n\r\]*\[\n\r\]+\[^\n\r\]*end of children of DIE 0x\\1" } }