/* Parse expressions for GDB.
Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009
+ 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Modified from expread.y by the Department of Computer Science at the
during the process of parsing; the lower levels of the tree always
come first in the result. */
-#include <ctype.h>
-
#include "defs.h"
+#include <ctype.h>
+#include "arch-utils.h"
#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
{
print_subexp_standard,
operator_length_standard,
+ operator_check_standard,
op_name_standard,
dump_subexp_body_standard,
evaluate_subexp_standard
fprintf_filtered (file, _("Expression debugging is %s.\n"), value);
}
+
+/* Non-zero if an expression parser should set yydebug. */
+int 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);
+}
+
+
static void free_funcalls (void *ignore);
static int prefixify_expression (struct expression *);
{
int val = arglist_len;
struct funcall *call = funcall_chain;
+
funcall_chain = call->next;
arglist_len = call->arglist_len;
xfree (call);
write_exp_elt_opcode (enum exp_opcode expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.opcode = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_sym (struct symbol *expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.symbol = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_block (struct block *b)
{
union exp_element tmp;
+
memset (&tmp, 0, sizeof (union exp_element));
tmp.block = b;
write_exp_elt (tmp);
write_exp_elt_objfile (struct objfile *objfile)
{
union exp_element tmp;
+
memset (&tmp, 0, sizeof (union exp_element));
tmp.objfile = objfile;
write_exp_elt (tmp);
write_exp_elt_longcst (LONGEST expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.longconst = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_dblcst (DOUBLEST expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.doubleconst = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_type (struct type *expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.type = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_intern (struct internalvar *expelt)
{
union exp_element tmp;
- memset (&tmp, 0, sizeof (union exp_element));
+ memset (&tmp, 0, sizeof (union exp_element));
tmp.internalvar = expelt;
-
write_exp_elt (tmp);
}
write_exp_elt_opcode (OP_LONG);
/* Let's make the type big enough to hold a 64-bit address. */
- write_exp_elt_type (builtin_type (gdbarch)->builtin_core_addr);
+ write_exp_elt_type (objfile_type (objfile)->builtin_core_addr);
write_exp_elt_longcst ((LONGEST) addr);
write_exp_elt_opcode (OP_LONG);
{
write_exp_elt_opcode (UNOP_MEMVAL_TLS);
write_exp_elt_objfile (objfile);
- write_exp_elt_type (builtin_type (gdbarch)->nodebug_tls_symbol);
+ write_exp_elt_type (objfile_type (objfile)->nodebug_tls_symbol);
write_exp_elt_opcode (UNOP_MEMVAL_TLS);
return;
}
case mst_text:
case mst_file_text:
case mst_solib_trampoline:
- write_exp_elt_type (builtin_type (gdbarch)->nodebug_text_symbol);
+ write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol);
break;
case mst_data:
case mst_file_data:
case mst_bss:
case mst_file_bss:
- write_exp_elt_type (builtin_type (gdbarch)->nodebug_data_symbol);
+ write_exp_elt_type (objfile_type (objfile)->nodebug_data_symbol);
break;
default:
- write_exp_elt_type (builtin_type (gdbarch)->nodebug_unknown_symbol);
+ write_exp_elt_type (objfile_type (objfile)->nodebug_unknown_symbol);
break;
}
write_exp_elt_opcode (UNOP_MEMVAL);
int
length_of_subexp (struct expression *expr, int endpos)
{
- int oplen, args, i;
+ int oplen, args;
operator_length (expr, endpos, &oplen, &args);
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
break;
+ case TYPE_INSTANCE:
+ oplen = 4 + longest_to_int (expr->elts[endpos - 2].longconst);
+ args = 1;
+ break;
+
case OP_OBJC_MSGCALL: /* Objective C message (method) call */
oplen = 4;
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
case BINOP_VAL:
case UNOP_CAST:
+ case UNOP_DYNAMIC_CAST:
+ case UNOP_REINTERPRET_CAST:
case UNOP_MEMVAL:
oplen = 3;
args = 1;
args = 1;
break;
+ case OP_ADL_FUNC:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ oplen++;
+ oplen++;
+ break;
+
case OP_LABELED:
case STRUCTOP_STRUCT:
case STRUCTOP_PTR:
int args;
int i;
int *arglens;
- enum exp_opcode opcode;
int result = -1;
operator_length (inexpr, inend, &oplen, &args);
for (i = 0; i < args; i++)
{
int r;
+
oplen = arglens[i];
inend += oplen;
r = prefixify_subexp (inexpr, outexpr, inend, outbeg);
{
volatile struct gdb_exception except;
struct cleanup *old_chain;
+ const struct language_defn *lang = NULL;
int subexp;
lexptr = *stringptr;
expression_context_pc = BLOCK_START (expression_context_block);
}
+ if (language_mode == language_mode_auto && block != NULL)
+ {
+ /* Find the language associated to the given context block.
+ Default to the current language if it can not be determined.
+
+ Note that using the language corresponding to the current frame
+ can sometimes give unexpected results. For instance, this
+ routine is often called several times during the inferior
+ startup phase to re-parse breakpoint expressions after
+ a new shared library has been loaded. The language associated
+ to the current frame at this moment is not relevant for
+ the breakpoint. Using it would therefore be silly, so it seems
+ better to rely on the current language rather than relying on
+ 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);
+
+ if (func != NULL)
+ lang = language_def (SYMBOL_LANGUAGE (func));
+ if (lang == NULL || lang->la_language == language_unknown)
+ lang = current_language;
+ }
+ else
+ lang = current_language;
+
expout_size = 10;
expout_ptr = 0;
expout = (struct expression *)
xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
- expout->language_defn = current_language;
- expout->gdbarch = current_gdbarch;
+ expout->language_defn = lang;
+ expout->gdbarch = get_current_arch ();
TRY_CATCH (except, RETURN_MASK_ALL)
{
- if (current_language->la_parser ())
- current_language->la_error (NULL);
+ if (lang->la_parser ())
+ lang->la_error (NULL);
}
if (except.reason < 0)
{
if (out_subexp)
*out_subexp = subexp;
- current_language->la_post_parser (&expout, void_context_p);
+ lang->la_post_parser (&expout, void_context_p);
if (expressiondebug)
dump_prefix_expression (expout, gdb_stdlog);
parse_expression (char *string)
{
struct expression *exp;
+
exp = parse_exp_1 (&string, 0, 0);
if (*string)
error (_("Junk after end of expression."));
void
push_type_address_space (char *string)
{
- push_type_int (address_space_name_to_int (string));
+ push_type_int (address_space_name_to_int (parse_gdbarch, string));
}
enum type_pieces
int make_volatile = 0;
int make_addr_space = 0;
int array_size;
- struct type *range_type;
while (!done)
switch (pop_type ())
array_size = pop_type_int ();
/* FIXME-type-allocation: need a way to free this type when we are
done with it. */
- range_type =
- create_range_type ((struct type *) NULL,
- builtin_type_int32, 0,
- array_size >= 0 ? array_size - 1 : 0);
follow_type =
- create_array_type ((struct type *) NULL,
- follow_type, range_type);
+ lookup_array_range_type (follow_type,
+ 0, array_size >= 0 ? array_size - 1 : 0);
if (array_size < 0)
TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (follow_type) = 1;
break;
parser_fprintf (FILE *x, const char *y, ...)
{
va_list args;
+
va_start (args, y);
if (x == stderr)
vfprintf_unfiltered (gdb_stderr, y, args);
va_end (args);
}
+/* Implementation of the exp_descriptor method operator_check. */
+
+int
+operator_check_standard (struct expression *exp, int pos,
+ int (*objfile_func) (struct objfile *objfile,
+ void *data),
+ void *data)
+{
+ const union exp_element *const elts = exp->elts;
+ struct type *type = NULL;
+ struct objfile *objfile = NULL;
+
+ /* Extended operators should have been already handled by exp_descriptor
+ iterate method of its specific language. */
+ gdb_assert (elts[pos].opcode < OP_EXTENDED0);
+
+ /* Track the callers of write_exp_elt_type for this table. */
+
+ switch (elts[pos].opcode)
+ {
+ case BINOP_VAL:
+ case OP_COMPLEX:
+ case OP_DECFLOAT:
+ case OP_DOUBLE:
+ case OP_LONG:
+ case OP_SCOPE:
+ case OP_TYPE:
+ case UNOP_CAST:
+ case UNOP_DYNAMIC_CAST:
+ case UNOP_REINTERPRET_CAST:
+ case UNOP_MAX:
+ case UNOP_MEMVAL:
+ case UNOP_MIN:
+ type = elts[pos + 1].type;
+ break;
+
+ case TYPE_INSTANCE:
+ {
+ LONGEST arg, nargs = elts[pos + 1].longconst;
+
+ for (arg = 0; arg < nargs; arg++)
+ {
+ struct type *type = elts[pos + 2 + arg].type;
+ struct objfile *objfile = TYPE_OBJFILE (type);
+
+ if (objfile && (*objfile_func) (objfile, data))
+ return 1;
+ }
+ }
+ break;
+
+ case UNOP_MEMVAL_TLS:
+ objfile = elts[pos + 1].objfile;
+ type = elts[pos + 2].type;
+ break;
+
+ case OP_VAR_VALUE:
+ {
+ const struct block *const block = elts[pos + 1].block;
+ const struct symbol *const symbol = elts[pos + 2].symbol;
+
+ /* Check objfile where the variable itself is placed.
+ SYMBOL_OBJ_SECTION (symbol) may be NULL. */
+ if ((*objfile_func) (SYMBOL_SYMTAB (symbol)->objfile, data))
+ return 1;
+
+ /* Check objfile where is placed the code touching the variable. */
+ objfile = lookup_objfile_from_block (block);
+
+ type = SYMBOL_TYPE (symbol);
+ }
+ break;
+ }
+
+ /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */
+
+ if (type && TYPE_OBJFILE (type)
+ && (*objfile_func) (TYPE_OBJFILE (type), data))
+ return 1;
+ if (objfile && (*objfile_func) (objfile, data))
+ return 1;
+
+ return 0;
+}
+
+/* Call OBJFILE_FUNC for any TYPE and OBJFILE found being referenced by EXP.
+ The functions are never called with NULL OBJFILE. Functions get passed an
+ arbitrary caller supplied DATA pointer. If any of the functions returns
+ non-zero value then (any other) non-zero value is immediately returned to
+ the caller. Otherwise zero is returned after iterating through whole EXP.
+ */
+
+static int
+exp_iterate (struct expression *exp,
+ int (*objfile_func) (struct objfile *objfile, void *data),
+ void *data)
+{
+ int endpos;
+
+ for (endpos = exp->nelts; endpos > 0; )
+ {
+ int pos, args, oplen = 0;
+
+ operator_length (exp, endpos, &oplen, &args);
+ gdb_assert (oplen > 0);
+
+ pos = endpos - oplen;
+ if (exp->language_defn->la_exp_desc->operator_check (exp, pos,
+ objfile_func, data))
+ return 1;
+
+ endpos = pos;
+ }
+
+ return 0;
+}
+
+/* Helper for exp_uses_objfile. */
+
+static int
+exp_uses_objfile_iter (struct objfile *exp_objfile, void *objfile_voidp)
+{
+ struct objfile *objfile = objfile_voidp;
+
+ if (exp_objfile->separate_debug_objfile_backlink)
+ exp_objfile = exp_objfile->separate_debug_objfile_backlink;
+
+ return exp_objfile == objfile;
+}
+
+/* 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. */
+
+int
+exp_uses_objfile (struct expression *exp, struct objfile *objfile)
+{
+ gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+
+ return exp_iterate (exp, exp_uses_objfile_iter, objfile);
+}
+
void
_initialize_parse (void)
{
NULL,
show_expressiondebug,
&setdebuglist, &showdebuglist);
+ add_setshow_boolean_cmd ("parser", class_maintenance,
+ &parser_debug, _("\
+Set parser debugging."), _("\
+Show parser debugging."), _("\
+When non-zero, expression parser tracing will be enabled."),
+ NULL,
+ show_parserdebug,
+ &setdebuglist, &showdebuglist);
}