]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/parse.c
sim: bfin: initial bf60x support
[thirdparty/binutils-gdb.git] / gdb / parse.c
index a76a6c1afdbc2730f4bfbda05e08b76449217caf..b57d112fafd9515ff9d2ea09af6e0be7ccdd2d74 100644 (file)
@@ -1,6 +1,6 @@
 /* Parse expressions for GDB.
 
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
    Modified from expread.y by the Department of Computer Science at the
    State University of New York at Buffalo, 1991.
@@ -41,7 +41,7 @@
 #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"
@@ -49,7 +49,7 @@
 #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;
@@ -57,26 +57,21 @@ static void
 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);
 }
 
 
 /* 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,
                  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 *);
-
 /* Documented at it's declaration.  */
 
 void
@@ -85,90 +80,19 @@ innermost_block_tracker::update (const struct block *b,
 {
   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)
+bool
+expr_complete_tag::complete (struct expression *exp,
+                            completion_tracker &tracker)
 {
-  bound_minimal_symbol bound_msym = {msymbol, objfile};
-  struct obj_section *section = msymbol->obj_section (objfile);
-  enum minimal_symbol_type type = MSYMBOL_TYPE (msymbol);
-
-  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 = MSYMBOL_VALUE_RAW_ADDRESS (bound_msym.minsym);
-    }
-  else if (msymbol_is_function (objfile, msymbol, &addr))
-    {
-      if (addr != BMSYMBOL_VALUE_ADDRESS (bound_msym))
-       {
-         /* 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)
-           type = mst_text_gnu_ifunc;
-         else
-           type = mst_text;
-         section = NULL;
-       }
-    }
-  else
-    addr = BMSYMBOL_VALUE_ADDRESS (bound_msym);
-
-  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;
-    }
+  collect_symbol_completion_matches_type (tracker, m_name.get (),
+                                         m_name.get (), m_code);
+  return true;
 }
 
 /* See parser-defs.h.  */
@@ -176,10 +100,8 @@ find_minsym_type_and_address (minimal_symbol *msymbol,
 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.
@@ -190,17 +112,12 @@ void
 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
-    = make_unique_xstrndup (ptr, length);
+  m_completion_state.reset
+    (new expr_complete_tag (tag, make_unique_xstrndup (ptr, length)));
 }
 
 /* See parser-defs.h.  */
@@ -265,7 +182,8 @@ parser_state::push_dollar (struct stoken str)
     {
       /* 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++)
@@ -276,7 +194,8 @@ parser_state::push_dollar (struct stoken str)
       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:
@@ -284,7 +203,14 @@ parser_state::push_dollar (struct stoken str)
   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.  */
 
@@ -316,17 +242,6 @@ parser_state::push_dollar (struct stoken str)
 
   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
@@ -407,33 +322,15 @@ copy_name (struct stoken token)
 }
 \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,
-                     expr_completion_state *cstate)
+                     std::unique_ptr<expr_completion_base> *completer)
 {
   const struct language_defn *lang = NULL;
 
@@ -447,25 +344,31 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
   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 = BLOCK_ENTRY_PC (expression_context_block);
-  else
-    expression_context_pc = pc;
-
-  /* Fall back to using the current source static context, if any.  */
-
-  if (!expression_context_block)
+  if ((flags & PARSER_LEAVE_BLOCK_ALONE) == 0)
     {
-      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
-      if (cursal.symtab)
+      /* If no context specified, try using the current frame, if any.  */
+      if (!expression_context_block)
        expression_context_block
-         = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (cursal.symtab),
-                              STATIC_BLOCK);
-      if (expression_context_block)
-       expression_context_pc = BLOCK_ENTRY_PC (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.  */
+
+      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 (expression_context_block)
+           expression_context_pc = expression_context_block->entry_pc ();
+       }
     }
 
   if (language_mode == language_mode_auto && block != NULL)
@@ -484,7 +387,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
         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 ());
@@ -500,8 +403,8 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
      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,
-                  cstate != nullptr, tracker, void_context_p);
+                  expression_context_pc, flags, *stringptr,
+                  completer != nullptr, tracker);
 
   scoped_restore_current_language lang_saver;
   set_language (lang->la_language);
@@ -510,7 +413,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
     {
       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
@@ -523,27 +426,39 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc,
   result->op->set_outermost ();
 
   if (expressiondebug)
-    dump_prefix_expression (result.get (), gdb_stdlog);
+    result->dump (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;
 }
 
+/* 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."));
@@ -556,7 +471,7 @@ parse_expression (const char *string, innermost_block_tracker *tracker,
 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 ();
@@ -566,47 +481,32 @@ parse_expression_with_language (const char *string, enum language lang)
   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, 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.
@@ -622,6 +522,69 @@ parse_float (const char *p, int len,
 {
   return target_float_from_string (data, type, std::string (p, len));
 }
+
+/* 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, ULONGEST n, int type_bits, bool type_signed_p)
+{
+  /* Normalize -0.  */
+  if (n == 0 && n_sign == -1)
+    n_sign = 1;
+
+  if (n_sign == -1 && !type_signed_p)
+    /* Can't fit a negative number in an unsigned type.  */
+    return false;
+
+  if (type_bits > sizeof (ULONGEST) * 8)
+    return true;
+
+  ULONGEST smax = (ULONGEST)1 << (type_bits - 1);
+  if (n_sign == -1)
+    {
+      /* Negative number, signed type.  */
+      return (n <= smax);
+    }
+  else if (n_sign == 1 && type_signed_p)
+    {
+      /* Positive number, signed type.  */
+      return (n < smax);
+    }
+  else if (n_sign == 1 && !type_signed_p)
+    {
+      /* Positive number, unsigned type.  */
+      return ((n >> 1) >> (type_bits - 1)) == 0;
+    }
+  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.  */
@@ -632,27 +595,15 @@ parser_fprintf (FILE *x, const char *y, ...)
 
   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 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 ()