+
+/* Valid delimiters for linespec keywords "if", "thread" or "task". */
+
+static int
+is_linespec_boundary (char c)
+{
+ return c == ' ' || c == '\t' || c == '\0' || c == ',';
+}
+
+/* A helper function for decode_line_1 and friends which skips P
+ past any method overload information at the beginning of P, e.g.,
+ "(const struct foo *)".
+
+ This function assumes that P has already been validated to contain
+ overload information, and it will assert if *P != '('. */
+static char *
+find_method_overload_end (char *p)
+{
+ int depth = 0;
+
+ gdb_assert (*p == '(');
+
+ while (*p)
+ {
+ if (*p == '(')
+ ++depth;
+ else if (*p == ')')
+ {
+ if (--depth == 0)
+ {
+ ++p;
+ break;
+ }
+ }
+ ++p;
+ }
+
+ return p;
+}
+
+/* Keep important information used when looking up a name. This includes
+ template parameters, overload information, and important keywords, including
+ the possible Java trailing type. */
+
+static char *
+keep_name_info (char *p, int on_boundary)
+{
+ const char *quotes = get_gdb_completer_quote_characters ();
+ char *saved_p = p;
+ int nest = 0;
+
+ while (*p)
+ {
+ if (strchr (quotes, *p))
+ break;
+
+ if (*p == ',' && !nest)
+ break;
+
+ if (on_boundary && !nest)
+ {
+ const char *const words[] = { "if", "thread", "task" };
+ int wordi;
+
+ for (wordi = 0; wordi < ARRAY_SIZE (words); wordi++)
+ if (strncmp (p, words[wordi], strlen (words[wordi])) == 0
+ && is_linespec_boundary (p[strlen (words[wordi])]))
+ break;
+ if (wordi < ARRAY_SIZE (words))
+ break;
+ }
+
+ if (*p == '(' || *p == '<' || *p == '[')
+ nest++;
+ else if ((*p == ')' || *p == '>' || *p == ']') && nest > 0)
+ nest--;
+
+ p++;
+
+ /* The ',' check could fail on "operator ,". */
+ p += cp_validate_operator (p);
+
+ on_boundary = is_linespec_boundary (p[-1]);
+ }
+
+ while (p > saved_p && is_linespec_boundary (p[-1]))
+ p--;
+
+ return p;
+}
+