diff options
author | Pedro Alves <palves@redhat.com> | 2017-11-08 14:49:10 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-11-08 16:02:24 +0000 |
commit | c62446b12b32ce57d2b40cdb0c1baa7fc1677d82 (patch) | |
tree | 641b99ee8abe91b0fd0d1288dc32873ce454c391 /gdb/symtab.c | |
parent | 61920122ba93d58cc2e8c78a30475c569c2506fd (diff) | |
download | gdb-c62446b12b32ce57d2b40cdb0c1baa7fc1677d82.zip gdb-c62446b12b32ce57d2b40cdb0c1baa7fc1677d82.tar.gz gdb-c62446b12b32ce57d2b40cdb0c1baa7fc1677d82.tar.bz2 |
lookup_name_info::make_ignore_params
A few places in the completion code look for a "(" to find a
function's parameter list, in order to strip it, because psymtabs (and
gdb index) don't include parameter info in the symbol names.
See compare_symbol_name and
default_collect_symbol_completion_matches_break_on.
This is too naive. Consider:
ns_overload2_test::([TAB]
We'd want to complete that to:
ns_overload2_test::(anonymous namespace)::struct_overload2_test
Or:
b (anonymous namespace)::[TAB]
That currently completes to:
b (anonymous namespace)
Which is obviously broken. This patch makes that work.
Also, the current compare_symbol_name hack means that while this
works:
"b function([TAB]" -> "b function()"
This does not:
"b function ([TAB]"
This patch fixes that. Whitespace "ignoring" now Just Works, i.e.,
assuming a symbol named "function(int, long)", this:
b function ( int , lon[TAB]
completes to:
b function ( int , long)
To address all of this, this patch builds on top of the rest of the
series, and pushes the responsibility of stripping parameters from a
lookup name to the new lookup_name_info object, where we can apply
per-language rules. Also note that we now only make a version of the
lookup name with parameters stripped out where it's actually required
to do that, in the psymtab and GDB index code.
For C++, the right way to strip parameters is with "cp_remove_params",
which uses a real parser (cp-name-parser.y) to split the name into a
component tree and then discards parameters.
The trouble for completion is that in that case we have an incomplete
name, like "foo::func(int" and thus cp_remove_params throws an error.
This patch sorts that by adding a cp_remove_params_if_any variant of
cp_remove_params that tries removing characters from the end of the
string until cp_remove_params works. So cp_remove_params_if_any
behaves like this:
With a complete name:
"foo::func(int)" => foo::func(int) # cp_remove_params_1 succeeds the first time.
With an incomplete name:
"foo::func(int" => NULL # cp_remove_params fails the first time.
"foo::func(in" => NULL # and again...
"foo::func(i" => NULL # and again...
"foo::func(" => NULL # and again...
"foo::func" => "foo::func" # success!
Note that even if this approach removes significant rightmost
characters, it's still OK, because this parameter stripping is only
necessary for psymtabs and gdb index, where we're determining whether
to expand a symbol table. Say cp_remove_params_if_any returned
"foo::" above for "foo::func(int". That'd cause us to expand more
symtabs than ideal (because we'd expand all symtabs with symbols that
start with "foo::", not just "foo::func"), but then when we actually
look for completion matches, we'd still use the original lookup name,
with parameter information ["foo::func(int"], and thus we'll return no
false positive to the user. Whether the stripping works as intended
and doesn't strip too much is thus covered by a unit test instead of a
testsuite test.
The "if_any" part of the name refers to the fact that while
cp_remove_params returns NULL if the input name has no parameters in
the first place, like:
"foo::func" => NULL # cp_remove_params
cp_remove_params_if_any still returns the function name:
"foo::func" => "foo::func" # cp_remove_params_if_any
gdb/ChangeLog:
2017-11-08 Pedro Alves <palves@redhat.com>
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
unittests/lookup_name_info-selftests.c.
(SUBDIR_UNITTESTS_OBS): Add lookup_name_info-selftests.o.
* cp-support.c: Include "selftest.h".
(cp_remove_params_1): Rename from cp_remove_params. Add
'require_param' parameter, and handle it.
(cp_remove_params): Reimplement.
(cp_remove_params_if_any): New.
(selftests::quote): New.
(selftests::check_remove_params): New.
(selftests::test_cp_remove_params): New.
(_initialize_cp_support): Install
selftests::test_cp_remove_params.
* cp-support.h (cp_remove_params_if_any): Declare.
* dwarf2read.c :Include "selftest.h".
(dw2_expand_symtabs_matching_symbol): Use
lookup_name_info::make_ignore_params.
(selftests::dw2_expand_symtabs_matching::mock_mapped_index)
(selftests::dw2_expand_symtabs_matching::string_or_null)
(selftests::dw2_expand_symtabs_matching::check_match)
(selftests::dw2_expand_symtabs_matching::test_symbols)
(selftests::dw2_expand_symtabs_matching::run_test): New.
(_initialize_dwarf2_read): Register
selftests::dw2_expand_symtabs_matching::run_test.
* psymtab.c (psym_expand_symtabs_matching): Use
lookup_name_info::make_ignore_params.
* symtab.c (demangle_for_lookup_info::demangle_for_lookup_info):
If the lookup name wants to ignore parameters, strip them.
(compare_symbol_name): Remove sym_text/sym_text_len parameters and
code handling '('.
(completion_list_add_name): Don't pass down sym_text/sym_text_len.
(default_collect_symbol_completion_matches_break_on): Don't try to
strip parameters.
* symtab.h (lookup_name_info::lookup_name_info): Add
'ignore_parameters' parameter.
(lookup_name_info::ignore_parameters)
(lookup_name_info::make_ignore_params): New methods.
(lookup_name_info::m_ignore_parameters): New field.
* unittests/lookup_name_info-selftests.c: New file.
Diffstat (limited to 'gdb/symtab.c')
-rw-r--r-- | gdb/symtab.c | 65 |
1 files changed, 18 insertions, 47 deletions
diff --git a/gdb/symtab.c b/gdb/symtab.c index aecee8f..2d09f94 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1766,6 +1766,20 @@ demangle_for_lookup_info::demangle_for_lookup_info { demangle_result_storage storage; + if (lookup_name.ignore_parameters () && lang == language_cplus) + { + gdb::unique_xmalloc_ptr<char> without_params + = cp_remove_params_if_any (lookup_name.name ().c_str (), + lookup_name.completion_mode ()); + + if (without_params != NULL) + { + m_demangled_name = demangle_for_lookup (without_params.get (), + lang, storage); + return; + } + } + m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (), lang, storage); } @@ -4619,20 +4633,11 @@ rbreak_command (const char *regexp, int from_tty) } -/* Evaluate if NAME matches SYM_TEXT and SYM_TEXT_LEN. - - Either sym_text[sym_text_len] != '(' and then we search for any - symbol starting with SYM_TEXT text. - - Otherwise sym_text[sym_text_len] == '(' and then we require symbol name to - be terminated at that point. Partial symbol tables do not have parameters - information. */ +/* Evaluate if SYMNAME matches LOOKUP_NAME. */ static int -compare_symbol_name (const char *name, - language symbol_language, +compare_symbol_name (const char *symbol_name, language symbol_language, const lookup_name_info &lookup_name, - const char *sym_text, int sym_text_len, completion_match_result &match_res) { const language_defn *lang; @@ -4654,23 +4659,7 @@ compare_symbol_name (const char *name, symbol_name_matcher_ftype *name_match = language_get_symbol_name_matcher (lang, lookup_name); - /* Clip symbols that cannot match. */ - if (!name_match (name, lookup_name, &match_res.match)) - return 0; - - if (sym_text[sym_text_len] == '(') - { - /* User searches for `name(someth...'. Require NAME to be terminated. - Normally psymtabs and gdbindex have no parameter types so '\0' will be - present but accept even parameters presence. In this case this - function is in fact strcmp_iw but whitespace skipping is not supported - for tab completion. */ - - if (name[sym_text_len] != '\0' && name[sym_text_len] != '(') - return 0; - } - - return 1; + return name_match (symbol_name, lookup_name, &match_res.match); } /* See symtab.h. */ @@ -4687,10 +4676,7 @@ completion_list_add_name (completion_tracker &tracker, = tracker.reset_completion_match_result (); /* Clip symbols that cannot match. */ - if (!compare_symbol_name (symname, symbol_language, - lookup_name, - sym_text, sym_text_len, - match_res)) + if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res)) return; /* Refresh SYMNAME from the match string. It's potentially @@ -5014,21 +5000,6 @@ default_collect_symbol_completion_matches_break_on sym_text_len = strlen (sym_text); - /* Prepare SYM_TEXT_LEN for compare_symbol_name. */ - - if (current_language->la_language == language_cplus - || current_language->la_language == language_fortran) - { - /* These languages may have parameters entered by user but they are never - present in the partial symbol tables. */ - - const char *cs = (const char *) memchr (sym_text, '(', sym_text_len); - - if (cs) - sym_text_len = cs - sym_text; - } - gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '('); - lookup_name_info lookup_name (std::string (sym_text, sym_text_len), name_match_type, true); |