|  | /* Evaluate expressions for GDB. | 
|  |  | 
|  | Copyright (C) 1986-2025 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 3 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, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #include "symtab.h" | 
|  | #include "gdbtypes.h" | 
|  | #include "value.h" | 
|  | #include "expression.h" | 
|  | #include "target.h" | 
|  | #include "frame.h" | 
|  | #include "gdbthread.h" | 
|  | #include "language.h" | 
|  | #include "cp-abi.h" | 
|  | #include "infcall.h" | 
|  | #include "objc-lang.h" | 
|  | #include "block.h" | 
|  | #include "parser-defs.h" | 
|  | #include "cp-support.h" | 
|  | #include "ui-out.h" | 
|  | #include "regcache.h" | 
|  | #include "user-regs.h" | 
|  | #include "valprint.h" | 
|  | #include "gdbsupport/gdb_obstack.h" | 
|  | #include "objfiles.h" | 
|  | #include "typeprint.h" | 
|  | #include "expop.h" | 
|  | #include "c-exp.h" | 
|  | #include "inferior.h" | 
|  |  | 
|  |  | 
|  | /* Parse the string EXP as a C expression, evaluate it, | 
|  | and return the result as a number.  */ | 
|  |  | 
|  | CORE_ADDR | 
|  | parse_and_eval_address (const char *exp) | 
|  | { | 
|  | expression_up expr = parse_expression (exp); | 
|  |  | 
|  | return value_as_address (expr->evaluate ()); | 
|  | } | 
|  |  | 
|  | /* Like parse_and_eval_address, but treats the value of the expression | 
|  | as an integer, not an address, returns a LONGEST, not a CORE_ADDR.  */ | 
|  | LONGEST | 
|  | parse_and_eval_long (const char *exp) | 
|  | { | 
|  | expression_up expr = parse_expression (exp); | 
|  |  | 
|  | return value_as_long (expr->evaluate ()); | 
|  | } | 
|  |  | 
|  | struct value * | 
|  | parse_and_eval (const char *exp, parser_flags flags) | 
|  | { | 
|  | expression_up expr = parse_expression (exp, nullptr, flags); | 
|  |  | 
|  | return expr->evaluate (); | 
|  | } | 
|  |  | 
|  | /* 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.  */ | 
|  |  | 
|  | struct value * | 
|  | parse_to_comma_and_eval (const char **expp) | 
|  | { | 
|  | expression_up expr = parse_exp_1 (expp, 0, nullptr, | 
|  | PARSER_COMMA_TERMINATES); | 
|  |  | 
|  | return expr->evaluate (); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* See expression.h.  */ | 
|  |  | 
|  | bool | 
|  | expression::uses_objfile (struct objfile *objfile) const | 
|  | { | 
|  | gdb_assert (objfile->separate_debug_objfile_backlink == nullptr); | 
|  | return op->uses_objfile (objfile); | 
|  | } | 
|  |  | 
|  | /* See expression.h.  */ | 
|  |  | 
|  | struct value * | 
|  | expression::evaluate (struct type *expect_type, enum noside noside) | 
|  | { | 
|  | std::optional<enable_thread_stack_temporaries> stack_temporaries; | 
|  | if (target_has_execution () && inferior_ptid != null_ptid | 
|  | && language_defn->la_language == language_cplus | 
|  | && !thread_stack_temporaries_enabled_p (inferior_thread ())) | 
|  | stack_temporaries.emplace (inferior_thread ()); | 
|  |  | 
|  | struct value *retval = op->evaluate (expect_type, this, noside); | 
|  |  | 
|  | if (stack_temporaries.has_value () | 
|  | && value_in_thread_stack_temporaries (retval, inferior_thread ())) | 
|  | retval = retval->non_lval (); | 
|  |  | 
|  | return retval; | 
|  | } | 
|  |  | 
|  | /* Find the current value of a watchpoint on EXP.  Return the value in | 
|  | *VALP and *RESULTP and the chain of intermediate and final values | 
|  | in *VAL_CHAIN.  RESULTP and VAL_CHAIN may be NULL if the caller does | 
|  | not need them. | 
|  |  | 
|  | If PRESERVE_ERRORS is true, then exceptions are passed through. | 
|  | Otherwise, if PRESERVE_ERRORS is false, then if a memory error | 
|  | occurs while evaluating the expression, *RESULTP will be set to | 
|  | NULL.  *RESULTP may be a lazy value, if the result could not be | 
|  | read from memory.  It is used to determine whether a value is | 
|  | user-specified (we should watch the whole value) or intermediate | 
|  | (we should watch only the bit used to locate the final value). | 
|  |  | 
|  | If the final value, or any intermediate value, could not be read | 
|  | from memory, *VALP will be set to NULL.  *VAL_CHAIN will still be | 
|  | set to any referenced values.  *VALP will never be a lazy value. | 
|  | This is the value which we store in struct breakpoint. | 
|  |  | 
|  | If VAL_CHAIN is non-NULL, the values put into *VAL_CHAIN will be | 
|  | released from the value chain.  If VAL_CHAIN is NULL, all generated | 
|  | values will be left on the value chain.  */ | 
|  |  | 
|  | void | 
|  | fetch_subexp_value (struct expression *exp, | 
|  | expr::operation *op, | 
|  | struct value **valp, struct value **resultp, | 
|  | std::vector<value_ref_ptr> *val_chain, | 
|  | bool preserve_errors) | 
|  | { | 
|  | struct value *mark, *new_mark, *result; | 
|  |  | 
|  | *valp = NULL; | 
|  | if (resultp) | 
|  | *resultp = NULL; | 
|  | if (val_chain) | 
|  | val_chain->clear (); | 
|  |  | 
|  | /* Evaluate the expression.  */ | 
|  | mark = value_mark (); | 
|  | result = NULL; | 
|  |  | 
|  | try | 
|  | { | 
|  | result = op->evaluate (nullptr, exp, EVAL_NORMAL); | 
|  | } | 
|  | catch (const gdb_exception &ex) | 
|  | { | 
|  | /* Ignore memory errors if we want watchpoints pointing at | 
|  | inaccessible memory to still be created; otherwise, throw the | 
|  | error to some higher catcher.  */ | 
|  | switch (ex.error) | 
|  | { | 
|  | case MEMORY_ERROR: | 
|  | if (!preserve_errors) | 
|  | break; | 
|  | [[fallthrough]]; | 
|  | default: | 
|  | throw; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | new_mark = value_mark (); | 
|  | if (mark == new_mark) | 
|  | return; | 
|  | if (resultp) | 
|  | *resultp = result; | 
|  |  | 
|  | /* Make sure it's not lazy, so that after the target stops again we | 
|  | have a non-lazy previous value to compare with.  */ | 
|  | if (result != NULL) | 
|  | { | 
|  | if (!result->lazy ()) | 
|  | *valp = result; | 
|  | else | 
|  | { | 
|  |  | 
|  | try | 
|  | { | 
|  | result->fetch_lazy (); | 
|  | *valp = result; | 
|  | } | 
|  | catch (const gdb_exception_error &except) | 
|  | { | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (val_chain) | 
|  | { | 
|  | /* Return the chain of intermediate values.  We use this to | 
|  | decide which addresses to watch.  */ | 
|  | *val_chain = value_release_to_mark (mark); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Promote value ARG1 as appropriate before performing a unary operation | 
|  | on this argument. | 
|  | If the result is not appropriate for any particular language then it | 
|  | needs to patch this function.  */ | 
|  |  | 
|  | void | 
|  | unop_promote (const struct language_defn *language, struct gdbarch *gdbarch, | 
|  | struct value **arg1) | 
|  | { | 
|  | struct type *type1; | 
|  |  | 
|  | *arg1 = coerce_ref (*arg1); | 
|  | type1 = check_typedef ((*arg1)->type ()); | 
|  |  | 
|  | if (is_integral_type (type1)) | 
|  | { | 
|  | switch (language->la_language) | 
|  | { | 
|  | default: | 
|  | /* Perform integral promotion for ANSI C/C++. | 
|  | If not appropriate for any particular language | 
|  | it needs to modify this function.  */ | 
|  | { | 
|  | struct type *builtin_int = builtin_type (gdbarch)->builtin_int; | 
|  |  | 
|  | if (type1->length () < builtin_int->length ()) | 
|  | *arg1 = value_cast (builtin_int, *arg1); | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Promote values ARG1 and ARG2 as appropriate before performing a binary | 
|  | operation on those two operands. | 
|  | If the result is not appropriate for any particular language then it | 
|  | needs to patch this function.  */ | 
|  |  | 
|  | void | 
|  | binop_promote (const struct language_defn *language, struct gdbarch *gdbarch, | 
|  | struct value **arg1, struct value **arg2) | 
|  | { | 
|  | struct type *promoted_type = NULL; | 
|  | struct type *type1; | 
|  | struct type *type2; | 
|  |  | 
|  | *arg1 = coerce_ref (*arg1); | 
|  | *arg2 = coerce_ref (*arg2); | 
|  |  | 
|  | type1 = check_typedef ((*arg1)->type ()); | 
|  | type2 = check_typedef ((*arg2)->type ()); | 
|  |  | 
|  | if ((type1->code () != TYPE_CODE_FLT | 
|  | && type1->code () != TYPE_CODE_DECFLOAT | 
|  | && !is_integral_type (type1)) | 
|  | || (type2->code () != TYPE_CODE_FLT | 
|  | && type2->code () != TYPE_CODE_DECFLOAT | 
|  | && !is_integral_type (type2))) | 
|  | return; | 
|  |  | 
|  | if (is_fixed_point_type (type1) || is_fixed_point_type (type2)) | 
|  | return; | 
|  |  | 
|  | if (type1->code () == TYPE_CODE_DECFLOAT | 
|  | || type2->code () == TYPE_CODE_DECFLOAT) | 
|  | { | 
|  | /* No promotion required.  */ | 
|  | } | 
|  | else if (type1->code () == TYPE_CODE_FLT | 
|  | || type2->code () == TYPE_CODE_FLT) | 
|  | { | 
|  | switch (language->la_language) | 
|  | { | 
|  | case language_c: | 
|  | case language_cplus: | 
|  | case language_asm: | 
|  | case language_objc: | 
|  | case language_opencl: | 
|  | /* No promotion required.  */ | 
|  | break; | 
|  |  | 
|  | default: | 
|  | /* For other languages the result type is unchanged from gdb | 
|  | version 6.7 for backward compatibility. | 
|  | If either arg was long double, make sure that value is also long | 
|  | double.  Otherwise use double.  */ | 
|  | if (type1->length () * 8 > gdbarch_double_bit (gdbarch) | 
|  | || type2->length () * 8 > gdbarch_double_bit (gdbarch)) | 
|  | promoted_type = builtin_type (gdbarch)->builtin_long_double; | 
|  | else | 
|  | promoted_type = builtin_type (gdbarch)->builtin_double; | 
|  | break; | 
|  | } | 
|  | } | 
|  | else if (type1->code () == TYPE_CODE_BOOL | 
|  | && type2->code () == TYPE_CODE_BOOL) | 
|  | { | 
|  | /* No promotion required.  */ | 
|  | } | 
|  | else | 
|  | /* Integral operations here.  */ | 
|  | /* FIXME: Also mixed integral/booleans, with result an integer.  */ | 
|  | { | 
|  | const struct builtin_type *builtin = builtin_type (gdbarch); | 
|  | unsigned int promoted_len1 = type1->length (); | 
|  | unsigned int promoted_len2 = type2->length (); | 
|  | int is_unsigned1 = type1->is_unsigned (); | 
|  | int is_unsigned2 = type2->is_unsigned (); | 
|  | unsigned int result_len; | 
|  | int unsigned_operation; | 
|  |  | 
|  | /* Determine type length and signedness after promotion for | 
|  | both operands.  */ | 
|  | if (promoted_len1 < builtin->builtin_int->length ()) | 
|  | { | 
|  | is_unsigned1 = 0; | 
|  | promoted_len1 = builtin->builtin_int->length (); | 
|  | } | 
|  | if (promoted_len2 < builtin->builtin_int->length ()) | 
|  | { | 
|  | is_unsigned2 = 0; | 
|  | promoted_len2 = builtin->builtin_int->length (); | 
|  | } | 
|  |  | 
|  | if (promoted_len1 > promoted_len2) | 
|  | { | 
|  | unsigned_operation = is_unsigned1; | 
|  | result_len = promoted_len1; | 
|  | } | 
|  | else if (promoted_len2 > promoted_len1) | 
|  | { | 
|  | unsigned_operation = is_unsigned2; | 
|  | result_len = promoted_len2; | 
|  | } | 
|  | else | 
|  | { | 
|  | unsigned_operation = is_unsigned1 || is_unsigned2; | 
|  | result_len = promoted_len1; | 
|  | } | 
|  |  | 
|  | switch (language->la_language) | 
|  | { | 
|  | case language_opencl: | 
|  | if (result_len | 
|  | <= lookup_signed_typename (language, "int")->length()) | 
|  | { | 
|  | promoted_type = | 
|  | (unsigned_operation | 
|  | ? lookup_unsigned_typename (language, "int") | 
|  | : lookup_signed_typename (language, "int")); | 
|  | } | 
|  | else if (result_len | 
|  | <= lookup_signed_typename (language, "long")->length()) | 
|  | { | 
|  | promoted_type = | 
|  | (unsigned_operation | 
|  | ? lookup_unsigned_typename (language, "long") | 
|  | : lookup_signed_typename (language,"long")); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | if (result_len <= builtin->builtin_int->length ()) | 
|  | { | 
|  | promoted_type = (unsigned_operation | 
|  | ? builtin->builtin_unsigned_int | 
|  | : builtin->builtin_int); | 
|  | } | 
|  | else if (result_len <= builtin->builtin_long->length ()) | 
|  | { | 
|  | promoted_type = (unsigned_operation | 
|  | ? builtin->builtin_unsigned_long | 
|  | : builtin->builtin_long); | 
|  | } | 
|  | else if (result_len <= builtin->builtin_long_long->length ()) | 
|  | { | 
|  | promoted_type = (unsigned_operation | 
|  | ? builtin->builtin_unsigned_long_long | 
|  | : builtin->builtin_long_long); | 
|  | } | 
|  | else | 
|  | { | 
|  | promoted_type = (unsigned_operation | 
|  | ? builtin->builtin_uint128 | 
|  | : builtin->builtin_int128); | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (promoted_type) | 
|  | { | 
|  | /* Promote both operands to common type.  */ | 
|  | *arg1 = value_cast (promoted_type, *arg1); | 
|  | *arg2 = value_cast (promoted_type, *arg2); | 
|  | } | 
|  | } | 
|  |  | 
|  | static int | 
|  | ptrmath_type_p (const struct language_defn *lang, struct type *type) | 
|  | { | 
|  | type = check_typedef (type); | 
|  | if (TYPE_IS_REFERENCE (type)) | 
|  | type = type->target_type (); | 
|  |  | 
|  | switch (type->code ()) | 
|  | { | 
|  | case TYPE_CODE_PTR: | 
|  | case TYPE_CODE_FUNC: | 
|  | return 1; | 
|  |  | 
|  | case TYPE_CODE_ARRAY: | 
|  | return type->is_vector () ? 0 : lang->c_style_arrays_p (); | 
|  |  | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Represents a fake method with the given parameter types.  This is | 
|  | used by the parser to construct a temporary "expected" type for | 
|  | method overload resolution.  FLAGS is used as instance flags of the | 
|  | new type, in order to be able to make the new type represent a | 
|  | const/volatile overload.  */ | 
|  |  | 
|  | class fake_method | 
|  | { | 
|  | public: | 
|  | fake_method (type_instance_flags flags, | 
|  | int num_types, struct type **param_types); | 
|  | ~fake_method (); | 
|  |  | 
|  | /* The constructed type.  */ | 
|  | struct type *type () { return &m_type; } | 
|  |  | 
|  | private: | 
|  | struct type m_type {}; | 
|  | main_type m_main_type {}; | 
|  | }; | 
|  |  | 
|  | fake_method::fake_method (type_instance_flags flags, | 
|  | int num_types, struct type **param_types) | 
|  | { | 
|  | struct type *type = &m_type; | 
|  |  | 
|  | TYPE_MAIN_TYPE (type) = &m_main_type; | 
|  | type->set_length (1); | 
|  | type->set_code (TYPE_CODE_METHOD); | 
|  | TYPE_CHAIN (type) = type; | 
|  | type->set_instance_flags (flags); | 
|  | if (num_types > 0) | 
|  | { | 
|  | if (param_types[num_types - 1] == NULL) | 
|  | { | 
|  | --num_types; | 
|  | type->set_has_varargs (true); | 
|  | } | 
|  | else if (check_typedef (param_types[num_types - 1])->code () | 
|  | == TYPE_CODE_VOID) | 
|  | { | 
|  | --num_types; | 
|  | /* Caller should have ensured this.  */ | 
|  | gdb_assert (num_types == 0); | 
|  | type->set_is_prototyped (true); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* We don't use TYPE_ZALLOC here to allocate space as TYPE is owned by | 
|  | neither an objfile nor a gdbarch.  As a result we must manually | 
|  | allocate memory for auxiliary fields, and free the memory ourselves | 
|  | when we are done with it.  */ | 
|  | type->set_num_fields (num_types); | 
|  | type->set_fields | 
|  | ((struct field *) xzalloc (sizeof (struct field) * num_types)); | 
|  |  | 
|  | while (num_types-- > 0) | 
|  | type->field (num_types).set_type (param_types[num_types]); | 
|  | } | 
|  |  | 
|  | fake_method::~fake_method () | 
|  | { | 
|  | xfree (m_type.fields ().data ()); | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | value * | 
|  | type_instance_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | type_instance_flags flags = std::get<0> (m_storage); | 
|  | std::vector<type *> &types = std::get<1> (m_storage); | 
|  |  | 
|  | fake_method fake_expect_type (flags, types.size (), types.data ()); | 
|  | return std::get<2> (m_storage)->evaluate (fake_expect_type.type (), | 
|  | exp, noside); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* Helper for evaluating an OP_VAR_VALUE.  */ | 
|  |  | 
|  | value * | 
|  | evaluate_var_value (enum noside noside, const block *blk, symbol *var) | 
|  | { | 
|  | /* JYG: We used to just return value::zero of the symbol type if | 
|  | we're asked to avoid side effects.  Otherwise we return | 
|  | value_of_variable (...).  However I'm not sure if | 
|  | value_of_variable () has any side effect.  We need a full value | 
|  | object returned here for whatis_exp () to call evaluate_type () | 
|  | and then pass the full value to value_rtti_target_type () if we | 
|  | are dealing with a pointer or reference to a base class and print | 
|  | object is on.  */ | 
|  |  | 
|  | struct value *ret = NULL; | 
|  |  | 
|  | try | 
|  | { | 
|  | ret = value_of_variable (var, blk); | 
|  | } | 
|  |  | 
|  | catch (const gdb_exception_error &except) | 
|  | { | 
|  | if (noside != EVAL_AVOID_SIDE_EFFECTS) | 
|  | throw; | 
|  |  | 
|  | ret = value::zero (var->type (), not_lval); | 
|  | } | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  |  | 
|  | { | 
|  |  | 
|  | value * | 
|  | var_value_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | symbol *var = std::get<0> (m_storage).symbol; | 
|  | if (var->type ()->code () == TYPE_CODE_ERROR) | 
|  | error_unknown_type (var->print_name ()); | 
|  | return evaluate_var_value (noside, std::get<0> (m_storage).block, var); | 
|  | } | 
|  |  | 
|  | } /* namespace expr */ | 
|  |  | 
|  | /* Helper for evaluating an OP_VAR_MSYM_VALUE.  */ | 
|  |  | 
|  | value * | 
|  | evaluate_var_msym_value (enum noside noside, | 
|  | struct objfile *objfile, minimal_symbol *msymbol) | 
|  | { | 
|  | CORE_ADDR address; | 
|  | type *the_type = find_minsym_type_and_address (msymbol, objfile, &address); | 
|  |  | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS && !the_type->is_gnu_ifunc ()) | 
|  | return value::zero (the_type, not_lval); | 
|  | else | 
|  | return value_at_lazy (the_type, address); | 
|  | } | 
|  |  | 
|  | /* See expression.h.  */ | 
|  |  | 
|  | value * | 
|  | evaluate_subexp_do_call (expression *exp, enum noside noside, | 
|  | value *callee, | 
|  | gdb::array_view<value *> argvec, | 
|  | const char *function_name, | 
|  | type *default_return_type) | 
|  | { | 
|  | if (callee == NULL) | 
|  | error (_("Cannot evaluate function -- may be inlined")); | 
|  |  | 
|  | type *ftype = callee->type (); | 
|  |  | 
|  | /* If the callee is a struct, there might be a user-defined function call | 
|  | operator that should be used instead.  */ | 
|  | std::vector<value *> vals; | 
|  | if (overload_resolution | 
|  | && exp->language_defn->la_language == language_cplus | 
|  | && check_typedef (ftype)->code () == TYPE_CODE_STRUCT) | 
|  | { | 
|  | /* Include space for the `this' pointer at the start.  */ | 
|  | vals.resize (argvec.size () + 1); | 
|  |  | 
|  | vals[0] = value_addr (callee); | 
|  | for (int i = 0; i < argvec.size (); ++i) | 
|  | vals[i + 1] = argvec[i]; | 
|  |  | 
|  | int static_memfuncp; | 
|  | find_overload_match (vals, "operator()", METHOD, &vals[0], nullptr, | 
|  | &callee, nullptr, &static_memfuncp, 0, noside); | 
|  | if (!static_memfuncp) | 
|  | argvec = vals; | 
|  |  | 
|  | ftype = callee->type (); | 
|  | } | 
|  |  | 
|  | 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.  */ | 
|  |  | 
|  | if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION) | 
|  | { | 
|  | /* The call to call_internal_function below handles noside.  */ | 
|  | } | 
|  | else if (ftype->code () == TYPE_CODE_XMETHOD) | 
|  | { | 
|  | type *return_type = callee->result_type_of_xmethod (argvec); | 
|  |  | 
|  | if (return_type == NULL) | 
|  | error (_("Xmethod is missing return type.")); | 
|  | return value::zero (return_type, not_lval); | 
|  | } | 
|  | else if (ftype->code () == TYPE_CODE_FUNC | 
|  | || ftype->code () == TYPE_CODE_METHOD) | 
|  | { | 
|  | if (ftype->is_gnu_ifunc ()) | 
|  | { | 
|  | CORE_ADDR address = callee->address (); | 
|  | type *resolved_type = find_gnu_ifunc_target_type (address); | 
|  |  | 
|  | if (resolved_type != NULL) | 
|  | ftype = resolved_type; | 
|  | } | 
|  |  | 
|  | type *return_type = ftype->target_type (); | 
|  |  | 
|  | if (return_type == NULL) | 
|  | return_type = default_return_type; | 
|  |  | 
|  | if (return_type == NULL) | 
|  | error_call_unknown_return_type (function_name); | 
|  |  | 
|  | return value::allocate (return_type); | 
|  | } | 
|  | else | 
|  | error (_("Expression of type other than " | 
|  | "\"Function returning ...\" used as function")); | 
|  | } | 
|  | switch (callee->type ()->code ()) | 
|  | { | 
|  | case TYPE_CODE_INTERNAL_FUNCTION: | 
|  | return call_internal_function (exp->gdbarch, exp->language_defn, | 
|  | callee, argvec.size (), argvec.data (), | 
|  | noside); | 
|  | case TYPE_CODE_XMETHOD: | 
|  | return callee->call_xmethod (argvec); | 
|  | default: | 
|  | return call_function_by_hand (callee, default_return_type, argvec); | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | value * | 
|  | operation::evaluate_funcall (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside, | 
|  | const char *function_name, | 
|  | const std::vector<operation_up> &args) | 
|  | { | 
|  | std::vector<value *> vals (args.size ()); | 
|  |  | 
|  | value *callee = evaluate_with_coercion (exp, noside); | 
|  | struct type *type = callee->type (); | 
|  | if (type->code () == TYPE_CODE_PTR) | 
|  | type = type->target_type (); | 
|  | /* If type is a struct, num_fields would refer to the number of | 
|  | members in the type, not the number of arguments.  */ | 
|  | bool type_has_arguments | 
|  | = type->code () == TYPE_CODE_FUNC || type->code () == TYPE_CODE_METHOD; | 
|  | for (int i = 0; i < args.size (); ++i) | 
|  | { | 
|  | if (type_has_arguments && i < type->num_fields ()) | 
|  | vals[i] = args[i]->evaluate (type->field (i).type (), exp, noside); | 
|  | else | 
|  | vals[i] = args[i]->evaluate_with_coercion (exp, noside); | 
|  | } | 
|  |  | 
|  | return evaluate_subexp_do_call (exp, noside, callee, vals, | 
|  | function_name, expect_type); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_value_operation::evaluate_funcall (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside, | 
|  | const std::vector<operation_up> &args) | 
|  | { | 
|  | if (!overload_resolution | 
|  | || exp->language_defn->la_language != language_cplus) | 
|  | return operation::evaluate_funcall (expect_type, exp, noside, args); | 
|  |  | 
|  | std::vector<value *> argvec (args.size ()); | 
|  | for (int i = 0; i < args.size (); ++i) | 
|  | argvec[i] = args[i]->evaluate_with_coercion (exp, noside); | 
|  |  | 
|  | struct symbol *symp; | 
|  | find_overload_match (argvec, NULL, NON_METHOD, | 
|  | NULL, std::get<0> (m_storage).symbol, | 
|  | NULL, &symp, NULL, 0, noside); | 
|  |  | 
|  | if (symp->type ()->code () == TYPE_CODE_ERROR) | 
|  | error_unknown_type (symp->print_name ()); | 
|  | value *callee = evaluate_var_value (noside, std::get<0> (m_storage).block, | 
|  | symp); | 
|  |  | 
|  | return evaluate_subexp_do_call (exp, noside, callee, argvec, | 
|  | nullptr, expect_type); | 
|  | } | 
|  |  | 
|  | value * | 
|  | scope_operation::evaluate_funcall (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside, | 
|  | const std::vector<operation_up> &args) | 
|  | { | 
|  | if (!overload_resolution | 
|  | || exp->language_defn->la_language != language_cplus) | 
|  | return operation::evaluate_funcall (expect_type, exp, noside, args); | 
|  |  | 
|  | /* Unpack it locally so we can properly handle overload | 
|  | resolution.  */ | 
|  | const std::string &name = std::get<1> (m_storage); | 
|  | struct type *type = std::get<0> (m_storage); | 
|  |  | 
|  | symbol *function = NULL; | 
|  | const char *function_name = NULL; | 
|  | std::vector<value *> argvec (1 + args.size ()); | 
|  | if (type->code () == TYPE_CODE_NAMESPACE) | 
|  | { | 
|  | function = cp_lookup_symbol_namespace (type->name (), | 
|  | name.c_str (), | 
|  | get_selected_block (0), | 
|  | SEARCH_FUNCTION_DOMAIN).symbol; | 
|  | if (function == NULL) | 
|  | error (_("No symbol \"%s\" in namespace \"%s\"."), | 
|  | name.c_str (), type->name ()); | 
|  | } | 
|  | else | 
|  | { | 
|  | gdb_assert (type->code () == TYPE_CODE_STRUCT | 
|  | || type->code () == TYPE_CODE_UNION); | 
|  | function_name = name.c_str (); | 
|  |  | 
|  | /* We need a properly typed value for method lookup.  */ | 
|  | argvec[0] = value::zero (type, lval_memory); | 
|  | } | 
|  |  | 
|  | for (int i = 0; i < args.size (); ++i) | 
|  | argvec[i + 1] = args[i]->evaluate_with_coercion (exp, noside); | 
|  | gdb::array_view<value *> arg_view = argvec; | 
|  |  | 
|  | value *callee = nullptr; | 
|  | if (function_name != nullptr) | 
|  | { | 
|  | int static_memfuncp; | 
|  |  | 
|  | find_overload_match (arg_view, function_name, METHOD, | 
|  | &argvec[0], nullptr, &callee, nullptr, | 
|  | &static_memfuncp, 0, noside); | 
|  | if (!static_memfuncp) | 
|  | { | 
|  | /* For the time being, we don't handle this.  */ | 
|  | error (_("Call to overloaded function %s requires " | 
|  | "`this' pointer"), | 
|  | function_name); | 
|  | } | 
|  |  | 
|  | arg_view = arg_view.slice (1); | 
|  | } | 
|  | else | 
|  | { | 
|  | symbol *symp; | 
|  | arg_view = arg_view.slice (1); | 
|  | find_overload_match (arg_view, nullptr, | 
|  | NON_METHOD, nullptr, function, | 
|  | nullptr, &symp, nullptr, 1, noside); | 
|  | callee = value_of_variable (symp, get_selected_block (0)); | 
|  | } | 
|  |  | 
|  | return evaluate_subexp_do_call (exp, noside, callee, arg_view, | 
|  | nullptr, expect_type); | 
|  | } | 
|  |  | 
|  | value * | 
|  | structop_member_base::evaluate_funcall (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside, | 
|  | const std::vector<operation_up> &args) | 
|  | { | 
|  | /* First, evaluate the structure into lhs.  */ | 
|  | value *lhs; | 
|  | if (opcode () == STRUCTOP_MEMBER) | 
|  | lhs = std::get<0> (m_storage)->evaluate_for_address (exp, noside); | 
|  | else | 
|  | lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  |  | 
|  | std::vector<value *> vals (args.size () + 1); | 
|  | gdb::array_view<value *> val_view = vals; | 
|  | /* 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.  */ | 
|  | value *rhs = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | value *callee; | 
|  |  | 
|  | type *a1_type = check_typedef (rhs->type ()); | 
|  | if (a1_type->code () == TYPE_CODE_METHODPTR) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | callee = value::zero (a1_type->target_type (), not_lval); | 
|  | else | 
|  | callee = cplus_method_ptr_to_value (&lhs, rhs); | 
|  |  | 
|  | vals[0] = lhs; | 
|  | } | 
|  | else if (a1_type->code () == TYPE_CODE_MEMBERPTR) | 
|  | { | 
|  | struct type *type_ptr | 
|  | = lookup_pointer_type (TYPE_SELF_TYPE (a1_type)); | 
|  | struct type *target_type_ptr | 
|  | = lookup_pointer_type (a1_type->target_type ()); | 
|  |  | 
|  | /* Now, convert this value to an address.  */ | 
|  | lhs = value_cast (type_ptr, lhs); | 
|  |  | 
|  | long mem_offset = value_as_long (rhs); | 
|  |  | 
|  | callee = value_from_pointer (target_type_ptr, | 
|  | value_as_long (lhs) + mem_offset); | 
|  | callee = value_ind (callee); | 
|  |  | 
|  | val_view = val_view.slice (1); | 
|  | } | 
|  | else | 
|  | error (_("Non-pointer-to-member value used in pointer-to-member " | 
|  | "construct")); | 
|  |  | 
|  | for (int i = 0; i < args.size (); ++i) | 
|  | vals[i + 1] = args[i]->evaluate_with_coercion (exp, noside); | 
|  |  | 
|  | return evaluate_subexp_do_call (exp, noside, callee, val_view, | 
|  | nullptr, expect_type); | 
|  |  | 
|  | } | 
|  |  | 
|  | value * | 
|  | structop_base_operation::evaluate_funcall | 
|  | (struct type *expect_type, struct expression *exp, enum noside noside, | 
|  | const std::vector<operation_up> &args) | 
|  | { | 
|  | /* Allocate space for the function call arguments, Including space for a | 
|  | `this' pointer at the start.  */ | 
|  | std::vector<value *> vals (args.size () + 1); | 
|  | /* First, evaluate the structure into vals[0].  */ | 
|  | enum exp_opcode op = opcode (); | 
|  | if (op == STRUCTOP_STRUCT) | 
|  | { | 
|  | /* If v is a variable in a register, and the user types | 
|  | v.method (), this will produce an error, because v has no | 
|  | address. | 
|  |  | 
|  | A possible way around this would be to allocate a copy of | 
|  | the variable on the stack, copy in the contents, call the | 
|  | function, and copy out the contents.  I.e. convert this | 
|  | from call by reference to call by copy-return (or | 
|  | whatever it's called).  However, this does not work | 
|  | because it is not the same: the method being called could | 
|  | stash a copy of the address, and then future uses through | 
|  | that address (after the method returns) would be expected | 
|  | to use the variable itself, not some copy of it.  */ | 
|  | vals[0] = std::get<0> (m_storage)->evaluate_for_address (exp, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | vals[0] = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | /* Check to see if the operator '->' has been overloaded. | 
|  | If the operator has been overloaded replace vals[0] with the | 
|  | value returned by the custom operator and continue | 
|  | evaluation.  */ | 
|  | while (unop_user_defined_p (op, vals[0])) | 
|  | { | 
|  | struct value *value = nullptr; | 
|  | try | 
|  | { | 
|  | value = value_x_unop (vals[0], op, noside); | 
|  | } | 
|  | catch (const gdb_exception_error &except) | 
|  | { | 
|  | if (except.error == NOT_FOUND_ERROR) | 
|  | break; | 
|  | else | 
|  | throw; | 
|  | } | 
|  |  | 
|  | vals[0] = value; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Evaluate the arguments.  The '+ 1' here is to allow for the `this' | 
|  | pointer we placed into vals[0].  */ | 
|  | for (int i = 0; i < args.size (); ++i) | 
|  | vals[i + 1] = args[i]->evaluate_with_coercion (exp, noside); | 
|  |  | 
|  | /* The array view includes the `this' pointer.  */ | 
|  | gdb::array_view<value *> arg_view (vals); | 
|  |  | 
|  | int static_memfuncp; | 
|  | value *callee; | 
|  | const char *tstr = std::get<1> (m_storage).c_str (); | 
|  | if (overload_resolution | 
|  | && exp->language_defn->la_language == language_cplus) | 
|  | { | 
|  | /* Language is C++, do some overload resolution before | 
|  | evaluation.  */ | 
|  | value *val0 = vals[0]; | 
|  | find_overload_match (arg_view, tstr, METHOD, | 
|  | &val0, nullptr, &callee, nullptr, | 
|  | &static_memfuncp, 0, noside); | 
|  | vals[0] = val0; | 
|  | } | 
|  | else | 
|  | /* Non-C++ case -- or no overload resolution.  */ | 
|  | { | 
|  | struct value *temp = vals[0]; | 
|  |  | 
|  | callee = value_struct_elt (&temp, arg_view, tstr, | 
|  | &static_memfuncp, | 
|  | op == STRUCTOP_STRUCT | 
|  | ? "structure" : "structure pointer"); | 
|  | /* value_struct_elt updates temp with the correct value of the | 
|  | ``this'' pointer if necessary, so modify it to reflect any | 
|  | ``this'' changes.  */ | 
|  | vals[0] = value_from_longest (lookup_pointer_type (temp->type ()), | 
|  | temp->address () | 
|  | + temp->embedded_offset ()); | 
|  | } | 
|  |  | 
|  | /* Take out `this' if needed.  */ | 
|  | if (static_memfuncp) | 
|  | arg_view = arg_view.slice (1); | 
|  |  | 
|  | return evaluate_subexp_do_call (exp, noside, callee, arg_view, | 
|  | nullptr, expect_type); | 
|  | } | 
|  |  | 
|  | /* Helper for structop_base_operation::complete which recursively adds | 
|  | field and method names from TYPE, a struct or union type, to the | 
|  | OUTPUT list.  PREFIX is prepended to each result.  */ | 
|  |  | 
|  | static void | 
|  | add_struct_fields (struct type *type, completion_list &output, | 
|  | const char *fieldname, int namelen, const char *prefix) | 
|  | { | 
|  | int i; | 
|  | int computed_type_name = 0; | 
|  | const char *type_name = NULL; | 
|  |  | 
|  | type = check_typedef (type); | 
|  | for (i = 0; i < type->num_fields (); ++i) | 
|  | { | 
|  | if (i < TYPE_N_BASECLASSES (type)) | 
|  | add_struct_fields (TYPE_BASECLASS (type, i), | 
|  | output, fieldname, namelen, prefix); | 
|  | else if (type->field (i).name ()) | 
|  | { | 
|  | if (type->field (i).name ()[0] != '\0') | 
|  | { | 
|  | if (! strncmp (type->field (i).name (), | 
|  | fieldname, namelen)) | 
|  | output.emplace_back (concat (prefix, type->field (i).name (), | 
|  | nullptr)); | 
|  | } | 
|  | else if (type->field (i).type ()->code () == TYPE_CODE_UNION | 
|  | || type->field (i).type ()->code () == TYPE_CODE_STRUCT) | 
|  | { | 
|  | /* Recurse into anonymous unions and structures.  */ | 
|  | add_struct_fields (type->field (i).type (), | 
|  | output, fieldname, namelen, prefix); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i) | 
|  | { | 
|  | const char *name = TYPE_FN_FIELDLIST_NAME (type, i); | 
|  |  | 
|  | if (name && ! strncmp (name, fieldname, namelen)) | 
|  | { | 
|  | if (!computed_type_name) | 
|  | { | 
|  | type_name = type->name (); | 
|  | computed_type_name = 1; | 
|  | } | 
|  | /* Omit constructors from the completion list.  */ | 
|  | if (!type_name || strcmp (type_name, name)) | 
|  | output.emplace_back (concat (prefix, name, nullptr)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* See expop.h.  */ | 
|  |  | 
|  | bool | 
|  | structop_base_operation::complete (struct expression *exp, | 
|  | completion_tracker &tracker, | 
|  | const char *prefix) | 
|  | { | 
|  | const std::string &fieldname = std::get<1> (m_storage); | 
|  |  | 
|  | value *lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  | struct type *type = lhs->type (); | 
|  | for (;;) | 
|  | { | 
|  | type = check_typedef (type); | 
|  | if (!type->is_pointer_or_reference ()) | 
|  | break; | 
|  | type = type->target_type (); | 
|  | } | 
|  |  | 
|  | if (type->code () == TYPE_CODE_UNION | 
|  | || type->code () == TYPE_CODE_STRUCT) | 
|  | { | 
|  | completion_list result; | 
|  |  | 
|  | add_struct_fields (type, result, fieldname.c_str (), | 
|  | fieldname.length (), prefix); | 
|  | tracker.add_completions (std::move (result)); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | } /* namespace expr */ | 
|  |  | 
|  | /* Return true if type is integral or reference to integral */ | 
|  |  | 
|  | static bool | 
|  | is_integral_or_integral_reference (struct type *type) | 
|  | { | 
|  | if (is_integral_type (type)) | 
|  | return true; | 
|  |  | 
|  | type = check_typedef (type); | 
|  | return (type != nullptr | 
|  | && TYPE_IS_REFERENCE (type) | 
|  | && is_integral_type (type->target_type ())); | 
|  | } | 
|  |  | 
|  | /* Helper function that implements the body of OP_VAR_ENTRY_VALUE.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_var_entry_value (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, symbol *sym) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (sym->type (), not_lval); | 
|  |  | 
|  | const symbol_computed_ops *computed_ops = sym->computed_ops (); | 
|  | if (computed_ops == nullptr | 
|  | || computed_ops->read_variable_at_entry == nullptr) | 
|  | error (_("Symbol \"%s\" does not have any specific entry value"), | 
|  | sym->print_name ()); | 
|  |  | 
|  | frame_info_ptr frame = get_selected_frame (NULL); | 
|  | return computed_ops->read_variable_at_entry (sym, frame); | 
|  | } | 
|  |  | 
|  | /* Helper function that implements the body of OP_VAR_MSYM_VALUE.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_var_msym_value (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, bool outermost_p, | 
|  | bound_minimal_symbol msymbol) | 
|  | { | 
|  | value *val = evaluate_var_msym_value (noside, msymbol.objfile, | 
|  | msymbol.minsym); | 
|  |  | 
|  | struct type *type = val->type (); | 
|  | if (type->code () == TYPE_CODE_ERROR | 
|  | && (noside != EVAL_AVOID_SIDE_EFFECTS || !outermost_p)) | 
|  | error_unknown_type (msymbol.minsym->print_name ()); | 
|  | return val; | 
|  | } | 
|  |  | 
|  | /* Helper function that implements the body of OP_FUNC_STATIC_VAR.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_func_static_var (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | value *func, const char *var) | 
|  | { | 
|  | CORE_ADDR addr = func->address (); | 
|  | const block *blk = block_for_pc (addr); | 
|  | struct block_symbol sym = lookup_symbol (var, blk, SEARCH_VAR_DOMAIN, | 
|  | nullptr); | 
|  | if (sym.symbol == NULL) | 
|  | error (_("No symbol \"%s\" in specified context."), var); | 
|  | return evaluate_var_value (noside, sym.block, sym.symbol); | 
|  | } | 
|  |  | 
|  | /* Helper function that implements the body of OP_REGISTER.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_register (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, const char *name) | 
|  | { | 
|  | int regno; | 
|  | struct value *val; | 
|  |  | 
|  | regno = user_reg_map_name_to_regnum (exp->gdbarch, | 
|  | name, strlen (name)); | 
|  | if (regno == -1) | 
|  | error (_("Register $%s not available."), name); | 
|  |  | 
|  | /* In EVAL_AVOID_SIDE_EFFECTS mode, we only need to return | 
|  | a value with the appropriate register type.  Unfortunately, | 
|  | we don't have easy access to the type of user registers. | 
|  | So for these registers, we fetch the register value regardless | 
|  | of the evaluation mode.  */ | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS | 
|  | && regno < gdbarch_num_cooked_regs (exp->gdbarch)) | 
|  | val = value::zero (register_type (exp->gdbarch, regno), not_lval); | 
|  | else | 
|  | val = value_of_register | 
|  | (regno, get_next_frame_sentinel_okay (get_selected_frame ())); | 
|  | if (val == NULL) | 
|  | error (_("Value of register %s not available."), name); | 
|  | else | 
|  | return val; | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | value * | 
|  | string_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | const std::string &str = std::get<0> (m_storage); | 
|  | struct type *type = language_string_char_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_string (str.c_str (), str.size (), type); | 
|  | } | 
|  |  | 
|  | struct value * | 
|  | ternop_slice_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | struct value *array | 
|  | = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | struct value *low | 
|  | = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | struct value *upper | 
|  | = std::get<2> (m_storage)->evaluate (nullptr, exp, noside); | 
|  |  | 
|  | LONGEST lowbound = value_as_long (low); | 
|  | LONGEST upperbound = value_as_long (upper); | 
|  | return value_slice (array, lowbound, upperbound - lowbound + 1); | 
|  | } | 
|  |  | 
|  | } /* namespace expr */ | 
|  |  | 
|  | /* Helper function that implements the body of OP_OBJC_SELECTOR.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_objc_selector (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | const char *sel) | 
|  | { | 
|  | struct type *selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; | 
|  | return value_from_longest (selector_type, | 
|  | lookup_child_selector (exp->gdbarch, sel)); | 
|  | } | 
|  |  | 
|  | /* A helper function for STRUCTOP_STRUCT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_structop_struct (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1, const char *string) | 
|  | { | 
|  | struct value *arg3 = value_struct_elt (&arg1, {}, string, | 
|  | NULL, "structure"); | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | arg3 = value::zero (arg3->type (), arg3->lval ()); | 
|  | return arg3; | 
|  | } | 
|  |  | 
|  | /* A helper function for STRUCTOP_PTR.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_structop_ptr (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1, const char *string) | 
|  | { | 
|  | /* Check to see if operator '->' has been overloaded.  If so replace | 
|  | arg1 with the value returned by evaluating operator->().  */ | 
|  | while (unop_user_defined_p (STRUCTOP_PTR, arg1)) | 
|  | { | 
|  | struct value *value = NULL; | 
|  | try | 
|  | { | 
|  | value = value_x_unop (arg1, STRUCTOP_PTR, noside); | 
|  | } | 
|  |  | 
|  | catch (const gdb_exception_error &except) | 
|  | { | 
|  | if (except.error == NOT_FOUND_ERROR) | 
|  | break; | 
|  | else | 
|  | throw; | 
|  | } | 
|  |  | 
|  | arg1 = value; | 
|  | } | 
|  |  | 
|  | /* JYG: if print object is on we need to replace the base type | 
|  | with rtti type in order to continue on with successful | 
|  | lookup of member / method only available in the rtti type.  */ | 
|  | { | 
|  | struct type *arg_type = arg1->type (); | 
|  | struct type *real_type; | 
|  | int full, using_enc; | 
|  | LONGEST top; | 
|  | struct value_print_options opts; | 
|  |  | 
|  | get_user_print_options (&opts); | 
|  | if (opts.objectprint && arg_type->target_type () | 
|  | && (arg_type->target_type ()->code () == TYPE_CODE_STRUCT)) | 
|  | { | 
|  | real_type = value_rtti_indirect_type (arg1, &full, &top, | 
|  | &using_enc); | 
|  | if (real_type) | 
|  | arg1 = value_cast (real_type, arg1); | 
|  | } | 
|  | } | 
|  |  | 
|  | struct value *arg3 = value_struct_elt (&arg1, {}, string, | 
|  | NULL, "structure pointer"); | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | arg3 = value::zero (arg3->type (), arg3->lval ()); | 
|  | return arg3; | 
|  | } | 
|  |  | 
|  | /* A helper function for STRUCTOP_MEMBER.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_member (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | long mem_offset; | 
|  |  | 
|  | struct value *arg3; | 
|  | struct type *type = check_typedef (arg2->type ()); | 
|  | switch (type->code ()) | 
|  | { | 
|  | case TYPE_CODE_METHODPTR: | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (type->target_type (), not_lval); | 
|  | else | 
|  | { | 
|  | arg2 = cplus_method_ptr_to_value (&arg1, arg2); | 
|  | gdb_assert (arg2->type ()->code () == TYPE_CODE_PTR); | 
|  | return value_ind (arg2); | 
|  | } | 
|  |  | 
|  | case TYPE_CODE_MEMBERPTR: | 
|  | /* Now, convert these values to an address.  */ | 
|  | if (check_typedef (arg1->type ())->code () != TYPE_CODE_PTR) | 
|  | arg1 = value_addr (arg1); | 
|  | arg1 = value_cast_pointers (lookup_pointer_type (TYPE_SELF_TYPE (type)), | 
|  | arg1, 1); | 
|  |  | 
|  | mem_offset = value_as_long (arg2); | 
|  |  | 
|  | arg3 = value_from_pointer (lookup_pointer_type (type->target_type ()), | 
|  | value_as_long (arg1) + mem_offset); | 
|  | return value_ind (arg3); | 
|  |  | 
|  | default: | 
|  | error (_("non-pointer-to-member value used " | 
|  | "in pointer-to-member construct")); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_ADD.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_add (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (BINOP_ADD, arg1, arg2)) | 
|  | return value_x_binop (arg1, arg2, BINOP_ADD, OP_NULL, noside); | 
|  | else if (ptrmath_type_p (exp->language_defn, arg1->type ()) | 
|  | && is_integral_or_integral_reference (arg2->type ())) | 
|  | return value_ptradd (arg1, value_as_long (arg2)); | 
|  | else if (ptrmath_type_p (exp->language_defn, arg2->type ()) | 
|  | && is_integral_or_integral_reference (arg1->type ())) | 
|  | return value_ptradd (arg2, value_as_long (arg1)); | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | return value_binop (arg1, arg2, BINOP_ADD); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_SUB.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_sub (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (BINOP_SUB, arg1, arg2)) | 
|  | return value_x_binop (arg1, arg2, BINOP_SUB, OP_NULL, noside); | 
|  | else if (ptrmath_type_p (exp->language_defn, arg1->type ()) | 
|  | && ptrmath_type_p (exp->language_defn, arg2->type ())) | 
|  | { | 
|  | /* FIXME -- should be ptrdiff_t */ | 
|  | struct type *type = builtin_type (exp->gdbarch)->builtin_long; | 
|  | return value_from_longest (type, value_ptrdiff (arg1, arg2)); | 
|  | } | 
|  | else if (ptrmath_type_p (exp->language_defn, arg1->type ()) | 
|  | && is_integral_or_integral_reference (arg2->type ())) | 
|  | return value_ptradd (arg1, - value_as_long (arg2)); | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | return value_binop (arg1, arg2, BINOP_SUB); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Helper function for several different binary operations.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_binary (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | else | 
|  | { | 
|  | /* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero, | 
|  | fudge arg2 to avoid division-by-zero, the caller is | 
|  | (theoretically) only looking for the type of the result.  */ | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS | 
|  | /* ??? Do we really want to test for BINOP_MOD here? | 
|  | The implementation of value_binop gives it a well-defined | 
|  | value.  */ | 
|  | && (op == BINOP_DIV | 
|  | || op == BINOP_INTDIV | 
|  | || op == BINOP_REM | 
|  | || op == BINOP_MOD) | 
|  | && value_logical_not (arg2)) | 
|  | { | 
|  | struct value *v_one; | 
|  |  | 
|  | v_one = value_one (arg2->type ()); | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &v_one); | 
|  | return value_binop (arg1, v_one, op); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* For shift and integer exponentiation operations, | 
|  | only promote the first argument.  */ | 
|  | if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) | 
|  | && is_integral_type (arg2->type ())) | 
|  | unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
|  | else | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  |  | 
|  | return value_binop (arg1, arg2, op); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_SUBSCRIPT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_subscript (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | else | 
|  | { | 
|  | /* If the user attempts to subscript something that is not an | 
|  | array or pointer type (like a plain int variable for example), | 
|  | then report this as an error.  */ | 
|  |  | 
|  | arg1 = coerce_ref (arg1); | 
|  | struct type *type = check_typedef (arg1->type ()); | 
|  | if (type->code () != TYPE_CODE_ARRAY | 
|  | && type->code () != TYPE_CODE_PTR) | 
|  | { | 
|  | if (type->name ()) | 
|  | error (_("cannot subscript something of type `%s'"), | 
|  | type->name ()); | 
|  | else | 
|  | error (_("cannot subscript requested type")); | 
|  | } | 
|  |  | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (type->target_type (), arg1->lval ()); | 
|  | else | 
|  | return value_subscript (arg1, value_as_long (arg2)); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_EQUAL.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_equal (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | { | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | int tem = value_equal (arg1, arg2); | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_NOTEQUAL.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_notequal (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | { | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | int tem = value_equal (arg1, arg2); | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) ! tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_LESS.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_less (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | { | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | int tem = value_less (arg1, arg2); | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_GTR.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_gtr (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | { | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | int tem = value_less (arg2, arg1); | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_GEQ.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_geq (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | { | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | int tem = value_less (arg2, arg1) || value_equal (arg1, arg2); | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_LEQ.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_leq (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | { | 
|  | return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
|  | int tem = value_less (arg1, arg2) || value_equal (arg1, arg2); | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_REPEAT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_repeat (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | struct type *type = check_typedef (arg2->type ()); | 
|  | if (type->code () != TYPE_CODE_INT | 
|  | && type->code () != TYPE_CODE_ENUM) | 
|  | error (_("Non-integral right operand for \"@\" operator.")); | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | { | 
|  | return allocate_repeat_value (arg1->type (), | 
|  | longest_to_int (value_as_long (arg2))); | 
|  | } | 
|  | else | 
|  | return value_repeat (arg1, longest_to_int (value_as_long (arg2))); | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_PLUS.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_plus (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (unop_user_defined_p (op, arg1)) | 
|  | return value_x_unop (arg1, op, noside); | 
|  | else | 
|  | { | 
|  | unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
|  | return value_pos (arg1); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_NEG.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_neg (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (unop_user_defined_p (op, arg1)) | 
|  | return value_x_unop (arg1, op, noside); | 
|  | else | 
|  | { | 
|  | unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
|  | return value_neg (arg1); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_COMPLEMENT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_complement (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (unop_user_defined_p (UNOP_COMPLEMENT, arg1)) | 
|  | return value_x_unop (arg1, UNOP_COMPLEMENT, noside); | 
|  | else | 
|  | { | 
|  | unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
|  | return value_complement (arg1); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_LOGICAL_NOT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_lognot (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (unop_user_defined_p (op, arg1)) | 
|  | return value_x_unop (arg1, op, noside); | 
|  | else | 
|  | { | 
|  | struct type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | return value_from_longest (type, (LONGEST) value_logical_not (arg1)); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_IND.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_ind (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1) | 
|  | { | 
|  | struct type *type = check_typedef (arg1->type ()); | 
|  | if (type->code () == TYPE_CODE_METHODPTR | 
|  | || type->code () == TYPE_CODE_MEMBERPTR) | 
|  | error (_("Attempt to dereference pointer " | 
|  | "to member without an object")); | 
|  | if (unop_user_defined_p (UNOP_IND, arg1)) | 
|  | return value_x_unop (arg1, UNOP_IND, noside); | 
|  | else if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | { | 
|  | type = check_typedef (arg1->type ()); | 
|  |  | 
|  | /* 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->is_pointer_or_reference () | 
|  | || !is_dynamic_type (type->target_type ())) | 
|  | { | 
|  | if (type->is_pointer_or_reference () | 
|  | /* In C you can dereference an array to get the 1st elt.  */ | 
|  | || type->code () == TYPE_CODE_ARRAY) | 
|  | return value::zero (type->target_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. | 
|  | This returns an int, which seems like the most C-like thing to | 
|  | do.  "long long" variables are rare enough that | 
|  | BUILTIN_TYPE_LONGEST would seem to be a mistake.  */ | 
|  | if (type->code () == TYPE_CODE_INT) | 
|  | return value_at_lazy (builtin_type (exp->gdbarch)->builtin_int, | 
|  | value_as_address (arg1)); | 
|  | return value_ind (arg1); | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_ALIGNOF.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_alignof (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1) | 
|  | { | 
|  | struct type *type = arg1->type (); | 
|  | /* FIXME: This should be size_t.  */ | 
|  | struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
|  | ULONGEST align = type_align (type); | 
|  | if (align == 0) | 
|  | error (_("could not determine alignment of type")); | 
|  | return value_from_longest (size_type, align); | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_MEMVAL.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_memval (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, | 
|  | struct value *arg1, struct type *type) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (type, lval_memory); | 
|  | else | 
|  | return value_at_lazy (type, value_as_address (arg1)); | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_PREINCREMENT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_preinc (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return arg1; | 
|  | else if (unop_user_defined_p (op, arg1)) | 
|  | { | 
|  | return value_x_unop (arg1, op, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | struct value *arg2; | 
|  | if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
|  | arg2 = value_ptradd (arg1, 1); | 
|  | else | 
|  | { | 
|  | struct value *tmp = arg1; | 
|  |  | 
|  | arg2 = value_one (arg1->type ()); | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
|  | arg2 = value_binop (tmp, arg2, BINOP_ADD); | 
|  | } | 
|  |  | 
|  | return value_assign (arg1, arg2); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_PREDECREMENT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_predec (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return arg1; | 
|  | else if (unop_user_defined_p (op, arg1)) | 
|  | { | 
|  | return value_x_unop (arg1, op, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | struct value *arg2; | 
|  | if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
|  | arg2 = value_ptradd (arg1, -1); | 
|  | else | 
|  | { | 
|  | struct value *tmp = arg1; | 
|  |  | 
|  | arg2 = value_one (arg1->type ()); | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
|  | arg2 = value_binop (tmp, arg2, BINOP_SUB); | 
|  | } | 
|  |  | 
|  | return value_assign (arg1, arg2); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_POSTINCREMENT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_postinc (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return arg1; | 
|  | else if (unop_user_defined_p (op, arg1)) | 
|  | { | 
|  | return value_x_unop (arg1, op, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | struct value *arg3 = arg1->non_lval (); | 
|  | struct value *arg2; | 
|  |  | 
|  | if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
|  | arg2 = value_ptradd (arg1, 1); | 
|  | else | 
|  | { | 
|  | struct value *tmp = arg1; | 
|  |  | 
|  | arg2 = value_one (arg1->type ()); | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
|  | arg2 = value_binop (tmp, arg2, BINOP_ADD); | 
|  | } | 
|  |  | 
|  | value_assign (arg1, arg2); | 
|  | return arg3; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* A helper function for UNOP_POSTDECREMENT.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_op_postdec (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return arg1; | 
|  | else if (unop_user_defined_p (op, arg1)) | 
|  | { | 
|  | return value_x_unop (arg1, op, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | struct value *arg3 = arg1->non_lval (); | 
|  | struct value *arg2; | 
|  |  | 
|  | if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
|  | arg2 = value_ptradd (arg1, -1); | 
|  | else | 
|  | { | 
|  | struct value *tmp = arg1; | 
|  |  | 
|  | arg2 = value_one (arg1->type ()); | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
|  | arg2 = value_binop (tmp, arg2, BINOP_SUB); | 
|  | } | 
|  |  | 
|  | value_assign (arg1, arg2); | 
|  | return arg3; | 
|  | } | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | struct value * | 
|  | type_operation::evaluate (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::allocate (std::get<0> (m_storage)); | 
|  | else | 
|  | error (_("Attempt to use a type name as an expression")); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* A helper function for BINOP_ASSIGN_MODIFY.  */ | 
|  |  | 
|  | struct value * | 
|  | eval_binop_assign_modify (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, enum exp_opcode op, | 
|  | struct value *arg1, struct value *arg2) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return arg1; | 
|  | if (binop_user_defined_p (op, arg1, arg2)) | 
|  | return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside); | 
|  | else if (op == BINOP_ADD && ptrmath_type_p (exp->language_defn, | 
|  | arg1->type ()) | 
|  | && is_integral_type (arg2->type ())) | 
|  | arg2 = value_ptradd (arg1, value_as_long (arg2)); | 
|  | else if (op == BINOP_SUB && ptrmath_type_p (exp->language_defn, | 
|  | arg1->type ()) | 
|  | && is_integral_type (arg2->type ())) | 
|  | arg2 = value_ptradd (arg1, - value_as_long (arg2)); | 
|  | else | 
|  | { | 
|  | struct value *tmp = arg1; | 
|  |  | 
|  | /* For shift and integer exponentiation operations, | 
|  | only promote the first argument.  */ | 
|  | if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) | 
|  | && is_integral_type (arg2->type ())) | 
|  | unop_promote (exp->language_defn, exp->gdbarch, &tmp); | 
|  | else | 
|  | binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
|  |  | 
|  | arg2 = value_binop (tmp, arg2, op); | 
|  | } | 
|  | return value_assign (arg1, arg2); | 
|  | } | 
|  |  | 
|  | /* Note that ARGS needs 2 empty slots up front and must end with a | 
|  | null pointer.  */ | 
|  | static struct value * | 
|  | eval_op_objc_msgcall (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, CORE_ADDR selector, | 
|  | value *target, gdb::array_view<value *> args) | 
|  | { | 
|  | CORE_ADDR responds_selector = 0; | 
|  | CORE_ADDR method_selector = 0; | 
|  |  | 
|  | int struct_return = 0; | 
|  |  | 
|  | struct value *msg_send = NULL; | 
|  | struct value *msg_send_stret = NULL; | 
|  | int gnu_runtime = 0; | 
|  |  | 
|  | struct value *method = NULL; | 
|  | struct value *called_method = NULL; | 
|  |  | 
|  | struct type *selector_type = NULL; | 
|  | struct type *long_type; | 
|  | struct type *type; | 
|  |  | 
|  | struct value *ret = NULL; | 
|  | CORE_ADDR addr = 0; | 
|  |  | 
|  | value *argvec[5]; | 
|  |  | 
|  | long_type = builtin_type (exp->gdbarch)->builtin_long; | 
|  | selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; | 
|  |  | 
|  | if (value_as_long (target) == 0) | 
|  | return value_from_longest (long_type, 0); | 
|  |  | 
|  | if (lookup_minimal_symbol (current_program_space, "objc_msg_lookup").minsym | 
|  | != nullptr) | 
|  | gnu_runtime = 1; | 
|  |  | 
|  | /* Find the method dispatch (Apple runtime) or method lookup | 
|  | (GNU runtime) function for Objective-C.  These will be used | 
|  | to lookup the symbol information for the method.  If we | 
|  | can't find any symbol information, then we'll use these to | 
|  | call the method, otherwise we can call the method | 
|  | directly.  The msg_send_stret function is used in the special | 
|  | case of a method that returns a structure (Apple runtime | 
|  | only).  */ | 
|  | if (gnu_runtime) | 
|  | { | 
|  | type = selector_type; | 
|  |  | 
|  | type = lookup_function_type (type); | 
|  | type = lookup_pointer_type (type); | 
|  | type = lookup_function_type (type); | 
|  | type = lookup_pointer_type (type); | 
|  |  | 
|  | msg_send = find_function_in_inferior ("objc_msg_lookup", NULL); | 
|  | msg_send_stret | 
|  | = find_function_in_inferior ("objc_msg_lookup", NULL); | 
|  |  | 
|  | msg_send = value_from_pointer (type, value_as_address (msg_send)); | 
|  | msg_send_stret = value_from_pointer (type, | 
|  | value_as_address (msg_send_stret)); | 
|  | } | 
|  | else | 
|  | { | 
|  | msg_send = find_function_in_inferior ("objc_msgSend", NULL); | 
|  | /* Special dispatcher for methods returning structs.  */ | 
|  | msg_send_stret | 
|  | = find_function_in_inferior ("objc_msgSend_stret", NULL); | 
|  | } | 
|  |  | 
|  | /* Verify the target object responds to this method.  The | 
|  | standard top-level 'Object' class uses a different name for | 
|  | the verification method than the non-standard, but more | 
|  | often used, 'NSObject' class.  Make sure we check for both.  */ | 
|  |  | 
|  | responds_selector | 
|  | = lookup_child_selector (exp->gdbarch, "respondsToSelector:"); | 
|  | if (responds_selector == 0) | 
|  | responds_selector | 
|  | = lookup_child_selector (exp->gdbarch, "respondsTo:"); | 
|  |  | 
|  | if (responds_selector == 0) | 
|  | error (_("no 'respondsTo:' or 'respondsToSelector:' method")); | 
|  |  | 
|  | method_selector | 
|  | = lookup_child_selector (exp->gdbarch, "methodForSelector:"); | 
|  | if (method_selector == 0) | 
|  | method_selector | 
|  | = lookup_child_selector (exp->gdbarch, "methodFor:"); | 
|  |  | 
|  | if (method_selector == 0) | 
|  | error (_("no 'methodFor:' or 'methodForSelector:' method")); | 
|  |  | 
|  | /* Call the verification method, to make sure that the target | 
|  | class implements the desired method.  */ | 
|  |  | 
|  | argvec[0] = msg_send; | 
|  | argvec[1] = target; | 
|  | argvec[2] = value_from_longest (long_type, responds_selector); | 
|  | argvec[3] = value_from_longest (long_type, selector); | 
|  | argvec[4] = 0; | 
|  |  | 
|  | ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
|  | if (gnu_runtime) | 
|  | { | 
|  | /* Function objc_msg_lookup returns a pointer.  */ | 
|  | argvec[0] = ret; | 
|  | ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
|  | } | 
|  | if (value_as_long (ret) == 0) | 
|  | error (_("Target does not respond to this message selector.")); | 
|  |  | 
|  | /* Call "methodForSelector:" method, to get the address of a | 
|  | function method that implements this selector for this | 
|  | class.  If we can find a symbol at that address, then we | 
|  | know the return type, parameter types etc.  (that's a good | 
|  | thing).  */ | 
|  |  | 
|  | argvec[0] = msg_send; | 
|  | argvec[1] = target; | 
|  | argvec[2] = value_from_longest (long_type, method_selector); | 
|  | argvec[3] = value_from_longest (long_type, selector); | 
|  | argvec[4] = 0; | 
|  |  | 
|  | ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
|  | if (gnu_runtime) | 
|  | { | 
|  | argvec[0] = ret; | 
|  | ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
|  | } | 
|  |  | 
|  | /* ret should now be the selector.  */ | 
|  |  | 
|  | addr = value_as_long (ret); | 
|  | if (addr) | 
|  | { | 
|  | struct symbol *sym = NULL; | 
|  |  | 
|  | /* The address might point to a function descriptor; | 
|  | resolve it to the actual code address instead.  */ | 
|  | addr = gdbarch_convert_from_func_ptr_addr | 
|  | (exp->gdbarch, addr, current_inferior ()->top_target ()); | 
|  |  | 
|  | /* Is it a high_level symbol?  */ | 
|  | sym = find_pc_function (addr); | 
|  | if (sym != NULL) | 
|  | method = value_of_variable (sym, 0); | 
|  | } | 
|  |  | 
|  | /* If we found a method with symbol information, check to see | 
|  | if it returns a struct.  Otherwise assume it doesn't.  */ | 
|  |  | 
|  | if (method) | 
|  | { | 
|  | CORE_ADDR funaddr; | 
|  | struct type *val_type; | 
|  |  | 
|  | funaddr = find_function_addr (method, &val_type); | 
|  |  | 
|  | block_for_pc (funaddr); | 
|  |  | 
|  | val_type = check_typedef (val_type); | 
|  |  | 
|  | if ((val_type == NULL) | 
|  | || (val_type->code () == TYPE_CODE_ERROR)) | 
|  | { | 
|  | if (expect_type != NULL) | 
|  | val_type = expect_type; | 
|  | } | 
|  |  | 
|  | struct_return = using_struct_return (exp->gdbarch, method, | 
|  | val_type); | 
|  | } | 
|  | else if (expect_type != NULL) | 
|  | { | 
|  | struct_return = using_struct_return (exp->gdbarch, NULL, | 
|  | check_typedef (expect_type)); | 
|  | } | 
|  |  | 
|  | /* Found a function symbol.  Now we will substitute its | 
|  | value in place of the message dispatcher (obj_msgSend), | 
|  | so that we call the method directly instead of through | 
|  | the dispatcher.  The main reason for doing this is that | 
|  | we can now evaluate the return value and parameter values | 
|  | according to their known data types, in case we need to | 
|  | do things like promotion, dereferencing, special handling | 
|  | of structs and doubles, etc. | 
|  |  | 
|  | We want to use the type signature of 'method', but still | 
|  | jump to objc_msgSend() or objc_msgSend_stret() to better | 
|  | mimic the behavior of the runtime.  */ | 
|  |  | 
|  | if (method) | 
|  | { | 
|  | if (method->type ()->code () != TYPE_CODE_FUNC) | 
|  | error (_("method address has symbol information " | 
|  | "with non-function type; skipping")); | 
|  |  | 
|  | /* Create a function pointer of the appropriate type, and | 
|  | replace its value with the value of msg_send or | 
|  | msg_send_stret.  We must use a pointer here, as | 
|  | msg_send and msg_send_stret are of pointer type, and | 
|  | the representation may be different on systems that use | 
|  | function descriptors.  */ | 
|  | if (struct_return) | 
|  | called_method | 
|  | = value_from_pointer (lookup_pointer_type (method->type ()), | 
|  | value_as_address (msg_send_stret)); | 
|  | else | 
|  | called_method | 
|  | = value_from_pointer (lookup_pointer_type (method->type ()), | 
|  | value_as_address (msg_send)); | 
|  | } | 
|  | else | 
|  | { | 
|  | if (struct_return) | 
|  | called_method = msg_send_stret; | 
|  | else | 
|  | called_method = msg_send; | 
|  | } | 
|  |  | 
|  |  | 
|  | 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 *callee_type = called_method->type (); | 
|  |  | 
|  | if (callee_type && callee_type->code () == TYPE_CODE_PTR) | 
|  | callee_type = callee_type->target_type (); | 
|  | callee_type = callee_type->target_type (); | 
|  |  | 
|  | if (callee_type) | 
|  | { | 
|  | if ((callee_type->code () == TYPE_CODE_ERROR) && expect_type) | 
|  | return value::allocate (expect_type); | 
|  | else | 
|  | return value::allocate (callee_type); | 
|  | } | 
|  | else | 
|  | error (_("Expression of type other than " | 
|  | "\"method returning ...\" used as a method")); | 
|  | } | 
|  |  | 
|  | /* Now depending on whether we found a symbol for the method, | 
|  | we will either call the runtime dispatcher or the method | 
|  | directly.  */ | 
|  |  | 
|  | args[0] = target; | 
|  | args[1] = value_from_longest (long_type, selector); | 
|  |  | 
|  | if (gnu_runtime && (method != NULL)) | 
|  | { | 
|  | /* Function objc_msg_lookup returns a pointer.  */ | 
|  | struct type *tem_type = called_method->type (); | 
|  | tem_type = lookup_pointer_type (lookup_function_type (tem_type)); | 
|  | called_method->deprecated_set_type (tem_type); | 
|  | called_method = call_function_by_hand (called_method, NULL, args); | 
|  | } | 
|  |  | 
|  | return call_function_by_hand (called_method, NULL, args); | 
|  | } | 
|  |  | 
|  | /* Helper function for MULTI_SUBSCRIPT.  */ | 
|  |  | 
|  | static struct value * | 
|  | eval_multi_subscript (struct type *expect_type, struct expression *exp, | 
|  | enum noside noside, value *arg1, | 
|  | gdb::array_view<value *> args) | 
|  | { | 
|  | for (value *arg2 : args) | 
|  | { | 
|  | if (binop_user_defined_p (MULTI_SUBSCRIPT, arg1, arg2)) | 
|  | { | 
|  | arg1 = value_x_binop (arg1, arg2, MULTI_SUBSCRIPT, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | arg1 = coerce_ref (arg1); | 
|  | struct type *type = check_typedef (arg1->type ()); | 
|  |  | 
|  | switch (type->code ()) | 
|  | { | 
|  | case TYPE_CODE_PTR: | 
|  | case TYPE_CODE_ARRAY: | 
|  | case TYPE_CODE_STRING: | 
|  | arg1 = value_subscript (arg1, value_as_long (arg2)); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | if (type->name ()) | 
|  | error (_("cannot subscript something of type `%s'"), | 
|  | type->name ()); | 
|  | else | 
|  | error (_("cannot subscript requested type")); | 
|  | } | 
|  | } | 
|  | } | 
|  | return (arg1); | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | value * | 
|  | objc_msgcall_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | enum noside sub_no_side = EVAL_NORMAL; | 
|  | struct type *selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; | 
|  |  | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | sub_no_side = EVAL_NORMAL; | 
|  | else | 
|  | sub_no_side = noside; | 
|  | value *target | 
|  | = std::get<1> (m_storage)->evaluate (selector_type, exp, sub_no_side); | 
|  |  | 
|  | if (value_as_long (target) == 0) | 
|  | sub_no_side = EVAL_AVOID_SIDE_EFFECTS; | 
|  | else | 
|  | sub_no_side = noside; | 
|  | std::vector<operation_up> &args = std::get<2> (m_storage); | 
|  | value **argvec = XALLOCAVEC (struct value *, args.size () + 3); | 
|  | argvec[0] = nullptr; | 
|  | argvec[1] = nullptr; | 
|  | for (int i = 0; i < args.size (); ++i) | 
|  | argvec[i + 2] = args[i]->evaluate_with_coercion (exp, sub_no_side); | 
|  | argvec[args.size () + 2] = nullptr; | 
|  |  | 
|  | return eval_op_objc_msgcall (expect_type, exp, noside, std:: | 
|  | get<0> (m_storage), target, | 
|  | gdb::make_array_view (argvec, | 
|  | args.size () + 3)); | 
|  | } | 
|  |  | 
|  | value * | 
|  | multi_subscript_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *arg1 = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside); | 
|  | std::vector<operation_up> &values = std::get<1> (m_storage); | 
|  | value **argvec = XALLOCAVEC (struct value *, values.size ()); | 
|  | for (int ix = 0; ix < values.size (); ++ix) | 
|  | argvec[ix] = values[ix]->evaluate_with_coercion (exp, noside); | 
|  | return eval_multi_subscript (expect_type, exp, noside, arg1, | 
|  | gdb::make_array_view (argvec, values.size ())); | 
|  | } | 
|  |  | 
|  | value * | 
|  | logical_and_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  |  | 
|  | value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  |  | 
|  | if (binop_user_defined_p (BINOP_LOGICAL_AND, arg1, arg2)) | 
|  | { | 
|  | arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | return value_x_binop (arg1, arg2, BINOP_LOGICAL_AND, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (type, not_lval); | 
|  |  | 
|  | bool tem = value_logical_not (arg1); | 
|  | if (!tem) | 
|  | { | 
|  | arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | tem = value_logical_not (arg2); | 
|  | } | 
|  |  | 
|  | return value_from_longest (type, !tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | value * | 
|  | logical_or_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  |  | 
|  | value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  |  | 
|  | if (binop_user_defined_p (BINOP_LOGICAL_OR, arg1, arg2)) | 
|  | { | 
|  | arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | return value_x_binop (arg1, arg2, BINOP_LOGICAL_OR, OP_NULL, noside); | 
|  | } | 
|  | else | 
|  | { | 
|  | type *type = language_bool_type (exp->language_defn, | 
|  | exp->gdbarch); | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (type, not_lval); | 
|  |  | 
|  | bool tem = value_logical_not (arg1); | 
|  | if (tem) | 
|  | { | 
|  | arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | tem = value_logical_not (arg2); | 
|  | } | 
|  |  | 
|  | return value_from_longest (type, !tem); | 
|  | } | 
|  | } | 
|  |  | 
|  | value * | 
|  | adl_func_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | std::vector<operation_up> &arg_ops = std::get<2> (m_storage); | 
|  | std::vector<value *> args (arg_ops.size ()); | 
|  | for (int i = 0; i < arg_ops.size (); ++i) | 
|  | args[i] = arg_ops[i]->evaluate_with_coercion (exp, noside); | 
|  |  | 
|  | struct symbol *symp; | 
|  | find_overload_match (args, std::get<0> (m_storage).c_str (), | 
|  | NON_METHOD, | 
|  | nullptr, nullptr, | 
|  | nullptr, &symp, nullptr, 0, noside); | 
|  | if (symp->type ()->code () == TYPE_CODE_ERROR) | 
|  | error_unknown_type (symp->print_name ()); | 
|  | value *callee = evaluate_var_value (noside, std::get<1> (m_storage), symp); | 
|  | return evaluate_subexp_do_call (exp, noside, callee, args, | 
|  | nullptr, expect_type); | 
|  |  | 
|  | } | 
|  |  | 
|  | /* This function evaluates brace-initializers (in C/C++) for | 
|  | structure types.  */ | 
|  |  | 
|  | struct value * | 
|  | array_operation::evaluate_struct_tuple (struct value *struct_val, | 
|  | struct expression *exp, | 
|  | enum noside noside, int nargs) | 
|  | { | 
|  | const std::vector<operation_up> &in_args = std::get<2> (m_storage); | 
|  | struct type *struct_type = check_typedef (struct_val->type ()); | 
|  | struct type *field_type; | 
|  | int fieldno = -1; | 
|  |  | 
|  | int idx = 0; | 
|  | while (--nargs >= 0) | 
|  | { | 
|  | struct value *val = NULL; | 
|  | int bitpos, bitsize; | 
|  | bfd_byte *addr; | 
|  |  | 
|  | fieldno++; | 
|  | /* Skip static fields.  */ | 
|  | while (fieldno < struct_type->num_fields () | 
|  | && struct_type->field (fieldno).is_static ()) | 
|  | fieldno++; | 
|  | if (fieldno >= struct_type->num_fields ()) | 
|  | error (_("too many initializers")); | 
|  | field_type = struct_type->field (fieldno).type (); | 
|  | if (field_type->code () == TYPE_CODE_UNION | 
|  | && struct_type->field (fieldno).name ()[0] == '0') | 
|  | error (_("don't know which variant you want to set")); | 
|  |  | 
|  | /* Here, struct_type is the type of the inner struct, | 
|  | while substruct_type is the type of the inner struct. | 
|  | These are the same for normal structures, but a variant struct | 
|  | contains anonymous union fields that contain substruct fields. | 
|  | The value fieldno is the index of the top-level (normal or | 
|  | anonymous union) field in struct_field, while the value | 
|  | subfieldno is the index of the actual real (named inner) field | 
|  | in substruct_type.  */ | 
|  |  | 
|  | field_type = struct_type->field (fieldno).type (); | 
|  | if (val == 0) | 
|  | val = in_args[idx++]->evaluate (field_type, exp, noside); | 
|  |  | 
|  | /* Now actually set the field in struct_val.  */ | 
|  |  | 
|  | /* Assign val to field fieldno.  */ | 
|  | if (val->type () != field_type) | 
|  | val = value_cast (field_type, val); | 
|  |  | 
|  | bitsize = struct_type->field (fieldno).bitsize (); | 
|  | bitpos = struct_type->field (fieldno).loc_bitpos (); | 
|  | addr = struct_val->contents_writeable ().data () + bitpos / 8; | 
|  | if (bitsize) | 
|  | modify_field (struct_type, addr, | 
|  | value_as_long (val), bitpos % 8, bitsize); | 
|  | else | 
|  | memcpy (addr, val->contents ().data (), | 
|  | val->type ()->length ()); | 
|  |  | 
|  | } | 
|  | return struct_val; | 
|  | } | 
|  |  | 
|  | value * | 
|  | array_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | const int provided_low_bound = std::get<0> (m_storage); | 
|  | const std::vector<operation_up> &in_args = std::get<2> (m_storage); | 
|  | const int nargs = std::get<1> (m_storage) - provided_low_bound + 1; | 
|  | struct type *type = expect_type ? check_typedef (expect_type) : nullptr; | 
|  |  | 
|  | if (expect_type != nullptr | 
|  | && type->code () == TYPE_CODE_STRUCT) | 
|  | { | 
|  | struct value *rec = value::allocate (expect_type); | 
|  |  | 
|  | memset (rec->contents_raw ().data (), '\0', type->length ()); | 
|  | return evaluate_struct_tuple (rec, exp, noside, nargs); | 
|  | } | 
|  |  | 
|  | if (expect_type != nullptr | 
|  | && type->code () == TYPE_CODE_ARRAY) | 
|  | { | 
|  | struct type *range_type = type->index_type (); | 
|  | struct type *element_type = type->target_type (); | 
|  | struct value *array = value::allocate (expect_type); | 
|  | int element_size = check_typedef (element_type)->length (); | 
|  | LONGEST low_bound, high_bound; | 
|  |  | 
|  | if (!get_discrete_bounds (range_type, &low_bound, &high_bound)) | 
|  | { | 
|  | low_bound = 0; | 
|  | high_bound = (type->length () / element_size) - 1; | 
|  | } | 
|  | if (low_bound + nargs - 1 > high_bound) | 
|  | error (_("Too many array elements")); | 
|  | memset (array->contents_raw ().data (), 0, expect_type->length ()); | 
|  | for (int idx = 0; idx < nargs; ++idx) | 
|  | { | 
|  | struct value *element; | 
|  |  | 
|  | element = in_args[idx]->evaluate (element_type, exp, noside); | 
|  | if (element->type () != element_type) | 
|  | element = value_cast (element_type, element); | 
|  | memcpy (array->contents_raw ().data () + idx * element_size, | 
|  | element->contents ().data (), | 
|  | element_size); | 
|  | } | 
|  | return array; | 
|  | } | 
|  |  | 
|  | if (expect_type != nullptr | 
|  | && type->code () == TYPE_CODE_SET) | 
|  | { | 
|  | struct value *set = value::allocate (expect_type); | 
|  | gdb_byte *valaddr = set->contents_raw ().data (); | 
|  | struct type *element_type = type->index_type (); | 
|  | struct type *check_type = element_type; | 
|  | LONGEST low_bound, high_bound; | 
|  |  | 
|  | /* Get targettype of elementtype.  */ | 
|  | while (check_type->code () == TYPE_CODE_RANGE | 
|  | || check_type->code () == TYPE_CODE_TYPEDEF) | 
|  | check_type = check_type->target_type (); | 
|  |  | 
|  | if (!get_discrete_bounds (element_type, &low_bound, &high_bound)) | 
|  | error (_("(power)set type with unknown size")); | 
|  | memset (valaddr, '\0', type->length ()); | 
|  | for (int idx = 0; idx < nargs; idx++) | 
|  | { | 
|  | LONGEST range_low, range_high; | 
|  | struct type *range_low_type, *range_high_type; | 
|  | struct value *elem_val; | 
|  |  | 
|  | elem_val = in_args[idx]->evaluate (element_type, exp, noside); | 
|  | range_low_type = range_high_type = elem_val->type (); | 
|  | 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.  */ | 
|  | if (range_low_type->code () == TYPE_CODE_RANGE) | 
|  | range_low_type = range_low_type->target_type (); | 
|  | if (range_high_type->code () == TYPE_CODE_RANGE) | 
|  | range_high_type = range_high_type->target_type (); | 
|  | if ((range_low_type->code () != range_high_type->code ()) | 
|  | || (range_low_type->code () == TYPE_CODE_ENUM | 
|  | && (range_low_type != range_high_type))) | 
|  | /* different element modes.  */ | 
|  | error (_("POWERSET tuple elements of different mode")); | 
|  | if ((check_type->code () != range_low_type->code ()) | 
|  | || (check_type->code () == TYPE_CODE_ENUM | 
|  | && range_low_type != check_type)) | 
|  | error (_("incompatible POWERSET tuple elements")); | 
|  | if (range_low > range_high) | 
|  | { | 
|  | warning (_("empty POWERSET tuple range")); | 
|  | continue; | 
|  | } | 
|  | if (range_low < low_bound || range_high > high_bound) | 
|  | error (_("POWERSET tuple element out of range")); | 
|  | range_low -= low_bound; | 
|  | range_high -= low_bound; | 
|  | for (; range_low <= range_high; range_low++) | 
|  | { | 
|  | int bit_index = (unsigned) range_low % TARGET_CHAR_BIT; | 
|  |  | 
|  | if (gdbarch_byte_order (exp->gdbarch) == BFD_ENDIAN_BIG) | 
|  | bit_index = TARGET_CHAR_BIT - 1 - bit_index; | 
|  | valaddr[(unsigned) range_low / TARGET_CHAR_BIT] | 
|  | |= 1 << bit_index; | 
|  | } | 
|  | } | 
|  | return set; | 
|  | } | 
|  |  | 
|  | std::vector<value *> argvec (nargs); | 
|  | for (int tem = 0; tem < nargs; tem++) | 
|  | { | 
|  | /* Ensure that array expressions are coerced into pointer | 
|  | objects.  */ | 
|  | argvec[tem] = in_args[tem]->evaluate_with_coercion (exp, noside); | 
|  | } | 
|  | return value_array (provided_low_bound, argvec); | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_extract_operation::evaluate (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *old_value = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  | struct type *type = get_type (); | 
|  |  | 
|  | if (type->length () > old_value->type ()->length ()) | 
|  | error (_("length type is larger than the value type")); | 
|  |  | 
|  | struct value *result = value::allocate (type); | 
|  | old_value->contents_copy (result, 0, 0, type->length ()); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* Helper for evaluate_subexp_for_address.  */ | 
|  |  | 
|  | static value * | 
|  | evaluate_subexp_for_address_base (enum noside noside, value *x) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | { | 
|  | struct type *type = check_typedef (x->type ()); | 
|  | enum type_code typecode = type->code (); | 
|  |  | 
|  | if (TYPE_IS_REFERENCE (type)) | 
|  | return value::zero (lookup_pointer_type (type->target_type ()), | 
|  | not_lval); | 
|  | else if (x->lval () == lval_memory || value_must_coerce_to_target (x) | 
|  | || typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION) | 
|  | return value::zero (lookup_pointer_type (x->type ()), not_lval); | 
|  | else | 
|  | error (_("Attempt to take address of value not located in memory.")); | 
|  | } | 
|  |  | 
|  | return value_addr (x); | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | value * | 
|  | operation::evaluate_for_cast (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *val = evaluate (expect_type, exp, noside); | 
|  | return value_cast (expect_type, val); | 
|  | } | 
|  |  | 
|  | value * | 
|  | operation::evaluate_for_address (struct expression *exp, enum noside noside) | 
|  | { | 
|  | value *val = evaluate (nullptr, exp, noside); | 
|  | return evaluate_subexp_for_address_base (noside, val); | 
|  | } | 
|  |  | 
|  | value * | 
|  | scope_operation::evaluate_internal (struct type *expect_type, | 
|  | struct expression *exp, | 
|  | enum noside noside, | 
|  | bool want_address) | 
|  | { | 
|  | const char *string = std::get<1> (m_storage).c_str (); | 
|  | value *x = value_aggregate_elt (std::get<0> (m_storage), string, | 
|  | expect_type, want_address, noside); | 
|  | if (x == nullptr) | 
|  | error (_("There is no field named %s"), string); | 
|  | return x; | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_ind_base_operation::evaluate_for_address (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *x = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
|  |  | 
|  | /* We can't optimize out "&*" if there's a user-defined operator*.  */ | 
|  | if (unop_user_defined_p (UNOP_IND, x)) | 
|  | { | 
|  | x = value_x_unop (x, UNOP_IND, noside); | 
|  | return evaluate_subexp_for_address_base (noside, x); | 
|  | } | 
|  |  | 
|  | return coerce_array (x); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_msym_value_operation::evaluate_for_address (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | const bound_minimal_symbol &b = std::get<0> (m_storage); | 
|  | value *val = evaluate_var_msym_value (noside, b.objfile, b.minsym); | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | { | 
|  | struct type *type = lookup_pointer_type (val->type ()); | 
|  | return value::zero (type, not_lval); | 
|  | } | 
|  | else | 
|  | return value_addr (val); | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_memval_operation::evaluate_for_address (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | return value_cast (lookup_pointer_type (std::get<1> (m_storage)), | 
|  | std::get<0> (m_storage)->evaluate (nullptr, exp, noside)); | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_memval_type_operation::evaluate_for_address (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *typeval = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  | struct type *type = typeval->type (); | 
|  | return value_cast (lookup_pointer_type (type), | 
|  | std::get<1> (m_storage)->evaluate (nullptr, exp, noside)); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_value_operation::evaluate_for_address (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | symbol *var = std::get<0> (m_storage).symbol; | 
|  |  | 
|  | /* C++: The "address" of a reference should yield the address | 
|  | * of the object pointed to.  Let value_addr() deal with it.  */ | 
|  | if (TYPE_IS_REFERENCE (var->type ())) | 
|  | return operation::evaluate_for_address (exp, noside); | 
|  |  | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | { | 
|  | struct type *type = lookup_pointer_type (var->type ()); | 
|  | location_class loc_class = var->loc_class (); | 
|  |  | 
|  | if (loc_class == LOC_CONST | 
|  | || loc_class == LOC_CONST_BYTES | 
|  | || loc_class == LOC_REGISTER) | 
|  | error (_("Attempt to take address of register or constant.")); | 
|  |  | 
|  | return value::zero (type, not_lval); | 
|  | } | 
|  | else | 
|  | return address_of_variable (var, std::get<0> (m_storage).block); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_value_operation::evaluate_with_coercion (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | struct symbol *var = std::get<0> (m_storage).symbol; | 
|  | struct type *type = check_typedef (var->type ()); | 
|  | if (type->code () == TYPE_CODE_ARRAY | 
|  | && !type->is_vector () | 
|  | && CAST_IS_CONVERSION (exp->language_defn)) | 
|  | { | 
|  | struct value *val = address_of_variable (var, | 
|  | std::get<0> (m_storage).block); | 
|  | return value_cast (lookup_pointer_type (type->target_type ()), val); | 
|  | } | 
|  | return evaluate (nullptr, exp, noside); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* Helper function for evaluating the size of a type.  */ | 
|  |  | 
|  | static value * | 
|  | evaluate_subexp_for_sizeof_base (struct expression *exp, struct type *type) | 
|  | { | 
|  | /* FIXME: This should be size_t.  */ | 
|  | struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
|  | /* $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 ()); | 
|  | else if (exp->language_defn->la_language == language_fortran | 
|  | && type->code () == TYPE_CODE_PTR) | 
|  | { | 
|  | /* Dereference Fortran pointer types to allow them for the Fortran | 
|  | sizeof intrinsic.  */ | 
|  | type = check_typedef (type->target_type ()); | 
|  | } | 
|  | return value_from_longest (size_type, (LONGEST) type->length ()); | 
|  | } | 
|  |  | 
|  | namespace expr | 
|  | { | 
|  |  | 
|  | value * | 
|  | operation::evaluate_for_sizeof (struct expression *exp, enum noside noside) | 
|  | { | 
|  | value *val = evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS); | 
|  | return evaluate_subexp_for_sizeof_base (exp, val->type ()); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_msym_value_operation::evaluate_for_sizeof (struct expression *exp, | 
|  | enum noside noside) | 
|  |  | 
|  | { | 
|  | const bound_minimal_symbol &b = std::get<0> (m_storage); | 
|  | value *mval = evaluate_var_msym_value (noside, b.objfile, b.minsym); | 
|  |  | 
|  | struct type *type = mval->type (); | 
|  | if (type->code () == TYPE_CODE_ERROR) | 
|  | error_unknown_type (b.minsym->print_name ()); | 
|  |  | 
|  | /* FIXME: This should be size_t.  */ | 
|  | struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
|  | return value_from_longest (size_type, type->length ()); | 
|  | } | 
|  |  | 
|  | value * | 
|  | subscript_operation::evaluate_for_sizeof (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | if (noside == EVAL_NORMAL) | 
|  | { | 
|  | value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  | struct type *type = check_typedef (val->type ()); | 
|  | if (type->code () == TYPE_CODE_ARRAY) | 
|  | { | 
|  | type = check_typedef (type->target_type ()); | 
|  | if (type->code () == TYPE_CODE_ARRAY) | 
|  | { | 
|  | type = type->index_type (); | 
|  | /* Only re-evaluate the right hand side if the resulting type | 
|  | is a variable length type.  */ | 
|  | if (type->bounds ()->flag_bound_evaluated) | 
|  | { | 
|  | val = evaluate (nullptr, exp, EVAL_NORMAL); | 
|  | /* FIXME: This should be size_t.  */ | 
|  | struct type *size_type | 
|  | = builtin_type (exp->gdbarch)->builtin_int; | 
|  | return value_from_longest | 
|  | (size_type, (LONGEST) val->type ()->length ()); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return operation::evaluate_for_sizeof (exp, noside); | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_ind_base_operation::evaluate_for_sizeof (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  | struct type *type = check_typedef (val->type ()); | 
|  | if (!type->is_pointer_or_reference () | 
|  | && type->code () != TYPE_CODE_ARRAY) | 
|  | error (_("Attempt to take contents of a non-pointer value.")); | 
|  | type = type->target_type (); | 
|  | if (is_dynamic_type (type)) | 
|  | type = value_ind (val)->type (); | 
|  | /* FIXME: This should be size_t.  */ | 
|  | struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
|  | return value_from_longest (size_type, (LONGEST) type->length ()); | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_memval_operation::evaluate_for_sizeof (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | return evaluate_subexp_for_sizeof_base (exp, std::get<1> (m_storage)); | 
|  | } | 
|  |  | 
|  | value * | 
|  | unop_memval_type_operation::evaluate_for_sizeof (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *typeval = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
|  | EVAL_AVOID_SIDE_EFFECTS); | 
|  | return evaluate_subexp_for_sizeof_base (exp, typeval->type ()); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_value_operation::evaluate_for_sizeof (struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | struct type *type = std::get<0> (m_storage).symbol->type (); | 
|  | if (is_dynamic_type (type)) | 
|  | { | 
|  | value *val = evaluate (nullptr, exp, EVAL_NORMAL); | 
|  | type = val->type (); | 
|  | if (type->code () == TYPE_CODE_ARRAY) | 
|  | { | 
|  | /* FIXME: This should be size_t.  */ | 
|  | struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
|  | if (type_not_allocated (type) || type_not_associated (type)) | 
|  | return value::zero (size_type, not_lval); | 
|  | else if (is_dynamic_type (type->index_type ()) | 
|  | && !type->bounds ()->high.is_available ()) | 
|  | return value::allocate_optimized_out (size_type); | 
|  | } | 
|  | } | 
|  | return evaluate_subexp_for_sizeof_base (exp, type); | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_msym_value_operation::evaluate_for_cast (struct type *to_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
|  | return value::zero (to_type, not_lval); | 
|  |  | 
|  | const bound_minimal_symbol &b = std::get<0> (m_storage); | 
|  | value *val = evaluate_var_msym_value (noside, b.objfile, b.minsym); | 
|  |  | 
|  | val = value_cast (to_type, val); | 
|  |  | 
|  | /* Don't allow e.g. '&(int)var_with_no_debug_info'.  */ | 
|  | if (val->lval () == lval_memory) | 
|  | { | 
|  | if (val->lazy ()) | 
|  | val->fetch_lazy (); | 
|  | val->set_lval (not_lval); | 
|  | } | 
|  | return val; | 
|  | } | 
|  |  | 
|  | value * | 
|  | var_value_operation::evaluate_for_cast (struct type *to_type, | 
|  | struct expression *exp, | 
|  | enum noside noside) | 
|  | { | 
|  | value *val = evaluate_var_value (noside, | 
|  | std::get<0> (m_storage).block, | 
|  | std::get<0> (m_storage).symbol); | 
|  |  | 
|  | val = value_cast (to_type, val); | 
|  |  | 
|  | /* Don't allow e.g. '&(int)var_with_no_debug_info'.  */ | 
|  | if (val->lval () == lval_memory) | 
|  | { | 
|  | if (val->lazy ()) | 
|  | val->fetch_lazy (); | 
|  | val->set_lval (not_lval); | 
|  | } | 
|  | return val; | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | /* Parse a type expression in the string [P..P+LENGTH).  */ | 
|  |  | 
|  | struct type * | 
|  | parse_and_eval_type (const char *p, int length) | 
|  | { | 
|  | char *tmp = (char *) alloca (length + 4); | 
|  |  | 
|  | tmp[0] = '('; | 
|  | memcpy (tmp + 1, p, length); | 
|  | tmp[length + 1] = ')'; | 
|  | tmp[length + 2] = '0'; | 
|  | tmp[length + 3] = '\0'; | 
|  | expression_up expr = parse_expression (tmp); | 
|  | expr::unop_cast_operation *op | 
|  | = dynamic_cast<expr::unop_cast_operation *> (expr->op.get ()); | 
|  | if (op == nullptr) | 
|  | error (_("Internal error in eval_type.")); | 
|  | return op->get_type (); | 
|  | } |