# 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 . # 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::template_overload_fn(int)" "template_struct::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::template_overload_fn" \ "template_struct::template_overload_fn(int)" } } # Test completing template methods with non-void return type. proc_with_prefix template-ret-type {} { set method_name "template2_fn" set param_list "(template2_ret_type, int, int)" set struct_type "template2_struct >" set ret_type "template2_ret_type" # Templates are listed both with and without return type, making # "template2_" 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