Bug 30726 - [gdb/ada] FAIL: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
Summary: [gdb/ada] FAIL: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: ada (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 14.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-08-06 13:06 UTC by Tom de Vries
Modified: 2023-09-07 19:41 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
enum_with_gap_main.gz (stripped with --only-keep-debug) (304.29 KB, application/gzip)
2023-08-06 14:39 UTC, Tom de Vries
Details
tentative patch (1.40 KB, patch)
2023-09-06 15:56 UTC, Tom de Vries
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2023-08-06 13:06:20 UTC
When running with target board cc-with-dwz, I run into:
...
(gdb) print enum_with_gaps'enum_rep(lit3)^M
'Enum_Rep requires argument to have same type as enum^M
(gdb) FAIL: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
...

With target_board unix, we have instead:
...
(gdb) PASS: gdb.ada/arr_acc_idx_w_gap.exp: print s(2)
print enum_with_gaps'enum_rep(lit3)^M
$16 = 13^M
(gdb) PASS: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
...

The error happens here:
...
8828	  if (!types_equal (type, arg->type ()))
8829	    error (_("'Enum_Rep requires argument to have same type as enum"));
...
because these types are not considered equal:
...
(gdb) p type->name ()
$1 = 0x7fffe4673e7d "enum_with_gap__enum_with_gaps"
(gdb) p arg->type()->name ()
$2 = 0x7fffe467411f "enum_with_gap__enum_subrangeB"
...

With target_board_unix, we have instead:
...
(gdb) p type->name ()
$1 = 0x7fffcc666c2d "enum_with_gap__enum_with_gaps"
(gdb) p arg->type()->name ()
$2 = 0x7fffcc666c2d "enum_with_gap__enum_with_gaps"
...
Comment 1 Tom de Vries 2023-08-06 14:28:01 UTC
With target board unix, looking at the debug info we have:
...
 <0><81c>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <822>   DW_AT_name        : enum_with_gap.adb
 <1><84c>: Abbrev Number: 4 (DW_TAG_enumeration_type)
    <84d>   DW_AT_name        : enum_with_gap__enum_with_gaps
 <2><86b>: Abbrev Number: 5 (DW_TAG_enumerator)
    <86c>   DW_AT_name        : enum_with_gap__lit3
    <870>   DW_AT_const_value : 13
<0><9e9>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <9ef>   DW_AT_name        : enum_with_gap_main.adb
 <1><a20>: Abbrev Number: 4 (DW_TAG_enumeration_type)
    <a21>   DW_AT_name        : enum_with_gap__enum_with_gaps
 <2><a3f>: Abbrev Number: 5 (DW_TAG_enumerator)
    <a40>   DW_AT_name        : enum_with_gap__lit3
    <a44>   DW_AT_const_value : 13
 <1><b4c>: Abbrev Number: 16 (DW_TAG_enumeration_type)
    <b4d>   DW_AT_name        : enum_with_gap__enum_subrangeB
    <b55>   DW_AT_artificial  : 1
 <2><b6b>: Abbrev Number: 5 (DW_TAG_enumerator)
    <b6c>   DW_AT_name        : enum_with_gap__lit3__2
    <b70>   DW_AT_const_value : 13
...

Dwz moves enum_with_gap__enum_with_gaps into a partial unit.

That somehow changes the symbol table.

With target board unix, the first item with canonical name lit3 is:
...
    [721] ((cooked_index_entry *) 0x7fe8d8009b00)
    name:       enum_with_gap__lit3
    canonical:  lit3
    DWARF tag:  DW_TAG_enumerator
    flags:      0x2 [IS_STATIC]
    DIE offset: 0x86b
    parent:     ((cooked_index_entry *) 0x7fe8d8021fe0) [enum_with_gap]
...

With target board cc-with-dwz, it's instead:
...
    [780] ((cooked_index_entry *) 0x7f9d1c0049c0)
    name:       enum_with_gap__lit3__2
    canonical:  lit3
    DWARF tag:  DW_TAG_enumerator
    flags:      0x2 [IS_STATIC]
    DIE offset: 0x23a5
    parent:     ((cooked_index_entry *) 0x7f9d1c025ad0) [enum_with_gap]
...
Comment 2 Tom de Vries 2023-08-06 14:39:14 UTC
Created attachment 15042 [details]
enum_with_gap_main.gz (stripped with --only-keep-debug)

$ gdb -q -batch ./enum_with_gap_main -ex "print enum_with_gaps'enum_rep(lit3)"
'Enum_Rep requires argument to have same type as enum

This is with gcc 12, analysis above done with gcc 7.
Comment 3 Tom de Vries 2023-08-07 01:08:53 UTC
Also fails with target board debug-types.
Comment 4 Tom de Vries 2023-09-06 13:04:04 UTC
Fixed by:
...
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index c0cc512bfa3..5b8b54331b7 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5104,7 +5104,8 @@ remove_extra_symbols (std::vector<struct block_symbol> &syms)
      to ask the user to disambiguate anyways.  And if we have to
      present a multiple-choice menu, it's less confusing if the list
      isn't missing some choices that were identical and yet distinct.  */
-  if (symbols_are_identical_enums (syms))
+  if (false && symbols_are_identical_enums (syms))
     syms.resize (1);
 }
...

Here in remove_extra_symbols we randomly throw away one of the two enums.

In the cc-with-dwz variant, we throw away the wrong one because the order in which the symbols is found has changed.

If there are two symbols remaining after remove_extra_symbols, write_var_or_type produces an ambiguous var, which then allows the ada_pop here:
...
        |       type_prefix TICK_ENUM_REP '(' exp ')'
                        {
                          operation_up arg = ada_pop (true, $1);
                          pstate->push_new<ada_atr_enum_rep_operation>
                            ($1, std::move (arg));
			}
...
to resolve the literal using the $1 context_type.
Comment 5 Tom de Vries 2023-09-06 13:15:43 UTC
Reproduces with target board unix:
...
diff --git a/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp b/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
index 4a1482b6d99..a98e9e1e2c3 100644
--- a/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
+++ b/gdb/testsuite/gdb.ada/arr_acc_idx_w_gap.exp
@@ -69,6 +69,8 @@ foreach_with_prefix scenario {all minimal} {
 
     gdb_test "print enum_with_gaps'enum_rep(lit3)" " = 13" \
 	"enum_rep"
+    gdb_test "print enum_subrange'enum_rep(lit3)" " = 13" \
+	"other enum_rep"
     gdb_test "print enum_with_gaps'enum_val(21)" " = lit4" \
 	"enum_val"
 }
...

Dropping the cc-with-dwz from $summary.
Comment 6 Tom de Vries 2023-09-06 14:58:03 UTC
(In reply to Tom de Vries from comment #4)
> Fixed by:

Well, in the sense that we have:
...
$ gdb -q -batch ./enum_with_gap_main-all -ex "print enum_with_gaps'enum_rep(lit3)"
$1 = 13
$ gdb -q -batch ./enum_with_gap_main-all -ex "print enum_subrange'enum_rep(lit3)"
$1 = 13
$ gdb -q -batch ./enum_with_gap_main-all.dwz -ex "print enum_with_gaps'enum_rep(lit3)"
$1 = 13
$ gdb -q -batch ./enum_with_gap_main-all.dwz -ex "print enum_subrange'enum_rep(lit3)"
$1 = 13
...

When running the test-case, we run into the unsurprising fallout:
...
(gdb) print indexed_by_enum(lit2..lit4)^M
Multiple matches for lit4^M
[0] cancel^M
[1] enum_with_gap.enum_with_gaps'(enum_with_gap.lit4) (enumeral)^M
[2] enum_with_gap.enum_subrangeB'(enum_with_gap.lit4) (enumeral)^M
> FAIL: gdb.ada/arr_acc_idx_w_gap.exp: scenario=all: print indexed_by_enum(lit2..lit4) (timeout)
...

Interestingly, the test-case that is supposed to fail is passing because the compiler drops an unused type, this fixes that:
...
diff --git a/gdb/testsuite/gdb.ada/same_enum/a.adb b/gdb/testsuite/gdb.ada/same_enum/a.adb
index ef2cceb3e60..4612aaa7283 100644
--- a/gdb/testsuite/gdb.ada/same_enum/a.adb
+++ b/gdb/testsuite/gdb.ada/same_enum/a.adb
@@ -17,7 +17,7 @@ with Pck; use Pck;
 
 procedure A is
    FC : Color := Red;
-   SC : Color := Green;
+   SC : RGB_Color := Green;
 begin
    Do_Nothing (FC'Address);
    Do_Nothing (SC'Address);
...

Anyway, the fallout is limited to gdb.ada/arr_acc_idx_w_gap.exp and the fixed gdb.ada/same_enum.exp test-cases, all other test-cases pass.
Comment 7 Tom de Vries 2023-09-06 15:27:18 UTC
(In reply to Tom de Vries from comment #6)
> -   SC : Color := Green;
> +   SC : RGB_Color := Green;

Committed here ( https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=313b2841b8e9046ea658104988e01bedf6148d5f ).
Comment 8 Tom de Vries 2023-09-06 15:56:00 UTC
Created attachment 15100 [details]
tentative patch
Comment 10 Sourceware Commits 2023-09-07 19:39:50 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ef136c7fa165cf3ee75c37d41561be8a7bdc89bd

commit ef136c7fa165cf3ee75c37d41561be8a7bdc89bd
Author: Tom de Vries <tdevries@suse.de>
Date:   Thu Sep 7 21:39:42 2023 +0200

    [gdb/ada] Move identical enums handling later
    
    When running test-case gdb.ada/arr_acc_idx_w_gap.exp with target board
    cc-with-dwz, I run into:
    ...
    (gdb) print enum_with_gaps'enum_rep(lit3)^M
    'Enum_Rep requires argument to have same type as enum^M
    (gdb) FAIL: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
    ...
    
    With target_board unix, we have instead:
    ...
    (gdb) print enum_with_gaps'enum_rep(lit3)^M
    $16 = 13^M
    (gdb) PASS: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
    ...
    
    Conversely, when I add this test to the test-case:
    ...
         gdb_test "print enum_with_gaps'enum_rep(lit3)" " = 13" \
            "enum_rep"
    +    gdb_test "print enum_subrange'enum_rep(lit3)" " = 13" \
    +       "other enum_rep"
    ...
    the extra test passes with target board cc-with-dwz, but fails with target
    board unix.
    
    The problem is here in remove_extra_symbols:
    ...
      if (symbols_are_identical_enums (syms))
        syms.resize (1);
    ...
    where one of the two identical enums is picked before the enum_rep handling
    can resolve lit3 to one of the two.
    
    Fix this by moving the code to ada_resolve_variable.
    
    Tested on x86_64-linux.
    
    Approved-By: Tom Tromey <tom@tromey.com>
    
    PR ada/30726
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30726
Comment 11 Tom de Vries 2023-09-07 19:41:59 UTC
Fixed.