diff options
author | Tom Tromey <tom@tromey.com> | 2024-12-28 14:10:56 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2025-01-24 13:53:11 -0700 |
commit | 2e724489260d02a528591eaea4710ce5aeeee0e8 (patch) | |
tree | 15dc6a5e75cfe3e9022dd3fd03d299ca7d740f95 /gdb/dwarf2 | |
parent | 2047479c10d6b3f213545cf759afe5f77dcdfe9d (diff) | |
download | fsf-binutils-gdb-2e724489260d02a528591eaea4710ce5aeeee0e8.zip fsf-binutils-gdb-2e724489260d02a528591eaea4710ce5aeeee0e8.tar.gz fsf-binutils-gdb-2e724489260d02a528591eaea4710ce5aeeee0e8.tar.bz2 |
Fix C++ template function matching in cooked index
In commit 64a97606 ("Support template lookups in
strncmp_iw_with_mode"), gdb was changed so that a command like "break
func<templ>" would match instantiations like "func<templ<int>>".
The new indexer does not support this and so this is a regression.
This went unnoticed because gdb.linespec.cpcompletion.exp puts all
these functions into the main file, and this CU is expanded early.
This patch fixes the bug by changing the cooked index entry comparison
function. It also updates the test to fail without this fix.
Regression tested on x86-64 Fedora 40.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32482
Diffstat (limited to 'gdb/dwarf2')
-rw-r--r-- | gdb/dwarf2/cooked-index.c | 51 |
1 files changed, 26 insertions, 25 deletions
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c index d776f2f..e024c78 100644 --- a/gdb/dwarf2/cooked-index.c +++ b/gdb/dwarf2/cooked-index.c @@ -93,39 +93,37 @@ int cooked_index_entry::compare (const char *stra, const char *strb, comparison_mode mode) { - auto munge = [] (char c) -> unsigned char + auto munge = [] (char c) constexpr -> unsigned char { - /* We want to sort '<' before any other printable character. - So, rewrite '<' to something just before ' '. */ + /* Treat '<' as if it ended the string. This lets something + like "func<t>" match "func<t<int>>". See the "Breakpoints in + template functions" section in the manual. */ if (c == '<') - return '\x1f'; + return '\0'; return TOLOWER ((unsigned char) c); }; - while (*stra != '\0' - && *strb != '\0' - && (munge (*stra) == munge (*strb))) + unsigned char a = munge (*stra); + unsigned char b = munge (*strb); + + while (a != '\0' && b != '\0' && a == b) { - ++stra; - ++strb; + a = munge (*++stra); + b = munge (*++strb); } - unsigned char c1 = munge (*stra); - unsigned char c2 = munge (*strb); - - if (c1 == c2) + if (a == b) return 0; /* When completing, if STRB ends earlier than STRA, consider them as - equal. When comparing, if STRB ends earlier and STRA ends with - '<', consider them as equal. */ - if (mode == COMPLETE || (mode == MATCH && c1 == munge ('<'))) + equal. */ + if (mode == COMPLETE || (mode == MATCH && a == munge ('<'))) { - if (c2 == '\0') + if (b == '\0') return 0; } - return c1 < c2 ? -1 : 1; + return a < b ? -1 : 1; } #if GDB_SELF_TEST @@ -155,33 +153,36 @@ test_compare () mode_complete) == 0); SELF_CHECK (cooked_index_entry::compare ("name", "name<>", - mode_compare) < 0); + mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name<>", "name", mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name", "name<>", - mode_complete) < 0); + mode_complete) == 0); SELF_CHECK (cooked_index_entry::compare ("name<>", "name", mode_complete) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>", mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>", - mode_compare) > 0); + mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<arg>", mode_complete) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg>", "name<ag>", - mode_complete) > 0); + mode_complete) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<more>>", mode_compare) == 0); + SELF_CHECK (cooked_index_entry::compare ("name<arg>", + "name<arg<more>>", + mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name", "name<arg<more>>", - mode_compare) < 0); + mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name", mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<", - mode_compare) > 0); + mode_compare) == 0); SELF_CHECK (cooked_index_entry::compare ("name<arg<more>>", "name<arg<", mode_complete) == 0); @@ -191,7 +192,7 @@ test_compare () SELF_CHECK (cooked_index_entry::compare ("abcd", "", mode_complete) == 0); SELF_CHECK (cooked_index_entry::compare ("func", "func<type>", - mode_sort) < 0); + mode_sort) == 0); SELF_CHECK (cooked_index_entry::compare ("func<type>", "func1", mode_sort) < 0); } |