diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index a09ad5c..daa0080 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -1781,7 +1781,7 @@ complete_on_cmdlist (struct completer_data *cdata,
      commands.  If we see no matching commands in the first pass, and
      if we did happen to see a matching deprecated command, we do
      another loop to collect those.  */
-  for (pass = 0; matchlist == 0 && pass < 2; ++pass)
+  for (pass = 0; get_completion_count (cdata) == 0 && pass < 2; ++pass)
     {
       for (ptr = list; ptr; ptr = ptr->next)
 	if (!strncmp (ptr->name, text, textlen)
diff --git a/gdb/completer.c b/gdb/completer.c
index 9a7af74..5682627 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -214,6 +214,20 @@ filename_completer (struct completer_data *cdata,
   return return_val;
 }
 
+/* A hashtable traversal function to remove leading file name
+   components, as required by rl_complete.  See more detailed explanation
+   in location_completer for more.  */
+
+static int
+remove_leading_fn_component (void **slot, void *calldata)
+{
+  char *fn = *slot;
+  int offset = *(int *) calldata;
+
+  memmove (fn, fn + offset, strlen (fn) + 1 - offset);
+  return 1;
+}
+
 /* Complete on locations, which might be of two possible forms:
 
        file:line
@@ -303,21 +317,25 @@ location_completer (struct completer_data *cdata,
     {
       list = make_file_symbol_completion_list (cdata, symbol_start, word,
 					       file_to_match);
+      n_syms = get_completion_count (cdata);
+      n_files = 0;
       xfree (file_to_match);
     }
   else
     {
       list = make_symbol_completion_list (cdata, symbol_start, word);
+      n_syms = get_completion_count (cdata);
+      n_files = 0;
       /* If text includes characters which cannot appear in a file
 	 name, they cannot be asking for completion on files.  */
       if (strcspn (text, 
 		   gdb_completer_file_name_break_characters) == text_len)
-	fn_list = make_source_files_completion_list (cdata, text, text);
+	{
+	  fn_list = make_source_files_completion_list (cdata, text, text);
+	  n_files = get_completion_count (cdata) - n_syms;
+	}
     }
 
-  n_syms = VEC_length (char_ptr, list);
-  n_files = VEC_length (char_ptr, fn_list);
-
   /* Catenate fn_list[] onto the end of list[].  */
   if (!n_syms)
     {
@@ -340,7 +358,7 @@ location_completer (struct completer_data *cdata,
     }
   else if (n_files)
     {
-      char *fn;
+      int offset = word - text;
 
       /* If we only have file names as possible completion, we should
 	 bring them in sync with what rl_complete expects.  The
@@ -355,13 +373,10 @@ location_completer (struct completer_data *cdata,
 	 the full "/foo/bar" and "/foo/baz" strings.  This produces
 	 wrong results when, e.g., there's only one possible
 	 completion, because rl_complete will prepend "/foo/" to each
-	 candidate completion.  The loop below removes that leading
+	 candidate completion.  The callback below removes that leading
 	 part.  */
-      for (ix = 0; VEC_iterate (char_ptr, list, ix, fn); ++ix)
-	{
-	  memmove (fn, fn + (word - text),
-		   strlen (fn) + 1 - (word - text));
-	}
+      htab_traverse (cdata->tracker, remove_leading_fn_component,
+		     &offset);
     }
   else if (!n_syms)
     {
@@ -857,14 +872,67 @@ new_completer_data (int size)
 /* Free the completion data represented by P.  */
 
 static void
-free_completer_data (void *p)
+free_completer_data (struct completer_data *cdata)
 {
-  struct completer_data *cdata = p;
-
   htab_delete (cdata->tracker);
   xfree (cdata);
 }
 
+/* A hashtable traversal function to free the elements of the table.  */
+
+static int
+free_entry_callback (void **slot, void *calldata)
+{
+  char *element = *slot;
+
+  xfree (element);
+  return 1;
+}
+
+/* A cleanup function to free all data associated with the completer_data
+   given by P.  */
+
+static void
+free_all_completer_data (void *p)
+{
+  struct completer_data *cdata = p;
+
+  htab_traverse (cdata->tracker, free_entry_callback, NULL);
+  free_completer_data (cdata);
+}
+
+/* A hashtable traversal function to turn the hashtable keys
+   into a vector.  */
+
+static int
+vectorize_htab (void **slot, void *calldata)
+{
+  char *element = *slot;
+  VEC (char_ptr) **vector = calldata;
+
+  VEC_safe_push (char_ptr, *vector, element);
+  return 1;
+}
+
+/* See completer.h.  */
+
+VEC (char_ptr) *
+get_completion_list (const struct completer_data *cdata)
+{
+  VEC (char_ptr) *result = NULL;
+
+  htab_traverse (cdata->tracker, vectorize_htab, &result);
+  return result;
+}
+
+/* See completer.h.  */
+
+size_t
+get_completion_count (const struct completer_data *cdata)
+{
+  return htab_elements (cdata->tracker);
+}
+
 /* Add the completion NAME to the list of generated completions if
    it is not there already.
    If max_completions is negative, nothing is done, not even watching
@@ -881,12 +949,11 @@ maybe_add_completion (struct completer_data *cdata, char *name)
 {
   void **slot;
 
-  if (max_completions < 0)
-    return MAYBE_ADD_COMPLETION_OK;
   if (max_completions == 0)
     return MAYBE_ADD_COMPLETION_MAX_REACHED;
 
-  if (htab_elements (cdata->tracker) >= max_completions)
+  if (max_completions > 0
+      && htab_elements (cdata->tracker) >= max_completions)
     return MAYBE_ADD_COMPLETION_MAX_REACHED;
 
   slot = htab_find_slot (cdata->tracker, name, INSERT);
@@ -896,7 +963,8 @@ maybe_add_completion (struct completer_data *cdata, char *name)
 
   *slot = name;
 
-  return (htab_elements (cdata->tracker) < max_completions
+  return ((max_completions < 0
+	   || htab_elements (cdata->tracker) < max_completions)
 	  ? MAYBE_ADD_COMPLETION_OK
 	  : MAYBE_ADD_COMPLETION_OK_MAX_REACHED);
 }
@@ -961,66 +1029,20 @@ throw_max_completions_reached_error (void)
 VEC (char_ptr) *
 complete_line (const char *text, const char *line_buffer, int point)
 {
-  VEC (char_ptr) *list;
-  VEC (char_ptr) *result = NULL;
-  struct cleanup *cdata_cleanup, *list_cleanup;
-  char *candidate;
-  int ix;
+  VEC (char_ptr) *result;
+  struct cleanup *cdata_cleanup;
   struct completer_data *cdata;
 
   if (max_completions == 0)
     return NULL;
 
   cdata = new_completer_data (max_completions);
-  cdata_cleanup = make_cleanup (free_completer_data, cdata);
-  list = complete_line_internal (cdata, text, line_buffer, point,
-				 handle_completions);
-  if (max_completions < 0)
-    {
-      do_cleanups (cdata_cleanup);
-      return list;
-    }
-
-  list_cleanup = make_cleanup_free_char_ptr_vec (list);
-
-  /* If complete_line_internal returned more completions than were
-     recorded by the completion tracker, then the completer function that
-     was run does not support completion tracking.  In this case,
-     do a final test for too many completions.
-
-     Duplicates are also removed here.  Otherwise the user is left
-     scratching his/her head: readline and complete_command will remove
-     duplicates, and if removal of duplicates there brings the total under
-     max_completions the user may think gdb quit searching too early.  */
-
-  if (VEC_length (char_ptr, list) > htab_elements (cdata->tracker))
-    {
-      enum add_completion_status max_reached = ADD_COMPLETION_OK;
-
-      /* Clear the tracker so that we can re-use it to count the number
-	 of returned completions.  */
-      htab_empty (cdata->tracker);
-
-      for (ix = 0; (max_reached == ADD_COMPLETION_OK
-		    && VEC_iterate (char_ptr, list, ix, candidate)); ++ix)
-	{
-	  max_reached = add_completion (cdata, &result, xstrdup (candidate));
-	}
-
-      /* The return result has been assembled and the original list from
-	 complete_line_internal is no longer needed.  Free it.  */
-      do_cleanups (list_cleanup);
-    }
-  else
-    {
-      /* There is a valid tracker for the completion -- simply return
-	 the completed list.  */
-      discard_cleanups (list_cleanup);
-      result = list;
-    }
-
-  do_cleanups (cdata_cleanup);
-
+  cdata_cleanup = make_cleanup (free_all_completer_data, cdata);
+  complete_line_internal (cdata, text, line_buffer, point,
+			  handle_completions);
+  result = get_completion_list (cdata);
+  discard_cleanups (cdata_cleanup);
+  free_completer_data (cdata);
   return result;
 }
 
@@ -1123,10 +1145,12 @@ gdb_completion_word_break_characters (void)
   struct cleanup *cleanup;
 
   cdata = new_completer_data (max_completions);
-  cleanup = make_cleanup (free_completer_data, cdata);
-  list = complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
-				 rl_point, handle_brkchars);
-  do_cleanups (cleanup);
+  cleanup = make_cleanup (free_all_completer_data, cdata);
+  complete_line_internal (cdata, rl_line_buffer, rl_line_buffer,
+			  rl_point, handle_brkchars);
+  list = get_completion_list (cdata);
+  discard_cleanups (cleanup);
+  free_completer_data (cdata);
   gdb_assert (list == NULL);
   return rl_completer_word_break_characters;
 }
diff --git a/gdb/completer.h b/gdb/completer.h
index 29ff2e9..ec551c8 100644
--- a/gdb/completer.h
+++ b/gdb/completer.h
@@ -128,6 +128,15 @@ extern const char *skip_quoted (const char *);
 
 extern int get_maximum_completions (void);
 
+/* Get the list of completions.  */
+
+extern VEC (char_ptr) *
+  get_completion_list (const struct completer_data *cdata);
+
+/* Get the number of completions in CDATA.  */
+
+extern size_t get_completion_count (const struct completer_data *cdata);
+
 /* Return values for add_completion.  */
 
 enum add_completion_status
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index 04c7309..440994c 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -402,7 +402,7 @@ cmdpy_completer (struct completer_data *cdata,
 
       /* If we got some results, ignore problems.  Otherwise, report
 	 the problem.  */
-      if (result != NULL && PyErr_Occurred ())
+      if (get_completion_count (cdata) > 0 && PyErr_Occurred ())
 	PyErr_Clear ();
     }
 
