This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 32/40] Make "break foo" find "A::foo", A::B::foo", etc. [C++ and wild matching]


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 <palves@redhat.com>
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<symtab_and_line> 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 (&copy,
-							   current_language);
+  event_location_up eloc
+    = string_to_event_location_basic (&copy,
+				      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<symtab_and_line>
-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<char> 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<event_location, event_location_deleter>
 
 /* 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 (&copy, current_language);
+	      = string_to_event_location_basic (&copy, 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<symtab_and_line> decoded_sals;
   symtab_and_line def_sal;
-- 
2.5.5



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]