diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9776cf2..8abe455 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,47 @@
 2017-11-08  Pedro Alves  <palves@redhat.com>
 
+	* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
+	unittests/lookup_name_info-selftests.c.
+	(SUBDIR_UNITTESTS_OBS): Add lookup_name_info-selftests.o.
+	* cp-support.c: Include "selftest.h".
+	(cp_remove_params_1): Rename from cp_remove_params.  Add
+	'require_param' parameter, and handle it.
+	(cp_remove_params): Reimplement.
+	(cp_remove_params_if_any): New.
+	(selftests::quote): New.
+	(selftests::check_remove_params): New.
+	(selftests::test_cp_remove_params): New.
+	(_initialize_cp_support): Install
+	selftests::test_cp_remove_params.
+	* cp-support.h (cp_remove_params_if_any): Declare.
+	* dwarf2read.c :Include "selftest.h".
+	(dw2_expand_symtabs_matching_symbol): Use
+	lookup_name_info::make_ignore_params.
+	(selftests::dw2_expand_symtabs_matching::mock_mapped_index)
+	(selftests::dw2_expand_symtabs_matching::string_or_null)
+	(selftests::dw2_expand_symtabs_matching::check_match)
+	(selftests::dw2_expand_symtabs_matching::test_symbols)
+	(selftests::dw2_expand_symtabs_matching::run_test): New.
+	(_initialize_dwarf2_read): Register
+	selftests::dw2_expand_symtabs_matching::run_test.
+	* psymtab.c (psym_expand_symtabs_matching): Use
+	lookup_name_info::make_ignore_params.
+	* symtab.c (demangle_for_lookup_info::demangle_for_lookup_info):
+	If the lookup name wants to ignore parameters, strip them.
+	(compare_symbol_name): Remove sym_text/sym_text_len parameters and
+	code handling '('.
+	(completion_list_add_name): Don't pass down sym_text/sym_text_len.
+	(default_collect_symbol_completion_matches_break_on): Don't try to
+	strip parameters.
+	* symtab.h (lookup_name_info::lookup_name_info): Add
+	'ignore_parameters' parameter.
+	(lookup_name_info::ignore_parameters)
+	(lookup_name_info::make_ignore_params): New methods.
+	(lookup_name_info::m_ignore_parameters): New field.
+	* unittests/lookup_name_info-selftests.c: New file.
+
+2017-11-08  Pedro Alves  <palves@redhat.com>
+
 	* dwarf2read.c (dw2_expand_marked_cus)
 	(dw2_expand_symtabs_matching_symbol): Remove forward declarations.
 	(dw2_expand_symtabs_matching): Move further below.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 6fe9b38..5e01816 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -530,6 +530,7 @@ SUBDIR_UNITTESTS_SRCS = \
 	unittests/common-utils-selftests.c \
 	unittests/environ-selftests.c \
 	unittests/function-view-selftests.c \
+	unittests/lookup_name_info-selftests.c \
 	unittests/memrange-selftests.c \
 	unittests/offset-type-selftests.c \
 	unittests/optional-selftests.c \
@@ -542,6 +543,7 @@ SUBDIR_UNITTESTS_OBS = \
 	common-utils-selftests.o \
 	environ-selftests.o \
 	function-view-selftests.o \
+	lookup_name_info-selftests.o \
 	memrange-selftests.o \
 	offset-type-selftests.o \
 	optional-selftests.o \
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index defe509..1cab69b 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -36,6 +36,7 @@
 #include <signal.h>
 #include "gdb_setjmp.h"
 #include "safe-ctype.h"
+#include "selftest.h"
 
 #define d_left(dc) (dc)->u.s_binary.left
 #define d_right(dc) (dc)->u.s_binary.right
@@ -830,12 +831,14 @@ cp_func_name (const char *full_name)
   return ret.release ();
 }
 
-/* DEMANGLED_NAME is the name of a function, including parameters and
-   (optionally) a return type.  Return the name of the function without
-   parameters or return type, or NULL if we can not parse the name.  */
+/* Helper for cp_remove_params.  DEMANGLED_NAME is the name of a
+   function, including parameters and (optionally) a return type.
+   Return the name of the function without parameters or return type,
+   or NULL if we can not parse the name.  If REQUIRE_PARAMS is false,
+   then tolerate a non-existing or unbalanced parameter list.  */
 
-gdb::unique_xmalloc_ptr<char>
-cp_remove_params (const char *demangled_name)
+static gdb::unique_xmalloc_ptr<char>
+cp_remove_params_1 (const char *demangled_name, bool require_params)
 {
   bool done = false;
   struct demangle_component *ret_comp;
@@ -871,10 +874,56 @@ cp_remove_params (const char *demangled_name)
   /* What we have now should be a function.  Return its name.  */
   if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
     ret = cp_comp_to_string (d_left (ret_comp), 10);
+  else if (!require_params
+	   && (ret_comp->type == DEMANGLE_COMPONENT_NAME
+	       || ret_comp->type == DEMANGLE_COMPONENT_QUAL_NAME
+	       || ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE))
+    ret = cp_comp_to_string (ret_comp, 10);
 
   return ret;
 }
 
+/* DEMANGLED_NAME is the name of a function, including parameters and
+   (optionally) a return type.  Return the name of the function
+   without parameters or return type, or NULL if we can not parse the
+   name.  */
+
+gdb::unique_xmalloc_ptr<char>
+cp_remove_params (const char *demangled_name)
+{
+  return cp_remove_params_1 (demangled_name, true);
+}
+
+/* See cp-support.h.  */
+
+gdb::unique_xmalloc_ptr<char>
+cp_remove_params_if_any (const char *demangled_name, bool completion_mode)
+{
+  /* Trying to remove parameters from the empty string fails.  If
+     we're completing / matching everything, avoid returning NULL
+     which would make callers interpret the result as an error.  */
+  if (demangled_name[0] == '\0' && completion_mode)
+    return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
+
+  gdb::unique_xmalloc_ptr<char> without_params
+    = cp_remove_params_1 (demangled_name, false);
+
+  if (without_params == NULL && completion_mode)
+    {
+      std::string copy = demangled_name;
+
+      while (!copy.empty ())
+	{
+	  copy.pop_back ();
+	  without_params = cp_remove_params_1 (copy.c_str (), false);
+	  if (without_params != NULL)
+	    break;
+	}
+    }
+
+  return without_params;
+}
+
 /* Here are some random pieces of trivia to keep in mind while trying
    to take apart demangled names:
 
@@ -1600,6 +1649,129 @@ cp_get_symbol_name_matcher (const lookup_name_info &lookup_name)
   return cp_fq_symbol_name_matches;
 }
 
+#if GDB_SELF_TEST
+
+namespace selftests {
+
+/* 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 ());
+    }
+}
+
+/* Entry point for cp_remove_params unit tests.  */
+
+static void
+test_cp_remove_params ()
+{
+  /* Check that removing parameter info out of NAME produces EXPECTED.
+     Checks both normal and completion modes.  */
+#define CHECK(NAME, EXPECTED)						\
+  do									\
+    {									\
+      check_remove_params (__FILE__, __LINE__, NAME, EXPECTED, false);	\
+      check_remove_params (__FILE__, __LINE__, NAME, EXPECTED, true);	\
+    }									\
+  while (0)
+
+  /* Similar, but used when NAME is incomplete -- i.e., is has
+     unbalanced parentheses.  In this case, looking for the exact name
+     should fail / return empty.  */
+#define CHECK_INCOMPL(NAME, EXPECTED)					\
+  do									\
+    {									\
+      check_remove_params (__FILE__, __LINE__, NAME, NULL, false);	\
+      check_remove_params (__FILE__, __LINE__, NAME, EXPECTED, true);	\
+    }									\
+  while (0)
+
+  CHECK ("function()", "function");
+  CHECK_INCOMPL ("function(", "function");
+  CHECK ("function() const", "function");
+
+  CHECK ("(anonymous namespace)::A::B::C",
+	 "(anonymous namespace)::A::B::C");
+
+  CHECK ("A::(anonymous namespace)",
+	 "A::(anonymous namespace)");
+
+  CHECK_INCOMPL ("A::(anonymou", "A");
+
+  CHECK ("A::foo<int>()",
+	 "A::foo<int>");
+
+  CHECK_INCOMPL ("A::foo<int>(",
+		 "A::foo<int>");
+
+  CHECK ("A::foo<(anonymous namespace)::B>::func(int)",
+	 "A::foo<(anonymous namespace)::B>::func");
+
+  CHECK_INCOMPL ("A::foo<(anonymous namespace)::B>::func(in",
+		 "A::foo<(anonymous namespace)::B>::func");
+
+  CHECK_INCOMPL ("A::foo<(anonymous namespace)::B>::",
+		 "A::foo<(anonymous namespace)::B>");
+
+  CHECK_INCOMPL ("A::foo<(anonymous namespace)::B>:",
+		 "A::foo<(anonymous namespace)::B>");
+
+  CHECK ("A::foo<(anonymous namespace)::B>",
+	 "A::foo<(anonymous namespace)::B>");
+
+  CHECK_INCOMPL ("A::foo<(anonymous namespace)::B",
+		 "A::foo");
+
+  /* Shouldn't this parse?  Looks like a bug in
+     cp_demangled_name_to_comp.  See PR c++/22411.  */
+#if 0
+  CHECK ("A::foo<void(int)>::func(int)",
+	 "A::foo<void(int)>::func");
+#else
+  CHECK_INCOMPL ("A::foo<void(int)>::func(int)",
+		 "A::foo");
+#endif
+
+  CHECK_INCOMPL ("A::foo<void(int",
+		 "A::foo");
+
+#undef CHECK
+#undef CHECK_INCOMPL
+}
+
+} // namespace selftests
+
+#endif /* GDB_SELF_CHECK */
+
 /* Don't allow just "maintenance cplus".  */
 
 static  void
@@ -1682,4 +1854,9 @@ display the offending symbol."),
 			   &maintenance_set_cmdlist,
 			   &maintenance_show_cmdlist);
 #endif
+
+#if GDB_SELF_TEST
+  selftests::register_test ("cp_remove_params",
+			    selftests::test_cp_remove_params);
+#endif
 }
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index a699a80..44d8269 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -98,6 +98,14 @@ extern char *cp_func_name (const char *full_name);
 extern gdb::unique_xmalloc_ptr<char> cp_remove_params
   (const char *demanged_name);
 
+/* DEMANGLED_NAME is the name of a function, (optionally) including
+   parameters and (optionally) a return type.  Return the name of the
+   function without parameters or return type, or NULL if we can not
+   parse the name.  If COMPLETION_MODE is true, then tolerate a
+   non-existing or unbalanced parameter list.  */
+extern gdb::unique_xmalloc_ptr<char> cp_remove_params_if_any
+  (const char *demangled_name, bool completion_mode);
+
 extern struct symbol **make_symbol_overload_list (const char *,
 						  const char *);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index d715082..389d8f7 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -81,6 +81,7 @@
 #include <algorithm>
 #include <unordered_set>
 #include <unordered_map>
+#include "selftest.h"
 
 typedef struct symbol *symbolp;
 DEF_VEC_P (symbolp);
@@ -4198,13 +4199,15 @@ gdb_index_symbol_name_matcher::matches (const char *symbol_name)
 static void
 dw2_expand_symtabs_matching_symbol
   (mapped_index &index,
-   const lookup_name_info &lookup_name,
+   const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    enum search_domain kind,
    gdb::function_view<void (offset_type)> match_callback)
 {
+  lookup_name_info lookup_name_without_params
+    = lookup_name_in.make_ignore_params ();
   gdb_index_symbol_name_matcher lookup_name_matcher
-    (lookup_name);
+    (lookup_name_without_params);
 
   auto *name_cmp = case_sensitivity == case_sensitive_on ? strcmp : strcasecmp;
 
@@ -4262,7 +4265,7 @@ dw2_expand_symtabs_matching_symbol
     }
 
   const char *cplus
-    = lookup_name.cplus ().lookup_name ().c_str ();
+    = lookup_name_without_params.cplus ().lookup_name ().c_str ();
 
   /* Comparison function object for lower_bound that matches against a
      given symbol name.  */
@@ -4290,7 +4293,7 @@ dw2_expand_symtabs_matching_symbol
   /* Find the lower bound.  */
   auto lower = [&] ()
     {
-      if (lookup_name.completion_mode () && cplus[0] == '\0')
+      if (lookup_name_in.completion_mode () && cplus[0] == '\0')
 	return begin;
       else
 	return std::lower_bound (begin, end, cplus, lookup_compare_lower);
@@ -4299,7 +4302,7 @@ dw2_expand_symtabs_matching_symbol
   /* Find the upper bound.  */
   auto upper = [&] ()
     {
-      if (lookup_name.completion_mode ())
+      if (lookup_name_in.completion_mode ())
 	{
 	  /* The string frobbing below won't work if the string is
 	     empty.  We don't need it then, anyway -- if we're
@@ -4365,6 +4368,288 @@ dw2_expand_symtabs_matching_symbol
   static_assert (sizeof (prev) > sizeof (offset_type), "");
 }
 
+#if GDB_SELF_TEST
+
+namespace selftests { namespace dw2_expand_symtabs_matching {
+
+/* A wrapper around mapped_index that builds a mock mapped_index, from
+   the symbol list passed as parameter to the constructor.  */
+class mock_mapped_index
+{
+public:
+  template<size_t N>
+  mock_mapped_index (const char *(&symbols)[N])
+    : mock_mapped_index (symbols, N)
+  {}
+
+  /* Access the built index.  */
+  mapped_index &index ()
+  { return m_index; }
+
+  /* Disable copy.  */
+  mock_mapped_index(const mock_mapped_index &) = delete;
+  void operator= (const mock_mapped_index &) = delete;
+
+private:
+  mock_mapped_index (const char **symbols, size_t symbols_size)
+  {
+    /* No string can live at offset zero.  Add a dummy entry.  */
+    obstack_grow_str0 (&m_constant_pool, "");
+
+    for (size_t i = 0; i < symbols_size; i++)
+      {
+	const char *sym = symbols[i];
+	size_t offset = obstack_object_size (&m_constant_pool);
+	obstack_grow_str0 (&m_constant_pool, sym);
+	m_symbol_table.push_back (offset);
+	m_symbol_table.push_back (0);
+      };
+
+    m_index.constant_pool = (const char *) obstack_base (&m_constant_pool);
+    m_index.symbol_table = m_symbol_table.data ();
+    m_index.symbol_table_slots = m_symbol_table.size () / 2;
+  }
+
+public:
+  /* The built mapped_index.  */
+  mapped_index m_index{};
+
+  /* The storage that the built mapped_index uses for symbol and
+     constant pool tables.  */
+  std::vector<offset_type> m_symbol_table;
+  auto_obstack m_constant_pool;
+};
+
+/* Convenience function that converts a NULL pointer to a "<null>"
+   string, to pass to print routines.  */
+
+static const char *
+string_or_null (const char *str)
+{
+  return str != NULL ? str : "<null>";
+}
+
+/* Check if a lookup_name_info built from
+   NAME/MATCH_TYPE/COMPLETION_MODE matches the symbols in the mock
+   index.  EXPECTED_LIST is the list of expected matches, in expected
+   matching order.  If no match expected, then an empty list is
+   specified.  Returns true on success.  On failure prints a warning
+   indicating the file:line that failed, and returns false.  */
+
+static bool
+check_match (const char *file, int line,
+	     mock_mapped_index &mock_index,
+	     const char *name, symbol_name_match_type match_type,
+	     bool completion_mode,
+	     std::initializer_list<const char *> expected_list)
+{
+  lookup_name_info lookup_name (name, match_type, completion_mode);
+
+  bool matched = true;
+
+  auto mismatch = [&] (const char *expected_str,
+		       const char *got)
+  {
+    warning (_("%s:%d: match_type=%s, looking-for=\"%s\", "
+	       "expected=\"%s\", got=\"%s\"\n"),
+	     file, line,
+	     (match_type == symbol_name_match_type::FULL
+	      ? "FULL" : "WILD"),
+	     name, string_or_null (expected_str), string_or_null (got));
+    matched = false;
+  };
+
+  auto expected_it = expected_list.begin ();
+  auto expected_end = expected_list.end ();
+
+  dw2_expand_symtabs_matching_symbol (mock_index.index (), lookup_name,
+				      NULL, ALL_DOMAIN,
+				      [&] (offset_type idx)
+  {
+    const char *matched_name = mock_index.index ().symbol_name_at (idx);
+    const char *expected_str
+      = expected_it == expected_end ? NULL : *expected_it++;
+
+    if (expected_str == NULL || strcmp (expected_str, matched_name) != 0)
+      mismatch (expected_str, matched_name);
+  });
+
+  const char *expected_str
+  = expected_it == expected_end ? NULL : *expected_it++;
+  if (expected_str != NULL)
+    mismatch (expected_str, NULL);
+
+  return matched;
+}
+
+/* The symbols added to the mock mapped_index for testing (in
+   canonical form).  */
+static const char *test_symbols[] = {
+  "function",
+  "std::bar",
+  "std::zfunction",
+  "std::zfunction2",
+  "w1::w2",
+  "ns::foo<char*>",
+  "ns::foo<int>",
+  "ns::foo<long>",
+
+  /* A name with all sorts of complications.  Starts with "z" to make
+     it easier for the completion tests below.  */
+#define Z_SYM_NAME \
+  "z::std::tuple<(anonymous namespace)::ui*, std::bar<(anonymous namespace)::ui> >" \
+    "::tuple<(anonymous namespace)::ui*, " \
+    "std::default_delete<(anonymous namespace)::ui>, void>"
+
+  Z_SYM_NAME
+};
+
+static void
+run_test ()
+{
+  mock_mapped_index mock_index (test_symbols);
+
+  /* We let all tests run until the end even if some fails, for debug
+     convenience.  */
+  bool any_mismatch = false;
+
+  /* Create the expected symbols list (an initializer_list).  Needed
+     because lists have commas, and we need to pass them to CHECK,
+     which is a macro.  */
+#define EXPECT(...) { __VA_ARGS__ }
+
+  /* Wrapper for check_match that passes down the current
+     __FILE__/__LINE__.  */
+#define CHECK_MATCH(NAME, MATCH_TYPE, COMPLETION_MODE, EXPECTED_LIST)	\
+  any_mismatch |= !check_match (__FILE__, __LINE__,			\
+				mock_index,				\
+				NAME, MATCH_TYPE, COMPLETION_MODE,	\
+				EXPECTED_LIST)
+
+  /* Identity checks.  */
+  for (const char *sym : test_symbols)
+    {
+      /* Should be able to match all existing symbols.  */
+      CHECK_MATCH (sym, symbol_name_match_type::FULL, false,
+		   EXPECT (sym));
+
+      /* Should be able to match all existing symbols with
+	 parameters.  */
+      std::string with_params = std::string (sym) + "(int)";
+      CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
+		   EXPECT (sym));
+
+      /* Should be able to match all existing symbols with
+	 parameters and qualifiers.  */
+      with_params = std::string (sym) + " ( int ) const";
+      CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
+		   EXPECT (sym));
+
+      /* This should really find sym, but cp-name-parser.y doesn't
+	 know about lvalue/rvalue qualifiers yet.  */
+      with_params = std::string (sym) + " ( int ) &&";
+      CHECK_MATCH (with_params.c_str (), symbol_name_match_type::FULL, false,
+		   {});
+    }
+
+  /* Check that completion mode works at each prefix of the expected
+     symbol name.  */
+  {
+    static const char str[] = "function(int)";
+    size_t len = strlen (str);
+    std::string lookup;
+
+    for (size_t i = 1; i < len; i++)
+      {
+	lookup.assign (str, i);
+	CHECK_MATCH (lookup.c_str (), symbol_name_match_type::FULL, true,
+		     EXPECT ("function"));
+      }
+  }
+
+  /* While "w" is a prefix of both components, the match function
+     should still only be called once.  */
+  {
+    CHECK_MATCH ("w", symbol_name_match_type::FULL, true,
+		 EXPECT ("w1::w2"));
+  }
+
+  /* Same, with a "complicated" symbol.  */
+  {
+    static const char str[] = Z_SYM_NAME;
+    size_t len = strlen (str);
+    std::string lookup;
+
+    for (size_t i = 1; i < len; i++)
+      {
+	lookup.assign (str, i);
+	CHECK_MATCH (lookup.c_str (), symbol_name_match_type::FULL, true,
+		     EXPECT (Z_SYM_NAME));
+      }
+  }
+
+  /* In FULL mode, an incomplete symbol doesn't match.  */
+  {
+    CHECK_MATCH ("std::zfunction(int", symbol_name_match_type::FULL, false,
+		 {});
+  }
+
+  /* A complete symbol with parameters matches any overload, since the
+     index has no overload info.  */
+  {
+    CHECK_MATCH ("std::zfunction(int)", symbol_name_match_type::FULL, true,
+		 EXPECT ("std::zfunction", "std::zfunction2"));
+  }
+
+  /* Check that whitespace is ignored appropriately.  A symbol with a
+     template argument list. */
+  {
+    static const char expected[] = "ns::foo<int>";
+    CHECK_MATCH ("ns :: foo < int > ", symbol_name_match_type::FULL, false,
+		 EXPECT (expected));
+  }
+
+  /* Check that whitespace is ignored appropriately.  A symbol with a
+     template argument list that includes a pointer.  */
+  {
+    static const char expected[] = "ns::foo<char*>";
+    /* Try both completion and non-completion modes.  */
+    static const bool completion_mode[2] = {false, true};
+    for (size_t i = 0; i < 2; i++)
+      {
+	CHECK_MATCH ("ns :: foo < char * >", symbol_name_match_type::FULL,
+		     completion_mode[i], EXPECT (expected));
+
+	CHECK_MATCH ("ns :: foo < char * > (int)", symbol_name_match_type::FULL,
+		     completion_mode[i], EXPECT (expected));
+      }
+  }
+
+  {
+    /* Check method qualifiers are ignored.  */
+    static const char expected[] = "ns::foo<char*>";
+    CHECK_MATCH ("ns :: foo < char * >  ( int ) const",
+		 symbol_name_match_type::FULL, true, EXPECT (expected));
+    CHECK_MATCH ("ns :: foo < char * >  ( int ) &&",
+		 symbol_name_match_type::FULL, true, EXPECT (expected));
+  }
+
+  /* Test lookup names that don't match anything.  */
+  {
+    CHECK_MATCH ("doesntexist", symbol_name_match_type::FULL, false,
+		 {});
+  }
+
+  SELF_CHECK (!any_mismatch);
+
+#undef EXPECT
+#undef CHECK_MATCH
+}
+
+}} // namespace selftests::dw2_expand_symtabs_matching
+
+#endif /* GDB_SELF_TEST */
+
 /* Helper for dw2_expand_matching symtabs.  Called on each symbol
    matched, to expand corresponding CUs that were marked.  IDX is the
    index of the symbol name that matched.  */
@@ -24454,4 +24739,9 @@ Usage: save gdb-index DIRECTORY"),
 					&dwarf2_block_frame_base_locexpr_funcs);
   dwarf2_loclist_block_index = register_symbol_block_impl (LOC_BLOCK,
 					&dwarf2_block_frame_base_loclist_funcs);
+
+#if GDB_SELF_TEST
+  selftests::register_test ("dw2_expand_symtabs_matching",
+			    selftests::dw2_expand_symtabs_matching::run_test);
+#endif
 }
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index d7881d2..29d40dc 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1390,13 +1390,15 @@ static void
 psym_expand_symtabs_matching
   (struct objfile *objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   const lookup_name_info &lookup_name,
+   const lookup_name_info &lookup_name_in,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
    enum search_domain domain)
 {
   struct partial_symtab *ps;
 
+  lookup_name_info lookup_name = lookup_name_in.make_ignore_params ();
+
   /* Clear the search flags.  */
   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
     {
diff --git a/gdb/symtab.c b/gdb/symtab.c
index aecee8f..2d09f94 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1766,6 +1766,20 @@ demangle_for_lookup_info::demangle_for_lookup_info
 {
   demangle_result_storage storage;
 
+  if (lookup_name.ignore_parameters () && lang == language_cplus)
+    {
+      gdb::unique_xmalloc_ptr<char> without_params
+	= cp_remove_params_if_any (lookup_name.name ().c_str (),
+				   lookup_name.completion_mode ());
+
+      if (without_params != NULL)
+	{
+	  m_demangled_name = demangle_for_lookup (without_params.get (),
+						  lang, storage);
+	  return;
+	}
+    }
+
   m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
 					  lang, storage);
 }
@@ -4619,20 +4633,11 @@ rbreak_command (const char *regexp, int from_tty)
 }
 
 
-/* Evaluate if NAME matches SYM_TEXT and SYM_TEXT_LEN.
-
-   Either sym_text[sym_text_len] != '(' and then we search for any
-   symbol starting with SYM_TEXT text.
-
-   Otherwise sym_text[sym_text_len] == '(' and then we require symbol name to
-   be terminated at that point.  Partial symbol tables do not have parameters
-   information.  */
+/* Evaluate if SYMNAME matches LOOKUP_NAME.  */
 
 static int
-compare_symbol_name (const char *name,
-		     language symbol_language,
+compare_symbol_name (const char *symbol_name, language symbol_language,
 		     const lookup_name_info &lookup_name,
-		     const char *sym_text, int sym_text_len,
 		     completion_match_result &match_res)
 {
   const language_defn *lang;
@@ -4654,23 +4659,7 @@ compare_symbol_name (const char *name,
   symbol_name_matcher_ftype *name_match
     = language_get_symbol_name_matcher (lang, lookup_name);
 
-  /* Clip symbols that cannot match.  */
-  if (!name_match (name, lookup_name, &match_res.match))
-    return 0;
-
-  if (sym_text[sym_text_len] == '(')
-    {
-      /* User searches for `name(someth...'.  Require NAME to be terminated.
-	 Normally psymtabs and gdbindex have no parameter types so '\0' will be
-	 present but accept even parameters presence.  In this case this
-	 function is in fact strcmp_iw but whitespace skipping is not supported
-	 for tab completion.  */
-
-      if (name[sym_text_len] != '\0' && name[sym_text_len] != '(')
-	return 0;
-    }
-
-  return 1;
+  return name_match (symbol_name, lookup_name, &match_res.match);
 }
 
 /*  See symtab.h.  */
@@ -4687,10 +4676,7 @@ completion_list_add_name (completion_tracker &tracker,
     = tracker.reset_completion_match_result ();
 
   /* Clip symbols that cannot match.  */
-  if (!compare_symbol_name (symname, symbol_language,
-			    lookup_name,
-			    sym_text, sym_text_len,
-			    match_res))
+  if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res))
     return;
 
   /* Refresh SYMNAME from the match string.  It's potentially
@@ -5014,21 +5000,6 @@ default_collect_symbol_completion_matches_break_on
 
   sym_text_len = strlen (sym_text);
 
-  /* Prepare SYM_TEXT_LEN for compare_symbol_name.  */
-
-  if (current_language->la_language == language_cplus
-      || current_language->la_language == language_fortran)
-    {
-      /* These languages may have parameters entered by user but they are never
-	 present in the partial symbol tables.  */
-
-      const char *cs = (const char *) memchr (sym_text, '(', sym_text_len);
-
-      if (cs)
-	sym_text_len = cs - sym_text;
-    }
-  gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
-
   lookup_name_info lookup_name (std::string (sym_text, sym_text_len),
 				name_match_type, true);
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 5dfe953..8cd3496 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -167,9 +167,11 @@ class lookup_name_info final
   /* Create a new object.  */
   lookup_name_info (std::string name,
 		    symbol_name_match_type match_type,
-		    bool completion_mode = false)
+		    bool completion_mode = false,
+		    bool ignore_parameters = false)
     : m_match_type (match_type),
       m_completion_mode (completion_mode),
+      m_ignore_parameters (ignore_parameters),
       m_name (std::move (name))
   {}
 
@@ -177,6 +179,16 @@ class lookup_name_info final
   symbol_name_match_type match_type () const { return m_match_type; }
   bool completion_mode () const { return m_completion_mode; }
   const std::string &name () const { return m_name; }
+  const bool ignore_parameters () const { return m_ignore_parameters; }
+
+  /* Return a version of this lookup name that is usable with
+     comparisons against symbols have no parameter info, such as
+     psymbols and GDB index symbols.  */
+  lookup_name_info make_ignore_params () const
+  {
+    return lookup_name_info (m_name, m_match_type, m_completion_mode,
+			     true /* ignore params */);
+  }
 
   /* Get the search name hash for searches in language LANG.  */
   unsigned int search_name_hash (language lang) const
@@ -253,6 +265,7 @@ private:
   /* The lookup info as passed to the ctor.  */
   symbol_name_match_type m_match_type;
   bool m_completion_mode;
+  bool m_ignore_parameters;
   std::string m_name;
 
   /* Language-specific info.  These fields are filled lazily the first
diff --git a/gdb/unittests/lookup_name_info-selftests.c b/gdb/unittests/lookup_name_info-selftests.c
new file mode 100644
index 0000000..b35a020
--- /dev/null
+++ b/gdb/unittests/lookup_name_info-selftests.c
@@ -0,0 +1,111 @@
+/* Self tests for lookup_name_info for GDB, the GNU debugger.
+
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+#include "defs.h"
+#include "selftest.h"
+#include "symtab.h"
+
+namespace selftests {
+namespace lookup_name {
+
+/* 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 the check fails.  */
+
+static void
+check_make_paramless (const char *file, int line,
+		      enum language lang,
+		      const char *name, const char *expected,
+		      bool completion_mode)
+{
+  lookup_name_info lookup_name (name, symbol_name_match_type::FULL,
+				completion_mode, true /* ignore_parameters */);
+  const std::string &result = lookup_name.language_lookup_name (lang);
+
+  if (result != expected)
+    {
+      error (_("%s:%d: make-paramless self-test failed: (completion=%d, lang=%d) "
+	       "\"%s\" -> \"%s\", expected \"%s\""),
+	     file, line, completion_mode, lang, name,
+	     result.c_str (), expected);
+    }
+}
+
+static void
+run_tests ()
+{
+  /* Helper for CHECK and CHECK_INCOMPL.  */
+#define CHECK_1(INCOMPLETE, LANG, NAME, EXPECTED)			\
+  do									\
+    {									\
+      check_make_paramless (__FILE__, __LINE__,				\
+			    LANG, NAME,					\
+			    (INCOMPLETE) ? "" : (EXPECTED), false);	\
+      check_make_paramless (__FILE__, __LINE__,				\
+			    LANG, NAME, EXPECTED, true);		\
+    }									\
+  while (0)
+
+  /* Check that removing parameter info out of NAME produces EXPECTED.
+     Checks both normal and completion modes.  */
+#define CHECK(LANG, NAME, EXPECTED)		\
+  CHECK_1(false, LANG, NAME, EXPECTED)
+
+  /* Similar, but used when NAME is incomplete -- i.e., NAME has
+     unbalanced parentheses.  In this case, looking for the exact name
+     should fail / return empty.  */
+#define CHECK_INCOMPL(LANG, NAME, EXPECTED)				\
+  CHECK_1 (true, LANG, NAME, EXPECTED)
+
+  /* None of these languages support function overloading like C++
+     does, so building a nameless lookup name ends up being just the
+     same as any other lookup name.  Mainly this serves as smoke test
+     that C++-specific code doesn't mess up with other languages that
+     use some other scoping character ('.' vs '::').  */
+  CHECK (language_ada, "pck.ada_hello", "pck__ada_hello");
+  CHECK (language_go, "pck.go_hello", "pck.go_hello");
+  CHECK (language_fortran, "mod::func", "mod::func");
+
+  /* D does support function overloading similar to C++, but we're
+     missing support for stripping parameters.  At least make sure the
+     input name is preserved unmodified.  */
+  CHECK (language_d, "pck.d_hello", "pck.d_hello");
+
+  /* Just a few basic tests to make sure
+     lookup_name_info::make_paramless is well integrated with
+     cp_remove_params_if_any.  gdb/cp-support.c has comprehensive
+     testing of C++ specifics.  */
+  CHECK (language_cplus, "function()", "function");
+  CHECK (language_cplus, "function() const", "function");
+  CHECK (language_cplus, "A::B::C()", "A::B::C");
+  CHECK (language_cplus, "A::B::C", "A::B::C");
+
+#undef CHECK
+#undef CHECK_INCOMPL
+}
+
+}} // namespace selftests::lookup_name
+
+void
+_initialize_lookup_name_info_selftests ()
+{
+  selftests::register_test ("lookup_name_info",
+			    selftests::lookup_name::run_tests);
+}
