2017-01-01 07:50:51 +01:00
|
|
|
# Copyright 2012-2017 Free Software Foundation, Inc.
|
2012-04-05 20:50:29 +02:00
|
|
|
|
|
|
|
# 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/>.
|
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Tests for linespec errors with C and C++.
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# The test proper. LANG is either C or C++.
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
proc do_test {lang} {
|
|
|
|
global testfile srcfile error_messages compiler_info
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
standard_testfile
|
|
|
|
set exefile $testfile
|
|
|
|
if [info exists compiler_info] {
|
|
|
|
# Unsetting compiler_info allows us to switch compilers
|
|
|
|
# used by prepare_for_testing.
|
|
|
|
unset compiler_info
|
|
|
|
}
|
|
|
|
set options {debug}
|
|
|
|
|
|
|
|
if {$lang == "C++"} {
|
|
|
|
if {[skip_cplus_tests]} {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
# Build ".c" source file with g++.
|
|
|
|
lappend options "c++"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-12-23 17:52:18 +01:00
|
|
|
if {[prepare_for_testing "failed to prepare" $exefile $srcfile $options]} {
|
2016-03-15 23:18:28 +01:00
|
|
|
return -1
|
|
|
|
}
|
2015-02-01 00:07:22 +01:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Turn off the pending breakpoint queries.
|
|
|
|
gdb_test_no_output "set breakpoint pending off"
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Turn off completion limiting
|
|
|
|
gdb_test_no_output "set max-completions unlimited"
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
if {![runto_main]} {
|
2016-12-01 21:40:05 +01:00
|
|
|
fail "can't run to main"
|
2016-03-15 23:18:28 +01:00
|
|
|
return 0
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Run to a location in the file.
|
|
|
|
set bp_location [gdb_get_line_number "set breakpoint here"]
|
|
|
|
|
|
|
|
gdb_test "break $srcfile:$bp_location" \
|
|
|
|
"Breakpoint.*at.* file .*$srcfile, line $bp_location\\." \
|
|
|
|
"breakpoint line number in file"
|
|
|
|
|
|
|
|
gdb_continue_to_breakpoint "$bp_location"
|
|
|
|
|
|
|
|
# Common error message format strings.
|
|
|
|
array set error_messages {
|
|
|
|
invalid_file "No source file named %s."
|
|
|
|
invalid_function "Function \"%s\" not defined."
|
|
|
|
invalid_var_or_func
|
|
|
|
"Undefined convenience variable or function \"%s\" not defined."
|
|
|
|
invalid_function_f "Function \"%s\" not defined in \"%s\"."
|
|
|
|
invalid_var_or_func_f \
|
|
|
|
"Undefined convenience variable or function \"%s\" not defined in \"%s\"."
|
|
|
|
invalid_label "No label \"%s\" defined in function \"%s\"."
|
|
|
|
invalid_parm "invalid linespec argument, \"%s\""
|
|
|
|
invalid_offset "No line %d in the current file."
|
|
|
|
invalid_offset_f "No line %d in file \"%s\"."
|
|
|
|
malformed_line_offset "malformed line offset: \"%s\""
|
|
|
|
source_incomplete \
|
|
|
|
"Source filename requires function, label, or line offset."
|
|
|
|
unexpected "malformed linespec error: unexpected %s"
|
|
|
|
unexpected_opt "malformed linespec error: unexpected %s, \"%s\""
|
|
|
|
unmatched_quote "unmatched quote"
|
|
|
|
garbage "Garbage '%s' at end of command"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# We intentionally do not use gdb_breakpoint for these tests.
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Break at 'linespec' and expect the message in ::error_messages
|
|
|
|
# indexed by msg_id with the associated args.
|
|
|
|
proc test_break {linespec msg_id args} {
|
|
|
|
global error_messages
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
gdb_test "break $linespec" [string_to_regexp \
|
|
|
|
[eval format \$error_messages($msg_id) \
|
|
|
|
$args]]
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Some commonly used whitespace tests around ':'.
|
A smarter linespec completer
Continuing the theme of the explicit locations patch, this patch gets
rid of the need for quoting function names in linespec TAB completion.
To recap, when you have overloads in your program, and you want to set
a breakpoint in one of them:
void function(int); // set breakpoint here.
void function(long);
(gdb) b function(i[TAB]
<all the symbols in the program that start with "i" are uselessly shown...>
This patch gets rid of the need for quoting by switching the linespec
completer to use the custom completion word point mechanism added in
the previous explicit location patch (extending it as needed), to
correctly determine the right completion word point. In the case
above, we want the completer to figure out that it's completing a
function name that starts with "function(i", and it now does.
We also want the completer to know when it's potentially completing a
source file name, for:
(gdb) break source.[TAB] -> source.c:
(gdb) break source.c: # Type line number or function name now
And we want it to know to complete label names, which it doesn't today:
(gdb) break function:lab[TAB]
etc., etc.
So what we want is for completion to grok the input string as closely
to how the linespec parser groks it.
With that in mind, the solution suggests itself - make the linespec
completer use the same parsing code as normal linespec parsing.
That's what the patch does. The old completer is replaced by one that
reuses the actual linespec parser as much as possible. This (ideally)
eliminate differences between what completion understands and actually
setting breakpoints understands by design.
The completer now offers sensible completion candidates depending on
which component of the linespec is being completed, source filename,
function, line number, expression, and (a new addition), labels. For
example, when completing the function part, we now show the full name
of the method as completion candidates, instead of showing whatever
comes after what readline considered the word break character:
(gdb) break klass::method[TAB]
klass:method1(int)
klass:method2()
If input is past the function, then we now offer keyword condidates:
(gdb) b function(int) [TAB]
if task thread
If input is past a keyword, we offer expression completion, which is
different from linespec completion:
(gdb) b main if 1 + glo[TAB]
global
(e.g., completes on types, struct data fields, etc.)
As mentioned, this teaches the linespec completer about completing
label symbols too:
(gdb) b source.c:function:lab[TAB]
A nice convenience is that when completion uniquely matches a source
name, gdb adds the ":" automatically for you:
(gdb) b filenam[TAB]
(gdb) b filename.c: # ':' auto-added, cursor right after it.
It's the little details. :-)
I worked on this patch in parallel with writing the (big) testcase
added closer to the end of the series, which exercises many many
tricky cases around quoting and whitespace insertion placement. In
general, I think it now all Just Works.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* completer.c (complete_source_filenames): New function.
(complete_address_and_linespec_locations): New function.
(location_completer): Use complete_address_and_linespec_locations.
(completion_tracker::build_completion_result): Honor the tracker's
request to suppress append.
* completer.h (completion_tracker::suppress_append_ws)
(completion_tracker::set_suppress_append_ws): New methods.
(completion_tracker::m_suppress_append_ws): New field.
(complete_source_filenames): New declaration.
* linespec.c (linespec_complete_what): New.
(struct ls_parser) <complete_what, completion_word,
completion_quote_char, completion_quote_end, completion_tracker>:
New fields.
(string_find_incomplete_keyword_at_end): New.
(linespec_lexer_lex_string): Record quote char. If in completion
mode, don't throw.
(linespec_lexer_consume_token): Advance the completion word point.
(linespec_lexer_peek_token): Save/restore completion info.
(save_stream_and_consume_token): New.
(set_completion_after_number): New.
(linespec_parse_basic): Set what to complete next depending on
token. Handle function and label completions specially.
(parse_linespec): Disable objc shortcut in completion mode. Set
what to complete next depending on token type. Skip keyword if in
completion mode.
(complete_linespec_component, linespec_complete): New.
* linespec.h (linespec_complete): Declare.
gdb/testsuite/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* gdb.base/completion.exp: Adjust expected output.
* gdb.linespec/ls-errs.exp: Don't send tab characters, now that
the completer works.
2017-07-17 21:08:02 +02:00
|
|
|
set spaces [list \
|
|
|
|
":" \
|
|
|
|
": " \
|
|
|
|
" :" \
|
|
|
|
" : " \
|
|
|
|
" : " \
|
|
|
|
]
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# A list of invalid offsets.
|
|
|
|
set invalid_offsets [list -100 +500 1000]
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Try some simple, invalid linespecs involving spaces.
|
|
|
|
foreach x $spaces {
|
|
|
|
test_break $x unexpected "colon"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Test invalid filespecs starting with offset. This is done
|
|
|
|
# first so that default offsets are tested.
|
|
|
|
foreach x $invalid_offsets {
|
|
|
|
set offset $x
|
|
|
|
|
2017-10-13 16:22:17 +02:00
|
|
|
# Relative offsets are relative to the current line. Adjust
|
2016-03-15 23:18:28 +01:00
|
|
|
# expected offset from error message accordingly.
|
|
|
|
if {[string index $x 0] == "+" || [string index $x 0] == "-"} {
|
2017-10-13 16:22:17 +02:00
|
|
|
incr offset $bp_location
|
2016-03-15 23:18:28 +01:00
|
|
|
}
|
|
|
|
test_break $x invalid_offset $offset
|
|
|
|
test_break "-line $x" invalid_offset $offset
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Test offsets with trailing tokens w/ and w/o spaces.
|
|
|
|
foreach x $spaces {
|
|
|
|
test_break "3$x" unexpected "colon"
|
|
|
|
test_break "+10$x" unexpected "colon"
|
|
|
|
test_break "-10$x" unexpected "colon"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
foreach x {1 +1 +100 -10} {
|
|
|
|
test_break "3 $x" unexpected_opt "number" $x
|
|
|
|
test_break "-line 3 $x" garbage $x
|
|
|
|
test_break "+10 $x" unexpected_opt "number" $x
|
|
|
|
test_break "-line +10 $x" garbage $x
|
|
|
|
test_break "-10 $x" unexpected_opt "number" $x
|
|
|
|
test_break "-line -10 $x" garbage $x
|
|
|
|
}
|
2015-08-12 02:09:36 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
foreach x {3 +10 -10} {
|
|
|
|
test_break "$x foo" unexpected_opt "string" "foo"
|
|
|
|
test_break "-line $x foo" garbage "foo"
|
|
|
|
}
|
2015-08-12 02:09:36 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Test invalid linespecs starting with filename.
|
|
|
|
# It's OK to use the ".c" extension for the C++ test
|
|
|
|
# since the extension doesn't affect GDB's lookup.
|
|
|
|
set invalid_files [list "this_file_doesn't_exist.c" \
|
|
|
|
"this file has spaces.c" \
|
|
|
|
"\"file::colons.c\"" \
|
|
|
|
"'file::colons.c'" \
|
|
|
|
"\"this \"file\" has quotes.c\"" \
|
|
|
|
"'this \"file\" has quotes.c'" \
|
|
|
|
"'this 'file' has quotes.c'" \
|
|
|
|
"\"this 'file' has quotes.c\"" \
|
|
|
|
"\"spaces: and :colons.c\"" \
|
|
|
|
"'more: :spaces: :and colons::.c'" \
|
|
|
|
"C:/nonexist-with-windrive.c"]
|
|
|
|
|
|
|
|
foreach x $invalid_files {
|
|
|
|
# Remove any quoting from FILENAME for the error message.
|
|
|
|
test_break "$x:3" invalid_file [string trim $x \"']
|
|
|
|
}
|
|
|
|
foreach x [list "this_file_doesn't_exist.c" \
|
|
|
|
"file::colons.c" \
|
|
|
|
"'file::colons.c'"] {
|
|
|
|
test_break "-source $x -line 3" invalid_file [string trim $x \"']
|
|
|
|
}
|
2015-08-12 02:09:36 +02:00
|
|
|
|
Rewrite/enhance explicit locations completer, parse left->right
One of the most annoying (to me) things about GDB's completion is when
you have overloads in your program, and you want to set a breakpoint
in one of them:
void function(int); // set breakpoint here.
void function(long);
(gdb) b -f func[TAB]
(gdb) b -f function( # ok, gdb completed as much as possible.
(gdb) b -f function([TAB] # show me the overloads, please.
<_all_ symbols in the program are shown...>
E.g., when debugging GDB, that'd be:
(gdb) b -f function([TAB]
(anonymous namespace)::get_global()::global pt_insn_get_offset@plt scm_new_port_table_entry
asprintf pt_pkt_alloc_decoder scm_new_port_table_entry@plt
asprintf@plt pt_pkt_alloc_decoder@plt scm_out_of_range
bt_ctf_get_char_array pt_pkt_sync_forward scm_out_of_range@plt
bt_ctf_get_char_array@plt pt_pkt_sync_forward@plt scm_putc
bt_ctf_get_uint64 pwrite scm_putc@plt
bt_ctf_get_uint64@plt pwrite@plt scm_reverse_x
bt_ctf_iter_read_event PyErr_Restore scm_reverse_x@plt
bt_ctf_iter_read_event@plt PyErr_Restore@plt scm_set_port_filename_x
<snip...>
Now that's a load of completely useless completions.
The reason GDB offers those is that the completer relies on readline
figuring out the completion word point in the input line based on the
language's word break characters, which include "(". So readline
tells the completer to complete on "", the string that is after '('.
Likewise, if you type "function(i[TAB]" to try to complete to "int",
you're out of luck. GDB shows you all the symbols in the program that
start with "i"... This makes sense for the expression completer, as
what you'd want to type is e.g., a global variable, say:
(gdb) print function(i[TAB]
but, it makes no sense when specifying a function name for a
breakpoint location.
To get around that limitation, users need to quote the function name,
like:
(gdb) b -f 'function([TAB]
function(int) function(long)
(gdb) b 'function(i[TAB]
(gdb) b 'function(int)' # now completes correctly!
Note that the quoting is only necessary for completion. Creating the
breakpoint does not require the quoting:
(gdb) b -f function(int) [RET]
Breakpoint 1 at ....
This patch removes this limitation.
(
Actually, it's a necessary patch, though not sufficient. That'll
start working correctly by the end of the series. With this patch, if try it,
you'll see:
(gdb) b -f function(i[TAB]
(gdb) b -f function
i.e., gdb strips everything after the "(". That's caused by some code
in symtab.c that'll be eliminated further down the series. These
patches are all unfortunately interrelated, which is also the reason
new tests only appear much later in the series.
But let's ignore that reality for the remainder of the description.
)
So... this patch gets rid of the need for quoting.
It does that by adding a way for a completer to control the exact
completion word point that readline should start the completion
request for, instead of letting readline try to figure it out using
the current language's word break chars array, and often failing.
In the case above, we want the completer to figure out that it's
completing a function name that starts with "function(i". It now
does.
It took me a while to figure out a way to ask readline to "use this
exact word point", and for a while I feared that it'd be impossible
with current readline (and having to rely on master readline for core
functionality is something I'd like to avoid very much). Eventually,
after several different attempts, I came up with what is described in
the comment above gdb_custom_word_point_brkchars in the patch.
With this patch, the handle_brkchars phase of the explicit location
completer advances the expected word point as it parses the input line
left to right, until it figures out exactly what we're completing,
instead of expecting readline to break the string using the word break
characters, and then having the completer heuristically fix up a bad
decision by parsing the input string backwards. This allows correctly
knowning that we're completing a symbol name after -function, complete
functions without quoting, etc.
Later, we'll make use of this same mechanims to implement a proper
linespec completer that avoids need for quoting too.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_collect_symbol_completion_matches): Add
complete_symbol_mode parameter.
* cli/cli-cmds.c (complete_command): Get the completion result out
of the handle_brkchars tracker if used a custom word point.
* completer.c: Include "linespec.h".
(enum explicit_location_match_type) <MATCH_LINE>: New enumerator.
(advance_to_expression_complete_word_point): New.
(completion_tracker::completes_to_completion_word): New.
(complete_files_symbols): Pass down
complete_symbol_mode::EXPRESSION.
(explicit_options, probe_options): New.
(collect_explicit_location_matches): Complete on the
explictit_loc->foo instead of word. Use
linespec_complete_function. Handle MATCH_LINE. Handle offering
keyword and options completions.
(backup_text_ptr): Delete.
(skip_keyword): New.
(complete_explicit_location): Remove 'word' parameter. Add
language, quoted_arg_start and quoted_arg_end parameters.
Rewrite, parsing left to right.
(location_completer): Rewrite.
(location_completer_handle_brkchars): New function.
(symbol_completer): Pass down complete_symbol_mode::EXPRESSION.
(enum complete_line_internal_reason): Adjust comments.
(completion_tracker::discard_completions): New.
(completer_handle_brkchars_func_for_completer): Handle
location_completer.
(gdb_custom_word_point_brkchars)
(gdb_org_rl_basic_quote_characters): New.
(gdb_completion_word_break_characters_throw)
(completion_find_completion_word): Handle trackers that use a
custom word point.
(completion_tracker::advance_custom_word_point_by): New.
(completion_tracker::build_completion_result): Don't rely on
readline appending the quote char.
(gdb_rl_attempted_completion_function_throw): Handle trackers that
use a custom word point.
(gdb_rl_attempted_completion_function): Restore
rl_basic_quote_characters.
* completer.h (class completion_tracker): Extend intro comment.
(completion_tracker::set_quote_char)
(completion_tracker::quote_char)
(completion_tracker::set_use_custom_word_point)
(completion_tracker::use_custom_word_point)
(completion_tracker::custom_word_point)
(completion_tracker::set_custom_word_point)
(completion_tracker::advance_custom_word_point_by)
(completion_tracker::completes_to_completion_word)
(completion_tracker::discard_completions): New methods.
(completion_tracker::m_quote_char)
(completion_tracker::m_use_custom_word_point)
(completion_tracker::m_custom_word_point): New fields.
(advance_to_expression_complete_word_point): Declare.
* f-lang.c (f_collect_symbol_completion_matches): Add
complete_symbol_mode parameter.
* language.h (struct language_defn)
<la_collect_symbol_completion_matches>: Add complete_symbol_mode
parameter.
* linespec.c (linespec_keywords): Add NULL terminator. Make extern.
(linespec_complete_function): New function.
(linespec_lexer_lex_keyword): Adjust.
* linespec.h (linespec_keywords, linespec_complete_function): New
declarations.
* location.c (find_end_quote): New function.
(explicit_location_lex_one): Add explicit_completion_info
parameter. Save quoting info. Don't throw if being called for
completion. Don't handle Ada operators here.
(is_cp_operator, skip_op_false_positives, first_of)
(explicit_location_lex_one_function): New function.
(string_to_explicit_location): Replace 'dont_throw' parameter with
an explicit_completion_info pointer parameter. Handle it. Don't
use explicit_location_lex_one to lex function names. Use
explicit_location_lex_one_function instead.
* location.h (struct explicit_completion_info): New.
(string_to_explicit_location): Replace 'dont_throw' parameter with
an explicit_completion_info pointer parameter.
* symtab.c (default_collect_symbol_completion_matches_break_on):
Add complete_symbol_mode parameter. Handle LINESPEC mode.
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches): Add complete_symbol_mode
parameter.
(collect_symbol_completion_matches_type): Pass down
complete_symbol_mode::EXPRESSION.
(collect_file_symbol_completion_matches): Add complete_symbol_mode
parameter. Handle LINESPEC mode.
* symtab.h (complete_symbol_mode): New.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_file_symbol_completion_matches): Add complete_symbol_mode
parameter.
gdb/testsuite/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* gdb.linespec/ls-errs.exp (do_test): Adjust expected output.
2017-07-17 21:21:33 +02:00
|
|
|
# Test that option lexing stops at whitespace boundaries, except
|
|
|
|
# when lexing function names, where we want to handle setting
|
|
|
|
# breakpoints on e.g., "int template_function<int>()".
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break "-source this file has spaces.c -line 3" invalid_file "this"
|
Rewrite/enhance explicit locations completer, parse left->right
One of the most annoying (to me) things about GDB's completion is when
you have overloads in your program, and you want to set a breakpoint
in one of them:
void function(int); // set breakpoint here.
void function(long);
(gdb) b -f func[TAB]
(gdb) b -f function( # ok, gdb completed as much as possible.
(gdb) b -f function([TAB] # show me the overloads, please.
<_all_ symbols in the program are shown...>
E.g., when debugging GDB, that'd be:
(gdb) b -f function([TAB]
(anonymous namespace)::get_global()::global pt_insn_get_offset@plt scm_new_port_table_entry
asprintf pt_pkt_alloc_decoder scm_new_port_table_entry@plt
asprintf@plt pt_pkt_alloc_decoder@plt scm_out_of_range
bt_ctf_get_char_array pt_pkt_sync_forward scm_out_of_range@plt
bt_ctf_get_char_array@plt pt_pkt_sync_forward@plt scm_putc
bt_ctf_get_uint64 pwrite scm_putc@plt
bt_ctf_get_uint64@plt pwrite@plt scm_reverse_x
bt_ctf_iter_read_event PyErr_Restore scm_reverse_x@plt
bt_ctf_iter_read_event@plt PyErr_Restore@plt scm_set_port_filename_x
<snip...>
Now that's a load of completely useless completions.
The reason GDB offers those is that the completer relies on readline
figuring out the completion word point in the input line based on the
language's word break characters, which include "(". So readline
tells the completer to complete on "", the string that is after '('.
Likewise, if you type "function(i[TAB]" to try to complete to "int",
you're out of luck. GDB shows you all the symbols in the program that
start with "i"... This makes sense for the expression completer, as
what you'd want to type is e.g., a global variable, say:
(gdb) print function(i[TAB]
but, it makes no sense when specifying a function name for a
breakpoint location.
To get around that limitation, users need to quote the function name,
like:
(gdb) b -f 'function([TAB]
function(int) function(long)
(gdb) b 'function(i[TAB]
(gdb) b 'function(int)' # now completes correctly!
Note that the quoting is only necessary for completion. Creating the
breakpoint does not require the quoting:
(gdb) b -f function(int) [RET]
Breakpoint 1 at ....
This patch removes this limitation.
(
Actually, it's a necessary patch, though not sufficient. That'll
start working correctly by the end of the series. With this patch, if try it,
you'll see:
(gdb) b -f function(i[TAB]
(gdb) b -f function
i.e., gdb strips everything after the "(". That's caused by some code
in symtab.c that'll be eliminated further down the series. These
patches are all unfortunately interrelated, which is also the reason
new tests only appear much later in the series.
But let's ignore that reality for the remainder of the description.
)
So... this patch gets rid of the need for quoting.
It does that by adding a way for a completer to control the exact
completion word point that readline should start the completion
request for, instead of letting readline try to figure it out using
the current language's word break chars array, and often failing.
In the case above, we want the completer to figure out that it's
completing a function name that starts with "function(i". It now
does.
It took me a while to figure out a way to ask readline to "use this
exact word point", and for a while I feared that it'd be impossible
with current readline (and having to rely on master readline for core
functionality is something I'd like to avoid very much). Eventually,
after several different attempts, I came up with what is described in
the comment above gdb_custom_word_point_brkchars in the patch.
With this patch, the handle_brkchars phase of the explicit location
completer advances the expected word point as it parses the input line
left to right, until it figures out exactly what we're completing,
instead of expecting readline to break the string using the word break
characters, and then having the completer heuristically fix up a bad
decision by parsing the input string backwards. This allows correctly
knowning that we're completing a symbol name after -function, complete
functions without quoting, etc.
Later, we'll make use of this same mechanims to implement a proper
linespec completer that avoids need for quoting too.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_collect_symbol_completion_matches): Add
complete_symbol_mode parameter.
* cli/cli-cmds.c (complete_command): Get the completion result out
of the handle_brkchars tracker if used a custom word point.
* completer.c: Include "linespec.h".
(enum explicit_location_match_type) <MATCH_LINE>: New enumerator.
(advance_to_expression_complete_word_point): New.
(completion_tracker::completes_to_completion_word): New.
(complete_files_symbols): Pass down
complete_symbol_mode::EXPRESSION.
(explicit_options, probe_options): New.
(collect_explicit_location_matches): Complete on the
explictit_loc->foo instead of word. Use
linespec_complete_function. Handle MATCH_LINE. Handle offering
keyword and options completions.
(backup_text_ptr): Delete.
(skip_keyword): New.
(complete_explicit_location): Remove 'word' parameter. Add
language, quoted_arg_start and quoted_arg_end parameters.
Rewrite, parsing left to right.
(location_completer): Rewrite.
(location_completer_handle_brkchars): New function.
(symbol_completer): Pass down complete_symbol_mode::EXPRESSION.
(enum complete_line_internal_reason): Adjust comments.
(completion_tracker::discard_completions): New.
(completer_handle_brkchars_func_for_completer): Handle
location_completer.
(gdb_custom_word_point_brkchars)
(gdb_org_rl_basic_quote_characters): New.
(gdb_completion_word_break_characters_throw)
(completion_find_completion_word): Handle trackers that use a
custom word point.
(completion_tracker::advance_custom_word_point_by): New.
(completion_tracker::build_completion_result): Don't rely on
readline appending the quote char.
(gdb_rl_attempted_completion_function_throw): Handle trackers that
use a custom word point.
(gdb_rl_attempted_completion_function): Restore
rl_basic_quote_characters.
* completer.h (class completion_tracker): Extend intro comment.
(completion_tracker::set_quote_char)
(completion_tracker::quote_char)
(completion_tracker::set_use_custom_word_point)
(completion_tracker::use_custom_word_point)
(completion_tracker::custom_word_point)
(completion_tracker::set_custom_word_point)
(completion_tracker::advance_custom_word_point_by)
(completion_tracker::completes_to_completion_word)
(completion_tracker::discard_completions): New methods.
(completion_tracker::m_quote_char)
(completion_tracker::m_use_custom_word_point)
(completion_tracker::m_custom_word_point): New fields.
(advance_to_expression_complete_word_point): Declare.
* f-lang.c (f_collect_symbol_completion_matches): Add
complete_symbol_mode parameter.
* language.h (struct language_defn)
<la_collect_symbol_completion_matches>: Add complete_symbol_mode
parameter.
* linespec.c (linespec_keywords): Add NULL terminator. Make extern.
(linespec_complete_function): New function.
(linespec_lexer_lex_keyword): Adjust.
* linespec.h (linespec_keywords, linespec_complete_function): New
declarations.
* location.c (find_end_quote): New function.
(explicit_location_lex_one): Add explicit_completion_info
parameter. Save quoting info. Don't throw if being called for
completion. Don't handle Ada operators here.
(is_cp_operator, skip_op_false_positives, first_of)
(explicit_location_lex_one_function): New function.
(string_to_explicit_location): Replace 'dont_throw' parameter with
an explicit_completion_info pointer parameter. Handle it. Don't
use explicit_location_lex_one to lex function names. Use
explicit_location_lex_one_function instead.
* location.h (struct explicit_completion_info): New.
(string_to_explicit_location): Replace 'dont_throw' parameter with
an explicit_completion_info pointer parameter.
* symtab.c (default_collect_symbol_completion_matches_break_on):
Add complete_symbol_mode parameter. Handle LINESPEC mode.
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches): Add complete_symbol_mode
parameter.
(collect_symbol_completion_matches_type): Pass down
complete_symbol_mode::EXPRESSION.
(collect_file_symbol_completion_matches): Add complete_symbol_mode
parameter. Handle LINESPEC mode.
* symtab.h (complete_symbol_mode): New.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_file_symbol_completion_matches): Add complete_symbol_mode
parameter.
gdb/testsuite/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* gdb.linespec/ls-errs.exp (do_test): Adjust expected output.
2017-07-17 21:21:33 +02:00
|
|
|
test_break "-function ret_type tmpl_function" \
|
|
|
|
invalid_function "ret_type tmpl_function"
|
|
|
|
test_break "-source $srcfile -function ret_type tmpl_function" \
|
|
|
|
invalid_function_f "ret_type tmpl_function" $srcfile
|
2015-08-12 02:09:36 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break "-function main -label label whitespace" \
|
|
|
|
invalid_label "label" "main"
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Test unmatched quotes.
|
|
|
|
foreach x {"\"src-file.c'" "'src-file.c"} {
|
|
|
|
test_break "$x:3" unmatched_quote
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break $srcfile invalid_function $srcfile
|
|
|
|
foreach x {"foo" " foo" " foo "} {
|
|
|
|
# Trim any leading/trailing whitespace for error messages.
|
|
|
|
test_break "$srcfile:$x" invalid_function_f [string trim $x] $srcfile
|
|
|
|
test_break "-source $srcfile -function $x" \
|
|
|
|
invalid_function_f [string trim $x] $srcfile
|
|
|
|
test_break "$srcfile:main:$x" invalid_label [string trim $x] "main"
|
|
|
|
test_break "-source $srcfile -function main -label $x" \
|
|
|
|
invalid_label [string trim $x] "main"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
foreach x $spaces {
|
|
|
|
test_break "$srcfile$x" unexpected "end of input"
|
|
|
|
test_break "$srcfile:main$x" unexpected "end of input"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break "${srcfile}::" invalid_function "${srcfile}::"
|
|
|
|
test_break "$srcfile:3 1" unexpected_opt "number" "1"
|
|
|
|
test_break "-source $srcfile -line 3 1" garbage "1"
|
|
|
|
test_break "$srcfile:3 +100" unexpected_opt "number" "+100"
|
|
|
|
test_break "-source $srcfile -line 3 +100" garbage "+100"
|
|
|
|
test_break "$srcfile:3 -100" unexpected_opt "number" "-100"
|
|
|
|
test_break "$srcfile:3 foo" unexpected_opt "string" "foo"
|
|
|
|
test_break "-source $srcfile -line 3 foo" garbage "foo"
|
|
|
|
|
|
|
|
foreach x $invalid_offsets {
|
|
|
|
test_break "$srcfile:$x" invalid_offset_f $x $srcfile
|
|
|
|
test_break "\"$srcfile:$x\"" invalid_offset_f $x $srcfile
|
|
|
|
test_break "'$srcfile:$x'" invalid_offset_f $x $srcfile
|
|
|
|
test_break "-source $srcfile -line $x" invalid_offset_f $x $srcfile
|
|
|
|
}
|
|
|
|
test_break "-source $srcfile -line -x" malformed_line_offset "-x"
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Test invalid filespecs starting with function.
|
|
|
|
foreach x {"foobar" "foo::bar" "foo.bar" "foo ." "foo bar" "foo 1" \
|
2012-04-05 20:50:29 +02:00
|
|
|
"foo 0" "foo +10" "foo -10" "foo +100" "foo -100"} {
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break $x invalid_function $x
|
|
|
|
test_break "-function \"$x\"" invalid_function $x
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
foreach x $spaces {
|
|
|
|
test_break "main${x}there" invalid_label "there" "main"
|
|
|
|
if {[test_compiler_info {clang-*-*}]} {
|
|
|
|
setup_xfail clang/14500 *-*-*
|
|
|
|
}
|
|
|
|
test_break "main:here${x}" unexpected "end of input"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
foreach x {"3" "+100" "-100" "foo"} {
|
|
|
|
test_break "main 3" invalid_function "main 3"
|
|
|
|
test_break "-function \"main $x\"" invalid_function "main $x"
|
Rewrite/enhance explicit locations completer, parse left->right
One of the most annoying (to me) things about GDB's completion is when
you have overloads in your program, and you want to set a breakpoint
in one of them:
void function(int); // set breakpoint here.
void function(long);
(gdb) b -f func[TAB]
(gdb) b -f function( # ok, gdb completed as much as possible.
(gdb) b -f function([TAB] # show me the overloads, please.
<_all_ symbols in the program are shown...>
E.g., when debugging GDB, that'd be:
(gdb) b -f function([TAB]
(anonymous namespace)::get_global()::global pt_insn_get_offset@plt scm_new_port_table_entry
asprintf pt_pkt_alloc_decoder scm_new_port_table_entry@plt
asprintf@plt pt_pkt_alloc_decoder@plt scm_out_of_range
bt_ctf_get_char_array pt_pkt_sync_forward scm_out_of_range@plt
bt_ctf_get_char_array@plt pt_pkt_sync_forward@plt scm_putc
bt_ctf_get_uint64 pwrite scm_putc@plt
bt_ctf_get_uint64@plt pwrite@plt scm_reverse_x
bt_ctf_iter_read_event PyErr_Restore scm_reverse_x@plt
bt_ctf_iter_read_event@plt PyErr_Restore@plt scm_set_port_filename_x
<snip...>
Now that's a load of completely useless completions.
The reason GDB offers those is that the completer relies on readline
figuring out the completion word point in the input line based on the
language's word break characters, which include "(". So readline
tells the completer to complete on "", the string that is after '('.
Likewise, if you type "function(i[TAB]" to try to complete to "int",
you're out of luck. GDB shows you all the symbols in the program that
start with "i"... This makes sense for the expression completer, as
what you'd want to type is e.g., a global variable, say:
(gdb) print function(i[TAB]
but, it makes no sense when specifying a function name for a
breakpoint location.
To get around that limitation, users need to quote the function name,
like:
(gdb) b -f 'function([TAB]
function(int) function(long)
(gdb) b 'function(i[TAB]
(gdb) b 'function(int)' # now completes correctly!
Note that the quoting is only necessary for completion. Creating the
breakpoint does not require the quoting:
(gdb) b -f function(int) [RET]
Breakpoint 1 at ....
This patch removes this limitation.
(
Actually, it's a necessary patch, though not sufficient. That'll
start working correctly by the end of the series. With this patch, if try it,
you'll see:
(gdb) b -f function(i[TAB]
(gdb) b -f function
i.e., gdb strips everything after the "(". That's caused by some code
in symtab.c that'll be eliminated further down the series. These
patches are all unfortunately interrelated, which is also the reason
new tests only appear much later in the series.
But let's ignore that reality for the remainder of the description.
)
So... this patch gets rid of the need for quoting.
It does that by adding a way for a completer to control the exact
completion word point that readline should start the completion
request for, instead of letting readline try to figure it out using
the current language's word break chars array, and often failing.
In the case above, we want the completer to figure out that it's
completing a function name that starts with "function(i". It now
does.
It took me a while to figure out a way to ask readline to "use this
exact word point", and for a while I feared that it'd be impossible
with current readline (and having to rely on master readline for core
functionality is something I'd like to avoid very much). Eventually,
after several different attempts, I came up with what is described in
the comment above gdb_custom_word_point_brkchars in the patch.
With this patch, the handle_brkchars phase of the explicit location
completer advances the expected word point as it parses the input line
left to right, until it figures out exactly what we're completing,
instead of expecting readline to break the string using the word break
characters, and then having the completer heuristically fix up a bad
decision by parsing the input string backwards. This allows correctly
knowning that we're completing a symbol name after -function, complete
functions without quoting, etc.
Later, we'll make use of this same mechanims to implement a proper
linespec completer that avoids need for quoting too.
gdb/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_collect_symbol_completion_matches): Add
complete_symbol_mode parameter.
* cli/cli-cmds.c (complete_command): Get the completion result out
of the handle_brkchars tracker if used a custom word point.
* completer.c: Include "linespec.h".
(enum explicit_location_match_type) <MATCH_LINE>: New enumerator.
(advance_to_expression_complete_word_point): New.
(completion_tracker::completes_to_completion_word): New.
(complete_files_symbols): Pass down
complete_symbol_mode::EXPRESSION.
(explicit_options, probe_options): New.
(collect_explicit_location_matches): Complete on the
explictit_loc->foo instead of word. Use
linespec_complete_function. Handle MATCH_LINE. Handle offering
keyword and options completions.
(backup_text_ptr): Delete.
(skip_keyword): New.
(complete_explicit_location): Remove 'word' parameter. Add
language, quoted_arg_start and quoted_arg_end parameters.
Rewrite, parsing left to right.
(location_completer): Rewrite.
(location_completer_handle_brkchars): New function.
(symbol_completer): Pass down complete_symbol_mode::EXPRESSION.
(enum complete_line_internal_reason): Adjust comments.
(completion_tracker::discard_completions): New.
(completer_handle_brkchars_func_for_completer): Handle
location_completer.
(gdb_custom_word_point_brkchars)
(gdb_org_rl_basic_quote_characters): New.
(gdb_completion_word_break_characters_throw)
(completion_find_completion_word): Handle trackers that use a
custom word point.
(completion_tracker::advance_custom_word_point_by): New.
(completion_tracker::build_completion_result): Don't rely on
readline appending the quote char.
(gdb_rl_attempted_completion_function_throw): Handle trackers that
use a custom word point.
(gdb_rl_attempted_completion_function): Restore
rl_basic_quote_characters.
* completer.h (class completion_tracker): Extend intro comment.
(completion_tracker::set_quote_char)
(completion_tracker::quote_char)
(completion_tracker::set_use_custom_word_point)
(completion_tracker::use_custom_word_point)
(completion_tracker::custom_word_point)
(completion_tracker::set_custom_word_point)
(completion_tracker::advance_custom_word_point_by)
(completion_tracker::completes_to_completion_word)
(completion_tracker::discard_completions): New methods.
(completion_tracker::m_quote_char)
(completion_tracker::m_use_custom_word_point)
(completion_tracker::m_custom_word_point): New fields.
(advance_to_expression_complete_word_point): Declare.
* f-lang.c (f_collect_symbol_completion_matches): Add
complete_symbol_mode parameter.
* language.h (struct language_defn)
<la_collect_symbol_completion_matches>: Add complete_symbol_mode
parameter.
* linespec.c (linespec_keywords): Add NULL terminator. Make extern.
(linespec_complete_function): New function.
(linespec_lexer_lex_keyword): Adjust.
* linespec.h (linespec_keywords, linespec_complete_function): New
declarations.
* location.c (find_end_quote): New function.
(explicit_location_lex_one): Add explicit_completion_info
parameter. Save quoting info. Don't throw if being called for
completion. Don't handle Ada operators here.
(is_cp_operator, skip_op_false_positives, first_of)
(explicit_location_lex_one_function): New function.
(string_to_explicit_location): Replace 'dont_throw' parameter with
an explicit_completion_info pointer parameter. Handle it. Don't
use explicit_location_lex_one to lex function names. Use
explicit_location_lex_one_function instead.
* location.h (struct explicit_completion_info): New.
(string_to_explicit_location): Replace 'dont_throw' parameter with
an explicit_completion_info pointer parameter.
* symtab.c (default_collect_symbol_completion_matches_break_on):
Add complete_symbol_mode parameter. Handle LINESPEC mode.
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches): Add complete_symbol_mode
parameter.
(collect_symbol_completion_matches_type): Pass down
complete_symbol_mode::EXPRESSION.
(collect_file_symbol_completion_matches): Add complete_symbol_mode
parameter. Handle LINESPEC mode.
* symtab.h (complete_symbol_mode): New.
(default_collect_symbol_completion_matches_break_on)
(default_collect_symbol_completion_matches)
(collect_symbol_completion_matches)
(collect_file_symbol_completion_matches): Add complete_symbol_mode
parameter.
gdb/testsuite/ChangeLog:
2017-07-17 Pedro Alves <palves@redhat.com>
* gdb.linespec/ls-errs.exp (do_test): Adjust expected output.
2017-07-17 21:21:33 +02:00
|
|
|
if {$x == "foo"} {
|
|
|
|
test_break "main:here $x" unexpected_opt "string" $x
|
|
|
|
} else {
|
|
|
|
test_break "main:here $x" unexpected_opt "number" $x
|
|
|
|
}
|
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break "-function main -label \"here $x\"" \
|
|
|
|
invalid_label "here $x" "main"
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
foreach x {"if" "task" "thread"} {
|
|
|
|
test_break $x invalid_function $x
|
|
|
|
}
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
test_break "'main.c'flubber" unexpected_opt "string" "flubber"
|
|
|
|
test_break "'main.c',21" invalid_function "main.c"
|
|
|
|
test_break "'main.c' " invalid_function "main.c"
|
|
|
|
test_break "'main.c'3" unexpected_opt "number" "3"
|
|
|
|
test_break "'main.c'+3" unexpected_opt "number" "+3"
|
2012-04-05 20:50:29 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Test undefined convenience variables.
|
|
|
|
set x {$zippo}
|
|
|
|
test_break $x invalid_var_or_func $x
|
|
|
|
test_break "$srcfile:$x" invalid_var_or_func_f $x $srcfile
|
2015-08-12 02:09:36 +02:00
|
|
|
|
2016-03-15 23:18:28 +01:00
|
|
|
# Explicit linespec-specific tests
|
|
|
|
test_break "-source $srcfile" source_incomplete
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach_with_prefix lang {"C" "C++"} {
|
|
|
|
do_test ${lang}
|
|
|
|
}
|