From patchwork Fri Nov 24 16:48:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 24498 Received: (qmail 24437 invoked by alias); 24 Nov 2017 16:48:35 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 24370 invoked by uid 89); 24 Nov 2017 16:48:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.0 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ADVERT2, KAM_LAZY_DOMAIN_SECURITY, KB_WAM_FROM_NAME_SINGLEWORD, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=mild, UD:stream, believes X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 24 Nov 2017 16:48:26 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 29A9181224 for ; Fri, 24 Nov 2017 16:48:25 +0000 (UTC) Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1308B5D9C8; Fri, 24 Nov 2017 16:48:23 +0000 (UTC) Subject: Re: [PATCH 32/40] Make "break foo" find "A::foo", A::B::foo", etc. [C++ and wild matching] To: Keith Seitz , gdb-patches@sourceware.org References: <1496406158-12663-1-git-send-email-palves@redhat.com> <1496406158-12663-33-git-send-email-palves@redhat.com> <024edecc-7bfa-08a4-de46-3536297f0654@redhat.com> <943402c5-0bbb-8ff7-66e3-5522256fbc1e@redhat.com> From: Pedro Alves Message-ID: <3692eedd-6f0f-2c6b-535c-2c5682dc938e@redhat.com> Date: Fri, 24 Nov 2017 16:48:23 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <943402c5-0bbb-8ff7-66e3-5522256fbc1e@redhat.com> Hey Keith, So I took your suggestion and ran with it. And in the end I like it! See more below. On 11/22/2017 04:48 PM, Pedro Alves wrote: > > On 08/09/2017 12:48 AM, Keith Seitz wrote: >> On 06/02/2017 05:22 AM, Pedro Alves wrote: >> >>> /* This help string is used for the break, hbreak, tbreak and thbreak >>> commands. It is defined as a macro to prevent duplication. >>> diff --git a/gdb/completer.c b/gdb/completer.c >>> index eabbce7..99e40a3 100644 >>> --- a/gdb/completer.c >>> +++ b/gdb/completer.c >>> @@ -609,6 +612,7 @@ static const char *const explicit_options[] = >>> { >>> "-source", >>> "-function", >>> + "-qualified", >>> "-line", >>> "-label", >>> NULL >> >> The "-qualified" option can be used with linespecs, too, right? > > Not really, no. > >> >> (gdb) b -qualified A::b (a linespec location) >> (gdb) b -qualified -function A::b (an explicit location) >> >> Actually, I see that it does not work (yet?). Consider: >> >> 1 struct A >> 2 { >> 3 int doit () >> 4 { >> 5 int i; >> 6 >> 7 for (i = 0; i < 10; ++i) >> 8 { >> 9 switch (i) >> 10 { >> 11 top: >> 12 case 5: >> 13 ++i; >> 14 goto top; >> 15 default: break; >> 16 } >> 17 } >> 18 return i; >> 19 } >> 20 }; >> >> (gdb) b A::doit:top >> Breakpoint 1 at 0x400633: file simple-label.cc, line 11. >> (gdb) b -function A::doit -label top >> Note: breakpoint 1 also set at pc 0x400633. >> Breakpoint 2 at 0x400633: file simple-label.cc, line 11. >> (gdb) b -qualified A::doit:top >> Function "A::doit:top" not defined. >> Make breakpoint pending on future shared library load? (y or [n]) n >> (gdb) b -qualified A::doit -label top >> Note: breakpoints 1 and 2 also set at pc 0x400633. >> Breakpoint 3 at 0x400633: file simple-label.cc, line 11. >> >> Is there a reason to exclude linespecs? Perhaps naively, I would have thought to >> make -qualified a parsing option instead of a replacement for -function. > > I went this route because it seemed to me that a separate > option would end up being less convenient, because it forces you > to type/combine two options: > > (gdb) b -q -f A::doit:top > Sorry, here I was really trying to talk about: (gdb) b -q -f A::doit -label top vs: (gdb) b -q A::doit -label top But ... > and I thought that since you're requiring an option, and > explicit linespecs are just superior to regular linespecs, that > it'd be OK to move users to explicit linespecs if they need > a qualified name. > > Dunno. ... well, I'll be d*mn+d... I gave your suggestion a try, and I actually like it! If we make "-qualified" a flag instead of an option with an argument, then usual case of: (gdb) b -q A::doit works the exact same. It's only when you specify source files and labels that it makes a difference. So with your suggestion, we get a lot of benefit (works with linespecs, which is the common case, I guess) with only a mild downside (a little more typing in the explicit location case). Here's what the delta patch looks like. I left "-qualified" as an explicit location option, rather than splitting the parsing of "qualified" and the real explicit options, because this way support for "-qualified" in the middle of other options "-source filename.cc -qualified -function func" falls out naturally. Surprisingly, I didn't have to change much in the tests. But I did extend them to cover these new possibilities. I'll show the tests delta as a follow up. From b84d26c68ced2a6544660e1f3cf5584c9e1dd4ef Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Fri, 24 Nov 2017 15:28:43 +0000 Subject: [PATCH] alternative --- gdb/ax-gdb.c | 3 +- gdb/breakpoint.c | 23 +++++++------ gdb/completer.c | 39 +++++++++++++++++---- gdb/guile/scm-breakpoint.c | 6 ++-- gdb/linespec.c | 31 +++++++++++------ gdb/linespec.h | 3 +- gdb/location.c | 86 ++++++++++++++++++++++++++++++---------------- gdb/location.h | 35 ++++++++++++++----- gdb/mi/mi-cmd-break.c | 3 +- gdb/python/py-breakpoint.c | 3 +- gdb/python/python.c | 3 +- 11 files changed, 163 insertions(+), 72 deletions(-) diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 52ca081..5027f6a 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -2638,7 +2638,8 @@ agent_command_1 (const char *exp, int eval) exp = skip_spaces (exp); - event_location_up location = new_linespec_location (&exp); + event_location_up location + = new_linespec_location (&exp, symbol_name_match_type::WILD); decode_line_full (location.get (), DECODE_LINE_FUNFIRSTLINE, NULL, (struct symtab *) NULL, 0, &canonical, NULL, NULL); diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 88cb505..c7bb77d 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -9100,9 +9100,9 @@ parse_breakpoint_sals (const struct event_location *location, if (event_location_type (location) == LINESPEC_LOCATION) { - const char *address = get_linespec_location (location); + const char *spec = get_linespec_location (location)->spec_string; - if (address == NULL) + if (spec == NULL) { /* The last displayed codepoint, if it's valid, is our default breakpoint address. */ @@ -9148,15 +9148,15 @@ parse_breakpoint_sals (const struct event_location *location, cursal = get_current_source_symtab_and_line (); if (last_displayed_sal_is_valid ()) { - const char *address = NULL; + const char *spec = NULL; if (event_location_type (location) == LINESPEC_LOCATION) - address = get_linespec_location (location); + spec = get_linespec_location (location)->spec_string; if (!cursal.symtab - || (address != NULL - && strchr ("+-", address[0]) != NULL - && address[1] != '[')) + || (spec != NULL + && strchr ("+-", spec[0]) != NULL + && spec[1] != '[')) { decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL, get_last_displayed_symtab (), @@ -13147,12 +13147,13 @@ strace_marker_create_sals_from_location (const struct event_location *location, struct linespec_sals lsal; const char *arg_start, *arg; - arg = arg_start = get_linespec_location (location); + arg = arg_start = get_linespec_location (location)->spec_string; lsal.sals = decode_static_tracepoint_spec (&arg); std::string str (arg_start, arg - arg_start); const char *ptr = str.c_str (); - canonical->location = new_linespec_location (&ptr); + canonical->location + = new_linespec_location (&ptr, symbol_name_match_type::FULL); lsal.canonical = xstrdup (event_location_to_string (canonical->location.get ())); @@ -13213,7 +13214,7 @@ strace_marker_decode_location (struct breakpoint *b, struct program_space *search_pspace) { struct tracepoint *tp = (struct tracepoint *) b; - const char *s = get_linespec_location (location); + const char *s = get_linespec_location (location)->spec_string; std::vector sals = decode_static_tracepoint_spec (&s); if (sals.size () > tp->static_trace_marker_id_idx) @@ -14759,7 +14760,7 @@ strace_command (const char *arg, int from_tty) if (arg && startswith (arg, "-m") && isspace (arg[2])) { ops = &strace_marker_breakpoint_ops; - location = new_linespec_location (&arg); + location = new_linespec_location (&arg, symbol_name_match_type::FULL); } else { diff --git a/gdb/completer.c b/gdb/completer.c index aa0f105..d0224aa 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -582,7 +582,8 @@ complete_source_filenames (const char *text) static void complete_address_and_linespec_locations (completion_tracker &tracker, - const char *text) + const char *text, + symbol_name_match_type match_type) { if (*text == '*') { @@ -594,7 +595,7 @@ complete_address_and_linespec_locations (completion_tracker &tracker, } else { - linespec_complete (tracker, text); + linespec_complete (tracker, text, match_type); } } @@ -642,6 +643,9 @@ collect_explicit_location_matches (completion_tracker &tracker, const struct explicit_location *explicit_loc = get_explicit_location (location); + /* True if the option expects an argument. */ + bool needs_arg = true; + /* Note, in the various MATCH_* below, we complete on explicit_loc->foo instead of WORD, because only the former will have already skipped past any quote char. */ @@ -657,7 +661,6 @@ collect_explicit_location_matches (completion_tracker &tracker, break; case MATCH_FUNCTION: - case MATCH_QUALIFIED: { const char *function = string_or_empty (explicit_loc->function_name); linespec_complete_function (tracker, function, @@ -666,6 +669,9 @@ collect_explicit_location_matches (completion_tracker &tracker, } break; + case MATCH_QUALIFIED: + needs_arg = false; + break; case MATCH_LINE: /* Nothing to offer. */ break; @@ -685,7 +691,7 @@ collect_explicit_location_matches (completion_tracker &tracker, gdb_assert_not_reached ("unhandled explicit_location_match_type"); } - if (tracker.completes_to_completion_word (word)) + if (!needs_arg || tracker.completes_to_completion_word (word)) { tracker.discard_completions (); tracker.advance_custom_word_point_by (strlen (word)); @@ -874,7 +880,7 @@ location_completer (struct cmd_list_element *ignore, tracker.advance_custom_word_point_by (1); } - if (location != NULL) + if (completion_info.saw_explicit_location_option) { if (*copy != '\0') { @@ -914,10 +920,29 @@ location_completer (struct cmd_list_element *ignore, } } + /* This is an address or linespec location. */ + else if (location != NULL) + { + /* Handle non-explicit location options. */ + + int keyword = skip_keyword (tracker, explicit_options, &text); + if (keyword == -1) + complete_on_enum (tracker, explicit_options, text, text); + else + { + tracker.advance_custom_word_point_by (copy - text); + text = copy; + + symbol_name_match_type match_type + = get_explicit_location (location.get ())->func_name_match_type; + complete_address_and_linespec_locations (tracker, text, match_type); + } + } else { - /* This is an address or linespec location. */ - complete_address_and_linespec_locations (tracker, text); + /* No options. */ + complete_address_and_linespec_locations (tracker, text, + symbol_name_match_type::WILD); } /* Add matches for option names, if either: diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c index ec75be5..f84815e 100644 --- a/gdb/guile/scm-breakpoint.c +++ b/gdb/guile/scm-breakpoint.c @@ -424,8 +424,10 @@ gdbscm_register_breakpoint_x (SCM self) pending_breakpoint_scm = self; location = bp_smob->spec.location; copy = skip_spaces (location); - event_location_up eloc = string_to_event_location_basic (©, - current_language); + event_location_up eloc + = string_to_event_location_basic (©, + current_language, + symbol_name_match_type::WILD); TRY { diff --git a/gdb/linespec.c b/gdb/linespec.c index c11ca1d..fca3efd 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -302,6 +302,9 @@ struct ls_parser struct linespec result; #define PARSER_RESULT(PPTR) (&(PPTR)->result) + /* Whether to do full matching or wild matching. */ + symbol_name_match_type match_type; + /* What the parser believes the current word point should complete to. */ linespec_complete_what complete_what; @@ -1869,7 +1872,7 @@ linespec_parse_basic (linespec_parser *parser) linespec_complete_function (tmp_tracker, parser->completion_word, - symbol_name_match_type::WILD, + parser->match_type, source_filename); if (tmp_tracker.have_completions ()) @@ -1894,7 +1897,7 @@ linespec_parse_basic (linespec_parser *parser) /* Try looking it up as a function/method. */ find_linespec_symbols (PARSER_STATE (parser), PARSER_RESULT (parser)->file_symtabs, name, - symbol_name_match_type::WILD, + parser->match_type, &symbols, &minimal_symbols); if (symbols != NULL || minimal_symbols != NULL) @@ -2511,10 +2514,12 @@ convert_explicit_location_to_sals (struct linespec_state *self, if no file is validly specified. Callers must check that. Also, the line number returned may be invalid. */ -/* Parse the linespec in ARG. */ +/* Parse the linespec in ARG. MATCH_TYPE indicates how function names + should be matched. */ static std::vector -parse_linespec (linespec_parser *parser, const char *arg) +parse_linespec (linespec_parser *parser, const char *arg, + symbol_name_match_type match_type) { linespec_token token; struct gdb_exception file_exception = exception_none; @@ -2544,6 +2549,7 @@ parse_linespec (linespec_parser *parser, const char *arg) parser->lexer.stream = arg; parser->completion_word = arg; parser->complete_what = linespec_complete_what::FUNCTION; + parser->match_type = match_type; /* Initialize the default symtab and line offset. */ initialize_defaults (&PARSER_STATE (parser)->default_symtab, @@ -2875,7 +2881,7 @@ complete_linespec_component (linespec_parser *parser, { completion_list fn_list; - linespec_complete_function (tracker, text, symbol_name_match_type::WILD, + linespec_complete_function (tracker, text, parser->match_type, source_filename); if (source_filename == NULL) { @@ -2981,7 +2987,8 @@ linespec_complete_label (completion_tracker &tracker, /* See description in linespec.h. */ void -linespec_complete (completion_tracker &tracker, const char *text) +linespec_complete (completion_tracker &tracker, const char *text, + symbol_name_match_type match_type) { linespec_parser parser; struct cleanup *cleanup; @@ -2990,6 +2997,7 @@ linespec_complete (completion_tracker &tracker, const char *text) linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL); cleanup = make_cleanup (linespec_parser_delete, &parser); parser.lexer.saved_arg = text; + parser.match_type = match_type; PARSER_STREAM (&parser) = text; parser.completion_tracker = &tracker; @@ -2999,7 +3007,7 @@ linespec_complete (completion_tracker &tracker, const char *text) furthest completion point we managed to parse to. */ TRY { - parse_linespec (&parser, text); + parse_linespec (&parser, text, match_type); } CATCH (except, RETURN_MASK_ERROR) { @@ -3047,7 +3055,7 @@ linespec_complete (completion_tracker &tracker, const char *text) VEC (bound_minimal_symbol_d) *minimal_symbols; find_linespec_symbols (PARSER_STATE (&parser), PARSER_RESULT (&parser)->file_symtabs, - func_name, symbol_name_match_type::WILD, + func_name, parser.match_type, &function_symbols, &minimal_symbols); PARSER_RESULT (&parser)->function_symbols = function_symbols; @@ -3189,7 +3197,9 @@ event_location_to_sals (linespec_parser *parser, PARSER_STATE (parser)->is_linespec = 1; TRY { - result = parse_linespec (parser, get_linespec_location (location)); + const linespec_location *ls = get_linespec_location (location); + result = parse_linespec (parser, + ls->spec_string, ls->match_type); } CATCH (except, RETURN_MASK_ERROR) { @@ -3500,7 +3510,8 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char *arg) else str = saved_arg; - self->canonical->location = new_linespec_location (&str); + self->canonical->location + = new_linespec_location (&str, symbol_name_match_type::FULL); } } diff --git a/gdb/linespec.h b/gdb/linespec.h index 7add83e..85beb62 100644 --- a/gdb/linespec.h +++ b/gdb/linespec.h @@ -180,7 +180,8 @@ extern const char * const linespec_keywords[]; /* Complete a linespec. */ extern void linespec_complete (completion_tracker &tracker, - const char *text); + const char *text, + symbol_name_match_type match_type); /* Complete a function symbol, in linespec mode, according to FUNC_MATCH_TYPE. If SOURCE_FILENAME is non-NULL, limits completion diff --git a/gdb/location.c b/gdb/location.c index cbd37ba..c767890 100644 --- a/gdb/location.c +++ b/gdb/location.c @@ -41,13 +41,14 @@ struct event_location union { - /* A generic "this is a string specification" for a location. - This representation is used by both "normal" linespecs and - probes. */ + /* A probe. */ char *addr_string; -#define EL_LINESPEC(P) ((P)->u.addr_string) #define EL_PROBE(P) ((P)->u.addr_string) + /* A "normal" linespec. */ + struct linespec_location linespec_location; +#define EL_LINESPEC(P) (&(P)->u.linespec_location) + /* An address in the inferior. */ CORE_ADDR address; #define EL_ADDRESS(P) (P)->u.address @@ -78,17 +79,20 @@ initialize_explicit_location (struct explicit_location *explicit_loc) { memset (explicit_loc, 0, sizeof (struct explicit_location)); explicit_loc->line_offset.sign = LINE_OFFSET_UNKNOWN; + explicit_loc->func_name_match_type = symbol_name_match_type::WILD; } /* See description in location.h. */ event_location_up -new_linespec_location (const char **linespec) +new_linespec_location (const char **linespec, + symbol_name_match_type match_type) { struct event_location *location; location = XCNEW (struct event_location); EL_TYPE (location) = LINESPEC_LOCATION; + EL_LINESPEC (location)->match_type = match_type; if (*linespec != NULL) { const char *p; @@ -97,14 +101,14 @@ new_linespec_location (const char **linespec) linespec_lex_to_end (linespec); p = remove_trailing_whitespace (orig, *linespec); if ((p - orig) > 0) - EL_LINESPEC (location) = savestring (orig, p - orig); + EL_LINESPEC (location)->spec_string = savestring (orig, p - orig); } return event_location_up (location); } /* See description in location.h. */ -const char * +const linespec_location * get_linespec_location (const struct event_location *location) { gdb_assert (EL_TYPE (location) == LINESPEC_LOCATION); @@ -249,8 +253,7 @@ explicit_to_string_internal (int as_linespec, if (explicit_loc->func_name_match_type == symbol_name_match_type::FULL) buf.puts ("-qualified "); - else - buf.puts ("-function "); + buf.puts ("-function "); } buf.puts (explicit_loc->function_name); need_space = 1; @@ -313,8 +316,10 @@ copy_event_location (const struct event_location *src) switch (EL_TYPE (src)) { case LINESPEC_LOCATION: - if (EL_LINESPEC (src) != NULL) - EL_LINESPEC (dst) = xstrdup (EL_LINESPEC (src)); + EL_LINESPEC (dst)->match_type = EL_LINESPEC (src)->match_type; + if (EL_LINESPEC (src)->spec_string != NULL) + EL_LINESPEC (dst)->spec_string + = xstrdup (EL_LINESPEC (src)->spec_string); break; case ADDRESS_LOCATION: @@ -359,7 +364,7 @@ event_location_deleter::operator() (event_location *location) const switch (EL_TYPE (location)) { case LINESPEC_LOCATION: - xfree (EL_LINESPEC (location)); + xfree (EL_LINESPEC (location)->spec_string); break; case ADDRESS_LOCATION: @@ -394,8 +399,17 @@ event_location_to_string (struct event_location *location) switch (EL_TYPE (location)) { case LINESPEC_LOCATION: - if (EL_LINESPEC (location) != NULL) - EL_STRING (location) = xstrdup (EL_LINESPEC (location)); + if (EL_LINESPEC (location)->spec_string != NULL) + { + linespec_location *ls = EL_LINESPEC (location); + if (ls->match_type == symbol_name_match_type::FULL) + { + EL_STRING (location) + = concat ("-qualified ", ls->spec_string, (char *) NULL); + } + else + EL_STRING (location) = xstrdup (ls->spec_string); + } break; case ADDRESS_LOCATION: @@ -762,12 +776,23 @@ string_to_explicit_location (const char **argp, argument. */ bool have_oarg = false; + /* True if the option needs an argument. */ + bool need_oarg = false; + /* Convenience to consistently set both OARG/HAVE_OARG from ARG. */ auto set_oarg = [&] (gdb::unique_xmalloc_ptr arg) { + if (completion_info != NULL) + { + /* We do this here because the set of options that take + arguments matches the set of explicit location + options. */ + completion_info->saw_explicit_location_option = true; + } oarg = std::move (arg); have_oarg = oarg != NULL; + need_oarg = true; }; if (strncmp (opt.get (), "-source", len) == 0) @@ -781,14 +806,9 @@ string_to_explicit_location (const char **argp, set_oarg (explicit_location_lex_one_function (argp, language, completion_info)); EL_EXPLICIT (location)->function_name = oarg.release (); - EL_EXPLICIT (location)->func_name_match_type - = symbol_name_match_type::WILD; } else if (strncmp (opt.get (), "-qualified", len) == 0) { - set_oarg (explicit_location_lex_one_function (argp, language, - completion_info)); - EL_EXPLICIT (location)->function_name = oarg.release (); EL_EXPLICIT (location)->func_name_match_type = symbol_name_match_type::FULL; } @@ -830,7 +850,7 @@ string_to_explicit_location (const char **argp, case, it provides a much better user experience to issue the "invalid argument" error before any missing argument error. */ - if (!have_oarg && completion_info == NULL) + if (need_oarg && !have_oarg && completion_info == NULL) error (_("missing argument for \"%s\""), opt.get ()); } @@ -853,7 +873,8 @@ string_to_explicit_location (const char **argp, event_location_up string_to_event_location_basic (const char **stringp, - const struct language_defn *language) + const struct language_defn *language, + symbol_name_match_type match_type) { event_location_up location; const char *cs; @@ -881,7 +902,7 @@ string_to_event_location_basic (const char **stringp, else { /* Everything else is a linespec. */ - location = new_linespec_location (stringp); + location = new_linespec_location (stringp, match_type); } } @@ -895,6 +916,7 @@ string_to_event_location (const char **stringp, const struct language_defn *language) { const char *arg, *orig; + symbol_name_match_type match_type = symbol_name_match_type::WILD; /* Try an explicit location. */ orig = arg = *stringp; @@ -904,15 +926,21 @@ string_to_event_location (const char **stringp, /* It was a valid explicit location. Advance STRINGP to the end of input. */ *stringp += arg - orig; - } - else - { - /* Everything else is a "basic" linespec, address, or probe - location. */ - location = string_to_event_location_basic (stringp, language); + + /* If the user really specified a location, then we're done. */ + if (!event_location_empty_p (location.get ())) + return location; + + /* Otherwise, the user _only_ specified optional flags like + "-qualified", otherwise string_to_explicit_location would + have thrown an error. Save the flags for "basic" linespec + parsing below and discard the explicit location. */ + match_type = EL_EXPLICIT (location)->func_name_match_type; } - return location; + /* Everything else is a "basic" linespec, address, or probe + location. */ + return string_to_event_location_basic (stringp, language, match_type); } /* See description in location.h. */ diff --git a/gdb/location.h b/gdb/location.h index 74fd868..fcfa8fb 100644 --- a/gdb/location.h +++ b/gdb/location.h @@ -66,6 +66,17 @@ enum event_location_type PROBE_LOCATION }; +/* A traditional linespec. */ + +struct linespec_location +{ + /* Whether the function name is fully-qualified or not. */ + symbol_name_match_type match_type; + + /* The linespec. */ + char *spec_string; +}; + /* An explicit location. This structure is used to bypass the parsing done on linespecs. It still has the same requirements as linespecs, though. For example, source_filename requires @@ -110,7 +121,7 @@ extern char * /* Return a string representation of the LOCATION. This function may return NULL for unspecified linespecs, - e.g, LOCATION_LINESPEC and addr_string is NULL. + e.g, LINESPEC_LOCATION and spec_string is NULL. The result is cached in LOCATION. */ @@ -130,12 +141,13 @@ typedef std::unique_ptr /* Create a new linespec location. */ -extern event_location_up new_linespec_location (const char **linespec); +extern event_location_up new_linespec_location + (const char **linespec, symbol_name_match_type match_type); -/* Return the linespec location (a string) of the given event_location - (which must be of type LINESPEC_LOCATION). */ +/* Return the linespec location of the given event_location (which + must be of type LINESPEC_LOCATION). */ -extern const char * +extern const linespec_location * get_linespec_location (const struct event_location *location); /* Create a new address location. @@ -214,12 +226,14 @@ extern event_location_up string_to_event_location (const char **argp, const struct language_defn *langauge); -/* Like string_to_event_location, but does not attempt to parse explicit - locations. */ +/* Like string_to_event_location, but does not attempt to parse + explicit locations. MATCH_TYPE indicates how function names should + be matched. */ extern event_location_up string_to_event_location_basic (const char **argp, - const struct language_defn *language); + const struct language_defn *language, + symbol_name_match_type match_type); /* Structure filled in by string_to_explicit_location to aid the completer. */ @@ -236,6 +250,11 @@ struct explicit_completion_info If the last option is not quoted, then both are set to NULL. */ const char *quoted_arg_start = NULL; const char *quoted_arg_end = NULL; + + /* True if we saw an explicit location option, as opposed to only + flags that affect both explicit locations and linespecs, like + "-qualified". */ + bool saw_explicit_location_option = false; }; /* Attempt to convert the input string in *ARGP into an explicit location. diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 833bdc0..6cb1d71 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -337,7 +337,8 @@ mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc) } else { - location = string_to_event_location_basic (&address, current_language); + location = string_to_event_location_basic (&address, current_language, + symbol_name_match_type::WILD); if (*address) error (_("Garbage '%s' at end of location"), address); } diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 86719d1..5bc073e 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -681,7 +681,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) case bp_breakpoint: { event_location_up location - = string_to_event_location_basic (©, current_language); + = string_to_event_location_basic (©, current_language, + symbol_name_match_type::WILD); create_breakpoint (python_gdbarch, location.get (), NULL, -1, NULL, 0, diff --git a/gdb/python/python.c b/gdb/python/python.c index 5f15261..8ca2eed 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -838,7 +838,8 @@ gdbpy_decode_line (PyObject *self, PyObject *args) return NULL; if (arg != NULL) - location = string_to_event_location_basic (&arg, python_language); + location = string_to_event_location_basic (&arg, python_language, + symbol_name_match_type::WILD); std::vector decoded_sals; symtab_and_line def_sal;