You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1079 lines
31 KiB

36 years ago
/* Evaluate expressions for GDB.
Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
36 years ago
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
36 years ago
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.
36 years ago
This program is distributed in the hope that it will be useful,
36 years ago
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. */
36 years ago
#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
36 years ago
#include "value.h"
#include "expression.h"
#include "target.h"
#include "frame.h"
36 years ago
/* 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));
36 years ago
/* 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);
36 years ago
register CORE_ADDR addr;
register struct cleanup *old_chain =
make_cleanup (free_current_contents, &expr);
36 years ago
addr = value_as_pointer (evaluate_expression (expr));
36 years ago
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);
36 years ago
register CORE_ADDR addr;
register struct cleanup *old_chain =
make_cleanup (free_current_contents, &expr);
36 years ago
addr = value_as_pointer (evaluate_expression (expr));
36 years ago
do_cleanups (old_chain);
return addr;
}
value
parse_and_eval (exp)
char *exp;
{
struct expression *expr = parse_expression (exp);
36 years ago
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);
36 years ago
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.
36 years ago
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;
36 years ago
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,
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;
36 years ago
case OP_LONG:
(*pos) += 3;
return value_from_longest (exp->elts[pc + 1].type,
36 years ago
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));
36 years ago
case OP_REGISTER:
(*pos) += 2;
return value_of_register (longest_to_int (exp->elts[pc + 1].longconst));
36 years ago
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;
36 years ago
/* 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));
/* FIXME-tiemann: this is way obsolete. */
36 years ago
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)
fill_in_vptr_fieldno (basetype);
36 years ago
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 = longest_to_int (exp->elts[pc + 1].longconst) + 1;
36 years ago
/* 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 (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);
36 years ago
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[1] = arg2;
argvec[0] =
value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 1].string,
&static_memfuncp,
op == STRUCTOP_STRUCT
? "structure" : "structure pointer");
if (VALUE_OFFSET (temp))
{
arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (temp)),
36 years ago
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);
36 years ago
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + ((tem + sizeof (union exp_element))
/ sizeof (union exp_element));
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
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 + 1].string,
1),
36 years ago
lval_memory);
else
{
value temp = arg1;
return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 1].string,
(int *) 0, "structure");
}
case STRUCTOP_PTR:
tem = strlen (&exp->elts[pc + 1].string);
(*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
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 + 1].string,
1),
36 years ago
lval_memory);
else
{
value temp = arg1;
return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 1].string,
(int *) 0, "structure pointer");
}
case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside);
goto handle_pointer_to_member;
36 years ago
case STRUCTOP_MPTR:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
handle_pointer_to_member:
36 years ago
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;
36 years ago
/* 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));
36 years ago
return value_ind (arg3);
bad_pointer_to_member:
error("non-pointer-to-member value used in pointer-to-member construct");
36 years ago
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);
36 years ago
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);
36 years ago
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);
36 years ago
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);
36 years ago
else
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& op == BINOP_DIV)
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)
return value_zero (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
VALUE_LVAL (arg1));
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, op, OP_NULL);
36 years ago
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);
36 years ago
}
else
{
tem = value_zerop (arg1);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(tem ? EVAL_SKIP : noside));
return value_from_longest (builtin_type_int,
36 years ago
(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);
36 years ago
}
else
{
tem = value_zerop (arg1);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(!tem ? EVAL_SKIP : noside));
return value_from_longest (builtin_type_int,
36 years ago
(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);
36 years ago
}
else
{
tem = value_equal (arg1, arg2);
return value_from_longest (builtin_type_int, (LONGEST) tem);
36 years ago
}
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);
36 years ago
}
else
{
tem = value_equal (arg1, arg2);
return value_from_longest (builtin_type_int, (LONGEST) ! tem);
36 years ago
}
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);
36 years ago
}
else
{
tem = value_less (arg1, arg2);
return value_from_longest (builtin_type_int, (LONGEST) tem);
36 years ago
}
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);
36 years ago
}
else
{
tem = value_less (arg2, arg1);
return value_from_longest (builtin_type_int, (LONGEST) tem);
36 years ago
}
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);
36 years ago
}
else
{
tem = value_less (arg1, arg2);
return value_from_longest (builtin_type_int, (LONGEST) ! tem);
36 years ago
}
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);
36 years ago
}
else
{
tem = value_less (arg2, arg1);
return value_from_longest (builtin_type_int, (LONGEST) ! tem);
36 years ago
}
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)));
36 years ago
else
return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
36 years ago
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;
36 years ago
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);
36 years ago
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,
36 years ago
(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);
36 years ago
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));
36 years ago
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,
36 years ago
(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,
36 years ago
(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,
36 years ago
(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,
36 years ago
(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);
36 years ago
}
/* 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;
36 years ago
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;
36 years ago
(*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);
36 years ago
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);
36 years ago
default:
default_case:
36 years ago
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)),
36 years ago
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;
36 years ago
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)
36 years ago
{
(*pos) += 3;
val = locate_var_value (var, (FRAME) 0);
return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))),
36 years ago
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)
36 years ago
TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
case UNOP_MEMVAL:
(*pos) += 3;
return value_from_longest (builtin_type_int,
36 years ago
(LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type));
case OP_VAR_VALUE:
(*pos) += 3;
return value_from_longest (builtin_type_int,
36 years ago
(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,
36 years ago
(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] = '(';
bcopy (p, tmp+1, 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;
}