aboutsummaryrefslogtreecommitdiff
path: root/gdb/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/eval.c')
-rw-r--r--gdb/eval.c234
1 files changed, 213 insertions, 21 deletions
diff --git a/gdb/eval.c b/gdb/eval.c
index 97f39c3..dcca415 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -50,7 +50,7 @@ CORE_ADDR
parse_and_eval_address_1 (expptr)
char **expptr;
{
- struct expression *expr = parse_c_1 (expptr, 0);
+ struct expression *expr = parse_c_1 (expptr, 0, 0);
register CORE_ADDR addr;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
@@ -73,6 +73,24 @@ parse_and_eval (exp)
do_cleanups (old_chain);
return val;
}
+
+/* Parse up to a comma (or to a closeparen)
+ in the string EXPP as an expression, evaluate it, and return the value.
+ EXPP is advanced to point to the comma. */
+
+value
+parse_to_comma_and_eval (expp)
+ char **expp;
+{
+ struct expression *expr = parse_c_1 (expp, 0, 1);
+ register value val;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
/* Evaluate an expression in internal prefix form
such as is constructed by expread.y.
@@ -118,8 +136,8 @@ evaluate_subexp (exp, pos, noside)
{
enum exp_opcode op;
int tem;
- register int pc;
- register value arg1, arg2;
+ register int pc, pc2, *oldpos;
+ register value arg1, arg2, arg3;
int nargs;
value *argvec;
@@ -128,6 +146,12 @@ evaluate_subexp (exp, pos, noside)
switch (op)
{
+ case OP_SCOPE:
+ tem = strlen (&exp->elts[pc + 2].string);
+ (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ return value_static_field (exp->elts[pc + 1].type,
+ &exp->elts[pc + 2].string, -1);
+
case OP_LONG:
(*pos) += 3;
return value_from_long (exp->elts[pc + 1].type,
@@ -156,21 +180,6 @@ evaluate_subexp (exp, pos, noside)
(*pos) += 2;
return value_of_internalvar (exp->elts[pc + 1].internalvar);
- case OP_FUNCALL:
- (*pos) += 2;
- nargs = exp->elts[pc + 1].longconst;
- argvec = (value *) alloca (sizeof (value) * (nargs + 1));
- for (tem = 0; tem <= nargs; tem++)
-
- /* Ensure that array expressions are coerced into pointer objects. */
- argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
-
- if (noside == EVAL_SKIP)
- goto nosideret;
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
- return call_function (argvec[0], nargs, argvec + 1);
-
case OP_STRING:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
@@ -193,13 +202,146 @@ evaluate_subexp (exp, pos, noside)
return arg2;
}
+ case OP_FUNCALL:
+ (*pos) += 2;
+ op = exp->elts[*pos].opcode;
+ if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ int fnptr;
+ int tem2;
+
+ nargs = exp->elts[pc + 1].longconst + 1;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_MEMBER)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (exp, pos, noside);
+ }
+
+ /* If the function is a virtual function, then the
+ aggregate value (providing the structure) plays
+ its part by providing the vtable. Otherwise,
+ it is just along for the ride: call the function
+ directly. */
+
+ arg1 = evaluate_subexp (exp, pos, noside);
+
+ fnptr = value_as_long (arg1);
+ if (fnptr < 128)
+ {
+ struct type *basetype;
+ int i, j;
+ basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+ basetype = TYPE_VPTR_BASETYPE (basetype);
+ for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
+ /* If one is virtual, then all are virtual. */
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
+ for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
+ if (TYPE_FN_FIELD_VOFFSET (f, j) == fnptr)
+ {
+ value vtbl;
+ value base = value_ind (arg2);
+ struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+ if (TYPE_VPTR_FIELDNO (basetype) < 0)
+ TYPE_VPTR_FIELDNO (basetype)
+ = fill_in_vptr_fieldno (basetype);
+
+ VALUE_TYPE (base) = basetype;
+ vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype));
+ VALUE_TYPE (vtbl) = lookup_pointer_type (fntype);
+ VALUE_TYPE (arg1) = builtin_type_int;
+ arg1 = value_subscript (vtbl, arg1);
+ VALUE_TYPE (arg1) = fntype;
+ goto got_it;
+ }
+ }
+ if (i < 0)
+ error ("virtual function at index %d not found", fnptr);
+ }
+ else
+ {
+ VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
+ }
+ got_it:
+
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ /* Hair for method invocations */
+ int tem2;
+
+ nargs = exp->elts[pc + 1].longconst + 1;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+ tem2 = strlen (&exp->elts[pc2 + 1].string);
+ *pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_STRUCT)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (exp, pos, noside);
+ }
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else
+ {
+ nargs = exp->elts[pc + 1].longconst;
+ tem = 0;
+ }
+ argvec = (value *) alloca (sizeof (value) * (nargs + 2));
+ for (; tem <= nargs; tem++)
+ /* Ensure that array expressions are coerced into pointer objects. */
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ /* signal end of arglist */
+ argvec[tem] = 0;
+
+ if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ argvec[1] = arg2;
+ argvec[0] =
+ value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string,
+ op == STRUCTOP_STRUCT
+ ? "structure" : "structure pointer");
+ }
+ else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ argvec[1] = arg2;
+ argvec[0] = arg1;
+ }
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
+ return call_function (argvec[0], nargs, argvec + 1);
+
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
arg1 = evaluate_subexp (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
- return value_struct_elt (arg1, &exp->elts[pc + 1].string,
+ return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
"structure");
case STRUCTOP_PTR:
@@ -208,9 +350,37 @@ evaluate_subexp (exp, pos, noside)
arg1 = evaluate_subexp (exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
- return value_struct_elt (arg1, &exp->elts[pc + 1].string,
+ return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string,
"structure pointer");
+ case STRUCTOP_MEMBER:
+ arg1 = evaluate_subexp_for_address (exp, pos, noside);
+ arg2 = evaluate_subexp (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ /* Now, convert these values to an address.
+ @@ We do not know what type we are looking for,
+ @@ so we must assume that the value requested is a
+ @@ member address (as opposed to a member function address). */
+ arg3 = value_from_long (builtin_type_long,
+ value_as_long (arg1) + value_as_long (arg2));
+ VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)));
+ return value_ind (arg3);
+
+ case STRUCTOP_MPTR:
+ arg1 = evaluate_subexp (exp, pos, noside);
+ arg2 = evaluate_subexp (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ /* Now, convert these values to an address.
+ @@ We do not know what type we are looking for,
+ @@ so we must assume that the value requested is a
+ @@ member address (as opposed to a member function address). */
+ arg3 = value_from_long (builtin_type_long,
+ value_as_long (arg1) + value_as_long (arg2));
+ VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)));
+ return value_ind (arg3);
+
case BINOP_ASSIGN:
arg1 = evaluate_subexp (exp, pos, noside);
arg2 = evaluate_subexp (exp, pos, noside);
@@ -373,7 +543,22 @@ evaluate_subexp (exp, pos, noside)
evaluate_subexp (exp, pos, EVAL_SKIP);
goto nosideret;
}
- return evaluate_subexp_for_address (exp, pos, noside);
+ /* C++: check for and handle pointer to members. */
+
+ op = exp->elts[*pos].opcode;
+ if (op == OP_SCOPE)
+ {
+ char *name = &exp->elts[pc+3].string;
+ int tem = strlen (name);
+ struct type *domain = exp->elts[pc+2].type;
+ (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ arg1 = value_struct_elt_for_address (domain, 0, name);
+ if (arg1)
+ return arg1;
+ error ("no field `%s' in structure", name);
+ }
+ else
+ return evaluate_subexp_for_address (exp, pos, noside);
case UNOP_SIZEOF:
if (noside == EVAL_SKIP)
@@ -426,6 +611,13 @@ evaluate_subexp (exp, pos, noside)
return arg1;
value_assign (arg1, arg2);
return arg1;
+
+ case OP_THIS:
+ (*pos) += 1;
+ return value_of_this (1);
+
+ default:
+ error ("internal error: I dont know how to evaluation what you gave me");
}
nosideret: