Created attachment 48085 [details] gzipped C++ source code For the attached C++ source code, with recent gcc trunk, does this: ../tdutils/td/utils/logging.cpp:263:1: internal compiler error: in splice_child_die, at dwarf2out.c:5657 263 | } // namespace td | ^ 0x7064f4 splice_child_die ../../trunk.git/gcc/dwarf2out.c:5657 0x7064f4 gen_member_die ../../trunk.git/gcc/dwarf2out.c:25154 0x7064f4 gen_struct_or_union_type_die ../../trunk.git/gcc/dwarf2out.c:25265 0x7064f4 gen_tagged_type_die ../../trunk.git/gcc/dwarf2out.c:25466 Compile line needs flag -g1. I'll have my usual go at reducing the code and finding a set of dates where it first starts to go wrong.
The problem seems to occur first sometime between 20200317 and 20200318: /home/dcb/gcc/results.20200317.asan/bin/g++ /home/dcb/gcc/results.20200317/bin/g++ /home/dcb/gcc/results.20200317.ubsan/bin/g++ /home/dcb/gcc/results.20200318/bin/g++ ../tdutils/td/utils/logging.cpp:263:1: internal compiler error: in splice_child_die, at dwarf2out.c:5657 0x706494 splice_child_die Reducing now.
Reduced C++ source code is class a { virtual void c() {} } extern b; a b; Flag -g1 required.
Possibly the vars we output should additionally be constrained to DECL_FILE_SCOPE_P?
Or add a similar "return if debug level is terse" at the beginning of `gen_type_die` - I didn't notice that in C++ it could also get called not through the `add_type_attribute`: ``` diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 89e52a41508..b0f6680bd61 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -25709,6 +25709,9 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, static void gen_type_die (tree type, dw_die_ref context_die) { + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + if (type != error_mark_node) { gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE); ``` I verified that it makes the attached test case compile successfully.
Any progress on this? It breaks quite a lot of stuff in real world code.
(In reply to Alexey Neyman from comment #4) > Or add a similar "return if debug level is terse" at the beginning of > `gen_type_die` - I didn't notice that in C++ it could also get called not > through the `add_type_attribute`: > > ``` > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c > index 89e52a41508..b0f6680bd61 100644 > --- a/gcc/dwarf2out.c > +++ b/gcc/dwarf2out.c > @@ -25709,6 +25709,9 @@ gen_type_die_with_usage (tree type, dw_die_ref > context_die, > static void > gen_type_die (tree type, dw_die_ref context_die) > { > + if (debug_info_level <= DINFO_LEVEL_TERSE) > + return; > + > if (type != error_mark_node) > { > gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE); > ``` > > I verified that it makes the attached test case compile successfully. But then the static var is improperly scoped in the debug info? IMHO it's better left out.
(In reply to Richard Biener from comment #6) > (In reply to Alexey Neyman from comment #4) > > Or add a similar "return if debug level is terse" at the beginning of > > `gen_type_die` - I didn't notice that in C++ it could also get called not > > through the `add_type_attribute`: > > > > ``` > > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c > > index 89e52a41508..b0f6680bd61 100644 > > --- a/gcc/dwarf2out.c > > +++ b/gcc/dwarf2out.c > > @@ -25709,6 +25709,9 @@ gen_type_die_with_usage (tree type, dw_die_ref > > context_die, > > static void > > gen_type_die (tree type, dw_die_ref context_die) > > { > > + if (debug_info_level <= DINFO_LEVEL_TERSE) > > + return; > > + > > if (type != error_mark_node) > > { > > gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE); > > ``` > > > > I verified that it makes the attached test case compile successfully. > > But then the static var is improperly scoped in the debug info? IMHO > it's better left out. First, which static variable? The test case for this PR does not have any static vars: ``` class a { virtual void c() {} } extern b; a b; ``` As to DECL_FILE_SCOPE_P check, do you mean something like this? ``` @@ -26360,7 +26365,8 @@ gen_decl_die (tree decl, tree origin, struct vlr_context *ctx, variable declarations or definitions unless it is external. */ if (debug_info_level < DINFO_LEVEL_TERSE || (debug_info_level == DINFO_LEVEL_TERSE - && !TREE_PUBLIC (decl_or_origin))) + && (!TREE_PUBLIC (decl_or_origin) + || !DECL_FILE_SCOPE_P(decl_or_origin)))) break; if (debug_info_level > DINFO_LEVEL_TERSE) { @@ -26841,7 +26847,8 @@ dwarf2out_decl (tree decl) variable declarations or definitions unless it is external. */ if (debug_info_level < DINFO_LEVEL_TERSE || (debug_info_level == DINFO_LEVEL_TERSE - && !TREE_PUBLIC (decl))) + && (!TREE_PUBLIC (decl) + || !DECL_FILE_SCOPE_P(decl)))) return; break; ``` This change doesn't resolve the ICE with that test. I am going to attach a patch with what I suggested. Whether it is accepted, or something different needs to be done - I don't have commit access, so somebody else will have to commit it.
Created attachment 48129 [details] Patch
OK, so during early creation of the DIE for the type we end up in static void gen_struct_or_union_type_die (tree type, dw_die_ref context_die, enum debug_info_usage usage) { ... int complete = (TYPE_SIZE (type) && (! TYPE_STUB_DECL (type) || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)))); where complete is false because of TYPE_DECL_SUPPRESS_DEBUG. When record the type to be re-processed later and between now and then the C++ FE does note_debug_info_needed via maybe_emit_vtables and clears TYPE_DECL_SUPPRESS_DEBUG, causing the type to be completed during retry_incomplete_types processing. I think PR93951 may be related in the end because the conditions on when exactly we emit what parts of debug info is quite intricate in dwarf2out. Now, for this bug I guess we should choose to piggy-back on that, making should_emit_struct_debug return false for DINFO_LEVEL_TERSE or initializing debug_struct_{generic,ordinary} accordingly. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index b1fa6f5ff7c..378a27394e8 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -399,6 +399,9 @@ get_full_len (const wide_int &op) static bool should_emit_struct_debug (tree type, enum debug_info_usage usage) { + if (debug_info_level <= DINFO_LEVEL_TERSE) + return false; + enum debug_struct_file criterion; tree type_decl; bool generic = lang_hooks.types.generic_p (type); thoughts? The DWARF we generate for the testcase at -g1 is then <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit) <c> DW_AT_producer : (indirect string, offset: 0x0): GNU C++14 10.0.1 2 0200325 (experimental) -mtune=generic -march=x86-64 -g1 <10> DW_AT_language : 4 (C++) <11> DW_AT_name : (indirect string, offset: 0x4a): t.ii <15> DW_AT_comp_dir : (indirect string, offset: 0x4f): /home/rguenther/ obj/gcc <19> DW_AT_ranges : 0x0 <1d> DW_AT_low_pc : 0x0 <25> DW_AT_stmt_list : 0x0 <1><29>: Abbrev Number: 2 (DW_TAG_variable) <2a> DW_AT_name : b <2c> DW_AT_decl_file : 1 <2d> DW_AT_decl_line : 3 <2e> DW_AT_decl_column : 12 <2f> DW_AT_external : 1 <2f> DW_AT_declaration : 1 <1><2f>: Abbrev Number: 3 (DW_TAG_variable) <30> DW_AT_specification: <0x29> <34> DW_AT_decl_line : 4 <35> DW_AT_decl_column : 5 <36> DW_AT_location : 9 byte block: 3 0 0 0 0 0 0 0 0 (DW_OP_addr: 0) <1><40>: Abbrev Number: 4 (DW_TAG_subprogram) <41> DW_AT_external : 1 <41> DW_AT_name : c <43> DW_AT_decl_file : 1 <44> DW_AT_decl_line : 2 <45> DW_AT_decl_column : 16 <46> DW_AT_linkage_name: (indirect string, offset: 0x67): _ZN1a1cEv <4a> DW_AT_virtuality : 1 (virtual) <4b> DW_AT_vtable_elem_location: 2 byte block: 10 0 (DW_OP_constu: 0) <4e> DW_AT_accessibility: 3 (private) <4f> DW_AT_low_pc : 0x0 <57> DW_AT_high_pc : 0xb <5f> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <61> DW_AT_GNU_all_call_sites: 1 <1><61>: Abbrev Number: 0
I'm testing this patch now.
The master branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:45cfaf9903d3f5aa916d330f2013eb7d820a7137 commit r10-7418-g45cfaf9903d3f5aa916d330f2013eb7d820a7137 Author: Richard Biener <rguenther@suse.de> Date: Fri Mar 27 13:57:42 2020 +0100 debug/94273 - avoid creating type DIEs for DINFO_LEVEL_TERSE This avoids completing types for DINFO_LEVEL_TERSE by using the should_emit_struct_debug machinery. 2020-03-27 Richard Biener <rguenther@suse.de> PR debug/94273 * dwarf2out.c (should_emit_struct_debug): Return false for DINFO_LEVEL_TERSE. * g++.dg/debug/pr94273.C: New testcase.
Fixed.