#include "language.h"
#include "parser-defs.h"
#include "gdbcmd.h"
-#include "symfile.h" /* for overlay functions */
+#include "symfile.h"
#include "inferior.h"
#include "target-float.h"
#include "block.h"
#include "objfiles.h"
#include "user-regs.h"
#include <algorithm>
-#include "gdbsupport/gdb_optional.h"
+#include <optional>
#include "c-exp.h"
static unsigned int expressiondebug = 0;
/* True if an expression parser should set yydebug. */
-bool parser_debug;
+static bool parser_debug;
static void
show_parserdebug (struct ui_file *file, int from_tty,
}
-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. */
void
{
if ((m_types & t) != 0
&& (m_innermost_block == NULL
- || contained_in (b, m_innermost_block)))
+ || m_innermost_block->contains (b)))
m_innermost_block = b;
}
\f
-/* Return the type of MSYMBOL, a minimal symbol of OBJFILE. If
- ADDRESS_P is not NULL, set it to the MSYMBOL's resolved
- address. */
-
-type *
-find_minsym_type_and_address (minimal_symbol *msymbol,
- struct objfile *objfile,
- CORE_ADDR *address_p)
-{
- bound_minimal_symbol bound_msym = {msymbol, objfile};
- struct obj_section *section = msymbol->obj_section (objfile);
- enum minimal_symbol_type type = msymbol->type ();
-
- bool is_tls = (section != NULL
- && section->the_bfd_section->flags & SEC_THREAD_LOCAL);
-
- /* The minimal symbol might point to a function descriptor;
- resolve it to the actual code address instead. */
- CORE_ADDR addr;
- if (is_tls)
- {
- /* Addresses of TLS symbols are really offsets into a
- per-objfile/per-thread storage block. */
- addr = bound_msym.minsym->value_raw_address ();
- }
- else if (msymbol_is_function (objfile, msymbol, &addr))
- {
- 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 () == mst_data_gnu_ifunc)
- type = mst_text_gnu_ifunc;
- else
- type = mst_text;
- section = NULL;
- }
- }
- else
- addr = bound_msym.value_address ();
-
- if (overlay_debugging)
- addr = symbol_overlayed_address (addr, section);
-
- if (is_tls)
- {
- /* Skip translation if caller does not need the address. */
- if (address_p != NULL)
- *address_p = target_translate_tls_address (objfile, addr);
- return objfile_type (objfile)->nodebug_tls_symbol;
- }
-
- if (address_p != NULL)
- *address_p = addr;
-
- switch (type)
- {
- case mst_text:
- case mst_file_text:
- case mst_solib_trampoline:
- return objfile_type (objfile)->nodebug_text_symbol;
-
- case mst_text_gnu_ifunc:
- return objfile_type (objfile)->nodebug_text_gnu_ifunc_symbol;
-
- case mst_data:
- case mst_file_data:
- case mst_bss:
- case mst_file_bss:
- return objfile_type (objfile)->nodebug_data_symbol;
-
- case mst_slot_got_plt:
- return objfile_type (objfile)->nodebug_got_plt_symbol;
-
- default:
- return objfile_type (objfile)->nodebug_unknown_symbol;
- }
-}
-
bool
expr_complete_tag::complete (struct expression *exp,
completion_tracker &tracker)
{
/* Just dollars (one or two). */
i = -negate;
- goto handle_last;
+ push_new<expr::last_operation> (i);
+ return;
}
/* Is the rest of the token digits? */
for (; i < str.length; i++)
i = atoi (str.ptr + 1 + negate);
if (negate)
i = -i;
- goto handle_last;
+ push_new<expr::last_operation> (i);
+ return;
}
/* Handle tokens that refer to machine registers:
i = user_reg_map_name_to_regnum (gdbarch (),
str.ptr + 1, str.length - 1);
if (i >= 0)
- goto handle_register;
+ {
+ str.length--;
+ str.ptr++;
+ push_new<expr::register_operation> (copy_name (str));
+ block_tracker->update (expression_context_block,
+ INNERMOST_BLOCK_FOR_REGISTERS);
+ return;
+ }
/* Any names starting with $ are probably debugger internal variables. */
push_new<expr::internalvar_operation>
(create_internalvar (copy.c_str () + 1));
- return;
-handle_last:
- push_new<expr::last_operation> (i);
- return;
-handle_register:
- str.length--;
- str.ptr++;
- push_new<expr::register_operation> (copy_name (str));
- block_tracker->update (expression_context_block,
- INNERMOST_BLOCK_FOR_REGISTERS);
- return;
}
\f
}
\f
-/* Read an expression from the string *STRINGPTR points to,
- parse it, and return a pointer to a struct expression that we malloc.
- Use block BLOCK as the lexical context for variable names;
- if BLOCK is zero, use the block of the selected stack frame.
- Meanwhile, advance *STRINGPTR to point after the expression,
- at the first nonwhite character that is not part of the expression
- (possibly a null character).
-
- If COMMA is nonzero, stop if a comma is reached. */
-
-expression_up
-parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
- int comma, innermost_block_tracker *tracker)
-{
- return parse_exp_in_context (stringptr, pc, block, comma, false,
- tracker, nullptr);
-}
-
/* As for parse_exp_1, except that if VOID_CONTEXT_P, then
no value is expected from the expression. */
static expression_up
parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
const struct block *block,
- int comma, bool void_context_p,
+ parser_flags flags,
innermost_block_tracker *tracker,
std::unique_ptr<expr_completion_base> *completer)
{
if (tracker == nullptr)
tracker = &local_tracker;
- /* If no context specified, try using the current frame, if any. */
- if (!expression_context_block)
- expression_context_block = get_selected_block (&expression_context_pc);
- else if (pc == 0)
- expression_context_pc = expression_context_block->entry_pc ();
- else
- expression_context_pc = pc;
+ if ((flags & PARSER_LEAVE_BLOCK_ALONE) == 0)
+ {
+ /* If no context specified, try using the current frame, if any. */
+ if (!expression_context_block)
+ expression_context_block
+ = get_selected_block (&expression_context_pc);
+ else if (pc == 0)
+ expression_context_pc = expression_context_block->entry_pc ();
+ else
+ expression_context_pc = pc;
- /* Fall back to using the current source static context, if any. */
+ /* Fall back to using the current source static context, if any. */
- if (!expression_context_block)
- {
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+ if (!expression_context_block)
+ {
+ struct symtab_and_line cursal
+ = get_current_source_symtab_and_line ();
- if (cursal.symtab)
- expression_context_block
- = cursal.symtab->compunit ()->blockvector ()->static_block ();
+ if (cursal.symtab)
+ expression_context_block
+ = cursal.symtab->compunit ()->blockvector ()->static_block ();
- if (expression_context_block)
- expression_context_pc = expression_context_block->entry_pc ();
+ if (expression_context_block)
+ expression_context_pc = expression_context_block->entry_pc ();
+ }
}
if (language_mode == language_mode_auto && block != NULL)
the current frame language to parse the expression. That's why
we do the following language detection only if the context block
has been specifically provided. */
- struct symbol *func = block_linkage_function (block);
+ struct symbol *func = block->linkage_function ();
if (func != NULL)
lang = language_def (func->language ());
to the value matching SELECTED_FRAME as set by get_current_arch. */
parser_state ps (lang, get_current_arch (), expression_context_block,
- expression_context_pc, comma, *stringptr,
- completer != nullptr, tracker, void_context_p);
+ expression_context_pc, flags, *stringptr,
+ completer != nullptr, tracker);
scoped_restore_current_language lang_saver;
set_language (lang->la_language);
{
lang->parser (&ps);
}
- catch (const gdb_exception &except)
+ catch (const gdb_exception_error &except)
{
/* If parsing for completion, allow this to succeed; but if no
expression elements have been written, then there's nothing
return result;
}
+/* Read an expression from the string *STRINGPTR points to,
+ parse it, and return a pointer to a struct expression that we malloc.
+ Use block BLOCK as the lexical context for variable names;
+ if BLOCK is zero, use the block of the selected stack frame.
+ Meanwhile, advance *STRINGPTR to point after the expression,
+ at the first nonwhite character that is not part of the expression
+ (possibly a null character). FLAGS are passed to the parser. */
+
+expression_up
+parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block,
+ parser_flags flags, innermost_block_tracker *tracker)
+{
+ return parse_exp_in_context (stringptr, pc, block, flags,
+ tracker, nullptr);
+}
+
/* Parse STRING as an expression, and complain if this fails to use up
all of the contents of STRING. TRACKER, if non-null, will be
- updated by the parser. VOID_CONTEXT_P should be true to indicate
- that the expression may be expected to return a value with void
- type. Parsers are free to ignore this, or to use it to help with
- overload resolution decisions. */
+ updated by the parser. FLAGS are passed to the parser. */
expression_up
parse_expression (const char *string, innermost_block_tracker *tracker,
- bool void_context_p)
+ parser_flags flags)
{
- expression_up exp = parse_exp_in_context (&string, 0, nullptr, 0,
- void_context_p,
+ expression_up exp = parse_exp_in_context (&string, 0, nullptr, flags,
tracker, nullptr);
if (*string)
error (_("Junk after end of expression."));
expression_up
parse_expression_with_language (const char *string, enum language lang)
{
- gdb::optional<scoped_restore_current_language> lang_saver;
+ std::optional<scoped_restore_current_language> lang_saver;
if (current_language->la_language != lang)
{
lang_saver.emplace ();
try
{
- exp = parse_exp_in_context (&string, 0, 0, 0, false, nullptr, completer);
+ exp = parse_exp_in_context (&string, 0, 0, 0, nullptr, completer);
}
catch (const gdb_exception_error &except)
{
else
gdb_assert_not_reached ("");
}
+
+/* Return true if the number N_SIGN * N fits in a type with TYPE_BITS and
+ TYPE_SIGNED_P. N_SIGNED is either 1 or -1. */
+
+bool
+fits_in_type (int n_sign, const gdb_mpz &n, int type_bits, bool type_signed_p)
+{
+ /* N must be nonnegative. */
+ gdb_assert (n.sgn () >= 0);
+
+ /* Zero always fits. */
+ /* Normalize -0. */
+ if (n.sgn () == 0)
+ return true;
+
+ if (n_sign == -1 && !type_signed_p)
+ /* Can't fit a negative number in an unsigned type. */
+ return false;
+
+ gdb_mpz max = gdb_mpz::pow (2, (type_signed_p
+ ? type_bits - 1
+ : type_bits));
+ if (n_sign == -1)
+ return n <= max;
+ return n < max;
+}
\f
/* This function avoids direct calls to fprintf
in the parser generated debug code. */
va_end (args);
}
-/* 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. */
-
-bool
-exp_uses_objfile (struct expression *exp, struct objfile *objfile)
-{
- gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
-
- return exp->op->uses_objfile (objfile);
-}
-
void _initialize_parse ();
void
_initialize_parse ()