| # Copyright 2017-2021 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 <http://www.gnu.org/licenses/>. |
| |
| # This file is part of the gdb testsuite. |
| |
| load_lib completion-support.exp |
| |
| standard_testfile cpls.cc cpls2.cc cpls-hyphen.cc |
| |
| if {[prepare_for_testing "failed to prepare" $testfile \ |
| [list $srcfile $srcfile2 $srcfile3] {debug}]} { |
| return -1 |
| } |
| |
| # Tests below are about tab-completion, which doesn't work if readline |
| # library isn't used. Check it first. |
| |
| if { ![readline_is_used] } { |
| untested "no tab completion support without readline" |
| return -1 |
| } |
| |
| # Disable the completion limit for the whole testcase. |
| gdb_test_no_output "set max-completions unlimited" |
| |
| # Start of tests. |
| |
| # Test completion of all parameter prefixes, crossing "(" and ")", |
| # with and without whitespace. |
| |
| proc_with_prefix all-param-prefixes {} { |
| |
| # Test both linespecs and explicit locations. |
| foreach cmd_prefix {"b" "b -function"} { |
| set line "$cmd_prefix param_prefixes_test_long(long)" |
| set start [index_after "test_long" $line] |
| test_complete_prefix_range $line $start |
| |
| # Same, but with extra spaces. Note that the original spaces in |
| # the input line are preserved after completion. |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_long(long " \ |
| "$cmd_prefix param_prefixes_test_long(long )" |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_long( long " \ |
| "$cmd_prefix param_prefixes_test_long( long )" |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_long ( long " \ |
| "$cmd_prefix param_prefixes_test_long ( long )" |
| |
| # Complete all parameter prefixes between "(i" and "(int*, int&)". |
| # Note that this exercises completing when the point is at the |
| # space in "param_prefixes_test_intp_intr(int*, ". |
| set line "$cmd_prefix param_prefixes_test_intp_intr(int*, int&)" |
| set start [index_after "intp_intr" $line] |
| test_complete_prefix_range $line $start |
| |
| # Similar, but with extra spaces. |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int* " \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int* , int&)" |
| |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int *" \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int *, int&)" |
| |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int *, int " \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int *, int &)" |
| |
| test_gdb_complete_unique \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int *, int & " \ |
| "$cmd_prefix param_prefixes_test_intp_intr ( int *, int & )" |
| } |
| } |
| |
| # Test completion of an overloaded function. |
| |
| proc_with_prefix overload {} { |
| set completion_list { |
| "overload_ambiguous_test(int, int)" |
| "overload_ambiguous_test(int, long)" |
| "overload_ambiguous_test(long)" |
| } |
| |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "overload_ambiguous_" "test(" \ |
| $completion_list |
| check_bp_locations_match_list \ |
| "$cmd_prefix overload_ambiguous_test" \ |
| $completion_list |
| |
| # Test disambiguating by typing enough to pick the "int" as |
| # first parameter type. This then tests handling ambiguity in |
| # the second parameter, which checks that tab completion when |
| # the point is at the whitespace behaves naturally, by showing |
| # the remaining matching overloads to the user. |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "overload_ambiguous_test(i" "nt, " { |
| "overload_ambiguous_test(int, int)" |
| "overload_ambiguous_test(int, long)" |
| } |
| |
| # Add a few more characters to make the completion |
| # unambiguous. |
| test_gdb_complete_unique \ |
| "$cmd_prefix overload_ambiguous_test(int, i" \ |
| "$cmd_prefix overload_ambiguous_test(int, int)" |
| check_bp_locations_match_list \ |
| "$cmd_prefix overload_ambiguous_test(int, int)" { |
| "overload_ambiguous_test(int, int)" |
| } |
| } |
| } |
| |
| # Test completion of a function that is defined in different scopes |
| # with different parameters. |
| |
| proc_with_prefix overload-2 {} { |
| with_test_prefix "all" { |
| set completion_list { |
| "(anonymous namespace)::overload2_function(overload2_arg3)" |
| "(anonymous namespace)::struct_overload2_test::overload2_function(overload2_arg4)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::struct_overload2_test::overload2_function(overload2_arga)" |
| "ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)" |
| "ns_overload2_test::(anonymous namespace)::struct_overload2_test::overload2_function(overload2_arg8)" |
| "ns_overload2_test::overload2_function(overload2_arg5)" |
| "ns_overload2_test::struct_overload2_test::overload2_function(overload2_arg6)" |
| "overload2_function(overload2_arg1)" |
| "struct_overload2_test::overload2_function(overload2_arg2)" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "overload2_func" "tion(overload2_arg" $completion_list |
| check_bp_locations_match_list \ |
| "$cmd_prefix overload2_function" $completion_list |
| } |
| } |
| |
| # Same, but restrict to functions/methods in some scope. |
| with_test_prefix "restrict scope" { |
| set completion_list { |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| "ns_overload2_test::overload2_function(overload2_arg5)" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "ns_overload2_test::overload2_func" "tion(overload2_arg" $completion_list |
| check_bp_locations_match_list \ |
| "$cmd_prefix ns_overload2_test::overload2_function" $completion_list |
| } |
| } |
| |
| # Restrict to anonymous namespace scopes. |
| with_test_prefix "restrict scope 2" { |
| set completion_list { |
| "(anonymous namespace)::overload2_function(overload2_arg3)" |
| "ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "(anonymous namespace)::overload2_func" "tion(overload2_arg" $completion_list |
| check_bp_locations_match_list \ |
| "$cmd_prefix (anonymous namespace)::overload2_function" $completion_list |
| } |
| } |
| |
| # Add enough scopes, and we get a unique completion. |
| with_test_prefix "unique completion" { |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_unique \ |
| "$cmd_prefix ns_overload2_test::(anonymous namespace)::overload2_func" \ |
| "$cmd_prefix ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)" |
| check_setting_bp_fails "$cmd_prefix ns_overload2_test::(anonymous namespace)::overload2_func" |
| check_bp_locations_match_list \ |
| "$cmd_prefix ns_overload2_test::(anonymous namespace)::overload2_function" \ |
| {"ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)"} |
| } |
| } |
| } |
| |
| # Test linespecs / locations using fully-qualified names. |
| |
| proc_with_prefix fqn {} { |
| |
| # "-qualified" works with both explicit locations and linespecs. |
| # Also test that combining a source file with a function name |
| # still results in a full match, with both linespecs and explicit |
| # locations. |
| foreach cmd_prefix { |
| "b -qualified " |
| "b -qualified -function " |
| "b -qualified cpls.cc:" |
| "b -qualified -source cpls.cc -function " |
| "b -source cpls.cc -qualified -function " |
| } { |
| test_gdb_complete_unique \ |
| "${cmd_prefix}overload2_func" \ |
| "${cmd_prefix}overload2_function(overload2_arg1)" |
| |
| # Drill down until we find a unique completion. |
| test_gdb_complete_multiple "${cmd_prefix}" "ns_overload2_test::" "" { |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::struct_overload2_test::overload2_function(overload2_arga)" |
| "ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)" |
| "ns_overload2_test::(anonymous namespace)::struct_overload2_test::overload2_function(overload2_arg8)" |
| "ns_overload2_test::overload2_function(overload2_arg5)" |
| "ns_overload2_test::struct_overload2_test::overload2_function(overload2_arg6)" |
| } |
| |
| test_gdb_complete_multiple "${cmd_prefix}" "ns_overload2_test::(anonymous namespace)::" "" { |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::struct_overload2_test::overload2_function(overload2_arga)" |
| "ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)" |
| "ns_overload2_test::(anonymous namespace)::struct_overload2_test::overload2_function(overload2_arg8)" |
| } |
| |
| test_gdb_complete_multiple "${cmd_prefix}" "ns_overload2_test::(anonymous namespace)::ns_overload2_test::" "" { |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::struct_overload2_test::overload2_function(overload2_arga)" |
| } |
| |
| test_gdb_complete_unique \ |
| "${cmd_prefix}ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_func" \ |
| "${cmd_prefix}ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| |
| } |
| } |
| |
| # Check that a fully-qualified lookup name doesn't match symbols in |
| # nested scopes. |
| |
| proc_with_prefix fqn-2 {} { |
| set linespec "struct_overload2_test::overload2_function(overload2_arg6)" |
| set cmd_prefix "b -qualified" |
| check_setting_bp_fails "$cmd_prefix $linespec" |
| test_gdb_complete_none "$cmd_prefix $linespec" |
| |
| # Check that using the same name, but not fully-qualifying it, |
| # would find something, just to make sure the test above is |
| # testing what we intend to test. |
| set cmd_prefix "b -function" |
| test_gdb_complete_unique "$cmd_prefix $linespec" "$cmd_prefix $linespec" |
| check_bp_locations_match_list \ |
| "$cmd_prefix $linespec" \ |
| {"ns_overload2_test::struct_overload2_test::overload2_function(overload2_arg6)"} |
| } |
| |
| # Test completion of functions in different scopes that have the same |
| # name and parameters. Restricting the scopes should find fewer and |
| # fewer matches. |
| |
| proc_with_prefix overload-3 {} { |
| with_test_prefix "all overloads" { |
| set completion_list { |
| "(anonymous namespace)::overload3_function(int)" |
| "(anonymous namespace)::overload3_function(long)" |
| "(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "(anonymous namespace)::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::overload3_function(int)" |
| "ns_overload3_test::overload3_function(long)" |
| "ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::struct_overload3_test::overload3_function(long)" |
| "overload3_function(int)" |
| "overload3_function(long)" |
| "struct_overload3_test::overload3_function(int)" |
| "struct_overload3_test::overload3_function(long)" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple "$cmd_prefix " "overload3_func" "tion(" $completion_list |
| check_bp_locations_match_list "$cmd_prefix overload3_function" $completion_list |
| } |
| } |
| |
| with_test_prefix "restrict overload" { |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_unique \ |
| "$cmd_prefix overload3_function(int)" \ |
| "$cmd_prefix overload3_function(int)" |
| check_bp_locations_match_list "$cmd_prefix overload3_function(int)" { |
| "(anonymous namespace)::overload3_function(int)" |
| "(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::overload3_function(int)" |
| "ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "overload3_function(int)" |
| "struct_overload3_test::overload3_function(int)" |
| } |
| } |
| } |
| |
| with_test_prefix "restrict scope" { |
| set completion_list { |
| "(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "(anonymous namespace)::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::struct_overload3_test::overload3_function(long)" |
| "struct_overload3_test::overload3_function(int)" |
| "struct_overload3_test::overload3_function(long)" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "struct_overload3_test::overload3_func" "tion(" \ |
| $completion_list |
| check_bp_locations_match_list \ |
| "$cmd_prefix struct_overload3_test::overload3_function" \ |
| $completion_list |
| } |
| } |
| } |
| |
| # Test completing an overloaded template method. |
| |
| proc_with_prefix template-overload {} { |
| set completion_list { |
| "template_struct<int>::template_overload_fn(int)" |
| "template_struct<long>::template_overload_fn(long)" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple "$cmd_prefix " "template_overload_fn" "(" $completion_list |
| check_bp_locations_match_list "$cmd_prefix template_overload_fn" $completion_list |
| check_bp_locations_match_list \ |
| "$cmd_prefix template_struct<int>::template_overload_fn" \ |
| "template_struct<int>::template_overload_fn(int)" |
| } |
| } |
| |
| # Test completing template methods with non-void return type. |
| |
| proc_with_prefix template-ret-type {} { |
| set method_name "template2_fn<int, int>" |
| set param_list "(template2_ret_type<int>, int, int)" |
| set struct_type "template2_struct<template2_ret_type<int> >" |
| set ret_type "template2_ret_type<int>" |
| |
| # Templates are listed both with and without return type, making |
| # "template2_<tab>" ambiguous. |
| foreach cmd_prefix {"b" "b -function"} { |
| set completion_list \ |
| [list \ |
| "${ret_type} ${struct_type}::${method_name}${param_list}" \ |
| "${struct_type}::${method_name}${param_list}"] |
| test_gdb_complete_multiple "$cmd_prefix " "template2_" "" $completion_list |
| |
| # Add one character more after "2_", and the linespec becomes |
| # unambiguous. Test completing the whole prefix range after that, |
| # thus testing completing either with or without return type. |
| foreach {s t} [list \ |
| "template2_r" \ |
| "${ret_type} ${struct_type}::${method_name}${param_list}" \ |
| "template2_s" \ |
| "${struct_type}::${method_name}${param_list}"] { |
| set linespec $t |
| set complete_line "$cmd_prefix $linespec" |
| set start [index_after $s $complete_line] |
| test_complete_prefix_range $complete_line $start |
| } |
| |
| # Setting a breakpoint without the template params doesn't work. |
| check_setting_bp_fails "$cmd_prefix template2_fn" |
| # However, setting a breakpoint with template params and without |
| # the method params does work, just like with non-template |
| # functions. It also works with or without return type. |
| foreach linespec [list \ |
| "${method_name}" \ |
| "${method_name}${param_list}" \ |
| "${struct_type}::${method_name}" \ |
| "${struct_type}::${method_name}${param_list}" \ |
| "${ret_type} ${struct_type}::${method_name}" \ |
| "${ret_type} ${struct_type}::${method_name}${param_list}"] { |
| check_bp_locations_match_list \ |
| "$cmd_prefix $linespec" \ |
| [list "${struct_type}::${method_name}${param_list}"] |
| } |
| } |
| } |
| |
| # Test completion of a const-overloaded funtion (const-overload). |
| # Note that "const" appears after the function/method parameters. |
| |
| proc_with_prefix const-overload {} { |
| set completion_list { |
| "struct_with_const_overload::const_overload_fn()" |
| "struct_with_const_overload::const_overload_fn() const" |
| } |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "const_overload_fn" "()" \ |
| $completion_list |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "const_overload_fn ( " ")" \ |
| $completion_list |
| test_gdb_complete_multiple \ |
| "$cmd_prefix " "const_overload_fn()" "" \ |
| $completion_list |
| |
| check_bp_locations_match_list \ |
| "$cmd_prefix const_overload_fn" \ |
| {"struct_with_const_overload::const_overload_fn()" |
| "struct_with_const_overload::const_overload_fn() const"} |
| |
| check_setting_bp_fails "$cmd_prefix const_overload_fn(" |
| check_bp_locations_match_list \ |
| "$cmd_prefix const_overload_fn()" \ |
| {"struct_with_const_overload::const_overload_fn()"} |
| check_bp_locations_match_list \ |
| "$cmd_prefix const_overload_fn() const" \ |
| {"struct_with_const_overload::const_overload_fn() const"} |
| } |
| } |
| |
| # Same but quote-enclose the function name. This makes the overload |
| # no longer be ambiguous. |
| |
| proc_with_prefix const-overload-quoted {} { |
| foreach cmd_prefix {"b" "b -function"} { |
| set linespec "'const_overload_fn()'" |
| test_gdb_complete_unique "$cmd_prefix $linespec" "$cmd_prefix $linespec" |
| check_bp_locations_match_list \ |
| "$cmd_prefix $linespec" { |
| "struct_with_const_overload::const_overload_fn()" |
| } |
| |
| set linespec "'const_overload_fn() const'" |
| test_gdb_complete_unique "$cmd_prefix $linespec" "$cmd_prefix $linespec" |
| check_bp_locations_match_list \ |
| "$cmd_prefix $linespec" { |
| "struct_with_const_overload::const_overload_fn() const" |
| } |
| } |
| } |
| |
| # Test that when the function is unambiguous, linespec completion |
| # appends the end quote char automatically, both ' and ". |
| |
| proc_with_prefix append-end-quote-char-when-unambiguous {} { |
| foreach cmd_prefix {"b" "b -function"} { |
| foreach qc $completion::all_quotes_list { |
| set linespec "${qc}not_overloaded_fn()${qc}" |
| foreach cmd [list "$cmd_prefix ${qc}not_overloaded_fn()" \ |
| "$cmd_prefix ${qc}not_overloaded_fn" \ |
| "$cmd_prefix ${qc}not_overloaded_"] { |
| test_gdb_complete_unique $cmd "$cmd_prefix $linespec" |
| } |
| check_bp_locations_match_list \ |
| "$cmd_prefix $linespec" {"not_overloaded_fn()"} |
| } |
| } |
| } |
| |
| # Test completing symbols of source files. |
| |
| proc_with_prefix in-source-file-unconstrained {} { |
| # First test that unconstrained matching picks up functions from |
| # multiple files. |
| test_gdb_complete_multiple "b " "file_constrained_test" "_cpls" { |
| "file_constrained_test_cpls2_function(int)" |
| "file_constrained_test_cpls_function(int)" |
| } |
| check_setting_bp_fails "b file_constrained_test_cpls" |
| } |
| |
| # Test an unambiguous completion that would be ambiguous if it weren't |
| # for the source file component, due to |
| # "file_constrained_test_cpls_function" in cpls.cc. Test with |
| # different components quoted, and with whitespace before the function |
| # name. |
| |
| proc_with_prefix in-source-file-unambiguous {} { |
| foreach sqc $completion::maybe_quoted_list { |
| foreach fqc $completion::maybe_quoted_list { |
| # Linespec. |
| foreach sep {":" ": "} { |
| set linespec \ |
| "${sqc}cpls2.cc${sqc}${sep}${fqc}file_constrained_test_cpls2_function(int)${fqc}" |
| set complete_line "b $linespec" |
| set start [index_after "constrained_test" $complete_line] |
| set input_line [string range $complete_line 0 $start] |
| test_gdb_complete_unique $input_line ${complete_line} |
| check_bp_locations_match_list "b $linespec" { |
| "file_constrained_test_cpls2_function(int)" |
| } |
| } |
| |
| # Explicit location. |
| set source_opt "-source ${sqc}cpls2.cc${sqc}" |
| set function_opt "-function ${fqc}file_constrained_test_cpls2_function(int)${fqc}" |
| set complete_line "b $source_opt $function_opt" |
| set start [index_after "cpls2_functio" $complete_line] |
| set input_line [string range $complete_line 0 $start] |
| test_gdb_complete_unique $input_line ${complete_line} |
| check_bp_locations_match_list "$complete_line" { |
| "file_constrained_test_cpls2_function(int)" |
| } |
| } |
| } |
| } |
| |
| # Test an ambiguous completion constrained by a source file. Test |
| # with different components quoted, and with whitespace before the |
| # function name. |
| |
| proc_with_prefix in-source-file-ambiguous {} { |
| foreach sqc $completion::maybe_quoted_list { |
| foreach fqc $completion::maybe_quoted_list { |
| # Linespec. |
| foreach sep {":" ": "} { |
| set cmd_prefix "b ${sqc}cpls2.cc${sqc}${sep}" |
| test_gdb_complete_multiple "${cmd_prefix}" ${fqc} "" { |
| "another_file_constrained_test_cpls2_function(int)" |
| "file_constrained_test_cpls2_function(int)" |
| } ${fqc} ${fqc} |
| } |
| |
| # Explicit location. |
| test_gdb_complete_multiple \ |
| "b -source ${sqc}cpls2.cc${sqc} -function " ${fqc} "" { |
| "another_file_constrained_test_cpls2_function(int)" |
| "file_constrained_test_cpls2_function(int)" |
| } ${fqc} ${fqc} |
| } |
| } |
| } |
| |
| # Check that completing a file name in a linespec auto-appends a colon |
| # instead of a whitespace character. |
| |
| proc_with_prefix source-complete-appends-colon {} { |
| # Test with quotes to make sure the end quote char is put at the |
| # right place. |
| foreach qc $completion::maybe_quoted_list { |
| test_gdb_complete_unique \ |
| "b ${qc}cpls2." \ |
| "b ${qc}cpls2.cc${qc}" ":" |
| test_gdb_complete_unique \ |
| "b ${qc}cpls2.c" \ |
| "b ${qc}cpls2.cc${qc}" ":" |
| test_gdb_complete_unique \ |
| "b ${qc}cpls2.cc" \ |
| "b ${qc}cpls2.cc${qc}" ":" |
| |
| # Same, but with a filename with an hyphen (which is normally |
| # a language word break char). |
| test_gdb_complete_unique \ |
| "b ${qc}cpls-" \ |
| "b ${qc}cpls-hyphen.cc${qc}" ":" |
| test_gdb_complete_unique \ |
| "b ${qc}cpls-hyphen" \ |
| "b ${qc}cpls-hyphen.cc${qc}" ":" |
| } |
| |
| # Test the same, but with the name of a nonexisting file. |
| |
| # Cursor at the end of the string. |
| test_gdb_complete_none "b nonexistingfilename.cc" |
| # Cursor past the end of the string. |
| test_gdb_complete_multiple "b nonexistingfilename.cc " "" "" \ |
| $completion::keyword_list |
| foreach qc $completion::all_quotes_list { |
| # Unterminated quote. |
| test_gdb_complete_none "b ${qc}nonexistingfilename.cc" |
| test_gdb_complete_none "b ${qc}nonexistingfilename.cc " |
| # Terminated quote, cursor at the quote. |
| test_gdb_complete_unique \ |
| "b ${qc}nonexistingfilename.cc${qc}" \ |
| "b ${qc}nonexistingfilename.cc${qc}" |
| # Terminated quote, cursor past the quote. |
| test_gdb_complete_multiple \ |
| "b ${qc}nonexistingfilename.cc${qc} " "" "" \ |
| $completion::keyword_list |
| } |
| } |
| |
| #################################################################### |
| |
| # Test that a colon at the end of the linespec is understood as an |
| # incomplete scope operator (incomplete-scope-colon), instead of a |
| # source/function separator. |
| |
| proc_with_prefix incomplete-scope-colon {} { |
| |
| # Helper for the loop below to simplify it. Tests completion of |
| # the range defined by the RANGE_SS found in the constructed line. |
| # |
| # E.g., with: |
| # |
| # source="source.cc" |
| # fqc="'" |
| # prototype="ns::function()" |
| # range_ss="s::f" |
| # |
| # we'd try completing with the cursor set in each of the |
| # underlined range's positions of: |
| # |
| # b source.cc:'ns::function()'" |
| # ^^^^ |
| # |
| # Also test that setting a breakpoint at the constructed line |
| # finds the same breakpoint location as completion does. |
| # |
| proc incomplete_scope_colon_helper {prototype range_ss {skip_check_bp 0}} { |
| foreach source {"" "cpls.cc"} { |
| # Test with and without source quoting. |
| foreach sqc $completion::maybe_quoted_list { |
| if {$source == "" && $sqc != ""} { |
| # Invalid combination. |
| continue |
| } |
| |
| # Test with and without function quoting. |
| foreach fqc $completion::maybe_quoted_list { |
| if {$source == ""} { |
| set linespec_source "" |
| set explicit_source "" |
| } else { |
| set linespec_source "${sqc}${source}${sqc}:" |
| set explicit_source "-source ${sqc}${source}${sqc}" |
| } |
| |
| # Even though this use case is trickier with |
| # linespecs due to the ":" as separator, test both |
| # linespecs and explicit locations for |
| # completeness. |
| foreach location [list \ |
| "${linespec_source}${fqc}$prototype${fqc}" \ |
| "${explicit_source} -function ${fqc}$prototype${fqc}"] { |
| set complete_line "b $location" |
| set start [string first $range_ss $complete_line] |
| set end [expr ($start + [string length $range_ss])] |
| test_complete_prefix_range $complete_line $start $end |
| if {!$skip_check_bp} { |
| check_bp_locations_match_list "b $location" [list "$prototype"] |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| incomplete_scope_colon_helper \ |
| "struct_incomplete_scope_colon_test::incomplete_scope_colon_test()" \ |
| "t::i" |
| |
| incomplete_scope_colon_helper \ |
| "ns_incomplete_scope_colon_test::incomplete_scope_colon_test()" \ |
| "t::i" |
| |
| # Test completing around both "::"s. |
| foreach range_ss {"t::s" "t::i"} skip_check_bp {0 1} { |
| incomplete_scope_colon_helper \ |
| "ns2_incomplete_scope_colon_test::struct_in_ns2_incomplete_scope_colon_test::incomplete_scope_colon_test()" \ |
| $range_ss $skip_check_bp |
| } |
| } |
| |
| # Test completing functions/methods in anonymous namespaces. |
| |
| proc_with_prefix anon-ns {} { |
| foreach cmd_prefix {"b" "b -function"} { |
| foreach qc $completion::maybe_quoted_list { |
| test_gdb_complete_unique \ |
| "$cmd_prefix ${qc}anon_ns_function" \ |
| "$cmd_prefix ${qc}anon_ns_function()${qc}" |
| check_bp_locations_match_list "$cmd_prefix ${qc}anon_ns_function()${qc}" { |
| "(anonymous namespace)::anon_ns_function()" |
| "(anonymous namespace)::anon_ns_struct::anon_ns_function()" |
| "the_anon_ns_wrapper_ns::(anonymous namespace)::anon_ns_function()" |
| "the_anon_ns_wrapper_ns::(anonymous namespace)::anon_ns_struct::anon_ns_function()" |
| } |
| } |
| |
| # A "(" finds all anonymous namespace functions/methods in all |
| # scopes. |
| test_gdb_complete_multiple "$cmd_prefix " "(" "anonymous namespace)::" { |
| "(anonymous namespace)::anon_ns_function()" |
| "(anonymous namespace)::anon_ns_struct::anon_ns_function()" |
| "(anonymous namespace)::overload2_function(overload2_arg3)" |
| "(anonymous namespace)::overload3_function(int)" |
| "(anonymous namespace)::overload3_function(long)" |
| "(anonymous namespace)::struct_overload2_test::overload2_function(overload2_arg4)" |
| "(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "(anonymous namespace)::struct_overload3_test::overload3_function(long)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::overload2_function(overload2_arg9)" |
| "ns_overload2_test::(anonymous namespace)::ns_overload2_test::struct_overload2_test::overload2_function(overload2_arga)" |
| "ns_overload2_test::(anonymous namespace)::overload2_function(overload2_arg7)" |
| "ns_overload2_test::(anonymous namespace)::struct_overload2_test::overload2_function(overload2_arg8)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::ns_overload3_test::struct_overload3_test::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::overload3_function(long)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(int)" |
| "ns_overload3_test::(anonymous namespace)::struct_overload3_test::overload3_function(long)" |
| "the_anon_ns_wrapper_ns::(anonymous namespace)::anon_ns_function()" |
| "the_anon_ns_wrapper_ns::(anonymous namespace)::anon_ns_struct::anon_ns_function()" |
| } |
| |
| set function "the_anon_ns_wrapper_ns::(anonymous namespace)::anon_ns_function()" |
| test_gdb_complete_unique "$cmd_prefix $function" "$cmd_prefix $function" |
| check_bp_locations_match_list "$cmd_prefix $function" [list $function] |
| |
| # Test completing after the "(anonymous namespace)" part. |
| test_gdb_complete_unique \ |
| "$cmd_prefix the_anon_ns_wrapper_ns::(anonymous namespace)::anon_ns_fu" \ |
| "$cmd_prefix $function" |
| |
| # Test whitespace in the "(anonymous namespace)" component. |
| |
| test_gdb_complete_unique \ |
| "$cmd_prefix the_anon_ns_wrapper_ns::( anonymous namespace )::anon_ns_fu" \ |
| "$cmd_prefix the_anon_ns_wrapper_ns::( anonymous namespace )::anon_ns_function()" |
| check_setting_bp_fails \ |
| "$cmd_prefix the_anon_ns_wrapper_ns::( anonymous namespace )::anon_ns_fu" |
| |
| set function_ws \ |
| "the_anon_ns_wrapper_ns::( anonymous namespace )::anon_ns_function ( )" |
| test_gdb_complete_unique "$cmd_prefix $function_ws" "$cmd_prefix $function_ws" |
| check_bp_locations_match_list "$cmd_prefix $function_ws" [list $function] |
| } |
| } |
| |
| # Basic test for completing "operator<". More extensive C++ operator |
| # tests in cpls-op.exp. |
| |
| proc_with_prefix operator< {} { |
| # Complete all prefixes between "oper" and the whole prototype. |
| set function "operator<(foo_enum, foo_enum)" |
| foreach cmd_prefix {"b" "b -function"} { |
| set line "$cmd_prefix $function" |
| set start [index_after "oper" $line] |
| test_complete_prefix_range $line $start |
| } |
| |
| # There's a label in the function; try completing it. (Exhaustive |
| # label completion tests further below.) |
| foreach location [list \ |
| "$function:label1" \ |
| "-function $function -label label1"] { |
| |
| set cmd "b $location" |
| set input_line [string range $cmd 0 [expr [string length $cmd] - 3]] |
| |
| test_gdb_complete_unique $input_line $cmd |
| test_gdb_complete_unique $cmd $cmd |
| check_bp_locations_match_list $cmd [list "$location"] |
| } |
| } |
| |
| # Test completion of scopes with an ambiguous prefix. |
| |
| proc_with_prefix ambiguous-prefix {} { |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple "$cmd_prefix " "ambiguous_pre" "fix_" { |
| "ambiguous_prefix_global_func()" |
| "the_ambiguous_prefix_ns::ambiguous_prefix_ns_func()" |
| "the_ambiguous_prefix_struct::ambiguous_prefix_method()" |
| } |
| check_setting_bp_fails "$cmd_prefix ambiguous_prefix_" |
| } |
| } |
| |
| # Test completion of function labels. |
| |
| proc_with_prefix function-labels {} { |
| # Test with and without a source file component. |
| foreach_location_functions \ |
| { "" "cpls.cc" } \ |
| { "function_with_labels(int)" } \ |
| { |
| # Linespec version. Test various spacing around the label |
| # colon separator. |
| foreach label_sep {":" " :" ": " " : "} { |
| set linespec "${location}${label_sep}" |
| test_gdb_complete_multiple "b $linespec" "l" "abel" { |
| "label1" |
| "label2" |
| } |
| check_setting_bp_fails "b ${linespec}label" |
| |
| set tsep [string trim ${source_sep}] |
| check_bp_locations_match_list \ |
| "b ${linespec}label1" [list "${source}${tsep}${function}:label1"] |
| check_bp_locations_match_list \ |
| "b ${linespec}label2" [list "${source}${tsep}${function}:label2"] |
| } |
| } \ |
| { |
| # Explicit locations version. |
| append location " -label" |
| test_gdb_complete_multiple "b $location " "l" "abel" { |
| "label1" |
| "label2" |
| } |
| check_setting_bp_fails "b $location label" |
| |
| if {$source != ""} { |
| set bp_loc_src "-source ${source} " |
| } else { |
| set bp_loc_src "" |
| } |
| check_bp_locations_match_list \ |
| "b ${location} label1" [list "${bp_loc_src}-function $function -label label1"] |
| check_bp_locations_match_list \ |
| "b ${location} label2" [list "${bp_loc_src}-function $function -label label2"] |
| } |
| } |
| |
| # Test that completion after a function name offers keyword |
| # (if/task/thread/-force-condition) matches in linespec mode, and also |
| # the explicit location options in explicit locations mode. |
| |
| proc_with_prefix keywords-after-function {} { |
| set explicit_list \ |
| [lsort [concat \ |
| $completion::explicit_opts_list \ |
| $completion::keyword_list]] |
| |
| # Test without a source file, with a known source file, and with |
| # and unknown source file. |
| # Test a known and an unknown function. |
| foreach_location_functions \ |
| { "" "cpls.cc" "unknown_file.cc" } \ |
| { "function_with_labels(int)" "unknown_function(int)" } \ |
| { |
| # Linespec version. |
| test_gdb_complete_multiple "b ${location} " "" "" \ |
| $completion::keyword_list |
| } \ |
| { |
| # Explicit locations version. |
| test_gdb_complete_multiple "b ${location} " "" "" \ |
| $explicit_list |
| } |
| } |
| |
| # Same, but after a label. |
| |
| proc_with_prefix keywords-after-label {} { |
| set explicit_list \ |
| [lsort [concat \ |
| $completion::explicit_opts_list \ |
| $completion::keyword_list]] |
| |
| foreach_location_labels \ |
| { "" "cpls.cc" } \ |
| { "function_with_labels(int)" "unknown_function(int)" } \ |
| { "label1" "non_existing_label" } \ |
| { |
| # Linespec version. |
| test_gdb_complete_multiple "b ${location} " "" "" \ |
| $completion::keyword_list |
| } \ |
| { |
| # Explicit locations version. |
| test_gdb_complete_multiple "b ${location} " "" "" \ |
| $explicit_list |
| } |
| } |
| |
| # Similar, but after an unknown file, and in linespec mode only. |
| |
| proc_with_prefix keywords-after-unknown-file {} { |
| # Test with and without quoting. |
| foreach qc $completion::maybe_quoted_list { |
| set line "b ${qc}unknown_file.cc${qc}: " |
| test_gdb_complete_multiple $line "" "" $completion::keyword_list |
| } |
| } |
| |
| # Test that linespec / function completion does not match data |
| # symbols, only functions/methods. |
| |
| proc_with_prefix no-data-symbols {} { |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_unique "$cmd_prefix code_" "$cmd_prefix code_function()" |
| } |
| } |
| |
| |
| # After "if", we expect an expression, which has a different completer |
| # that matches data symbols as well. Check that that works. |
| |
| proc_with_prefix if-expression {} { |
| foreach cmd_prefix {"b" "b -function"} { |
| test_gdb_complete_multiple "$cmd_prefix function() if " "code_" "" { |
| "code_data" |
| "code_function()" |
| } |
| |
| test_gdb_complete_unique \ |
| "$cmd_prefix function() if code_data + another_da" \ |
| "$cmd_prefix function() if code_data + another_data" |
| |
| test_gdb_complete_unique \ |
| "$cmd_prefix non_existing_function() if code_data + another_da" \ |
| "$cmd_prefix non_existing_function() if code_data + another_data" |
| |
| # FIXME: For now, thread and task also use the expression |
| # completer. |
| test_gdb_complete_unique \ |
| "$cmd_prefix function() thread code_data + another_da" \ |
| "$cmd_prefix function() thread code_data + another_data" |
| test_gdb_complete_unique \ |
| "$cmd_prefix function() task code_data + another_da" \ |
| "$cmd_prefix function() task code_data + another_data" |
| } |
| } |
| |
| # The testcase driver. Calls all test procedures. |
| |
| proc test_driver {} { |
| all-param-prefixes |
| overload |
| overload-2 |
| fqn |
| fqn-2 |
| overload-3 |
| template-overload |
| template-ret-type |
| const-overload |
| const-overload-quoted |
| append-end-quote-char-when-unambiguous |
| in-source-file-unconstrained |
| in-source-file-unambiguous |
| in-source-file-ambiguous |
| source-complete-appends-colon |
| incomplete-scope-colon |
| anon-ns |
| operator< |
| ambiguous-prefix |
| function-labels |
| keywords-after-function |
| keywords-after-label |
| keywords-after-unknown-file |
| no-data-symbols |
| if-expression |
| } |
| |
| test_driver |