/* Evaluate expressions for GDB. Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "symtab.h" #include "gdbtypes.h" #include "value.h" #include "expression.h" #include "target.h" #include "frame.h" /* Values of NOSIDE argument to eval_subexp. */ enum noside { EVAL_NORMAL, EVAL_SKIP, /* Only effect is to increment pos. */ EVAL_AVOID_SIDE_EFFECTS /* Don't modify any variables or call any functions. The value returned will have the correct type, and will have an approximately correct lvalue type (inaccuracy: anything that is listed as being in a register in the function in which it was declared will be lval_register). */ }; /* Prototypes for local functions. */ static value evaluate_subexp_for_sizeof PARAMS ((struct expression *, int *)); static value evaluate_subexp_with_coercion PARAMS ((struct expression *, int *, enum noside)); static value evaluate_subexp_for_address PARAMS ((struct expression *, int *, enum noside)); static value evaluate_subexp PARAMS ((struct type *, struct expression *, int *, enum noside)); /* Parse the string EXP as a C expression, evaluate it, and return the result as a number. */ CORE_ADDR parse_and_eval_address (exp) char *exp; { struct expression *expr = parse_expression (exp); register CORE_ADDR addr; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); addr = value_as_pointer (evaluate_expression (expr)); do_cleanups (old_chain); return addr; } /* Like parse_and_eval_address but takes a pointer to a char * variable and advanced that variable across the characters parsed. */ CORE_ADDR parse_and_eval_address_1 (expptr) char **expptr; { struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0); register CORE_ADDR addr; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); addr = value_as_pointer (evaluate_expression (expr)); do_cleanups (old_chain); return addr; } value parse_and_eval (exp) char *exp; { struct expression *expr = parse_expression (exp); register value val; register struct cleanup *old_chain = make_cleanup (free_current_contents, &expr); val = evaluate_expression (expr); 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_exp_1 (expp, (struct block *) 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 parse.y. See expression.h for info on the format of an expression. */ static value evaluate_subexp (); static value evaluate_subexp_for_address (); static value evaluate_subexp_for_sizeof (); static value evaluate_subexp_with_coercion (); value evaluate_expression (exp) struct expression *exp; { int pc = 0; return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL); } /* Evaluate an expression, avoiding all memory references and getting a value whose type alone is correct. */ value evaluate_type (exp) struct expression *exp; { int pc = 0; return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS); } static value evaluate_subexp (expect_type, exp, pos, noside) struct type *expect_type; register struct expression *exp; register int *pos; enum noside noside; { enum exp_opcode op; int tem; register int pc, pc2, oldpos; register value arg1, arg2, arg3; struct type *type; int nargs; value *argvec; pc = (*pos)++; op = exp->elts[pc].opcode; switch (op) { case OP_SCOPE: tem = strlen (&exp->elts[pc + 2].string); (*pos) += 3 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type, 0, exp->elts[pc + 1].type, &exp->elts[pc + 2].string, expect_type); if (arg1 == NULL) error ("There is no field named %s", &exp->elts[pc + 2].string); return arg1; case OP_LONG: (*pos) += 3; return value_from_longest (exp->elts[pc + 1].type, exp->elts[pc + 2].longconst); case OP_DOUBLE: (*pos) += 3; return value_from_double (exp->elts[pc + 1].type, exp->elts[pc + 2].doubleconst); case OP_VAR_VALUE: (*pos) += 2; if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) { struct symbol * sym = exp->elts[pc + 1].symbol; enum lval_type lv; switch (SYMBOL_CLASS (sym)) { case LOC_CONST: case LOC_LABEL: case LOC_CONST_BYTES: lv = not_lval; break; case LOC_REGISTER: case LOC_REGPARM: lv = lval_register; break; default: lv = lval_memory; break; } return value_zero (SYMBOL_TYPE (sym), lv); } else return value_of_variable (exp->elts[pc + 1].symbol); case OP_LAST: (*pos) += 2; return access_value_history (longest_to_int (exp->elts[pc + 1].longconst)); case OP_REGISTER: (*pos) += 2; return value_of_register (longest_to_int (exp->elts[pc + 1].longconst)); case OP_INTERNALVAR: (*pos) += 2; return value_of_internalvar (exp->elts[pc + 1].internalvar); case OP_STRING: tem = strlen (&exp->elts[pc + 1].string); (*pos) += 2 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); if (noside == EVAL_SKIP) goto nosideret; return value_string (&exp->elts[pc + 1].string, tem); case TERNOP_COND: /* Skip third and second args to evaluate the first one. */ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (value_zerop (arg1)) { evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); return evaluate_subexp (NULL_TYPE, exp, pos, noside); } else { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); return arg2; } case OP_FUNCALL: (*pos) += 2; op = exp->elts[*pos].opcode; if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { int fnptr; nargs = longest_to_int (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 (NULL_TYPE, 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 (NULL_TYPE, exp, pos, noside); fnptr = longest_to_int (value_as_long (arg1)); if (METHOD_PTR_IS_VIRTUAL(fnptr)) { int fnoffset = METHOD_PTR_TO_VOFFSET(fnptr); struct type *basetype; struct type *domain_type = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))); int i, j; basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2)); if (domain_type != basetype) arg2 = value_cast(lookup_pointer_type (domain_type), arg2); basetype = TYPE_VPTR_BASETYPE (domain_type); 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) == fnoffset) { value temp = value_ind (arg2); arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0); arg2 = value_addr (temp); goto got_it; } } if (i < 0) error ("virtual function at index %d not found", fnoffset); } 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 = longest_to_int (exp->elts[pc + 1].longconst) + 1; /* First, evaluate the structure into arg2 */ pc2 = (*pos)++; /* type = exp->elts[pc2 + 1].type; */ tem2 = strlen (&exp->elts[pc2 + 2].string); *pos += 3 + (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 (NULL_TYPE, exp, pos, noside); } /* Now, say which argument to start evaluating from */ tem = 2; } else { nargs = longest_to_int (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) { int static_memfuncp; value temp = arg2; /* argvec[0] gets the method; argvec[1] gets the 'this' pointer (unless static) (from arg2); the remaining args go into the rest of argvec. */ argvec[1] = arg2; argvec[0] = value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 2].string, &static_memfuncp, op == STRUCTOP_STRUCT ? "structure" : "structure pointer"); if (VALUE_OFFSET (temp)) { arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (temp)), value_as_long (arg2)+VALUE_OFFSET (temp)); argvec[1] = arg2; } if (static_memfuncp) { argvec[1] = argvec[0]; nargs--; argvec++; } } 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) { /* If the return type doesn't look like a function type, call an error. This can happen if somebody tries to turn a variable into a function call. This is here because people often want to call, eg, strcmp, which gdb doesn't know is a function. If gdb isn't asked for it's opinion (ie. through "whatis"), it won't offer it. */ struct type *ftype = TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])); if (ftype) return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]))); else error ("Expression of type other than \"Function returning ...\" used as function"); } return call_function_by_hand (argvec[0], nargs, argvec + 1); case STRUCTOP_STRUCT: tem = strlen (&exp->elts[pc + 2].string); (*pos) += 3 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) goto handle_structop_ptr; type = exp->elts[pc + 1].type; if (type) arg1 = value_ind (value_cast (lookup_pointer_type (type), value_addr (arg1))); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1), &exp->elts[pc + 2].string, 0), lval_memory); else { value temp = arg1; return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string, (int *) 0, "structure"); } case STRUCTOP_PTR: tem = strlen (&exp->elts[pc + 2].string); (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); handle_structop_ptr: type = exp->elts[pc + 1].type; if (type) arg1 = value_cast (lookup_pointer_type (type), arg1); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), &exp->elts[pc + 2].string, 0), lval_memory); else { value temp = arg1; return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string, (int *) 0, "structure pointer"); } case STRUCTOP_MEMBER: arg1 = evaluate_subexp_for_address (exp, pos, noside); goto handle_pointer_to_member; case STRUCTOP_MPTR: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); handle_pointer_to_member: arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR) goto bad_pointer_to_member; type = TYPE_TARGET_TYPE (VALUE_TYPE (arg2)); if (TYPE_CODE (type) == TYPE_CODE_METHOD) error ("not implemented: pointer-to-method in pointer-to-member construct"); if (TYPE_CODE (type) != TYPE_CODE_MEMBER) goto bad_pointer_to_member; /* Now, convert these values to an address. */ arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)), arg1); arg3 = value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)), value_as_long (arg1) + value_as_long (arg2)); return value_ind (arg3); bad_pointer_to_member: error("non-pointer-to-member value used in pointer-to-member construct"); case BINOP_ASSIGN: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, OP_NULL); else return value_assign (arg1, arg2); case BINOP_ASSIGN_MODIFY: (*pos) += 2; arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; op = exp->elts[pc + 1].opcode; if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op); else if (op == BINOP_ADD) arg2 = value_add (arg1, arg2); else if (op == BINOP_SUB) arg2 = value_sub (arg1, arg2); else arg2 = value_binop (arg1, arg2, op); return value_assign (arg1, arg2); case BINOP_ADD: arg1 = evaluate_subexp_with_coercion (exp, pos, noside); arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, OP_NULL); else return value_add (arg1, arg2); case BINOP_SUB: arg1 = evaluate_subexp_with_coercion (exp, pos, noside); arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, OP_NULL); else return value_sub (arg1, arg2); case BINOP_MUL: case BINOP_DIV: case BINOP_REM: case BINOP_LSH: case BINOP_RSH: case BINOP_LOGAND: case BINOP_LOGIOR: case BINOP_LOGXOR: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, OP_NULL); else if (noside == EVAL_AVOID_SIDE_EFFECTS && (op == BINOP_DIV || op == BINOP_REM)) return value_zero (VALUE_TYPE (arg1), not_lval); else return value_binop (arg1, arg2, op); case BINOP_SUBSCRIPT: arg1 = evaluate_subexp_with_coercion (exp, pos, noside); arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) { /* If the user attempts to subscript something that has no target type (like a plain int variable for example), then report this as an error. */ type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1)); if (type) return value_zero (type, VALUE_LVAL (arg1)); else error ("cannot subscript something of type `%s'", TYPE_NAME (VALUE_TYPE (arg1))); } if (binop_user_defined_p (op, arg1, arg2)) return value_x_binop (arg1, arg2, op, OP_NULL); else return value_subscript (arg1, arg2); case BINOP_AND: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); goto nosideret; } oldpos = *pos; arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); *pos = oldpos; if (binop_user_defined_p (op, arg1, arg2)) { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_zerop (arg1); arg2 = evaluate_subexp (NULL_TYPE, exp, pos, (tem ? EVAL_SKIP : noside)); return value_from_longest (builtin_type_int, (LONGEST) (!tem && !value_zerop (arg2))); } case BINOP_OR: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); goto nosideret; } oldpos = *pos; arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); *pos = oldpos; if (binop_user_defined_p (op, arg1, arg2)) { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_zerop (arg1); arg2 = evaluate_subexp (NULL_TYPE, exp, pos, (!tem ? EVAL_SKIP : noside)); return value_from_longest (builtin_type_int, (LONGEST) (!tem || !value_zerop (arg2))); } case BINOP_EQUAL: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) { return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_equal (arg1, arg2); return value_from_longest (builtin_type_int, (LONGEST) tem); } case BINOP_NOTEQUAL: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) { return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_equal (arg1, arg2); return value_from_longest (builtin_type_int, (LONGEST) ! tem); } case BINOP_LESS: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) { return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_less (arg1, arg2); return value_from_longest (builtin_type_int, (LONGEST) tem); } case BINOP_GTR: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) { return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_less (arg2, arg1); return value_from_longest (builtin_type_int, (LONGEST) tem); } case BINOP_GEQ: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) { return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_less (arg2, arg1) || value_equal (arg1, arg2); return value_from_longest (builtin_type_int, (LONGEST) tem); } case BINOP_LEQ: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (binop_user_defined_p (op, arg1, arg2)) { return value_x_binop (arg1, arg2, op, OP_NULL); } else { tem = value_less (arg1, arg2) || value_equal (arg1, arg2); return value_from_longest (builtin_type_int, (LONGEST) tem); } case BINOP_REPEAT: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT) error ("Non-integral right operand for \"@\" operator."); if (noside == EVAL_AVOID_SIDE_EFFECTS) return allocate_repeat_value (VALUE_TYPE (arg1), longest_to_int (value_as_long (arg2))); else return value_repeat (arg1, longest_to_int (value_as_long (arg2))); case BINOP_COMMA: evaluate_subexp (NULL_TYPE, exp, pos, noside); return evaluate_subexp (NULL_TYPE, exp, pos, noside); case UNOP_NEG: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (op, arg1)) return value_x_unop (arg1, op); else return value_neg (arg1); case UNOP_LOGNOT: /* C++: check for and handle destructor names. */ op = exp->elts[*pos].opcode; arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (UNOP_LOGNOT, arg1)) return value_x_unop (arg1, UNOP_LOGNOT); else return value_lognot (arg1); case UNOP_ZEROP: arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (unop_user_defined_p (op, arg1)) return value_x_unop (arg1, op); else return value_from_longest (builtin_type_int, (LONGEST) value_zerop (arg1)); case UNOP_IND: if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR) expect_type = TYPE_TARGET_TYPE (expect_type); arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) { if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF /* In C you can dereference an array to get the 1st elt. */ || TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY ) return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), lval_memory); else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT) /* GDB allows dereferencing an int. */ return value_zero (builtin_type_int, lval_memory); else error ("Attempt to take contents of a non-pointer value."); } return value_ind (arg1); case UNOP_ADDR: /* C++: check for and handle pointer to members. */ op = exp->elts[*pos].opcode; if (noside == EVAL_SKIP) { if (op == OP_SCOPE) { char *name = &exp->elts[pc+3].string; int temm = strlen (name); (*pos) += 2 + (temm + sizeof (union exp_element)) / sizeof (union exp_element); } else evaluate_subexp (expect_type, exp, pos, EVAL_SKIP); goto nosideret; } return evaluate_subexp_for_address (exp, pos, noside); case UNOP_SIZEOF: if (noside == EVAL_SKIP) { evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); goto nosideret; } return evaluate_subexp_for_sizeof (exp, pos); case UNOP_CAST: (*pos) += 2; arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; return value_cast (exp->elts[pc + 1].type, arg1); case UNOP_MEMVAL: (*pos) += 2; arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) return value_zero (exp->elts[pc + 1].type, lval_memory); else return value_at_lazy (exp->elts[pc + 1].type, value_as_pointer (arg1)); case UNOP_PREINCREMENT: arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; else if (unop_user_defined_p (op, arg1)) { return value_x_unop (arg1, op); } else { arg2 = value_add (arg1, value_from_longest (builtin_type_char, (LONGEST) 1)); return value_assign (arg1, arg2); } case UNOP_PREDECREMENT: arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; else if (unop_user_defined_p (op, arg1)) { return value_x_unop (arg1, op); } else { arg2 = value_sub (arg1, value_from_longest (builtin_type_char, (LONGEST) 1)); return value_assign (arg1, arg2); } case UNOP_POSTINCREMENT: arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; else if (unop_user_defined_p (op, arg1)) { return value_x_unop (arg1, op); } else { arg2 = value_add (arg1, value_from_longest (builtin_type_char, (LONGEST) 1)); value_assign (arg1, arg2); return arg1; } case UNOP_POSTDECREMENT: arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; else if (unop_user_defined_p (op, arg1)) { return value_x_unop (arg1, op); } else { arg2 = value_sub (arg1, value_from_longest (builtin_type_char, (LONGEST) 1)); value_assign (arg1, arg2); return arg1; } case OP_THIS: (*pos) += 1; return value_of_this (1); default: error ("internal error: I do not know how to evaluate what you gave me"); } nosideret: return value_from_longest (builtin_type_long, (LONGEST) 1); } /* Evaluate a subexpression of EXP, at index *POS, and return the address of that subexpression. Advance *POS over the subexpression. If the subexpression isn't an lvalue, get an error. NOSIDE may be EVAL_AVOID_SIDE_EFFECTS; then only the type of the result need be correct. */ static value evaluate_subexp_for_address (exp, pos, noside) register struct expression *exp; register int *pos; enum noside noside; { enum exp_opcode op; register int pc; struct symbol *var; pc = (*pos); op = exp->elts[pc].opcode; switch (op) { case UNOP_IND: (*pos)++; return evaluate_subexp (NULL_TYPE, exp, pos, noside); case UNOP_MEMVAL: (*pos) += 3; return value_cast (lookup_pointer_type (exp->elts[pc + 1].type), evaluate_subexp (NULL_TYPE, exp, pos, noside)); case OP_VAR_VALUE: var = exp->elts[pc + 1].symbol; /* C++: The "address" of a reference should yield the address * of the object pointed to. Let value_addr() deal with it. */ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF) goto default_case; (*pos) += 3; if (noside == EVAL_AVOID_SIDE_EFFECTS) { struct type *type = lookup_pointer_type (SYMBOL_TYPE (var)); enum address_class sym_class = SYMBOL_CLASS (var); if (sym_class == LOC_CONST || sym_class == LOC_CONST_BYTES || sym_class == LOC_REGISTER || sym_class == LOC_REGPARM) error ("Attempt to take address of register or constant."); return value_zero (type, not_lval); } else return locate_var_value (var, (FRAME) 0); default: default_case: if (noside == EVAL_AVOID_SIDE_EFFECTS) { value x = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (VALUE_LVAL (x) == lval_memory) return value_zero (lookup_pointer_type (VALUE_TYPE (x)), not_lval); else error ("Attempt to take address of non-lval"); } return value_addr (evaluate_subexp (NULL_TYPE, exp, pos, noside)); } } /* Evaluate like `evaluate_subexp' except coercing arrays to pointers. When used in contexts where arrays will be coerced anyway, this is equivalent to `evaluate_subexp' but much faster because it avoids actually fetching array contents. */ static value evaluate_subexp_with_coercion (exp, pos, noside) register struct expression *exp; register int *pos; enum noside noside; { register enum exp_opcode op; register int pc; register value val; struct symbol *var; pc = (*pos); op = exp->elts[pc].opcode; switch (op) { case OP_VAR_VALUE: var = exp->elts[pc + 1].symbol; if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ARRAY) { (*pos) += 3; val = locate_var_value (var, (FRAME) 0); return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))), val); } default: return evaluate_subexp (NULL_TYPE, exp, pos, noside); } } /* Evaluate a subexpression of EXP, at index *POS, and return a value for the size of that subexpression. Advance *POS over the subexpression. */ static value evaluate_subexp_for_sizeof (exp, pos) register struct expression *exp; register int *pos; { enum exp_opcode op; register int pc; value val; pc = (*pos); op = exp->elts[pc].opcode; switch (op) { /* This case is handled specially so that we avoid creating a value for the result type. If the result type is very big, it's desirable not to create a value unnecessarily. */ case UNOP_IND: (*pos)++; val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); return value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val)))); case UNOP_MEMVAL: (*pos) += 3; return value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type)); case OP_VAR_VALUE: (*pos) += 3; return value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol))); default: val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); return value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (VALUE_TYPE (val))); } } /* Parse a type expression in the string [P..P+LENGTH). */ struct type * parse_and_eval_type (p, length) char *p; int length; { char *tmp = (char *)alloca (length + 4); struct expression *expr; tmp[0] = '('; memcpy (tmp+1, p, length); tmp[length+1] = ')'; tmp[length+2] = '0'; tmp[length+3] = '\0'; expr = parse_expression (tmp); if (expr->elts[0].opcode != UNOP_CAST) error ("Internal error in eval_type."); return expr->elts[1].type; }