Bug 94273 - [10 Regression] ICE in splice_child_die, at dwarf2out.c:5657 since r10-7235-g52b3aa8be1893848
Summary: [10 Regression] ICE in splice_child_die, at dwarf2out.c:5657 since r10-7235-g...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 10.0
: P1 normal
Target Milestone: 10.0
Assignee: Richard Biener
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2020-03-23 11:20 UTC by David Binderman
Modified: 2020-03-27 13:01 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work: 9.3.0
Known to fail: 10.0
Last reconfirmed: 2020-03-23 00:00:00


Attachments
gzipped C++ source code (145.80 KB, application/gzip)
2020-03-23 11:20 UTC, David Binderman
Details
Patch (702 bytes, patch)
2020-03-26 23:39 UTC, Alexey Neyman
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description David Binderman 2020-03-23 11:20:25 UTC
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.
Comment 1 David Binderman 2020-03-23 11:28:51 UTC
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.
Comment 2 David Binderman 2020-03-23 11:41:08 UTC
Reduced C++ source code is

class a {
  virtual void c() {}
} extern b;
a b;

Flag -g1 required.
Comment 3 Richard Biener 2020-03-23 14:08:19 UTC
Possibly the vars we output should additionally be constrained to DECL_FILE_SCOPE_P?
Comment 4 Alexey Neyman 2020-03-23 19:53:51 UTC
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.
Comment 5 Jakub Jelinek 2020-03-26 13:12:51 UTC
Any progress on this?  It breaks quite a lot of stuff in real world code.
Comment 6 Richard Biener 2020-03-26 13:21:58 UTC
(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.
Comment 7 Alexey Neyman 2020-03-26 19:01:08 UTC
(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.
Comment 8 Alexey Neyman 2020-03-26 23:39:12 UTC
Created attachment 48129 [details]
Patch
Comment 9 Richard Biener 2020-03-27 08:37:15 UTC
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
Comment 10 Richard Biener 2020-03-27 08:46:43 UTC
I'm testing this patch now.
Comment 11 GCC Commits 2020-03-27 13:01:36 UTC
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.
Comment 12 Richard Biener 2020-03-27 13:01:46 UTC
Fixed.