[1/5,gdb/testsuite] Add gdb.dwarf2/enum-type-c++.exp, regression test for PR31900.

Message ID 20240912115242.17062-1-tdevries@suse.de
State Committed
Headers
Series [1/5,gdb/testsuite] Add gdb.dwarf2/enum-type-c++.exp, regression test for PR31900. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed

Commit Message

Tom de Vries Sept. 12, 2024, 11:52 a.m. UTC
  Consider the following test-case:
...
$ cat a.h
namespace ns {

class A {
public:
  enum {
    val1 = 1
  };
};

}
$ cat main.c

ns::A a;

int
main (void)
{
  return 0;
}
$ cat val1.c

int u1 = ns::A::val1;
...
compiled with debug info:
...
$ g++ main.c val1.c -g
...

When trying to print ns::A::val with current trunk and gdb 15.1 we get:
...
$ gdb -q -batch a.out -ex "print ns::A::val1"
There is no field named val1
...

This PR c++/31900.

With gdb 14.2 we get the expected:
...
$ gdb -q -batch a.out -ex "print ns::A::val1"
$1 = ns::A::val1
...

This is a regression since commit 4e417d7bb1c ("Change handling of
DW_TAG_enumeration_type in DWARF scanner").

Reverting the commit on current trunk fixes the problem.

So how does this problem happen?

First, let's consider the current trunk, with the commit reverted.

Gdb looks for the entry ns::A::val1, and find this entry:
...
    [29] ((cooked_index_entry *) 0x7f7830002ef0)
    name:       val1
    canonical:  val1
    qualified:  ns::A::val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0x15a
    parent:     ((cooked_index_entry *) 0x7f7830002ec0) [A]
...
and expands the corresponding CU val1.c containing this debug info:
...
 <2><14a>: Abbrev Number: 3 (DW_TAG_class_type)
    <14b>   DW_AT_name        : A
    <14d>   DW_AT_byte_size   : 1
 <3><150>: Abbrev Number: 4 (DW_TAG_enumeration_type)
    <151>   DW_AT_encoding    : 7       (unsigned)
    <152>   DW_AT_byte_size   : 4
    <153>   DW_AT_type        : <0x163>
    <159>   DW_AT_accessibility: 1      (public)
 <4><15a>: Abbrev Number: 5 (DW_TAG_enumerator)
    <15b>   DW_AT_name        : val1
    <15f>   DW_AT_const_value : 1
 <4><160>: Abbrev Number: 0
 <3><161>: Abbrev Number: 0
 <2><162>: Abbrev Number: 0
...
after which it finds ns::A::val1 in the expanded symtabs.

Now let's consider the current trunk as is (so, with the commit present).

Gdb looks for the entry ns::A::val1, but doesn't find it because the val1
entry is missing its parent:
...
   [29] ((cooked_index_entry *) 0x7f5240002ef0)
    name:       val1
    canonical:  val1
    qualified:  val1
    DWARF tag:  DW_TAG_enumerator
    flags:      0x0 []
    DIE offset: 0x15a
    parent:     ((cooked_index_entry *) 0)
...

Then gdb looks for the entry ns::A, and finds this entry:
...
   [3] ((cooked_index_entry *) 0x7f5248002ec0)
    name:       A
    canonical:  A
    qualified:  ns::A
    DWARF tag:  DW_TAG_class_type
    flags:      0x0 []
    DIE offset: 0xdd
    parent:     ((cooked_index_entry *) 0x7f5248002e90) [ns]
...
which corresponds to this debug info, which doesn't contain val1
due to -fno-eliminate-unused-debug-types:
...
 <2><dd>: Abbrev Number: 3 (DW_TAG_class_type)
    <de>   DW_AT_name        : A
    <e0>   DW_AT_byte_size   : 1
 <2><e3>: Abbrev Number: 0
...

Gdb expands the corresponding CU main.c, after which it doesn't find
ns::A::val1 in the expanded symtabs.

The root cause of the problem is the missing parent on the val1
cooked_index_entry, but this only becomes user-visible through the
elaborate scenario above.

Add a test-case gdb.dwarf2/enum-type-c++.exp that contains a regression test
for this problem that doesn't rely on expansion state or
-feliminate-unused-debug-types, but simply tests for the root cause by
grepping for ns::A::val1 in the output of "maint print objfile".

Tested on x86_64-linux.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31900
---
 gdb/testsuite/gdb.dwarf2/enum-type-c++.cc  | 29 ++++++++++++++
 gdb/testsuite/gdb.dwarf2/enum-type-c++.exp | 44 ++++++++++++++++++++++
 2 files changed, 73 insertions(+)
 create mode 100644 gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
 create mode 100644 gdb/testsuite/gdb.dwarf2/enum-type-c++.exp


base-commit: 4290b2c07e2d9bc1e1661a4ad5e343e3eb307770
  

Comments

Tom Tromey Sept. 13, 2024, 7:02 p.m. UTC | #1
>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:

Tom> Add a test-case gdb.dwarf2/enum-type-c++.exp that contains a regression test
Tom> for this problem that doesn't rely on expansion state or
Tom> -feliminate-unused-debug-types, but simply tests for the root cause by
Tom> grepping for ns::A::val1 in the output of "maint print objfile".

Ok.
Approved-By: Tom Tromey <tom@tromey.com>

Tom
  
Guinevere Larsen Sept. 16, 2024, 7:21 p.m. UTC | #2
On 9/12/24 8:52 AM, Tom de Vries wrote:
> Consider the following test-case:
> ...
> $ cat a.h
> namespace ns {
>
> class A {
> public:
>    enum {
>      val1 = 1
>    };
> };
>
> }
> $ cat main.c
>
> ns::A a;
>
> int
> main (void)
> {
>    return 0;
> }
> $ cat val1.c
>
> int u1 = ns::A::val1;
> ...
> compiled with debug info:
> ...
> $ g++ main.c val1.c -g
> ...
>
> When trying to print ns::A::val with current trunk and gdb 15.1 we get:
> ...
> $ gdb -q -batch a.out -ex "print ns::A::val1"
> There is no field named val1
> ...
>
> This PR c++/31900.
>
> With gdb 14.2 we get the expected:
> ...
> $ gdb -q -batch a.out -ex "print ns::A::val1"
> $1 = ns::A::val1
> ...
>
> This is a regression since commit 4e417d7bb1c ("Change handling of
> DW_TAG_enumeration_type in DWARF scanner").
>
> Reverting the commit on current trunk fixes the problem.
>
> So how does this problem happen?
>
> First, let's consider the current trunk, with the commit reverted.
>
> Gdb looks for the entry ns::A::val1, and find this entry:
> ...
>      [29] ((cooked_index_entry *) 0x7f7830002ef0)
>      name:       val1
>      canonical:  val1
>      qualified:  ns::A::val1
>      DWARF tag:  DW_TAG_enumerator
>      flags:      0x0 []
>      DIE offset: 0x15a
>      parent:     ((cooked_index_entry *) 0x7f7830002ec0) [A]
> ...
> and expands the corresponding CU val1.c containing this debug info:
> ...
>   <2><14a>: Abbrev Number: 3 (DW_TAG_class_type)
>      <14b>   DW_AT_name        : A
>      <14d>   DW_AT_byte_size   : 1
>   <3><150>: Abbrev Number: 4 (DW_TAG_enumeration_type)
>      <151>   DW_AT_encoding    : 7       (unsigned)
>      <152>   DW_AT_byte_size   : 4
>      <153>   DW_AT_type        : <0x163>
>      <159>   DW_AT_accessibility: 1      (public)
>   <4><15a>: Abbrev Number: 5 (DW_TAG_enumerator)
>      <15b>   DW_AT_name        : val1
>      <15f>   DW_AT_const_value : 1
>   <4><160>: Abbrev Number: 0
>   <3><161>: Abbrev Number: 0
>   <2><162>: Abbrev Number: 0
> ...
> after which it finds ns::A::val1 in the expanded symtabs.
>
> Now let's consider the current trunk as is (so, with the commit present).
>
> Gdb looks for the entry ns::A::val1, but doesn't find it because the val1
> entry is missing its parent:
> ...
>     [29] ((cooked_index_entry *) 0x7f5240002ef0)
>      name:       val1
>      canonical:  val1
>      qualified:  val1
>      DWARF tag:  DW_TAG_enumerator
>      flags:      0x0 []
>      DIE offset: 0x15a
>      parent:     ((cooked_index_entry *) 0)
> ...
>
> Then gdb looks for the entry ns::A, and finds this entry:
> ...
>     [3] ((cooked_index_entry *) 0x7f5248002ec0)
>      name:       A
>      canonical:  A
>      qualified:  ns::A
>      DWARF tag:  DW_TAG_class_type
>      flags:      0x0 []
>      DIE offset: 0xdd
>      parent:     ((cooked_index_entry *) 0x7f5248002e90) [ns]
> ...
> which corresponds to this debug info, which doesn't contain val1
> due to -fno-eliminate-unused-debug-types:
> ...
>   <2><dd>: Abbrev Number: 3 (DW_TAG_class_type)
>      <de>   DW_AT_name        : A
>      <e0>   DW_AT_byte_size   : 1
>   <2><e3>: Abbrev Number: 0
> ...
>
> Gdb expands the corresponding CU main.c, after which it doesn't find
> ns::A::val1 in the expanded symtabs.
>
> The root cause of the problem is the missing parent on the val1
> cooked_index_entry, but this only becomes user-visible through the
> elaborate scenario above.
>
> Add a test-case gdb.dwarf2/enum-type-c++.exp that contains a regression test
> for this problem that doesn't rely on expansion state or
> -feliminate-unused-debug-types, but simply tests for the root cause by
> grepping for ns::A::val1 in the output of "maint print objfile".
>
> Tested on x86_64-linux.
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31900
> ---
>   gdb/testsuite/gdb.dwarf2/enum-type-c++.cc  | 29 ++++++++++++++
>   gdb/testsuite/gdb.dwarf2/enum-type-c++.exp | 44 ++++++++++++++++++++++
>   2 files changed, 73 insertions(+)
>   create mode 100644 gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
>   create mode 100644 gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
>
> diff --git a/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc b/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
> new file mode 100644
> index 00000000000..c0ffaad0316
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
> @@ -0,0 +1,29 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2024 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +namespace ns {
> +
> +class A {
> +public:
> +  enum {
> +    val1 = 1
> +  };
> +};
> +
> +}
> +
> +int u1 = ns::A::val1;
> diff --git a/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp b/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
> new file mode 100644
> index 00000000000..44ad225de02
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
> @@ -0,0 +1,44 @@
> +# Copyright 2024 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +require !readnow
> +
> +load_lib dwarf.exp
> +
> +# This test can only be run on targets which support DWARF-2 and use gas.
> +require dwarf2_support
> +
> +standard_testfile main.c .cc
> +
> +if { [prepare_for_testing "failed to prepare" $testfile \
> +	  [list $srcfile $srcfile2] {debug c++}] } {
> +    return -1
> +}
> +
> +require {string equal [have_index $binfile] ""}
> +
> +set re_ws "\[ \t\]"
> +
> +# Regression test for PR31900.
> +setup_kfail "gdb/31900" *-*-*
> +set val1 ns::A::val1
> +gdb_test_lines "maint print objfiles" \
> +    "val1 has a parent" \
> +    [multi_line \
> +	 "" \
> +	 "$re_ws+qualified:$re_ws+$val1" \
> +	 ".*"]
> +
> +gdb_test "print $val1" " = $val1"
>
> base-commit: 4290b2c07e2d9bc1e1661a4ad5e343e3eb307770

Hi Tom

The test introduced by this patch fails with clang with the attached log.

Some of the fails come from later patches, but "print ns::A::val1" fails 
ever since this patch.
  
Tom de Vries Sept. 26, 2024, 1:30 p.m. UTC | #3
On 9/16/24 21:21, Guinevere Larsen wrote:
> Hi Tom
> 
> The test introduced by this patch fails with clang with the attached log.
> 
> Some of the fails come from later patches, but "print ns::A::val1" fails 
> ever since this patch.

Hi Gwen,

thanks for reporting this.

I'm working on a fix, but a more complicated one that just bailing out 
for clang, so it's taking a bit longer.

Thanks,
- Tom
  

Patch

diff --git a/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc b/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
new file mode 100644
index 00000000000..c0ffaad0316
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/enum-type-c++.cc
@@ -0,0 +1,29 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2024 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+namespace ns {
+
+class A {
+public:
+  enum {
+    val1 = 1
+  };
+};
+
+}
+
+int u1 = ns::A::val1;
diff --git a/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp b/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
new file mode 100644
index 00000000000..44ad225de02
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/enum-type-c++.exp
@@ -0,0 +1,44 @@ 
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+require !readnow
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile main.c .cc
+
+if { [prepare_for_testing "failed to prepare" $testfile \
+	  [list $srcfile $srcfile2] {debug c++}] } {
+    return -1
+}
+
+require {string equal [have_index $binfile] ""}
+
+set re_ws "\[ \t\]"
+
+# Regression test for PR31900.
+setup_kfail "gdb/31900" *-*-*
+set val1 ns::A::val1
+gdb_test_lines "maint print objfiles" \
+    "val1 has a parent" \
+    [multi_line \
+	 "" \
+	 "$re_ws+qualified:$re_ws+$val1" \
+	 ".*"]
+
+gdb_test "print $val1" " = $val1"