From: Tom Tromey Date: Tue, 25 Jan 2022 18:26:15 +0000 (-0700) Subject: Handle 'QWW' encoding case in Ada enums X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7041de85a0cc43b86989eb697cef7a6cecdbdb7;p=binutils-gdb.git Handle 'QWW' encoding case in Ada enums In Ada, an enum can contain character literals. GNAT encodes these values in a special way. For example, the Unicode character U+0178 would be represented as 'QW0178' in the DWARF: <3><112f>: Abbrev Number: 2 (DW_TAG_enumerator) <1130> DW_AT_name : (indirect string, offset: 0x19ff): QW0178 <1134> DW_AT_const_value : 2 gdb handles this reasonably well, but failed to handle the 'QWW' encoding, which is used for characters outside the base plane. Also, while working on this, I noticed that gdb will print the decimal value for an enum character constant: (gdb) print Char_X $2 = 1 'x' This is a nice feature, IMO, because in this situation the 'x' enum constant does not have its usual decimal value -- it has the value that's assigned based on the enumeration type. However, gdb did not do this when it decided to print the constant using the bracket notation: (gdb) print Char_Thorn $3 = ["de"] This patch changes gdb to print the decimal value here as well, and to put the bracket notation in single quotes -- otherwise gdb will be printing something that it can't then read. Now it looks like: (gdb) print Char_Thorn $3 = 4 '["de"]' Note that gdb can't read longer bracket notations, like the other ones printed in this test case: (gdb) print Char_King $4 = 3 '["01fa00"]' While I think this is a bug, I plan to fix it separately. Finally, in the new test case, the copyright dates are chosen this way because this all started as a copy of an existing test. --- diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index d2f620cbb04..f1d59d2aadb 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -8786,7 +8786,13 @@ ada_enum_name (const char *name) if (name[1] == 'U' || name[1] == 'W') { - if (sscanf (name + 2, "%x", &v) != 1) + int offset = 2; + if (name[1] == 'W' && name[2] == 'W') + { + /* Also handle the QWW case. */ + ++offset; + } + if (sscanf (name + offset, "%x", &v) != 1) return name; } else if (((name[1] >= '0' && name[1] <= '9') @@ -8802,9 +8808,11 @@ ada_enum_name (const char *name) if (isascii (v) && isprint (v)) storage = string_printf ("'%c'", v); else if (name[1] == 'U') - storage = string_printf ("[\"%02x\"]", v); + storage = string_printf ("'[\"%02x\"]'", v); + else if (name[2] != 'W') + storage = string_printf ("'[\"%04x\"]'", v); else - storage = string_printf ("[\"%04x\"]", v); + storage = string_printf ("'[\"%06x\"]'", v); return storage.c_str (); } diff --git a/gdb/testsuite/gdb.ada/char_enum_unicode.exp b/gdb/testsuite/gdb.ada/char_enum_unicode.exp new file mode 100644 index 00000000000..aa8136054e7 --- /dev/null +++ b/gdb/testsuite/gdb.ada/char_enum_unicode.exp @@ -0,0 +1,43 @@ +# Copyright 2011-2022 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 . + +load_lib "ada.exp" + +if { [skip_ada_tests] } { return -1 } + +standard_ada_testfile foo + +set flags [list debug additional_flags=-gnatW8] +if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != "" } { + return -1 +} + +clean_restart ${testfile} + +set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb] +runto "foo.adb:$bp_location" + +set y "'\\\[\"0178\"\\\]'" +set king "'\\\[\"01fa00\"\\\]'" +set thorn "'\\\[\"de\"\\\]'" + +gdb_test "ptype Char_Enum_Type" "type = \\(alpha, 'x', $y, $king, $thorn\\)" +gdb_test "print Char_Alpha" " = alpha" +gdb_test "print Char_X" " = 1 'x'" +gdb_test "print Char_Y" " = 2 $y" +gdb_test "print Char_King" " = 3 $king" +gdb_test "print Char_Thorn" " = 4 $thorn" +gdb_test "print Char_Enum_Type'('x')" " = 1 'x'" +gdb_test "print Char_Enum_Type'('\[\"de\"\]')" " = 4 $thorn" diff --git a/gdb/testsuite/gdb.ada/char_enum_unicode/foo.adb b/gdb/testsuite/gdb.ada/char_enum_unicode/foo.adb new file mode 100644 index 00000000000..09756870320 --- /dev/null +++ b/gdb/testsuite/gdb.ada/char_enum_unicode/foo.adb @@ -0,0 +1,30 @@ +-- Copyright 2011-2022 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 . + +with Pck; use Pck; + +procedure Foo is + type Char_Enum_Type is (alpha, 'x', 'Ÿ', '🨀', 'Þ'); + Char_Alpha : Char_Enum_Type := alpha; + Char_X : Char_Enum_Type := 'x'; + Char_Thorn : Char_Enum_Type := 'Þ'; + Char_Y : Char_Enum_Type := 'Ÿ'; + Char_King : Char_Enum_Type := '🨀'; +begin + Do_Nothing (Char_Alpha'Address); -- STOP + Do_Nothing (Char_X'Address); + Do_Nothing (Char_Y'Address); + Do_Nothing (Char_King'Address); +end Foo; diff --git a/gdb/testsuite/gdb.ada/char_enum_unicode/pck.adb b/gdb/testsuite/gdb.ada/char_enum_unicode/pck.adb new file mode 100644 index 00000000000..d9308b6c04d --- /dev/null +++ b/gdb/testsuite/gdb.ada/char_enum_unicode/pck.adb @@ -0,0 +1,21 @@ +-- Copyright 2011-2022 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 . + +package body Pck is + procedure Do_Nothing (A : System.Address) is + begin + null; + end Do_Nothing; +end Pck; diff --git a/gdb/testsuite/gdb.ada/char_enum_unicode/pck.ads b/gdb/testsuite/gdb.ada/char_enum_unicode/pck.ads new file mode 100644 index 00000000000..4e937b8a5a2 --- /dev/null +++ b/gdb/testsuite/gdb.ada/char_enum_unicode/pck.ads @@ -0,0 +1,20 @@ +-- Copyright 2011-2022 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 . + +with System; + +package Pck is + procedure Do_Nothing (A : System.Address); +end Pck;