/* Parser for linespec for the GNU debugger, GDB.
- Copyright (C) 1986-2018 Free Software Foundation, Inc.
+ Copyright (C) 1986-2019 Free Software Foundation, Inc.
This file is part of GDB.
KEYWORD,
};
-/* Typedef for unique_ptrs of vectors of symtabs. */
-
-typedef std::unique_ptr<std::vector<symtab *>> symtab_vector_up;
-
/* An address entry is used to ensure that any given location is only
added to the result a single time. It holds an address and the
program space from which the address came. */
} result;
/* Possibly add a symbol to the results. */
- bool add_symbol (block_symbol *bsym);
+ virtual bool add_symbol (block_symbol *bsym);
};
bool
return true;
}
+/* Custom collect_info for symbol_searcher. */
+
+struct symbol_searcher_collect_info
+ : collect_info
+{
+ bool add_symbol (block_symbol *bsym) override
+ {
+ /* Add everything. */
+ this->result.symbols->push_back (*bsym);
+
+ /* Continue iterating. */
+ return true;
+ }
+};
+
/* Token types */
enum ls_token_type
/* An instance of the linespec parser. */
-struct ls_parser
+struct linespec_parser
{
+ linespec_parser (int flags, const struct language_defn *language,
+ struct program_space *search_pspace,
+ struct symtab *default_symtab,
+ int default_line,
+ struct linespec_result *canonical);
+
+ ~linespec_parser ();
+
+ DISABLE_COPY_AND_ASSIGN (linespec_parser);
+
/* Lexer internal data */
struct
{
/* The current token. */
linespec_token current;
- } lexer;
+ } lexer {};
/* Is the entire linespec quote-enclosed? */
- int is_quote_enclosed;
+ int is_quote_enclosed = 0;
/* The state of the parse. */
- struct linespec_state state;
+ struct linespec_state state {};
#define PARSER_STATE(PPTR) (&(PPTR)->state)
/* The result of the parse. */
- struct linespec result;
+ struct linespec result {};
#define PARSER_RESULT(PPTR) (&(PPTR)->result)
/* What the parser believes the current word point should complete
to. */
- linespec_complete_what complete_what;
+ linespec_complete_what complete_what = linespec_complete_what::NOTHING;
/* The completion word point. The parser advances this as it skips
tokens. At some point the input string will end or parsing will
fail, and then we attempt completion at the captured completion
word point, interpreting the string at completion_word as
COMPLETE_WHAT. */
- const char *completion_word;
+ const char *completion_word = nullptr;
/* If the current token was a quoted string, then this is the
quoting character (either " or '). */
- int completion_quote_char;
+ int completion_quote_char = 0;
/* If the current token was a quoted string, then this points at the
end of the quoted string. */
- const char *completion_quote_end;
+ const char *completion_quote_end = nullptr;
/* If parsing for completion, then this points at the completion
tracker. Otherwise, this is NULL. */
- struct completion_tracker *completion_tracker;
+ struct completion_tracker *completion_tracker = nullptr;
};
-typedef struct ls_parser linespec_parser;
/* A convenience macro for accessing the explicit location result of
the parser. */
linespec_p ls,
const char *arg);
-static symtab_vector_up symtabs_from_filename
+static std::vector<symtab *> symtabs_from_filename
(const char *, struct program_space *pspace);
static std::vector<block_symbol> *find_label_symbols
(struct collect_info *info, struct program_space *pspace,
const std::vector<const char *> &names, enum search_domain search_domain);
-static symtab_vector_up
+static std::vector<symtab *>
collect_symtabs_from_filename (const char *file,
struct program_space *pspace);
== language_cplus)
&& (PARSER_STREAM (parser) - start) >= CP_OPERATOR_LEN)
{
- const char *p = PARSER_STREAM (parser);
+ const char *op = PARSER_STREAM (parser);
- while (p > start && isspace (p[-1]))
- p--;
- if (p - start >= CP_OPERATOR_LEN)
+ while (op > start && isspace (op[-1]))
+ op--;
+ if (op - start >= CP_OPERATOR_LEN)
{
- p -= CP_OPERATOR_LEN;
- if (strncmp (p, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
- && (p == start
- || !(isalnum (p[-1]) || p[-1] == '_')))
+ op -= CP_OPERATOR_LEN;
+ if (strncmp (op, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
+ && (op == start
+ || !(isalnum (op[-1]) || op[-1] == '_')))
{
/* This is an operator name. Keep going. */
++(PARSER_STREAM (parser));
}
}
- const char *p = find_parameter_list_end (PARSER_STREAM (parser));
- PARSER_STREAM (parser) = p;
+ const char *end = find_parameter_list_end (PARSER_STREAM (parser));
+ PARSER_STREAM (parser) = end;
/* Don't loop around to the normal \0 case above because
we don't want to misinterpret a potential keyword at
the end of the token when the string isn't
"()<>"-balanced. This handles "b
function(thread<tab>" in completion mode. */
- if (*p == '\0')
+ if (*end == '\0')
{
LS_TOKEN_STOKEN (token).ptr = start;
LS_TOKEN_STOKEN (token).length
== language_cplus)
&& (PARSER_STREAM (parser) - start) > CP_OPERATOR_LEN)
{
- const char *p = strstr (start, CP_OPERATOR_STR);
+ const char *op = strstr (start, CP_OPERATOR_STR);
- if (p != NULL && is_operator_name (p))
+ if (op != NULL && is_operator_name (op))
{
/* This is an operator name. Keep going. */
++(PARSER_STREAM (parser));
struct program_space *search_pspace, bool include_inline,
gdb::function_view<symbol_found_callback_ftype> callback)
{
- struct objfile *objfile;
struct program_space *pspace;
ALL_PSPACES (pspace)
set_current_program_space (pspace);
- ALL_OBJFILES (objfile)
- {
- struct compunit_symtab *cu;
-
- if (objfile->sf)
- objfile->sf->qf->expand_symtabs_matching (objfile,
- NULL,
- lookup_name,
- NULL, NULL,
- search_domain);
-
- ALL_OBJFILE_COMPUNITS (objfile, cu)
- {
- struct symtab *symtab = COMPUNIT_FILETABS (cu);
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_matching (objfile,
+ NULL,
+ lookup_name,
+ NULL, NULL,
+ search_domain);
+
+ for (compunit_symtab *cu : objfile->compunits ())
+ {
+ struct symtab *symtab = COMPUNIT_FILETABS (cu);
- iterate_over_file_blocks (symtab, lookup_name, name_domain, callback);
+ iterate_over_file_blocks (symtab, lookup_name, name_domain,
+ callback);
- if (include_inline)
- {
- struct block *block;
- int i;
+ if (include_inline)
+ {
+ const struct block *block;
+ int i;
- for (i = FIRST_LOCAL_BLOCK;
- i < BLOCKVECTOR_NBLOCKS (SYMTAB_BLOCKVECTOR (symtab));
- i++)
- {
- block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
- state->language->la_iterate_over_symbols
- (block, lookup_name, name_domain, [&] (block_symbol *bsym)
- {
- /* Restrict calls to CALLBACK to symbols
- representing inline symbols only. */
- if (SYMBOL_INLINED (bsym->symbol))
- return callback (bsym);
- return true;
- });
- }
- }
- }
- }
+ for (i = FIRST_LOCAL_BLOCK;
+ i < BLOCKVECTOR_NBLOCKS (SYMTAB_BLOCKVECTOR (symtab));
+ i++)
+ {
+ block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
+ state->language->la_iterate_over_symbols
+ (block, lookup_name, name_domain,
+ [&] (block_symbol *bsym)
+ {
+ /* Restrict calls to CALLBACK to symbols
+ representing inline symbols only. */
+ if (SYMBOL_INLINED (bsym->symbol))
+ return callback (bsym);
+ return true;
+ });
+ }
+ }
+ }
+ }
}
}
static const struct block *
get_current_search_block (void)
{
- const struct block *block;
- enum language save_language;
-
/* get_selected_block can change the current language when there is
no selected frame yet. */
- save_language = current_language->la_language;
- block = get_selected_block (0);
- set_language (save_language);
-
- return block;
+ scoped_restore_current_language save_language;
+ return get_selected_block (0);
}
/* Iterate over static and global blocks. */
(struct symtab *symtab, const lookup_name_info &name,
domain_enum domain, gdb::function_view<symbol_found_callback_ftype> callback)
{
- struct block *block;
+ const struct block *block;
for (block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
block != NULL;
--method_counter)
{
const char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
- char dem_opname[64];
-
- if (startswith (method_name, "__") ||
- startswith (method_name, "op") ||
- startswith (method_name, "type"))
- {
- if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
- method_name = dem_opname;
- else if (cplus_demangle_opname (method_name, dem_opname, 0))
- method_name = dem_opname;
- }
if (symbol_name_compare (method_name, lookup_name, NULL))
{
/* A structure that contains two string representations of a struct
linespec_canonical_name:
- - one where the the symtab's fullname is used;
+ - one where the symtab's fullname is used;
- one where the filename followed the "set filename-display"
setting. */
if (ls->file_symtabs->size () == 1
&& ls->file_symtabs->front () == nullptr)
{
- const char *fullname;
-
set_current_program_space (self->program_space);
/* Make sure we have at least a default source line. */
set_default_source_symtab_and_line ();
initialize_defaults (&self->default_symtab, &self->default_line);
- fullname = symtab_to_fullname (self->default_symtab);
- symtab_vector_up r =
- collect_symtabs_from_filename (fullname, self->search_pspace);
- ls->file_symtabs = r.release ();
+ *ls->file_symtabs
+ = collect_symtabs_from_filename (self->default_symtab->filename,
+ self->search_pspace);
use_default = 1;
}
if (source_filename != NULL)
{
- TRY
+ try
{
- result->file_symtabs
- = symtabs_from_filename (source_filename,
- self->search_pspace).release ();
+ *result->file_symtabs
+ = symtabs_from_filename (source_filename, self->search_pspace);
}
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
source_file_not_found_error (source_filename);
}
- END_CATCH
result->explicit_loc.source_filename = xstrdup (source_filename);
}
else
symbol_name_match_type match_type)
{
linespec_token token;
- struct gdb_exception file_exception = exception_none;
+ struct gdb_exception file_exception;
/* A special case to start. It has become quite popular for
IDEs to work around bugs in the previous parser by quoting
gdb::unique_xmalloc_ptr<char> user_filename = copy_token_string (token);
/* Check if the input is a filename. */
- TRY
+ try
{
- symtab_vector_up r
+ *PARSER_RESULT (parser)->file_symtabs
= symtabs_from_filename (user_filename.get (),
PARSER_STATE (parser)->search_pspace);
- PARSER_RESULT (parser)->file_symtabs = r.release ();
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (gdb_exception_error &ex)
{
- file_exception = ex;
+ file_exception = std::move (ex);
}
- END_CATCH
if (file_exception.reason >= 0)
{
/* The linespec didn't parse. Re-throw the file exception if
there was one. */
if (file_exception.reason < 0)
- throw_exception (file_exception);
+ throw_exception (std::move (file_exception));
/* Otherwise, the symbol is not found. */
symbol_not_found_error (PARSER_EXPLICIT (parser)->function_name,
/* Initialize a new linespec parser. */
-static void
-linespec_parser_new (linespec_parser *parser,
- int flags, const struct language_defn *language,
- struct program_space *search_pspace,
- struct symtab *default_symtab,
- int default_line,
- struct linespec_result *canonical)
+linespec_parser::linespec_parser (int flags,
+ const struct language_defn *language,
+ struct program_space *search_pspace,
+ struct symtab *default_symtab,
+ int default_line,
+ struct linespec_result *canonical)
{
- memset (parser, 0, sizeof (linespec_parser));
- parser->lexer.current.type = LSTOKEN_CONSUMED;
- memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
- PARSER_RESULT (parser)->file_symtabs = new std::vector<symtab *> ();
- PARSER_EXPLICIT (parser)->func_name_match_type
+ lexer.current.type = LSTOKEN_CONSUMED;
+ PARSER_RESULT (this)->file_symtabs = new std::vector<symtab *> ();
+ PARSER_EXPLICIT (this)->func_name_match_type
= symbol_name_match_type::WILD;
- PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
- linespec_state_constructor (PARSER_STATE (parser), flags, language,
+ PARSER_EXPLICIT (this)->line_offset.sign = LINE_OFFSET_UNKNOWN;
+ linespec_state_constructor (PARSER_STATE (this), flags, language,
search_pspace,
default_symtab, default_line, canonical);
}
linespec_state_destructor (struct linespec_state *self)
{
htab_delete (self->addr_set);
+ xfree (self->canonical_names);
}
/* Delete a linespec parser. */
-static void
-linespec_parser_delete (void *arg)
+linespec_parser::~linespec_parser ()
{
- linespec_parser *parser = (linespec_parser *) arg;
-
- xfree (PARSER_EXPLICIT (parser)->source_filename);
- xfree (PARSER_EXPLICIT (parser)->label_name);
- xfree (PARSER_EXPLICIT (parser)->function_name);
+ xfree (PARSER_EXPLICIT (this)->source_filename);
+ xfree (PARSER_EXPLICIT (this)->label_name);
+ xfree (PARSER_EXPLICIT (this)->function_name);
- delete PARSER_RESULT (parser)->file_symtabs;
- delete PARSER_RESULT (parser)->function_symbols;
- delete PARSER_RESULT (parser)->minimal_symbols;
- delete PARSER_RESULT (parser)->labels.label_symbols;
- delete PARSER_RESULT (parser)->labels.function_symbols;
+ delete PARSER_RESULT (this)->file_symtabs;
+ delete PARSER_RESULT (this)->function_symbols;
+ delete PARSER_RESULT (this)->minimal_symbols;
+ delete PARSER_RESULT (this)->labels.label_symbols;
+ delete PARSER_RESULT (this)->labels.function_symbols;
- linespec_state_destructor (PARSER_STATE (parser));
+ linespec_state_destructor (PARSER_STATE (this));
}
/* See description in linespec.h. */
void
linespec_lex_to_end (const char **stringp)
{
- linespec_parser parser;
- struct cleanup *cleanup;
linespec_token token;
const char *orig;
if (stringp == NULL || *stringp == NULL)
return;
- linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL);
- cleanup = make_cleanup (linespec_parser_delete, &parser);
+ linespec_parser parser (0, current_language, NULL, NULL, 0, NULL);
parser.lexer.saved_arg = *stringp;
PARSER_STREAM (&parser) = orig = *stringp;
while (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD);
*stringp += PARSER_STREAM (&parser) - orig;
- do_cleanups (cleanup);
}
/* See linespec.h. */
symbol_name_match_type func_name_match_type,
const char *label_name)
{
- linespec_parser parser;
- struct cleanup *cleanup;
-
- linespec_parser_new (&parser, 0, language, NULL, NULL, 0, NULL);
- cleanup = make_cleanup (linespec_parser_delete, &parser);
+ linespec_parser parser (0, language, NULL, NULL, 0, NULL);
line_offset unknown_offset = { 0, LINE_OFFSET_UNKNOWN };
- TRY
+ try
{
convert_explicit_location_to_linespec (PARSER_STATE (&parser),
PARSER_RESULT (&parser),
func_name_match_type,
NULL, unknown_offset);
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &ex)
{
- do_cleanups (cleanup);
return;
}
- END_CATCH
complete_label (tracker, &parser, label_name);
-
- do_cleanups (cleanup);
}
/* See description in linespec.h. */
linespec_complete (completion_tracker &tracker, const char *text,
symbol_name_match_type match_type)
{
- linespec_parser parser;
- struct cleanup *cleanup;
const char *orig = text;
- linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL);
- cleanup = make_cleanup (linespec_parser_delete, &parser);
+ linespec_parser parser (0, current_language, NULL, NULL, 0, NULL);
parser.lexer.saved_arg = text;
PARSER_EXPLICIT (&parser)->func_name_match_type = match_type;
PARSER_STREAM (&parser) = text;
/* Parse as much as possible. parser.completion_word will hold
furthest completion point we managed to parse to. */
- TRY
+ try
{
parse_linespec (&parser, text, match_type);
}
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
}
- END_CATCH
if (parser.completion_quote_char != '\0'
&& parser.completion_quote_end != NULL
NULL);
}
}
-
- do_cleanups (cleanup);
}
/* A helper function for decode_line_full and decode_line_1 to
case LINESPEC_LOCATION:
{
PARSER_STATE (parser)->is_linespec = 1;
- TRY
+ try
{
const linespec_location *ls = get_linespec_location (location);
result = parse_linespec (parser,
ls->spec_string, ls->match_type);
}
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
- throw_exception (except);
+ throw;
}
- END_CATCH
}
break;
const char *select_mode,
const char *filter)
{
- struct cleanup *cleanups;
std::vector<const char *> filters;
- linespec_parser parser;
struct linespec_state *state;
gdb_assert (canonical != NULL);
|| select_mode == multiple_symbols_cancel);
gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
- linespec_parser_new (&parser, flags, current_language,
- search_pspace, default_symtab,
- default_line, canonical);
- cleanups = make_cleanup (linespec_parser_delete, &parser);
+ linespec_parser parser (flags, current_language,
+ search_pspace, default_symtab,
+ default_line, canonical);
scoped_restore_current_program_space restore_pspace;
canonical->pre_expanded = 1;
/* Arrange for allocated canonical names to be freed. */
- if (!result.empty ())
+ std::vector<gdb::unique_xmalloc_ptr<char>> hold_names;
+ for (int i = 0; i < result.size (); ++i)
{
- int i;
-
- make_cleanup (xfree, state->canonical_names);
- for (i = 0; i < result.size (); ++i)
- {
- gdb_assert (state->canonical_names[i].suffix != NULL);
- make_cleanup (xfree, state->canonical_names[i].suffix);
- }
+ gdb_assert (state->canonical_names[i].suffix != NULL);
+ hold_names.emplace_back (state->canonical_names[i].suffix);
}
if (select_mode == NULL)
}
else
decode_line_2 (state, &result, select_mode);
-
- do_cleanups (cleanups);
}
/* See linespec.h. */
struct symtab *default_symtab,
int default_line)
{
- linespec_parser parser;
- struct cleanup *cleanups;
-
- linespec_parser_new (&parser, flags, current_language,
- search_pspace, default_symtab,
- default_line, NULL);
- cleanups = make_cleanup (linespec_parser_delete, &parser);
+ linespec_parser parser (flags, current_language,
+ search_pspace, default_symtab,
+ default_line, NULL);
scoped_restore_current_program_space restore_pspace;
- std::vector<symtab_and_line> result = event_location_to_sals (&parser,
- location);
-
- do_cleanups (cleanups);
- return result;
+ return event_location_to_sals (&parser, location);
}
/* See linespec.h. */
{
public:
symtab_collector ()
- : m_symtabs (new std::vector<symtab *> ())
{
m_symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
NULL);
/* Callable as a symbol_found_callback_ftype callback. */
bool operator () (symtab *sym);
- /* Releases ownership of the collected symtabs and returns them. */
- symtab_vector_up release_symtabs ()
+ /* Return an rvalue reference to the collected symtabs. */
+ std::vector<symtab *> &&release_symtabs ()
{
return std::move (m_symtabs);
}
private:
/* The result vector of symtabs. */
- symtab_vector_up m_symtabs;
+ std::vector<symtab *> m_symtabs;
/* This is used to ensure the symtabs are unique. */
htab_t m_symtab_table;
if (!*slot)
{
*slot = symtab;
- m_symtabs->push_back (symtab);
+ m_symtabs.push_back (symtab);
}
return false;
SEARCH_PSPACE is not NULL, the search is restricted to just that
program space. */
-static symtab_vector_up
+static std::vector<symtab *>
collect_symtabs_from_filename (const char *file,
struct program_space *search_pspace)
{
/* Return all the symtabs associated to the FILENAME. If SEARCH_PSPACE is
not NULL, the search is restricted to just that program space. */
-static symtab_vector_up
+static std::vector<symtab *>
symtabs_from_filename (const char *filename,
struct program_space *search_pspace)
{
- symtab_vector_up result
+ std::vector<symtab *> result
= collect_symtabs_from_filename (filename, search_pspace);
- if (result->empty ())
+ if (result.empty ())
{
if (!have_full_symbols () && !have_partial_symbols ())
throw_error (NOT_FOUND_ERROR,
return result;
}
+/* See symtab.h. */
+
+void
+symbol_searcher::find_all_symbols (const std::string &name,
+ const struct language_defn *language,
+ enum search_domain search_domain,
+ std::vector<symtab *> *search_symtabs,
+ struct program_space *search_pspace)
+{
+ symbol_searcher_collect_info info;
+ struct linespec_state state;
+
+ memset (&state, 0, sizeof (state));
+ state.language = language;
+ info.state = &state;
+
+ info.result.symbols = &m_symbols;
+ info.result.minimal_symbols = &m_minimal_symbols;
+ std::vector<symtab *> all_symtabs;
+ if (search_symtabs == nullptr)
+ {
+ all_symtabs.push_back (nullptr);
+ search_symtabs = &all_symtabs;
+ }
+ info.file_symtabs = search_symtabs;
+
+ add_matching_symbols_to_info (name.c_str (), symbol_name_match_type::WILD,
+ search_domain, &info, search_pspace);
+}
+
/* Look up a function symbol named NAME in symtabs FILE_SYMTABS. Matching
debug symbols are returned in SYMBOLS. Matching minimal symbols are
returned in MINSYMS. */
if (!classes.empty ())
{
/* Now locate a list of suitable methods named METHOD. */
- TRY
+ try
{
find_method (state, file_symtabs,
klass.c_str (), method.c_str (),
/* If successful, we're done. If NOT_FOUND_ERROR
was not thrown, rethrow the exception that we did get. */
- CATCH (except, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &except)
{
if (except.error != NOT_FOUND_ERROR)
- throw_exception (except);
+ throw;
}
- END_CATCH
}
}
}
ALL_PSPACES (pspace)
{
- struct objfile *objfile;
-
if (search_pspace != NULL && search_pspace != pspace)
continue;
if (pspace->executing_startup)
set_current_program_space (pspace);
- ALL_OBJFILES (objfile)
- {
- iterate_over_minimal_symbols (objfile, name,
- [&] (struct minimal_symbol *msym)
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ iterate_over_minimal_symbols (objfile, name,
+ [&] (struct minimal_symbol *msym)
{
add_minsym (msym, objfile, nullptr,
info->state->list_mode,
&minsyms);
return false;
});
- }
+ }
}
}
else