# Copyright 2017-2018 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
}

# 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) matches in linespec mode, and also the explicit
# location options in explicit locations mode.

proc_with_prefix keywords-after-function {} {
    set explicit_list \
	[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 \
	[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