/* Parse expressions for GDB.
- Copyright (C) 1986-2021 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo, 1991.
show_expressiondebug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("Expression debugging is %s.\n"), value);
+ gdb_printf (file, _("Expression debugging is %s.\n"), value);
}
show_parserdebug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file, _("Parser debugging is %s.\n"), value);
+ gdb_printf (file, _("Parser debugging is %s.\n"), value);
}
-static expression_up parse_exp_in_context (const char **, CORE_ADDR,
- const struct block *, int,
- bool, innermost_block_tracker *,
- expr_completion_state *);
+static expression_up parse_exp_in_context
+ (const char **, CORE_ADDR,
+ const struct block *, int,
+ bool, innermost_block_tracker *,
+ std::unique_ptr<expr_completion_base> *);
/* Documented at it's declaration. */
{
bound_minimal_symbol bound_msym = {msymbol, objfile};
struct obj_section *section = msymbol->obj_section (objfile);
- enum minimal_symbol_type type = MSYMBOL_TYPE (msymbol);
+ enum minimal_symbol_type type = msymbol->type ();
bool is_tls = (section != NULL
&& section->the_bfd_section->flags & SEC_THREAD_LOCAL);
{
/* Addresses of TLS symbols are really offsets into a
per-objfile/per-thread storage block. */
- addr = MSYMBOL_VALUE_RAW_ADDRESS (bound_msym.minsym);
+ addr = bound_msym.minsym->value_raw_address ();
}
else if (msymbol_is_function (objfile, msymbol, &addr))
{
- if (addr != BMSYMBOL_VALUE_ADDRESS (bound_msym))
+ if (addr != bound_msym.value_address ())
{
/* This means we resolved a function descriptor, and we now
have an address for a code/text symbol instead of a data
symbol. */
- if (MSYMBOL_TYPE (msymbol) == mst_data_gnu_ifunc)
+ if (msymbol->type () == mst_data_gnu_ifunc)
type = mst_text_gnu_ifunc;
else
type = mst_text;
}
}
else
- addr = BMSYMBOL_VALUE_ADDRESS (bound_msym);
+ addr = bound_msym.value_address ();
if (overlay_debugging)
addr = symbol_overlayed_address (addr, section);
}
}
+bool
+expr_complete_tag::complete (struct expression *exp,
+ completion_tracker &tracker)
+{
+ collect_symbol_completion_matches_type (tracker, m_name.get (),
+ m_name.get (), m_code);
+ return true;
+}
+
/* See parser-defs.h. */
void
parser_state::mark_struct_expression (expr::structop_base_operation *op)
{
- gdb_assert (parse_completion
- && (m_completion_state.expout_tag_completion_type
- == TYPE_CODE_UNDEF));
- m_completion_state.expout_last_op = op;
+ gdb_assert (parse_completion && m_completion_state == nullptr);
+ m_completion_state.reset (new expr_complete_structop (op));
}
/* Indicate that the current parser invocation is completing a tag.
parser_state::mark_completion_tag (enum type_code tag, const char *ptr,
int length)
{
- gdb_assert (parse_completion
- && (m_completion_state.expout_tag_completion_type
- == TYPE_CODE_UNDEF)
- && m_completion_state.expout_completion_name == NULL
- && m_completion_state.expout_last_op == nullptr);
+ gdb_assert (parse_completion && m_completion_state == nullptr);
gdb_assert (tag == TYPE_CODE_UNION
|| tag == TYPE_CODE_STRUCT
|| tag == TYPE_CODE_ENUM);
- m_completion_state.expout_tag_completion_type = tag;
- m_completion_state.expout_completion_name.reset (xstrndup (ptr, length));
+ m_completion_state.reset
+ (new expr_complete_tag (tag, make_unique_xstrndup (ptr, length)));
}
/* See parser-defs.h. */
{
if (symbol_read_needs_frame (sym.symbol))
block_tracker->update (sym);
- push_new<expr::var_value_operation> (sym.symbol, sym.block);
+ push_new<expr::var_value_operation> (sym);
}
else
{
struct bound_minimal_symbol msymbol = lookup_bound_minimal_symbol (name);
if (msymbol.minsym != NULL)
- push_new<expr::var_msym_value_operation> (msymbol.minsym,
- msymbol.objfile);
+ push_new<expr::var_msym_value_operation> (msymbol);
else if (!have_full_symbols () && !have_partial_symbols ())
error (_("No symbol table is loaded. Use the \"file\" command."));
else
sym = lookup_symbol (copy.c_str (), NULL, VAR_DOMAIN, NULL);
if (sym.symbol)
{
- push_new<expr::var_value_operation> (sym.symbol, sym.block);
+ push_new<expr::var_value_operation> (sym);
return;
}
msym = lookup_bound_minimal_symbol (copy.c_str ());
if (msym.minsym)
{
- push_new<expr::var_msym_value_operation> (msym.minsym, msym.objfile);
+ push_new<expr::var_msym_value_operation> (msym);
return;
}
const struct block *block,
int comma, bool void_context_p,
innermost_block_tracker *tracker,
- expr_completion_state *cstate)
+ std::unique_ptr<expr_completion_base> *completer)
{
const struct language_defn *lang = NULL;
if (!expression_context_block)
expression_context_block = get_selected_block (&expression_context_pc);
else if (pc == 0)
- expression_context_pc = BLOCK_ENTRY_PC (expression_context_block);
+ expression_context_pc = expression_context_block->entry_pc ();
else
expression_context_pc = pc;
if (!expression_context_block)
{
struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
if (cursal.symtab)
expression_context_block
- = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (cursal.symtab),
- STATIC_BLOCK);
+ = cursal.symtab->compunit ()->blockvector ()->static_block ();
+
if (expression_context_block)
- expression_context_pc = BLOCK_ENTRY_PC (expression_context_block);
+ expression_context_pc = expression_context_block->entry_pc ();
}
if (language_mode == language_mode_auto && block != NULL)
parser_state ps (lang, get_current_arch (), expression_context_block,
expression_context_pc, comma, *stringptr,
- cstate != nullptr, tracker, void_context_p);
+ completer != nullptr, tracker, void_context_p);
scoped_restore_current_language lang_saver;
set_language (lang->la_language);
if (expressiondebug)
dump_prefix_expression (result.get (), gdb_stdlog);
- if (cstate != nullptr)
- *cstate = std::move (ps.m_completion_state);
+ if (completer != nullptr)
+ *completer = std::move (ps.m_completion_state);
*stringptr = ps.lexptr;
return result;
}
return parse_expression (string);
}
-/* Parse STRING as an expression. If parsing ends in the middle of a
- field reference, return the type of the left-hand-side of the
- reference; furthermore, if the parsing ends in the field name,
- return the field name in *NAME. If the parsing ends in the middle
- of a field reference, but the reference is somehow invalid, throw
- an exception. In all other cases, return NULL. */
-
-struct type *
-parse_expression_for_completion (const char *string,
- gdb::unique_xmalloc_ptr<char> *name,
- enum type_code *code)
+/* Parse STRING as an expression. If the parse is marked for
+ completion, set COMPLETER and return the expression. In all other
+ cases, return NULL. */
+
+expression_up
+parse_expression_for_completion
+ (const char *string,
+ std::unique_ptr<expr_completion_base> *completer)
{
expression_up exp;
- expr_completion_state cstate;
try
{
- exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, &cstate);
+ exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, completer);
}
catch (const gdb_exception_error &except)
{
/* Nothing, EXP remains NULL. */
}
- if (exp == NULL)
- return NULL;
-
- if (cstate.expout_tag_completion_type != TYPE_CODE_UNDEF)
- {
- *code = cstate.expout_tag_completion_type;
- *name = std::move (cstate.expout_completion_name);
- return NULL;
- }
-
- if (cstate.expout_last_op == nullptr)
+ /* If we didn't get a completion result, be sure to also not return
+ an expression to our caller. */
+ if (*completer == nullptr)
return nullptr;
- expr::structop_base_operation *op = cstate.expout_last_op;
- const std::string &fld = op->get_string ();
- *name = make_unique_xstrdup (fld.c_str ());
- return value_type (op->evaluate_lhs (exp.get ()));
+ return exp;
}
/* Parse floating point value P of length LEN.
va_start (args, y);
if (x == stderr)
- vfprintf_unfiltered (gdb_stderr, y, args);
+ gdb_vprintf (gdb_stderr, y, args);
else
{
- fprintf_unfiltered (gdb_stderr, " Unknown FILE used.\n");
- vfprintf_unfiltered (gdb_stderr, y, args);
+ gdb_printf (gdb_stderr, " Unknown FILE used.\n");
+ gdb_vprintf (gdb_stderr, y, args);
}
va_end (args);
}
-/* Return 1 if EXP uses OBJFILE (and will become dangling when OBJFILE
- is unloaded), otherwise return 0. OBJFILE must not be a separate debug info
- file. */
+/* Return rue if EXP uses OBJFILE (and will become dangling when
+ OBJFILE is unloaded), otherwise return false. OBJFILE must not be
+ a separate debug info file. */
-int
+bool
exp_uses_objfile (struct expression *exp, struct objfile *objfile)
{
gdb_assert (objfile->separate_debug_objfile_backlink == NULL);