+/* C++ symbol_name_matcher_ftype implementation. */
+
+static bool
+cp_fq_symbol_name_matches (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ /* Get the demangled name. */
+ const std::string &name = lookup_name.cplus ().lookup_name ();
+ completion_match_for_lcd *match_for_lcd
+ = (comp_match_res != NULL ? &comp_match_res->match_for_lcd : NULL);
+ strncmp_iw_mode mode = (lookup_name.completion_mode ()
+ ? strncmp_iw_mode::NORMAL
+ : strncmp_iw_mode::MATCH_PARAMS);
+
+ if (strncmp_iw_with_mode (symbol_search_name,
+ name.c_str (), name.size (),
+ mode, language_cplus, match_for_lcd) == 0)
+ {
+ if (comp_match_res != NULL)
+ comp_match_res->set_match (symbol_search_name);
+ return true;
+ }
+
+ return false;
+}
+
+/* C++ symbol_name_matcher_ftype implementation for wild matches.
+ Defers work to cp_symbol_name_matches_1. */
+
+static bool
+cp_symbol_name_matches (const char *symbol_search_name,
+ const lookup_name_info &lookup_name,
+ completion_match_result *comp_match_res)
+{
+ /* Get the demangled name. */
+ const std::string &name = lookup_name.cplus ().lookup_name ();
+
+ strncmp_iw_mode mode = (lookup_name.completion_mode ()
+ ? strncmp_iw_mode::NORMAL
+ : strncmp_iw_mode::MATCH_PARAMS);
+
+ return cp_symbol_name_matches_1 (symbol_search_name,
+ name.c_str (), name.size (),
+ mode, comp_match_res);
+}
+
+/* See cp-support.h. */
+
+symbol_name_matcher_ftype *
+cp_get_symbol_name_matcher (const lookup_name_info &lookup_name)
+{
+ switch (lookup_name.match_type ())
+ {
+ case symbol_name_match_type::FULL:
+ case symbol_name_match_type::EXPRESSION:
+ case symbol_name_match_type::SEARCH_NAME:
+ return cp_fq_symbol_name_matches;
+ case symbol_name_match_type::WILD:
+ return cp_symbol_name_matches;
+ }
+
+ gdb_assert_not_reached ("");
+}
+
+#if GDB_SELF_TEST
+
+namespace selftests {
+
+static void
+test_cp_symbol_name_matches ()
+{
+#define CHECK_MATCH(SYMBOL, INPUT) \
+ SELF_CHECK (cp_symbol_name_matches_1 (SYMBOL, \
+ INPUT, sizeof (INPUT) - 1, \
+ strncmp_iw_mode::MATCH_PARAMS, \
+ NULL))
+
+#define CHECK_NOT_MATCH(SYMBOL, INPUT) \
+ SELF_CHECK (!cp_symbol_name_matches_1 (SYMBOL, \
+ INPUT, sizeof (INPUT) - 1, \
+ strncmp_iw_mode::MATCH_PARAMS, \
+ NULL))
+
+ /* Like CHECK_MATCH, and also check that INPUT (and all substrings
+ that start at index 0) completes to SYMBOL. */
+#define CHECK_MATCH_C(SYMBOL, INPUT) \
+ do \
+ { \
+ CHECK_MATCH (SYMBOL, INPUT); \
+ for (size_t i = 0; i < sizeof (INPUT) - 1; i++) \
+ SELF_CHECK (cp_symbol_name_matches_1 (SYMBOL, INPUT, i, \
+ strncmp_iw_mode::NORMAL, \
+ NULL)); \
+ } while (0)
+
+ /* Like CHECK_NOT_MATCH, and also check that INPUT does NOT complete
+ to SYMBOL. */
+#define CHECK_NOT_MATCH_C(SYMBOL, INPUT) \
+ do \
+ { \
+ CHECK_NOT_MATCH (SYMBOL, INPUT); \
+ SELF_CHECK (!cp_symbol_name_matches_1 (SYMBOL, INPUT, \
+ sizeof (INPUT) - 1, \
+ strncmp_iw_mode::NORMAL, \
+ NULL)); \
+ } while (0)
+
+ /* Lookup name without parens matches all overloads. */
+ CHECK_MATCH_C ("function()", "function");
+ CHECK_MATCH_C ("function(int)", "function");
+
+ /* Check whitespace around parameters is ignored. */
+ CHECK_MATCH_C ("function()", "function ()");
+ CHECK_MATCH_C ("function ( )", "function()");
+ CHECK_MATCH_C ("function ()", "function( )");
+ CHECK_MATCH_C ("func(int)", "func( int )");
+ CHECK_MATCH_C ("func(int)", "func ( int ) ");
+ CHECK_MATCH_C ("func ( int )", "func( int )");
+ CHECK_MATCH_C ("func ( int )", "func ( int ) ");
+
+ /* Check symbol name prefixes aren't incorrectly matched. */
+ CHECK_NOT_MATCH ("func", "function");
+ CHECK_NOT_MATCH ("function", "func");
+ CHECK_NOT_MATCH ("function()", "func");
+
+ /* Check that if the lookup name includes parameters, only the right
+ overload matches. */
+ CHECK_MATCH_C ("function(int)", "function(int)");
+ CHECK_NOT_MATCH_C ("function(int)", "function()");
+
+ /* Check that whitespace within symbol names is not ignored. */
+ CHECK_NOT_MATCH_C ("function", "func tion");
+ CHECK_NOT_MATCH_C ("func__tion", "func_ _tion");
+ CHECK_NOT_MATCH_C ("func11tion", "func1 1tion");
+
+ /* Check the converse, which can happen with template function,
+ where the return type is part of the demangled name. */
+ CHECK_NOT_MATCH_C ("func tion", "function");
+ CHECK_NOT_MATCH_C ("func1 1tion", "func11tion");
+ CHECK_NOT_MATCH_C ("func_ _tion", "func__tion");
+
+ /* Within parameters too. */
+ CHECK_NOT_MATCH_C ("func(param)", "func(par am)");
+
+ /* Check handling of whitespace around C++ operators. */
+ CHECK_NOT_MATCH_C ("operator<<", "opera tor<<");
+ CHECK_NOT_MATCH_C ("operator<<", "operator< <");
+ CHECK_NOT_MATCH_C ("operator<<", "operator < <");
+ CHECK_NOT_MATCH_C ("operator==", "operator= =");
+ CHECK_NOT_MATCH_C ("operator==", "operator = =");
+ CHECK_MATCH_C ("operator<<", "operator <<");
+ CHECK_MATCH_C ("operator<<()", "operator <<");
+ CHECK_NOT_MATCH_C ("operator<<()", "operator<<(int)");
+ CHECK_NOT_MATCH_C ("operator<<(int)", "operator<<()");
+ CHECK_MATCH_C ("operator==", "operator ==");
+ CHECK_MATCH_C ("operator==()", "operator ==");
+ CHECK_MATCH_C ("operator <<", "operator<<");
+ CHECK_MATCH_C ("operator ==", "operator==");
+ CHECK_MATCH_C ("operator bool", "operator bool");
+ CHECK_MATCH_C ("operator bool ()", "operator bool");
+ CHECK_MATCH_C ("operatorX<<", "operatorX < <");
+ CHECK_MATCH_C ("Xoperator<<", "Xoperator < <");
+
+ CHECK_MATCH_C ("operator()(int)", "operator()(int)");
+ CHECK_MATCH_C ("operator()(int)", "operator ( ) ( int )");
+ CHECK_MATCH_C ("operator()<long>(int)", "operator ( ) < long > ( int )");
+ /* The first "()" is not the parameter list. */
+ CHECK_NOT_MATCH ("operator()(int)", "operator");
+
+ /* Misc user-defined operator tests. */
+
+ CHECK_NOT_MATCH_C ("operator/=()", "operator ^=");
+ /* Same length at end of input. */
+ CHECK_NOT_MATCH_C ("operator>>", "operator[]");
+ /* Same length but not at end of input. */
+ CHECK_NOT_MATCH_C ("operator>>()", "operator[]()");
+
+ CHECK_MATCH_C ("base::operator char*()", "base::operator char*()");
+ CHECK_MATCH_C ("base::operator char*()", "base::operator char * ()");
+ CHECK_MATCH_C ("base::operator char**()", "base::operator char * * ()");
+ CHECK_MATCH ("base::operator char**()", "base::operator char * *");
+ CHECK_MATCH_C ("base::operator*()", "base::operator*()");
+ CHECK_NOT_MATCH_C ("base::operator char*()", "base::operatorc");
+ CHECK_NOT_MATCH ("base::operator char*()", "base::operator char");
+ CHECK_NOT_MATCH ("base::operator char*()", "base::operat");
+
+ /* Check handling of whitespace around C++ scope operators. */
+ CHECK_NOT_MATCH_C ("foo::bar", "foo: :bar");
+ CHECK_MATCH_C ("foo::bar", "foo :: bar");
+ CHECK_MATCH_C ("foo :: bar", "foo::bar");
+
+ CHECK_MATCH_C ("abc::def::ghi()", "abc::def::ghi()");
+ CHECK_MATCH_C ("abc::def::ghi ( )", "abc::def::ghi()");
+ CHECK_MATCH_C ("abc::def::ghi()", "abc::def::ghi ( )");
+ CHECK_MATCH_C ("function()", "function()");
+ CHECK_MATCH_C ("bar::function()", "bar::function()");
+
+ /* Wild matching tests follow. */
+
+ /* Tests matching symbols in some scope. */
+ CHECK_MATCH_C ("foo::function()", "function");
+ CHECK_MATCH_C ("foo::function(int)", "function");
+ CHECK_MATCH_C ("foo::bar::function()", "function");
+ CHECK_MATCH_C ("bar::function()", "bar::function");
+ CHECK_MATCH_C ("foo::bar::function()", "bar::function");
+ CHECK_MATCH_C ("foo::bar::function(int)", "bar::function");
+
+ /* Same, with parameters in the lookup name. */
+ CHECK_MATCH_C ("foo::function()", "function()");
+ CHECK_MATCH_C ("foo::bar::function()", "function()");
+ CHECK_MATCH_C ("foo::function(int)", "function(int)");
+ CHECK_MATCH_C ("foo::function()", "foo::function()");
+ CHECK_MATCH_C ("foo::bar::function()", "bar::function()");
+ CHECK_MATCH_C ("foo::bar::function(int)", "bar::function(int)");
+ CHECK_MATCH_C ("bar::function()", "bar::function()");
+
+ CHECK_NOT_MATCH_C ("foo::bar::function(int)", "bar::function()");
+
+ CHECK_MATCH_C ("(anonymous namespace)::bar::function(int)",
+ "bar::function(int)");
+ CHECK_MATCH_C ("foo::(anonymous namespace)::bar::function(int)",
+ "function(int)");
+
+ /* Lookup scope wider than symbol scope, should not match. */
+ CHECK_NOT_MATCH_C ("function()", "bar::function");
+ CHECK_NOT_MATCH_C ("function()", "bar::function()");
+
+ /* Explicit global scope doesn't match. */
+ CHECK_NOT_MATCH_C ("foo::function()", "::function");
+ CHECK_NOT_MATCH_C ("foo::function()", "::function()");
+ CHECK_NOT_MATCH_C ("foo::function(int)", "::function()");
+ CHECK_NOT_MATCH_C ("foo::function(int)", "::function(int)");
+
+ /* Test ABI tag matching/ignoring. */
+
+ /* If the symbol name has an ABI tag, but the lookup name doesn't,
+ then the ABI tag in the symbol name is ignored. */
+ CHECK_MATCH_C ("function[abi:foo]()", "function");
+ CHECK_MATCH_C ("function[abi:foo](int)", "function");
+ CHECK_MATCH_C ("function[abi:foo]()", "function ()");
+ CHECK_NOT_MATCH_C ("function[abi:foo]()", "function (int)");
+
+ CHECK_MATCH_C ("function[abi:foo]()", "function[abi:foo]");
+ CHECK_MATCH_C ("function[abi:foo](int)", "function[abi:foo]");
+ CHECK_MATCH_C ("function[abi:foo]()", "function[abi:foo] ()");
+ CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function");
+ CHECK_MATCH_C ("function[abi:foo][abi:bar](int)", "function");
+ CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo]");
+ CHECK_MATCH_C ("function[abi:foo][abi:bar](int)", "function[abi:foo]");
+ CHECK_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo] ()");
+ CHECK_NOT_MATCH_C ("function[abi:foo][abi:bar]()", "function[abi:foo] (int)");
+
+ CHECK_MATCH_C ("function [abi:foo][abi:bar] ( )", "function [abi:foo]");
+
+ /* If the symbol name does not have an ABI tag, while the lookup
+ name has one, then there's no match. */
+ CHECK_NOT_MATCH_C ("function()", "function[abi:foo]()");
+ CHECK_NOT_MATCH_C ("function()", "function[abi:foo]");
+}
+
+/* If non-NULL, return STR wrapped in quotes. Otherwise, return a
+ "<null>" string (with no quotes). */
+
+static std::string
+quote (const char *str)
+{
+ if (str != NULL)
+ return std::string (1, '"') + str + '"';
+ else
+ return "<null>";
+}
+
+/* Check that removing parameter info out of NAME produces EXPECTED.
+ COMPLETION_MODE indicates whether we're testing normal and
+ completion mode. FILE and LINE are used to provide better test
+ location information in case ithe check fails. */
+
+static void
+check_remove_params (const char *file, int line,
+ const char *name, const char *expected,
+ bool completion_mode)
+{
+ gdb::unique_xmalloc_ptr<char> result
+ = cp_remove_params_if_any (name, completion_mode);
+
+ if ((expected == NULL) != (result == NULL)
+ || (expected != NULL
+ && strcmp (result.get (), expected) != 0))
+ {
+ error (_("%s:%d: make-paramless self-test failed: (completion=%d) "
+ "\"%s\" -> %s, expected %s"),
+ file, line, completion_mode, name,
+ quote (result.get ()).c_str (), quote (expected).c_str ());
+ }