/* Evaluate expressions for GDB.
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2021 Free Software Foundation, Inc.
This file is part of GDB.
evaluate_subexp (struct type *expect_type, struct expression *exp,
int *pos, enum noside noside)
{
- struct value *retval;
-
- gdb::optional<enable_thread_stack_temporaries> stack_temporaries;
- if (*pos == 0 && target_has_execution ()
- && exp->language_defn->la_language == language_cplus
- && !thread_stack_temporaries_enabled_p (inferior_thread ()))
- stack_temporaries.emplace (inferior_thread ());
-
- retval = (*exp->language_defn->expression_ops ()->evaluate_exp)
- (expect_type, exp, pos, noside);
-
- if (stack_temporaries.has_value ()
- && value_in_thread_stack_temporaries (retval, inferior_thread ()))
- retval = value_non_lval (retval);
-
- return retval;
+ return ((*exp->language_defn->expression_ops ()->evaluate_exp)
+ (expect_type, exp, pos, noside));
}
\f
/* Parse the string EXP as a C expression, evaluate it,
}
\f
+/* See expression.h. */
+
+struct value *
+expression::evaluate (struct type *expect_type, enum noside noside)
+{
+ gdb::optional<enable_thread_stack_temporaries> stack_temporaries;
+ if (target_has_execution ()
+ && language_defn->la_language == language_cplus
+ && !thread_stack_temporaries_enabled_p (inferior_thread ()))
+ stack_temporaries.emplace (inferior_thread ());
+
+ int pos = 0;
+ struct value *retval = evaluate_subexp (expect_type, this, &pos, noside);
+
+ if (stack_temporaries.has_value ()
+ && value_in_thread_stack_temporaries (retval, inferior_thread ()))
+ retval = value_non_lval (retval);
+
+ return retval;
+}
+
/* See value.h. */
struct value *
evaluate_expression (struct expression *exp, struct type *expect_type)
{
- int pc = 0;
-
- return evaluate_subexp (expect_type, exp, &pc, EVAL_NORMAL);
+ return exp->evaluate (expect_type, EVAL_NORMAL);
}
/* Evaluate an expression, avoiding all memory references
struct value *
evaluate_type (struct expression *exp)
{
- int pc = 0;
-
- return evaluate_subexp (nullptr, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+ return exp->evaluate (nullptr, EVAL_AVOID_SIDE_EFFECTS);
}
/* Evaluate a subexpression, avoiding all memory references and
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
type = check_typedef (value_type (arg1));
- if (type->code () == TYPE_CODE_PTR
- || TYPE_IS_REFERENCE (type)
- /* In C you can dereference an array to get the 1st elt. */
- || type->code () == TYPE_CODE_ARRAY
- )
- return value_zero (TYPE_TARGET_TYPE (type),
- lval_memory);
- else if (type->code () == TYPE_CODE_INT)
- /* GDB allows dereferencing an int. */
- return value_zero (builtin_type (exp->gdbarch)->builtin_int,
- lval_memory);
- else
- error (_("Attempt to take contents of a non-pointer value."));
+
+ /* If the type pointed to is dynamic then in order to resolve the
+ dynamic properties we must actually dereference the pointer.
+ There is a risk that this dereference will have side-effects
+ in the inferior, but being able to print accurate type
+ information seems worth the risk. */
+ if ((type->code () != TYPE_CODE_PTR
+ && !TYPE_IS_REFERENCE (type))
+ || !is_dynamic_type (TYPE_TARGET_TYPE (type)))
+ {
+ if (type->code () == TYPE_CODE_PTR
+ || TYPE_IS_REFERENCE (type)
+ /* In C you can dereference an array to get the 1st elt. */
+ || type->code () == TYPE_CODE_ARRAY)
+ return value_zero (TYPE_TARGET_TYPE (type),
+ lval_memory);
+ else if (type->code () == TYPE_CODE_INT)
+ /* GDB allows dereferencing an int. */
+ return value_zero (builtin_type (exp->gdbarch)->builtin_int,
+ lval_memory);
+ else
+ error (_("Attempt to take contents of a non-pointer value."));
+ }
}
/* Allow * on an integer so we can cast it to whatever we want.