/* Evaluate expressions for GDB.
- Copyright (C) 1986-2014 Free Software Foundation, Inc.
+ Copyright (C) 1986-2017 Free Software Foundation, Inc.
This file is part of GDB.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include <string.h>
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "expression.h"
#include "target.h"
#include "frame.h"
+#include "gdbthread.h"
#include "language.h" /* For CAST_IS_CONVERSION. */
#include "f-lang.h" /* For array bound stuff. */
#include "cp-abi.h"
#include "parser-defs.h"
#include "cp-support.h"
#include "ui-out.h"
-#include "exceptions.h"
#include "regcache.h"
#include "user-regs.h"
#include "valprint.h"
#include "gdb_obstack.h"
#include "objfiles.h"
-
-#include "gdb_assert.h"
-
#include <ctype.h>
/* This is defined in valops.c */
/* Prototypes for local functions. */
-static struct value *evaluate_subexp_for_sizeof (struct expression *, int *);
+static struct value *evaluate_subexp_for_sizeof (struct expression *, int *,
+ enum noside);
static struct value *evaluate_subexp_for_address (struct expression *,
int *, enum noside);
evaluate_subexp (struct type *expect_type, struct expression *exp,
int *pos, enum noside noside)
{
- return (*exp->language_defn->la_exp_desc->evaluate_exp)
+ struct cleanup *cleanups;
+ struct value *retval;
+ int cleanup_temps = 0;
+
+ if (*pos == 0 && target_has_execution
+ && exp->language_defn->la_language == language_cplus
+ && !thread_stack_temporaries_enabled_p (inferior_ptid))
+ {
+ cleanups = enable_thread_stack_temporaries (inferior_ptid);
+ cleanup_temps = 1;
+ }
+
+ retval = (*exp->language_defn->la_exp_desc->evaluate_exp)
(expect_type, exp, pos, noside);
+
+ if (cleanup_temps)
+ {
+ if (value_in_thread_stack_temporaries (retval, inferior_ptid))
+ retval = value_non_lval (retval);
+ do_cleanups (cleanups);
+ }
+
+ return retval;
}
\f
/* Parse the string EXP as a C expression, evaluate it,
CORE_ADDR
parse_and_eval_address (const char *exp)
{
- struct expression *expr = parse_expression (exp);
- CORE_ADDR addr;
- struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
-
- addr = value_as_address (evaluate_expression (expr));
- do_cleanups (old_chain);
- return addr;
+ expression_up expr = parse_expression (exp);
+
+ return value_as_address (evaluate_expression (expr.get ()));
}
/* Like parse_and_eval_address, but treats the value of the expression
LONGEST
parse_and_eval_long (const char *exp)
{
- struct expression *expr = parse_expression (exp);
- LONGEST retval;
- struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
-
- retval = value_as_long (evaluate_expression (expr));
- do_cleanups (old_chain);
- return (retval);
+ expression_up expr = parse_expression (exp);
+
+ return value_as_long (evaluate_expression (expr.get ()));
}
struct value *
parse_and_eval (const char *exp)
{
- struct expression *expr = parse_expression (exp);
- struct value *val;
- struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
+ expression_up expr = parse_expression (exp);
- val = evaluate_expression (expr);
- do_cleanups (old_chain);
- return val;
+ return evaluate_expression (expr.get ());
}
/* Parse up to a comma (or to a closeparen)
struct value *
parse_to_comma_and_eval (const char **expp)
{
- struct expression *expr = parse_exp_1 (expp, 0, (struct block *) 0, 1);
- struct value *val;
- struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
+ expression_up expr = parse_exp_1 (expp, 0, (struct block *) 0, 1);
- val = evaluate_expression (expr);
- do_cleanups (old_chain);
- return val;
+ return evaluate_expression (expr.get ());
}
\f
/* Evaluate an expression in internal prefix form
int preserve_errors)
{
struct value *mark, *new_mark, *result;
- volatile struct gdb_exception ex;
*valp = NULL;
if (resultp)
mark = value_mark ();
result = NULL;
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ TRY
{
result = evaluate_subexp (NULL_TYPE, exp, pc, EVAL_NORMAL);
}
- if (ex.reason < 0)
+ CATCH (ex, RETURN_MASK_ALL)
{
/* Ignore memory errors if we want watchpoints pointing at
inaccessible memory to still be created; otherwise, throw the
break;
}
}
+ END_CATCH
new_mark = value_mark ();
if (mark == new_mark)
*valp = result;
else
{
- volatile struct gdb_exception except;
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
value_fetch_lazy (result);
*valp = result;
}
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ }
+ END_CATCH
}
}
return struct_val;
}
-/* Recursive helper function for setting elements of array tuples for
- (the deleted) Chill. The target is ARRAY (which has bounds
- LOW_BOUND to HIGH_BOUND); the element value is ELEMENT; EXP, POS
- and NOSIDE are as usual. Evaluates index expresions and sets the
- specified element(s) of ARRAY to ELEMENT. Returns last index
- value. */
+/* Recursive helper function for setting elements of array tuples.
+ The target is ARRAY (which has bounds LOW_BOUND to HIGH_BOUND); the
+ element value is ELEMENT; EXP, POS and NOSIDE are as usual.
+ Evaluates index expresions and sets the specified element(s) of
+ ARRAY to ELEMENT. Returns last index value. */
static LONGEST
init_array_element (struct value *array, struct value *element,
return init_array_element (array, element,
exp, pos, noside, low_bound, high_bound);
}
- else if (exp->elts[*pos].opcode == BINOP_RANGE)
- {
- LONGEST low, high;
-
- (*pos)++;
- low = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
- high = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
- if (low < low_bound || high > high_bound)
- error (_("tuple range index out of range"));
- for (index = low; index <= high; index++)
- {
- memcpy (value_contents_raw (array)
- + (index - low_bound) * element_size,
- value_contents (element), element_size);
- }
- }
else
{
index = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
int pc = (*pos) + 1;
LONGEST low_bound, high_bound;
struct type *range = check_typedef (TYPE_INDEX_TYPE (value_type (array)));
- enum f90_range_type range_type = longest_to_int (exp->elts[pc].longconst);
+ enum range_type range_type
+ = (enum range_type) longest_to_int (exp->elts[pc].longconst);
*pos += 3;
ptrmath_type_p (const struct language_defn *lang, struct type *type)
{
type = check_typedef (type);
- if (TYPE_CODE (type) == TYPE_CODE_REF)
+ if (TYPE_IS_REFERENCE (type))
type = TYPE_TARGET_TYPE (type);
switch (TYPE_CODE (type))
TYPE_MAIN_TYPE (type) = XCNEW (struct main_type);
TYPE_LENGTH (type) = 1;
TYPE_CODE (type) = TYPE_CODE_METHOD;
- TYPE_VPTR_FIELDNO (type) = -1;
TYPE_CHAIN (type) = type;
if (num_types > 0)
{
or reference to a base class and print object is on. */
{
- volatile struct gdb_exception except;
struct value *ret = NULL;
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
ret = value_of_variable (exp->elts[pc + 2].symbol,
exp->elts[pc + 1].block);
}
- if (except.reason < 0)
+ CATCH (except, RETURN_MASK_ERROR)
{
if (noside == EVAL_AVOID_SIDE_EFFECTS)
ret = value_zero (SYMBOL_TYPE (exp->elts[pc + 2].symbol),
else
throw_exception (except);
}
+ END_CATCH
return ret;
}
struct value *element;
int index_pc = 0;
- if (exp->elts[*pos].opcode == BINOP_RANGE)
- {
- index_pc = ++(*pos);
- evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
- }
element = evaluate_subexp (element_type, exp, pos, noside);
if (value_type (element) != element_type)
element = value_cast (element_type, element);
struct type *range_low_type, *range_high_type;
struct value *elem_val;
- if (exp->elts[*pos].opcode == BINOP_RANGE)
- {
- (*pos)++;
- elem_val = evaluate_subexp (element_type, exp, pos, noside);
- range_low_type = value_type (elem_val);
- range_low = value_as_long (elem_val);
- elem_val = evaluate_subexp (element_type, exp, pos, noside);
- range_high_type = value_type (elem_val);
- range_high = value_as_long (elem_val);
- }
- else
- {
- elem_val = evaluate_subexp (element_type, exp, pos, noside);
- range_low_type = range_high_type = value_type (elem_val);
- range_low = range_high = value_as_long (elem_val);
- }
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_low_type = range_high_type = value_type (elem_val);
+ range_low = range_high = value_as_long (elem_val);
+
/* Check types of elements to avoid mixture of elements from
different types. Also check if type of element is "compatible"
with element type of powerset. */
return set;
}
- argvec = (struct value **) alloca (sizeof (struct value *) * nargs);
+ argvec = XALLOCAVEC (struct value *, nargs);
for (tem = 0; tem < nargs; tem++)
{
/* Ensure that array expressions are coerced into pointer
CORE_ADDR selector = 0;
int struct_return = 0;
- int sub_no_side = 0;
+ enum noside sub_no_side = EVAL_NORMAL;
struct value *msg_send = NULL;
struct value *msg_send_stret = NULL;
selector = exp->elts[pc + 1].longconst;
nargs = exp->elts[pc + 2].longconst;
- argvec = (struct value **) alloca (sizeof (struct value *)
- * (nargs + 5));
+ argvec = XALLOCAVEC (struct value *, nargs + 5);
(*pos) += 3;
argvec[3] = value_from_longest (long_type, selector);
argvec[4] = 0;
- ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1);
if (gnu_runtime)
{
/* Function objc_msg_lookup returns a pointer. */
argvec[0] = ret;
- ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1);
}
if (value_as_long (ret) == 0)
error (_("Target does not respond to this message selector."));
argvec[3] = value_from_longest (long_type, selector);
argvec[4] = 0;
- ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1);
if (gnu_runtime)
{
argvec[0] = ret;
- ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ ret = call_function_by_hand (argvec[0], NULL, 3, argvec + 1);
}
/* ret should now be the selector. */
block_for_pc (funaddr);
- CHECK_TYPEDEF (val_type);
+ val_type = check_typedef (val_type);
if ((val_type == NULL)
|| (TYPE_CODE(val_type) == TYPE_CODE_ERROR))
deprecated_set_value_type (argvec[0],
lookup_pointer_type (lookup_function_type (value_type (argvec[0]))));
argvec[0]
- = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ = call_function_by_hand (argvec[0], NULL, nargs + 2, argvec + 1);
}
- ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ ret = call_function_by_hand (argvec[0], NULL, nargs + 2, argvec + 1);
return ret;
}
break;
op = exp->elts[*pos].opcode;
nargs = longest_to_int (exp->elts[pc + 1].longconst);
/* Allocate arg vector, including space for the function to be
- called in argvec[0] and a terminating NULL. */
+ called in argvec[0], a potential `this', and a terminating NULL. */
argvec = (struct value **)
alloca (sizeof (struct value *) * (nargs + 3));
if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
/* 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);
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
type = check_typedef (value_type (arg1));
- if (TYPE_CODE (type) == TYPE_CODE_METHODPTR)
+ if (noside == EVAL_SKIP)
+ tem = 1; /* Set it to the right arg index so that all arguments
+ can also be skipped. */
+ else if (TYPE_CODE (type) == TYPE_CODE_METHODPTR)
{
if (noside == EVAL_AVOID_SIDE_EFFECTS)
arg1 = value_zero (TYPE_TARGET_TYPE (type), not_lval);
else if (TYPE_CODE (type) == TYPE_CODE_MEMBERPTR)
{
struct type *type_ptr
- = lookup_pointer_type (TYPE_DOMAIN_TYPE (type));
+ = lookup_pointer_type (TYPE_SELF_TYPE (type));
struct type *target_type_ptr
= lookup_pointer_type (TYPE_TARGET_TYPE (type));
pc2 = (*pos)++;
tem2 = longest_to_int (exp->elts[pc2 + 1].longconst);
*pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1);
- if (noside == EVAL_SKIP)
- goto nosideret;
if (op == STRUCTOP_STRUCT)
{
operator and continue evaluation. */
while (unop_user_defined_p (op, arg2))
{
- volatile struct gdb_exception except;
struct value *value = NULL;
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
value = value_x_unop (arg2, op, noside);
}
- if (except.reason < 0)
+ CATCH (except, RETURN_MASK_ERROR)
{
if (except.error == NOT_FOUND_ERROR)
break;
else
throw_exception (except);
}
+ END_CATCH
+
arg2 = value;
}
}
function = cp_lookup_symbol_namespace (TYPE_TAG_NAME (type),
name,
get_selected_block (0),
- VAR_DOMAIN);
+ VAR_DOMAIN).symbol;
if (function == NULL)
error (_("No symbol \"%s\" in namespace \"%s\"."),
name, TYPE_TAG_NAME (type));
tem = 1;
+ /* arg2 is left as NULL on purpose. */
}
else
{
|| TYPE_CODE (type) == TYPE_CODE_UNION);
function_name = name;
+ /* We need a properly typed value for method lookup. For
+ static methods arg2 is otherwise unused. */
arg2 = value_zero (type, lval_memory);
++nargs;
tem = 2;
}
}
- /* Evaluate arguments. */
+ /* Evaluate arguments (if not already done, e.g., namespace::func()
+ and overload-resolution is off). */
for (; tem <= nargs; tem++)
{
/* Ensure that array expressions are coerced into pointer
/* Signal end of arglist. */
argvec[tem] = 0;
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
if (op == OP_ADL_FUNC)
{
struct symbol *symp;
NON_METHOD, /* not method */
NULL, NULL, /* pass NULL symbol since
symbol is unknown */
- NULL, &symp, NULL, 0);
+ NULL, &symp, NULL, 0, noside);
/* Now fix the expression being evaluated. */
exp->elts[save_pos1 + 2].symbol = symp;
int static_memfuncp;
char *tstr;
- /* Method invocation : stuff "this" as first parameter. */
+ /* Method invocation: stuff "this" as first parameter.
+ If the method turns out to be static we undo this below. */
argvec[1] = arg2;
if (op != OP_SCOPE)
METHOD, /* method */
&arg2, /* the object */
NULL, &valp, NULL,
- &static_memfuncp, 0);
+ &static_memfuncp, 0, noside);
if (op == OP_SCOPE && !static_memfuncp)
{
argvec[1] = arg2; /* the ``this'' pointer */
}
+ /* Take out `this' if needed. */
if (static_memfuncp)
{
argvec[1] = argvec[0];
NULL, /* no need for name */
NON_METHOD, /* not method */
NULL, function, /* the function */
- NULL, &symp, NULL, no_adl);
+ NULL, &symp, NULL, no_adl, noside);
if (op == OP_VAR_VALUE)
{
do_call_it:
- if (noside == EVAL_SKIP)
- goto nosideret;
if (argvec[0] == NULL)
error (_("Cannot evaluate function -- may be inlined"));
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. */
+ /* 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. */
struct type *ftype = value_type (argvec[0]);
return value_zero (builtin_type (exp->gdbarch)->builtin_int,
not_lval);
}
- else if (TYPE_GNU_IFUNC (ftype))
- return allocate_value (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype)));
- else if (TYPE_TARGET_TYPE (ftype))
- return allocate_value (TYPE_TARGET_TYPE (ftype));
+ else if (TYPE_CODE (ftype) == TYPE_CODE_XMETHOD)
+ {
+ struct type *return_type
+ = result_type_of_xmethod (argvec[0], nargs, argvec + 1);
+
+ if (return_type == NULL)
+ error (_("Xmethod is missing return type."));
+ return value_zero (return_type, not_lval);
+ }
+ else if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+ || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+ struct type *return_type = TYPE_TARGET_TYPE (ftype);
+
+ if (return_type == NULL)
+ return_type = expect_type;
+
+ if (return_type == NULL)
+ error_call_unknown_return_type (NULL);
+
+ return allocate_value (return_type);
+ }
else
error (_("Expression of type other than "
"\"Function returning ...\" used as function"));
}
- if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_INTERNAL_FUNCTION)
- return call_internal_function (exp->gdbarch, exp->language_defn,
- argvec[0], nargs, argvec + 1);
-
- return call_function_by_hand (argvec[0], nargs, argvec + 1);
+ switch (TYPE_CODE (value_type (argvec[0])))
+ {
+ case TYPE_CODE_INTERNAL_FUNCTION:
+ return call_internal_function (exp->gdbarch, exp->language_defn,
+ argvec[0], nargs, argvec + 1);
+ case TYPE_CODE_XMETHOD:
+ return call_xmethod (argvec[0], nargs, argvec + 1);
+ default:
+ return call_function_by_hand (argvec[0],
+ expect_type, nargs, argvec + 1);
+ }
/* pai: FIXME save value from call_function_by_hand, then adjust
pc by adjust_fn_pc if +ve. */
switch (code)
{
case TYPE_CODE_ARRAY:
- if (exp->elts[*pos].opcode == OP_F90_RANGE)
+ if (exp->elts[*pos].opcode == OP_RANGE)
return value_f90_subarray (arg1, exp, pos, noside);
else
goto multi_f77_subscript;
case TYPE_CODE_STRING:
- if (exp->elts[*pos].opcode == OP_F90_RANGE)
+ if (exp->elts[*pos].opcode == OP_RANGE)
return value_f90_subarray (arg1, exp, pos, noside);
else
{
for (; tem <= nargs; tem++)
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
argvec[tem] = 0; /* signal end of arglist */
+ if (noside == EVAL_SKIP)
+ goto nosideret;
goto do_call_it;
default:
arg3 = value_struct_elt (&arg1, NULL, &exp->elts[pc + 2].string,
NULL, "structure");
if (noside == EVAL_AVOID_SIDE_EFFECTS)
- arg3 = value_zero (value_type (arg3), not_lval);
+ arg3 = value_zero (value_type (arg3), VALUE_LVAL (arg3));
return arg3;
case STRUCTOP_PTR:
arg1 with the value returned by evaluating operator->(). */
while (unop_user_defined_p (op, arg1))
{
- volatile struct gdb_exception except;
struct value *value = NULL;
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
value = value_x_unop (arg1, op, noside);
}
- if (except.reason < 0)
+ CATCH (except, RETURN_MASK_ERROR)
{
if (except.error == NOT_FOUND_ERROR)
break;
else
throw_exception (except);
}
+ END_CATCH
+
arg1 = value;
}
{
struct type *type = value_type (arg1);
struct type *real_type;
- int full, top, using_enc;
+ int full, using_enc;
+ LONGEST top;
struct value_print_options opts;
get_user_print_options (&opts);
if (opts.objectprint && TYPE_TARGET_TYPE(type)
- && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT))
{
real_type = value_rtti_indirect_type (arg1, &full, &top,
&using_enc);
arg3 = value_struct_elt (&arg1, NULL, &exp->elts[pc + 2].string,
NULL, "structure pointer");
if (noside == EVAL_AVOID_SIDE_EFFECTS)
- arg3 = value_zero (value_type (arg3), not_lval);
+ arg3 = value_zero (value_type (arg3), VALUE_LVAL (arg3));
return arg3;
case STRUCTOP_MEMBER:
case TYPE_CODE_MEMBERPTR:
/* Now, convert these values to an address. */
- arg1 = value_cast_pointers (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
+ arg1 = value_cast_pointers (lookup_pointer_type (TYPE_SELF_TYPE (type)),
arg1, 1);
mem_offset = value_as_long (arg2);
}
}
- case BINOP_RANGE:
- evaluate_subexp (NULL_TYPE, exp, pos, noside);
- evaluate_subexp (NULL_TYPE, exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- error (_("':' operator used in invalid context"));
-
case BINOP_SUBSCRIPT:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
else
return value_subscript (arg1, value_as_long (arg2));
}
-
- case BINOP_IN:
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- type = language_bool_type (exp->language_defn, exp->gdbarch);
- return value_from_longest (type, (LONGEST) value_in (arg1, arg2));
-
case MULTI_SUBSCRIPT:
(*pos) += 2;
nargs = longest_to_int (exp->elts[pc + 1].longconst);
if (noside == EVAL_SKIP)
goto nosideret;
type = check_typedef (value_type (arg2));
- if (TYPE_CODE (type) != TYPE_CODE_INT)
+ if (TYPE_CODE (type) != TYPE_CODE_INT
+ && TYPE_CODE (type) != TYPE_CODE_ENUM)
error (_("Non-integral right operand for \"@\" operator."));
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
{
type = check_typedef (value_type (arg1));
if (TYPE_CODE (type) == TYPE_CODE_PTR
- || TYPE_CODE (type) == TYPE_CODE_REF
+ || TYPE_IS_REFERENCE (type)
/* In C you can dereference an array to get the 1st elt. */
|| TYPE_CODE (type) == TYPE_CODE_ARRAY
)
evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
goto nosideret;
}
- return evaluate_subexp_for_sizeof (exp, pos);
+ return evaluate_subexp_for_sizeof (exp, pos, noside);
case UNOP_CAST:
(*pos) += 2;
if (noside == EVAL_SKIP)
goto nosideret;
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
- {
- struct type *type = exp->elts[pc + 1].type;
-
- /* If this is a typedef, then find its immediate target. We
- use check_typedef to resolve stubs, but we ignore its
- result because we do not want to dig past all
- typedefs. */
- check_typedef (type);
- if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
- type = TYPE_TARGET_TYPE (type);
- return allocate_value (type);
- }
+ return allocate_value (exp->elts[pc + 1].type);
else
error (_("Attempt to use a type name as an expression"));
{
struct type *type = value_type (result);
- if (TYPE_CODE (check_typedef (type)) != TYPE_CODE_REF)
+ if (!TYPE_IS_REFERENCE (type))
{
- type = lookup_reference_type (type);
+ type = lookup_lvalue_reference_type (type);
result = allocate_value (type);
}
}
/* 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)
+ if (TYPE_IS_REFERENCE (SYMBOL_TYPE (var)))
goto default_case;
(*pos) += 4;
{
struct type *type = check_typedef (value_type (x));
- if (TYPE_CODE (type) == TYPE_CODE_REF)
+ if (TYPE_IS_REFERENCE (type))
return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
not_lval);
else if (VALUE_LVAL (x) == lval_memory || value_must_coerce_to_target (x))
/* Evaluate a subexpression of EXP, at index *POS,
and return a value for the size of that subexpression.
- Advance *POS over the subexpression. */
+ Advance *POS over the subexpression. If NOSIDE is EVAL_NORMAL
+ we allow side-effects on the operand if its type is a variable
+ length array. */
static struct value *
-evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
+evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
+ enum noside noside)
{
/* FIXME: This should be size_t. */
struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
type = check_typedef (value_type (val));
if (TYPE_CODE (type) != TYPE_CODE_PTR
- && TYPE_CODE (type) != TYPE_CODE_REF
+ && !TYPE_IS_REFERENCE (type)
&& TYPE_CODE (type) != TYPE_CODE_ARRAY)
error (_("Attempt to take contents of a non-pointer value."));
- type = check_typedef (TYPE_TARGET_TYPE (type));
+ type = TYPE_TARGET_TYPE (type);
+ if (is_dynamic_type (type))
+ type = value_type (value_ind (val));
return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
case UNOP_MEMVAL:
(*pos) += 3;
- type = check_typedef (exp->elts[pc + 1].type);
- return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
+ type = exp->elts[pc + 1].type;
+ break;
case UNOP_MEMVAL_TYPE:
(*pos) += 1;
val = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- type = check_typedef (value_type (val));
- return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
+ type = value_type (val);
+ break;
case OP_VAR_VALUE:
- (*pos) += 4;
- type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
- return
- value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
+ type = SYMBOL_TYPE (exp->elts[pc + 2].symbol);
+ if (is_dynamic_type (type))
+ {
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+ type = value_type (val);
+ }
+ else
+ (*pos) += 4;
+ break;
+
+ /* Deal with the special case if NOSIDE is EVAL_NORMAL and the resulting
+ type of the subscript is a variable length array type. In this case we
+ must re-evaluate the right hand side of the subcription to allow
+ side-effects. */
+ case BINOP_SUBSCRIPT:
+ if (noside == EVAL_NORMAL)
+ {
+ int pc = (*pos) + 1;
+
+ val = evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+ type = check_typedef (value_type (val));
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ type = TYPE_INDEX_TYPE (type);
+ /* Only re-evaluate the right hand side if the resulting type
+ is a variable length type. */
+ if (TYPE_RANGE_DATA (type)->flag_bound_evaluated)
+ {
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+ return value_from_longest
+ (size_type, (LONGEST) TYPE_LENGTH (value_type (val)));
+ }
+ }
+ }
+ }
+
+ /* Fall through. */
default:
val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_longest (size_type,
- (LONGEST) TYPE_LENGTH (value_type (val)));
+ type = value_type (val);
+ break;
}
+
+ /* $5.3.3/2 of the C++ Standard (n3290 draft) says of sizeof:
+ "When applied to a reference or a reference type, the result is
+ the size of the referenced type." */
+ type = check_typedef (type);
+ if (exp->language_defn->la_language == language_cplus
+ && (TYPE_IS_REFERENCE (type)))
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
}
/* Parse a type expression in the string [P..P+LENGTH). */
parse_and_eval_type (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);
+ expression_up expr = parse_expression (tmp);
if (expr->elts[0].opcode != UNOP_CAST)
error (_("Internal error in eval_type."));
return expr->elts[1].type;