diff options
Diffstat (limited to 'gdb/eval.c')
-rw-r--r-- | gdb/eval.c | 234 |
1 files changed, 213 insertions, 21 deletions
@@ -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: |