X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Feval.c;h=bcdb78f05bcfedc8f832073b96e129a5f9a8e414;hb=14aa4ee440f85a0e4d86b7adb50c93bbf0b7fc5b;hp=ee7712281024e6d4c29fbe9d2841ec9d2108c037;hpb=c0df928969781cca1c270ed835407d0222cd1da7;p=binutils-gdb.git diff --git a/gdb/eval.c b/gdb/eval.c index ee771228102..bcdb78f05bc 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -40,30 +40,10 @@ #include "objfiles.h" #include "typeprint.h" #include +#include "expop.h" +#include "c-exp.h" +#include "inferior.h" -/* Prototypes for local functions. */ - -static struct value *evaluate_subexp_for_sizeof (struct expression *, int *, - enum noside); - -static struct value *evaluate_subexp_for_address (struct expression *, - int *, enum noside); - -static value *evaluate_subexp_for_cast (expression *exp, int *pos, - enum noside noside, - struct type *type); - -static struct value *evaluate_struct_tuple (struct value *, - struct expression *, int *, - enum noside, int); - -struct value * -evaluate_subexp (struct type *expect_type, struct expression *exp, - int *pos, enum noside noside) -{ - return ((*exp->language_defn->expression_ops ()->evaluate_exp) - (expect_type, exp, pos, noside)); -} /* Parse the string EXP as a C expression, evaluate it, and return the result as a number. */ @@ -113,13 +93,12 @@ struct value * expression::evaluate (struct type *expect_type, enum noside noside) { gdb::optional stack_temporaries; - if (target_has_execution () + 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 ()); - int pos = 0; - struct value *retval = evaluate_subexp (expect_type, this, &pos, noside); + struct value *retval = op->evaluate (expect_type, this, noside); if (stack_temporaries.has_value () && value_in_thread_stack_temporaries (retval, inferior_thread ())) @@ -145,15 +124,6 @@ evaluate_type (struct expression *exp) return exp->evaluate (nullptr, EVAL_AVOID_SIDE_EFFECTS); } -/* Evaluate a subexpression, avoiding all memory references and - getting a value whose type alone is correct. */ - -struct value * -evaluate_subexpression_type (struct expression *exp, int subexp) -{ - return evaluate_subexp (nullptr, exp, &subexp, EVAL_AVOID_SIDE_EFFECTS); -} - /* 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 @@ -177,8 +147,9 @@ evaluate_subexpression_type (struct expression *exp, int subexp) values will be left on the value chain. */ void -fetch_subexp_value (struct expression *exp, int *pc, struct value **valp, - struct value **resultp, +fetch_subexp_value (struct expression *exp, + expr::operation *op, + struct value **valp, struct value **resultp, std::vector *val_chain, bool preserve_errors) { @@ -196,7 +167,7 @@ fetch_subexp_value (struct expression *exp, int *pc, struct value **valp, try { - result = evaluate_subexp (nullptr, exp, pc, EVAL_NORMAL); + result = op->evaluate (nullptr, exp, EVAL_NORMAL); } catch (const gdb_exception &ex) { @@ -249,91 +220,6 @@ fetch_subexp_value (struct expression *exp, int *pc, struct value **valp, } } -/* Extract a field operation from an expression. If the subexpression - of EXP starting at *SUBEXP is not a structure dereference - operation, return NULL. Otherwise, return the name of the - dereferenced field, and advance *SUBEXP to point to the - subexpression of the left-hand-side of the dereference. This is - used when completing field names. */ - -const char * -extract_field_op (struct expression *exp, int *subexp) -{ - int tem; - char *result; - - if (exp->elts[*subexp].opcode != STRUCTOP_STRUCT - && exp->elts[*subexp].opcode != STRUCTOP_PTR) - return NULL; - tem = longest_to_int (exp->elts[*subexp + 1].longconst); - result = &exp->elts[*subexp + 2].string; - (*subexp) += 1 + 3 + BYTES_TO_EXP_ELEM (tem + 1); - return result; -} - -/* This function evaluates brace-initializers (in C/C++) for - structure types. */ - -static struct value * -evaluate_struct_tuple (struct value *struct_val, - struct expression *exp, - int *pos, enum noside noside, int nargs) -{ - struct type *struct_type = check_typedef (value_type (struct_val)); - struct type *field_type; - int fieldno = -1; - - while (--nargs >= 0) - { - struct value *val = NULL; - int bitpos, bitsize; - bfd_byte *addr; - - fieldno++; - /* Skip static fields. */ - while (fieldno < struct_type->num_fields () - && field_is_static (&struct_type->field (fieldno))) - 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 - && TYPE_FIELD_NAME (struct_type, fieldno)[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 = evaluate_subexp (field_type, exp, pos, noside); - - /* Now actually set the field in struct_val. */ - - /* Assign val to field fieldno. */ - if (value_type (val) != field_type) - val = value_cast (field_type, val); - - bitsize = TYPE_FIELD_BITSIZE (struct_type, fieldno); - bitpos = TYPE_FIELD_BITPOS (struct_type, fieldno); - addr = value_contents_writeable (struct_val) + bitpos / 8; - if (bitsize) - modify_field (struct_type, addr, - value_as_long (val), bitpos % 8, bitsize); - else - memcpy (addr, value_contents (val), - TYPE_LENGTH (value_type (val))); - - } - return struct_val; -} - /* 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 @@ -634,6 +520,24 @@ fake_method::~fake_method () xfree (m_type.fields ()); } +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 &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 * @@ -666,6 +570,23 @@ evaluate_var_value (enum noside noside, const block *blk, symbol *var) 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 (SYMBOL_TYPE (var)->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 * @@ -681,14 +602,6 @@ evaluate_var_msym_value (enum noside noside, return value_at_lazy (the_type, address); } -/* Helper for returning a value when handling EVAL_SKIP. */ - -value * -eval_skip_value (expression *exp) -{ - return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1); -} - /* See expression.h. */ value * @@ -762,412 +675,301 @@ evaluate_subexp_do_call (expression *exp, enum noside noside, } } -/* Helper for evaluating an OP_FUNCALL. */ - -static value * -evaluate_funcall (type *expect_type, expression *exp, int *pos, - enum noside noside) +namespace expr { - int tem; - int pc2 = 0; - value *arg1 = NULL; - value *arg2 = NULL; - int save_pos1; - symbol *function = NULL; - char *function_name = NULL; - const char *var_func_name = NULL; - int pc = (*pos); - (*pos) += 2; +value * +operation::evaluate_funcall (struct type *expect_type, + struct expression *exp, + enum noside noside, + const char *function_name, + const std::vector &args) +{ + std::vector vals (args.size ()); - exp_opcode op = exp->elts[*pos].opcode; - int nargs = longest_to_int (exp->elts[pc].longconst); - /* Allocate arg vector, including space for the function to be - called in argvec[0], a potential `this', and a terminating - NULL. */ - value **argvec = (value **) alloca (sizeof (value *) * (nargs + 3)); - if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) + value *callee = evaluate_with_coercion (exp, noside); + struct type *type = value_type (callee); + if (type->code () == TYPE_CODE_PTR) + type = TYPE_TARGET_TYPE (type); + for (int i = 0; i < args.size (); ++i) { - /* First, evaluate the structure into arg2. */ - pc2 = (*pos)++; - - if (op == STRUCTOP_MEMBER) - { - arg2 = evaluate_subexp_for_address (exp, pos, noside); - } + if (i < type->num_fields ()) + vals[i] = args[i]->evaluate (type->field (i).type (), exp, noside); else - { - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - } - - /* If the function is a virtual function, then the aggregate - value (providing the structure) plays its part by providing - the vtable. Otherwise, it is just along for the ride: call - the function directly. */ - - arg1 = evaluate_subexp (nullptr, exp, pos, noside); + vals[i] = args[i]->evaluate_with_coercion (exp, noside); + } - type *a1_type = check_typedef (value_type (arg1)); - if (noside == EVAL_SKIP) - tem = 1; /* Set it to the right arg index so that all - arguments can also be skipped. */ - else if (a1_type->code () == TYPE_CODE_METHODPTR) - { - if (noside == EVAL_AVOID_SIDE_EFFECTS) - arg1 = value_zero (TYPE_TARGET_TYPE (a1_type), not_lval); - else - arg1 = cplus_method_ptr_to_value (&arg2, arg1); + return evaluate_subexp_do_call (exp, noside, callee, vals, + function_name, expect_type); +} - /* Now, say which argument to start evaluating from. */ - nargs++; - tem = 2; - argvec[1] = arg2; - } - 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 (TYPE_TARGET_TYPE (a1_type)); +value * +var_value_operation::evaluate_funcall (struct type *expect_type, + struct expression *exp, + enum noside noside, + const std::vector &args) +{ + if (!overload_resolution + || exp->language_defn->la_language != language_cplus) + return operation::evaluate_funcall (expect_type, exp, noside, args); + + std::vector 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 (SYMBOL_TYPE (symp)->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); +} - /* Now, convert these values to an address. */ - arg2 = value_cast (type_ptr, arg2); +value * +scope_operation::evaluate_funcall (struct type *expect_type, + struct expression *exp, + enum noside noside, + const std::vector &args) +{ + if (!overload_resolution + || exp->language_defn->la_language != language_cplus) + return operation::evaluate_funcall (expect_type, exp, noside, args); - long mem_offset = value_as_long (arg1); + /* 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); - arg1 = value_from_pointer (target_type_ptr, - value_as_long (arg2) + mem_offset); - arg1 = value_ind (arg1); - tem = 1; - } - else - error (_("Non-pointer-to-member value used in pointer-to-member " - "construct")); + symbol *function = NULL; + const char *function_name = NULL; + std::vector argvec (1 + args.size ()); + if (type->code () == TYPE_CODE_NAMESPACE) + { + function = cp_lookup_symbol_namespace (type->name (), + name.c_str (), + get_selected_block (0), + VAR_DOMAIN).symbol; + if (function == NULL) + error (_("No symbol \"%s\" in namespace \"%s\"."), + name.c_str (), type->name ()); } - else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) + else { - /* Hair for method invocations. */ - int tem2; - - nargs++; - /* First, evaluate the structure into arg2. */ - pc2 = (*pos)++; - tem2 = longest_to_int (exp->elts[pc2 + 1].longconst); - *pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1); + gdb_assert (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION); + function_name = name.c_str (); - 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. */ - arg2 = evaluate_subexp_for_address (exp, pos, noside); - } - else - { - arg2 = evaluate_subexp (nullptr, exp, pos, noside); + /* We need a properly typed value for method lookup. */ + argvec[0] = value_zero (type, lval_memory); + } - /* Check to see if the operator '->' has been overloaded. - If the operator has been overloaded replace arg2 with the - value returned by the custom operator and continue - evaluation. */ - while (unop_user_defined_p (op, arg2)) - { - struct value *value = NULL; - try - { - value = value_x_unop (arg2, op, noside); - } + for (int i = 0; i < args.size (); ++i) + argvec[i + 1] = args[i]->evaluate_with_coercion (exp, noside); + gdb::array_view arg_view = argvec; - catch (const gdb_exception_error &except) - { - if (except.error == NOT_FOUND_ERROR) - break; - else - throw; - } + value *callee = nullptr; + if (function_name != nullptr) + { + int static_memfuncp; - arg2 = value; - } - } - /* Now, say which argument to start evaluating from. */ - tem = 2; - } - else if (op == OP_SCOPE - && overload_resolution - && (exp->language_defn->la_language == language_cplus)) - { - /* Unpack it locally so we can properly handle overload - resolution. */ - char *name; - int local_tem; - - pc2 = (*pos)++; - local_tem = longest_to_int (exp->elts[pc2 + 2].longconst); - (*pos) += 4 + BYTES_TO_EXP_ELEM (local_tem + 1); - struct type *type = exp->elts[pc2 + 1].type; - name = &exp->elts[pc2 + 3].string; - - function = NULL; - function_name = NULL; - if (type->code () == TYPE_CODE_NAMESPACE) - { - function = cp_lookup_symbol_namespace (type->name (), - name, - get_selected_block (0), - VAR_DOMAIN).symbol; - if (function == NULL) - error (_("No symbol \"%s\" in namespace \"%s\"."), - name, type->name ()); - - tem = 1; - /* arg2 is left as NULL on purpose. */ - } - else + find_overload_match (arg_view, function_name, METHOD, + &argvec[0], nullptr, &callee, nullptr, + &static_memfuncp, 0, noside); + if (!static_memfuncp) { - gdb_assert (type->code () == TYPE_CODE_STRUCT - || type->code () == TYPE_CODE_UNION); - function_name = name; - - /* We need a properly typed value for method lookup. For - static methods arg2 is otherwise unused. */ - arg2 = value_zero (type, lval_memory); - ++nargs; - tem = 2; + /* 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 if (op == OP_ADL_FUNC) + else { - /* Save the function position and move pos so that the arguments - can be evaluated. */ - int func_name_len; + 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)); + } - save_pos1 = *pos; - tem = 1; + return evaluate_subexp_do_call (exp, noside, callee, arg_view, + nullptr, expect_type); +} - func_name_len = longest_to_int (exp->elts[save_pos1 + 3].longconst); - (*pos) += 6 + BYTES_TO_EXP_ELEM (func_name_len + 1); - } +value * +structop_member_base::evaluate_funcall (struct type *expect_type, + struct expression *exp, + enum noside noside, + const std::vector &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 vals (args.size () + 1); + gdb::array_view 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 (value_type (rhs)); + if (a1_type->code () == TYPE_CODE_METHODPTR) { - /* Non-method function call. */ - save_pos1 = *pos; - tem = 1; - - /* If this is a C++ function wait until overload resolution. */ - if (op == OP_VAR_VALUE - && overload_resolution - && (exp->language_defn->la_language == language_cplus)) - { - (*pos) += 4; /* Skip the evaluation of the symbol. */ - argvec[0] = NULL; - } + if (noside == EVAL_AVOID_SIDE_EFFECTS) + callee = value_zero (TYPE_TARGET_TYPE (a1_type), not_lval); else - { - if (op == OP_VAR_MSYM_VALUE) - { - minimal_symbol *msym = exp->elts[*pos + 2].msymbol; - var_func_name = msym->print_name (); - } - else if (op == OP_VAR_VALUE) - { - symbol *sym = exp->elts[*pos + 2].symbol; - var_func_name = sym->print_name (); - } + callee = cplus_method_ptr_to_value (&lhs, rhs); - argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside); - type *type = value_type (argvec[0]); - if (type && type->code () == TYPE_CODE_PTR) - type = TYPE_TARGET_TYPE (type); - if (type && type->code () == TYPE_CODE_FUNC) - { - for (; tem <= nargs && tem <= type->num_fields (); tem++) - { - argvec[tem] = evaluate_subexp (type->field (tem - 1).type (), - exp, pos, noside); - } - } - } + vals[0] = lhs; } - - /* Evaluate arguments (if not already done, e.g., namespace::func() - and overload-resolution is off). */ - for (; tem <= nargs; tem++) + else if (a1_type->code () == TYPE_CODE_MEMBERPTR) { - /* Ensure that array expressions are coerced into pointer - objects. */ - argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); - } - - /* Signal end of arglist. */ - argvec[tem] = 0; + struct type *type_ptr + = lookup_pointer_type (TYPE_SELF_TYPE (a1_type)); + struct type *target_type_ptr + = lookup_pointer_type (TYPE_TARGET_TYPE (a1_type)); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); + /* Now, convert this value to an address. */ + lhs = value_cast (type_ptr, lhs); - if (op == OP_ADL_FUNC) - { - struct symbol *symp; - char *func_name; - int name_len; - int string_pc = save_pos1 + 3; - - /* Extract the function name. */ - name_len = longest_to_int (exp->elts[string_pc].longconst); - func_name = (char *) alloca (name_len + 1); - strcpy (func_name, &exp->elts[string_pc + 1].string); + long mem_offset = value_as_long (rhs); - find_overload_match (gdb::make_array_view (&argvec[1], nargs), - func_name, - NON_METHOD, /* not method */ - NULL, NULL, /* pass NULL symbol since - symbol is unknown */ - NULL, &symp, NULL, 0, noside); + callee = value_from_pointer (target_type_ptr, + value_as_long (lhs) + mem_offset); + callee = value_ind (callee); - /* Now fix the expression being evaluated. */ - exp->elts[save_pos1 + 2].symbol = symp; - argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside); + val_view = val_view.slice (1); } + else + error (_("Non-pointer-to-member value used in pointer-to-member " + "construct")); - if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR - || (op == OP_SCOPE && function_name != NULL)) - { - int static_memfuncp; - char *tstr; + for (int i = 0; i < args.size (); ++i) + vals[i + 1] = args[i]->evaluate_with_coercion (exp, noside); - /* Method invocation: stuff "this" as first parameter. If the - method turns out to be static we undo this below. */ - argvec[1] = arg2; + return evaluate_subexp_do_call (exp, noside, callee, val_view, + nullptr, expect_type); - if (op != OP_SCOPE) - { - /* Name of method from expression. */ - tstr = &exp->elts[pc2 + 2].string; - } - else - tstr = function_name; +} - if (overload_resolution && (exp->language_defn->la_language - == language_cplus)) - { - /* Language is C++, do some overload resolution before - evaluation. */ - struct value *valp = NULL; - - (void) find_overload_match (gdb::make_array_view (&argvec[1], nargs), - tstr, - METHOD, /* method */ - &arg2, /* the object */ - NULL, &valp, NULL, - &static_memfuncp, 0, noside); - - if (op == OP_SCOPE && !static_memfuncp) +value * +structop_base_operation::evaluate_funcall + (struct type *expect_type, struct expression *exp, enum noside noside, + const std::vector &args) +{ + /* Allocate space for the function call arguments, Including space for a + `this' pointer at the start. */ + std::vector 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 { - /* For the time being, we don't handle this. */ - error (_("Call to overloaded function %s requires " - "`this' pointer"), - function_name); + value = value_x_unop (vals[0], op, noside); + } + catch (const gdb_exception_error &except) + { + if (except.error == NOT_FOUND_ERROR) + break; + else + throw; } - argvec[1] = arg2; /* the ``this'' pointer */ - argvec[0] = valp; /* Use the method found after overload - resolution. */ - } - else - /* Non-C++ case -- or no overload resolution. */ - { - struct value *temp = arg2; - - argvec[0] = value_struct_elt (&temp, argvec + 1, 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 argvec[1] to - reflect any ``this'' changes. */ - arg2 - = value_from_longest (lookup_pointer_type(value_type (temp)), - value_address (temp) - + value_embedded_offset (temp)); - argvec[1] = arg2; /* the ``this'' pointer */ - } - /* Take out `this' if needed. */ - if (static_memfuncp) - { - argvec[1] = argvec[0]; - nargs--; - argvec++; + vals[0] = value; } } - else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) - { - /* Pointer to member. argvec[1] is already set up. */ - argvec[0] = arg1; - } - else if (op == OP_VAR_VALUE || (op == OP_SCOPE && function != NULL)) - { - /* Non-member function being called. */ - /* fn: This can only be done for C++ functions. A C-style - function in a C++ program, for instance, does not have the - fields that are expected here. */ - if (overload_resolution && (exp->language_defn->la_language - == language_cplus)) - { - /* Language is C++, do some overload resolution before - evaluation. */ - struct symbol *symp; - int no_adl = 0; - - /* If a scope has been specified disable ADL. */ - if (op == OP_SCOPE) - no_adl = 1; + /* 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); - if (op == OP_VAR_VALUE) - function = exp->elts[save_pos1+2].symbol; + /* The array view includes the `this' pointer. */ + gdb::array_view arg_view (vals); - (void) find_overload_match (gdb::make_array_view (&argvec[1], nargs), - NULL, /* no need for name */ - NON_METHOD, /* not method */ - NULL, function, /* the function */ - NULL, &symp, NULL, no_adl, noside); - - if (op == OP_VAR_VALUE) - { - /* Now fix the expression being evaluated. */ - exp->elts[save_pos1+2].symbol = symp; - argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, - noside); - } - else - argvec[0] = value_of_variable (symp, get_selected_block (0)); - } - else - { - /* Not C++, or no overload resolution allowed. */ - /* Nothing to be done; argvec already correctly set up. */ - } + 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. */ { - /* It is probably a C-style function. */ - /* Nothing to be done; argvec already correctly set up. */ + 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 (value_type (temp)), + value_address (temp) + + value_embedded_offset (temp)); } - return evaluate_subexp_do_call (exp, noside, argvec[0], - gdb::make_array_view (argvec + 1, nargs), - var_func_name, expect_type); + /* 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); } + +} /* namespace expr */ + /* Return true if type is integral or reference to integral */ static bool @@ -1184,13 +986,11 @@ is_integral_or_integral_reference (struct type *type) /* Helper function that implements the body of OP_SCOPE. */ -static struct value * +struct value * eval_op_scope (struct type *expect_type, struct expression *exp, enum noside noside, struct type *type, const char *string) { - if (noside == EVAL_SKIP) - return eval_skip_value (exp); struct value *arg1 = value_aggregate_elt (type, string, expect_type, 0, noside); if (arg1 == NULL) @@ -1200,12 +1000,10 @@ eval_op_scope (struct type *expect_type, struct expression *exp, /* Helper function that implements the body of OP_VAR_ENTRY_VALUE. */ -static struct value * +struct value * eval_op_var_entry_value (struct type *expect_type, struct expression *exp, enum noside noside, symbol *sym) { - if (noside == EVAL_SKIP) - return eval_skip_value (exp); if (noside == EVAL_AVOID_SIDE_EFFECTS) return value_zero (SYMBOL_TYPE (sym), not_lval); @@ -1220,1897 +1018,1786 @@ eval_op_var_entry_value (struct type *expect_type, struct expression *exp, /* Helper function that implements the body of OP_VAR_MSYM_VALUE. */ -static struct value * +struct value * eval_op_var_msym_value (struct type *expect_type, struct expression *exp, enum noside noside, bool outermost_p, - minimal_symbol *msymbol, struct objfile *objfile) + bound_minimal_symbol msymbol) { - value *val = evaluate_var_msym_value (noside, objfile, msymbol); + value *val = evaluate_var_msym_value (noside, msymbol.objfile, + msymbol.minsym); struct type *type = value_type (val); if (type->code () == TYPE_CODE_ERROR && (noside != EVAL_AVOID_SIDE_EFFECTS || !outermost_p)) - error_unknown_type (msymbol->print_name ()); + error_unknown_type (msymbol.minsym->print_name ()); return val; } -struct value * -evaluate_subexp_standard (struct type *expect_type, - struct expression *exp, int *pos, - enum noside noside) -{ - enum exp_opcode op; - int tem, tem2, tem3; - int pc, oldpos; - struct value *arg1 = NULL; - struct value *arg2 = NULL; - struct value *arg3; - struct type *type; - int nargs; - struct value **argvec; - int ix; - long mem_offset; - struct type **arg_types; +/* Helper function that implements the body of OP_FUNC_STATIC_VAR. */ - pc = (*pos)++; - op = exp->elts[pc].opcode; +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 = value_address (func); + const block *blk = block_for_pc (addr); + struct block_symbol sym = lookup_symbol (var, blk, VAR_DOMAIN, NULL); + if (sym.symbol == NULL) + error (_("No symbol \"%s\" in specified context."), var); + return evaluate_var_value (noside, sym.block, sym.symbol); +} - switch (op) - { - case OP_SCOPE: - tem = longest_to_int (exp->elts[pc + 2].longconst); - (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1); - return eval_op_scope (expect_type, exp, noside, - exp->elts[pc + 1].type, - &exp->elts[pc + 3].string); +/* Helper function that implements the body of OP_REGISTER. */ - case OP_LONG: - (*pos) += 3; - return value_from_longest (exp->elts[pc + 1].type, - exp->elts[pc + 2].longconst); +struct value * +eval_op_register (struct type *expect_type, struct expression *exp, + enum noside noside, const char *name) +{ + int regno; + struct value *val; - case OP_FLOAT: - (*pos) += 3; - return value_from_contents (exp->elts[pc + 1].type, - exp->elts[pc + 2].floatconst); + 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_selected_frame (NULL)); + if (val == NULL) + error (_("Value of register %s not available."), name); + else + return val; +} - case OP_ADL_FUNC: - case OP_VAR_VALUE: - { - (*pos) += 3; - symbol *var = exp->elts[pc + 2].symbol; - if (SYMBOL_TYPE (var)->code () == TYPE_CODE_ERROR) - error_unknown_type (var->print_name ()); - if (noside != EVAL_SKIP) - return evaluate_var_value (noside, exp->elts[pc + 1].block, var); - else - { - /* Return a dummy value of the correct type when skipping, so - that parent functions know what is to be skipped. */ - return allocate_value (SYMBOL_TYPE (var)); - } - } +/* Helper function that implements the body of OP_STRING. */ - case OP_VAR_MSYM_VALUE: - { - (*pos) += 3; +struct value * +eval_op_string (struct type *expect_type, struct expression *exp, + enum noside noside, int len, const char *string) +{ + struct type *type = language_string_char_type (exp->language_defn, + exp->gdbarch); + return value_string (string, len, type); +} - minimal_symbol *msymbol = exp->elts[pc + 2].msymbol; - return eval_op_var_msym_value (expect_type, exp, noside, - pc == 0, msymbol, - exp->elts[pc + 1].objfile); - } +/* Helper function that implements the body of OP_OBJC_SELECTOR. */ - case OP_VAR_ENTRY_VALUE: - (*pos) += 2; +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)); +} - { - struct symbol *sym = exp->elts[pc + 1].symbol; +/* Helper function that implements the body of BINOP_CONCAT. */ - return eval_op_var_entry_value (expect_type, exp, noside, sym); - } +struct value * +eval_op_concat (struct type *expect_type, struct expression *exp, + enum noside noside, struct value *arg1, struct value *arg2) +{ + if (binop_user_defined_p (BINOP_CONCAT, arg1, arg2)) + return value_x_binop (arg1, arg2, BINOP_CONCAT, OP_NULL, noside); + else + return value_concat (arg1, arg2); +} - case OP_FUNC_STATIC_VAR: - tem = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); +/* A helper function for TERNOP_SLICE. */ - { - value *func = evaluate_subexp_standard (NULL, exp, pos, noside); - CORE_ADDR addr = value_address (func); +struct value * +eval_op_ternop (struct type *expect_type, struct expression *exp, + enum noside noside, + struct value *array, struct value *low, struct value *upper) +{ + int lowbound = value_as_long (low); + int upperbound = value_as_long (upper); + return value_slice (array, lowbound, upperbound - lowbound + 1); +} - const block *blk = block_for_pc (addr); - const char *var = &exp->elts[pc + 2].string; +/* A helper function for STRUCTOP_STRUCT. */ - struct block_symbol sym = lookup_symbol (var, blk, VAR_DOMAIN, NULL); +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 (value_type (arg3), VALUE_LVAL (arg3)); + return arg3; +} - if (sym.symbol == NULL) - error (_("No symbol \"%s\" in specified context."), var); +/* A helper function for STRUCTOP_PTR. */ - return evaluate_var_value (noside, sym.block, sym.symbol); - } +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); + } - case OP_LAST: - (*pos) += 2; - return - access_value_history (longest_to_int (exp->elts[pc + 1].longconst)); + catch (const gdb_exception_error &except) + { + if (except.error == NOT_FOUND_ERROR) + break; + else + throw; + } - case OP_REGISTER: + 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 = value_type (arg1); + struct type *real_type; + int full, using_enc; + LONGEST top; + struct value_print_options opts; + + get_user_print_options (&opts); + if (opts.objectprint && TYPE_TARGET_TYPE (arg_type) + && (TYPE_TARGET_TYPE (arg_type)->code () == TYPE_CODE_STRUCT)) { - const char *name = &exp->elts[pc + 2].string; - int regno; - struct value *val; - - (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1); - 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_selected_frame (NULL)); - if (val == NULL) - error (_("Value of register %s not available."), name); - else - return val; + real_type = value_rtti_indirect_type (arg1, &full, &top, + &using_enc); + if (real_type) + arg1 = value_cast (real_type, arg1); } - case OP_BOOL: - (*pos) += 2; - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, exp->elts[pc + 1].longconst); - - case OP_INTERNALVAR: - (*pos) += 2; - return value_of_internalvar (exp->gdbarch, - exp->elts[pc + 1].internalvar); - - case OP_STRING: - tem = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - type = language_string_char_type (exp->language_defn, exp->gdbarch); - return value_string (&exp->elts[pc + 2].string, tem, type); - - case OP_OBJC_NSSTRING: /* Objective C Foundation Class - NSString constant. */ - tem = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - return value_nsstring (exp->gdbarch, &exp->elts[pc + 2].string, tem + 1); - - case OP_ARRAY: - (*pos) += 3; - tem2 = longest_to_int (exp->elts[pc + 1].longconst); - tem3 = longest_to_int (exp->elts[pc + 2].longconst); - nargs = tem3 - tem2 + 1; - type = expect_type ? check_typedef (expect_type) : nullptr; - - if (expect_type != nullptr && noside != EVAL_SKIP - && type->code () == TYPE_CODE_STRUCT) - { - struct value *rec = allocate_value (expect_type); + } - memset (value_contents_raw (rec), '\0', TYPE_LENGTH (type)); - return evaluate_struct_tuple (rec, exp, pos, noside, nargs); - } + struct value *arg3 = value_struct_elt (&arg1, {}, string, + NULL, "structure pointer"); + if (noside == EVAL_AVOID_SIDE_EFFECTS) + arg3 = value_zero (value_type (arg3), VALUE_LVAL (arg3)); + return arg3; +} - if (expect_type != nullptr && noside != EVAL_SKIP - && type->code () == TYPE_CODE_ARRAY) - { - struct type *range_type = type->index_type (); - struct type *element_type = TYPE_TARGET_TYPE (type); - struct value *array = allocate_value (expect_type); - int element_size = TYPE_LENGTH (check_typedef (element_type)); - LONGEST low_bound, high_bound, index; +/* A helper function for STRUCTOP_MEMBER. */ - if (!get_discrete_bounds (range_type, &low_bound, &high_bound)) - { - low_bound = 0; - high_bound = (TYPE_LENGTH (type) / element_size) - 1; - } - index = low_bound; - memset (value_contents_raw (array), 0, TYPE_LENGTH (expect_type)); - for (tem = nargs; --nargs >= 0;) - { - struct value *element; - - element = evaluate_subexp (element_type, exp, pos, noside); - if (value_type (element) != element_type) - element = value_cast (element_type, element); - if (index > high_bound) - /* To avoid memory corruption. */ - error (_("Too many array elements")); - memcpy (value_contents_raw (array) - + (index - low_bound) * element_size, - value_contents (element), - element_size); - index++; - } - return array; - } +struct value * +eval_op_member (struct type *expect_type, struct expression *exp, + enum noside noside, + struct value *arg1, struct value *arg2) +{ + long mem_offset; - if (expect_type != nullptr && noside != EVAL_SKIP - && type->code () == TYPE_CODE_SET) + struct value *arg3; + struct type *type = check_typedef (value_type (arg2)); + switch (type->code ()) + { + case TYPE_CODE_METHODPTR: + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (TYPE_TARGET_TYPE (type), not_lval); + else { - struct value *set = allocate_value (expect_type); - gdb_byte *valaddr = value_contents_raw (set); - 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 = TYPE_TARGET_TYPE (check_type); - - if (!get_discrete_bounds (element_type, &low_bound, &high_bound)) - error (_("(power)set type with unknown size")); - memset (valaddr, '\0', TYPE_LENGTH (type)); - for (tem = 0; tem < nargs; tem++) - { - LONGEST range_low, range_high; - struct type *range_low_type, *range_high_type; - struct value *elem_val; - - elem_val = evaluate_subexp (element_type, exp, pos, noside); - range_low_type = range_high_type = value_type (elem_val); - range_low = range_high = value_as_long (elem_val); - - /* Check types of elements to avoid mixture of elements from - different types. Also check if type of element is "compatible" - with element type of powerset. */ - if (range_low_type->code () == TYPE_CODE_RANGE) - range_low_type = TYPE_TARGET_TYPE (range_low_type); - if (range_high_type->code () == TYPE_CODE_RANGE) - range_high_type = TYPE_TARGET_TYPE (range_high_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; + arg2 = cplus_method_ptr_to_value (&arg1, arg2); + gdb_assert (value_type (arg2)->code () == TYPE_CODE_PTR); + return value_ind (arg2); } - argvec = XALLOCAVEC (struct value *, nargs); - for (tem = 0; tem < nargs; tem++) - { - /* Ensure that array expressions are coerced into pointer - objects. */ - argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); - } - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - return value_array (tem2, tem3, argvec); + case TYPE_CODE_MEMBERPTR: + /* Now, convert these values to an address. */ + arg1 = value_cast_pointers (lookup_pointer_type (TYPE_SELF_TYPE (type)), + arg1, 1); - case TERNOP_SLICE: - { - struct value *array = evaluate_subexp (nullptr, exp, pos, noside); - int lowbound - = value_as_long (evaluate_subexp (nullptr, exp, pos, noside)); - int upper = value_as_long (evaluate_subexp (nullptr, exp, pos, noside)); - - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - return value_slice (array, lowbound, upper - lowbound + 1); - } + mem_offset = value_as_long (arg2); - case TERNOP_COND: - /* Skip third and second args to evaluate the first one. */ - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (value_logical_not (arg1)) - { - evaluate_subexp (nullptr, exp, pos, EVAL_SKIP); - return evaluate_subexp (nullptr, exp, pos, noside); + arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (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, value_type (arg1)) + && is_integral_or_integral_reference (value_type (arg2))) + return value_ptradd (arg1, value_as_long (arg2)); + else if (ptrmath_type_p (exp->language_defn, value_type (arg2)) + && is_integral_or_integral_reference (value_type (arg1))) + 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, value_type (arg1)) + && ptrmath_type_p (exp->language_defn, value_type (arg2))) + { + /* 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, value_type (arg1)) + && is_integral_or_integral_reference (value_type (arg2))) + 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 (value_type (arg2)); + binop_promote (exp->language_defn, exp->gdbarch, &arg1, &v_one); + return value_binop (arg1, v_one, op); } else { - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - evaluate_subexp (nullptr, exp, pos, EVAL_SKIP); - return arg2; + /* For shift and integer exponentiation operations, + only promote the first argument. */ + if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) + && is_integral_type (value_type (arg2))) + unop_promote (exp->language_defn, exp->gdbarch, &arg1); + else + binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); + + return value_binop (arg1, arg2, op); } + } +} - case OP_OBJC_SELECTOR: - { /* Objective C @selector operator. */ - char *sel = &exp->elts[pc + 2].string; - int len = longest_to_int (exp->elts[pc + 1].longconst); - struct type *selector_type; +/* A helper function for BINOP_SUBSCRIPT. */ - (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); +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 (value_type (arg1)); + 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 (sel[len] != 0) - sel[len] = 0; /* Make sure it's terminated. */ + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1)); + else + return value_subscript (arg1, value_as_long (arg2)); + } +} - 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 BINOP_EQUAL. */ - case OP_OBJC_MSGCALL: - { /* Objective C message (method) call. */ +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); + } +} - CORE_ADDR responds_selector = 0; - CORE_ADDR method_selector = 0; +/* A helper function for BINOP_NOTEQUAL. */ - CORE_ADDR selector = 0; +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); + } +} - int struct_return = 0; - enum noside sub_no_side = EVAL_NORMAL; +/* A helper function for BINOP_LESS. */ - struct value *msg_send = NULL; - struct value *msg_send_stret = NULL; - int gnu_runtime = 0; +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); + } +} - struct value *target = NULL; - struct value *method = NULL; - struct value *called_method = NULL; +/* A helper function for BINOP_GTR. */ - struct type *selector_type = NULL; - struct type *long_type; +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); + } +} - struct value *ret = NULL; - CORE_ADDR addr = 0; +/* A helper function for BINOP_GEQ. */ - selector = exp->elts[pc + 1].longconst; - nargs = exp->elts[pc + 2].longconst; - argvec = XALLOCAVEC (struct value *, nargs + 5); +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); + } +} - (*pos) += 3; +/* A helper function for BINOP_LEQ. */ - long_type = builtin_type (exp->gdbarch)->builtin_long; - selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; +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); + } +} - if (noside == EVAL_AVOID_SIDE_EFFECTS) - sub_no_side = EVAL_NORMAL; - else - sub_no_side = noside; +/* A helper function for BINOP_REPEAT. */ - target = evaluate_subexp (selector_type, exp, pos, sub_no_side); +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 (value_type (arg2)); + 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 (value_type (arg1), + longest_to_int (value_as_long (arg2))); + } + else + return value_repeat (arg1, longest_to_int (value_as_long (arg2))); +} - if (value_as_long (target) == 0) - return value_from_longest (long_type, 0); - - if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0).minsym) - 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; +/* A helper function for UNOP_PLUS. */ - type = lookup_function_type (type); - type = lookup_pointer_type (type); - type = lookup_function_type (type); - type = lookup_pointer_type (type); +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); + } +} - msg_send = find_function_in_inferior ("objc_msg_lookup", NULL); - msg_send_stret - = find_function_in_inferior ("objc_msg_lookup", NULL); +/* A helper function for UNOP_NEG. */ - 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); - } +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); + } +} - /* 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}); - } +/* A helper function for UNOP_COMPLEMENT. */ - /* ret should now be the selector. */ +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); + } +} - addr = value_as_long (ret); - if (addr) - { - struct symbol *sym = NULL; +/* A helper function for UNOP_LOGICAL_NOT. */ - /* 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_top_target ()); +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)); + } +} - /* Is it a high_level symbol? */ - sym = find_pc_function (addr); - if (sym != NULL) - method = value_of_variable (sym, 0); - } +/* A helper function for UNOP_IND. */ - /* If we found a method with symbol information, check to see - if it returns a struct. Otherwise assume it doesn't. */ +struct value * +eval_op_ind (struct type *expect_type, struct expression *exp, + enum noside noside, + struct value *arg1) +{ + struct type *type = check_typedef (value_type (arg1)); + 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 (value_type (arg1)); - if (method) - { - CORE_ADDR funaddr; - struct type *val_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 (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 (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.")); + } + } - funaddr = find_function_addr (method, &val_type); + /* 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, + (CORE_ADDR) value_as_address (arg1)); + return value_ind (arg1); +} - block_for_pc (funaddr); +/* A helper function for UNOP_ALIGNOF. */ - val_type = check_typedef (val_type); +struct value * +eval_op_alignof (struct type *expect_type, struct expression *exp, + enum noside noside, + struct value *arg1) +{ + struct type *type = value_type (arg1); + /* 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); +} - if ((val_type == NULL) - || (val_type->code () == TYPE_CODE_ERROR)) - { - if (expect_type != NULL) - val_type = expect_type; - } +/* A helper function for UNOP_MEMVAL. */ - 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)); - } +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)); +} - /* 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 thru - 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 (value_type (method)->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 (value_type (method)), - value_as_address (msg_send_stret)); - else - called_method - = value_from_pointer (lookup_pointer_type (value_type (method)), - value_as_address (msg_send)); - } - else - { - if (struct_return) - called_method = msg_send_stret; - else - called_method = msg_send; - } +/* 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, value_type (arg1))) + arg2 = value_ptradd (arg1, 1); + else + { + struct value *tmp = arg1; + + arg2 = value_one (value_type (arg1)); + 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, value_type (arg1))) + arg2 = value_ptradd (arg1, -1); + else + { + struct value *tmp = arg1; + + arg2 = value_one (value_type (arg1)); + 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 = value_non_lval (arg1); + struct value *arg2; + + if (ptrmath_type_p (exp->language_defn, value_type (arg1))) + arg2 = value_ptradd (arg1, 1); + else + { + struct value *tmp = arg1; + + arg2 = value_one (value_type (arg1)); + 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 = value_non_lval (arg1); + struct value *arg2; - if (noside == EVAL_SKIP) - return eval_skip_value (exp); + if (ptrmath_type_p (exp->language_defn, value_type (arg1))) + arg2 = value_ptradd (arg1, -1); + else + { + struct value *tmp = arg1; - 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. */ + arg2 = value_one (value_type (arg1)); + binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); + arg2 = value_binop (tmp, arg2, BINOP_SUB); + } - struct type *callee_type = value_type (called_method); + value_assign (arg1, arg2); + return arg3; + } +} - if (callee_type && callee_type->code () == TYPE_CODE_PTR) - callee_type = TYPE_TARGET_TYPE (callee_type); - callee_type = TYPE_TARGET_TYPE (callee_type); +/* A helper function for OP_TYPE. */ - if (callee_type) - { - if ((callee_type->code () == TYPE_CODE_ERROR) && expect_type) - return allocate_value (expect_type); - else - return allocate_value (callee_type); - } - else - error (_("Expression of type other than " - "\"method returning ...\" used as a method")); - } +struct value * +eval_op_type (struct type *expect_type, struct expression *exp, + enum noside noside, struct type *type) +{ + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return allocate_value (type); + else + error (_("Attempt to use a type name as an expression")); +} - /* Now depending on whether we found a symbol for the method, - we will either call the runtime dispatcher or the method - directly. */ +/* A helper function for BINOP_ASSIGN_MODIFY. */ - argvec[0] = called_method; - argvec[1] = target; - argvec[2] = value_from_longest (long_type, selector); - /* User-supplied arguments. */ - for (tem = 0; tem < nargs; tem++) - argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside); - argvec[tem + 3] = 0; +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, + value_type (arg1)) + && is_integral_type (value_type (arg2))) + arg2 = value_ptradd (arg1, value_as_long (arg2)); + else if (op == BINOP_SUB && ptrmath_type_p (exp->language_defn, + value_type (arg1)) + && is_integral_type (value_type (arg2))) + arg2 = value_ptradd (arg1, - value_as_long (arg2)); + else + { + struct value *tmp = arg1; - auto call_args = gdb::make_array_view (argvec + 1, nargs + 2); + /* For shift and integer exponentiation operations, + only promote the first argument. */ + if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) + && is_integral_type (value_type (arg2))) + unop_promote (exp->language_defn, exp->gdbarch, &tmp); + else + binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); - if (gnu_runtime && (method != NULL)) - { - /* Function objc_msg_lookup returns a pointer. */ - deprecated_set_value_type (argvec[0], - lookup_pointer_type (lookup_function_type (value_type (argvec[0])))); - argvec[0] = call_function_by_hand (argvec[0], NULL, call_args); - } + arg2 = value_binop (tmp, arg2, op); + } + return value_assign (arg1, arg2); +} - return call_function_by_hand (argvec[0], NULL, call_args); - } - break; - - case OP_FUNCALL: - return evaluate_funcall (expect_type, exp, pos, noside); - - case OP_COMPLEX: - /* We have a complex number, There should be 2 floating - point numbers that compose it. */ - (*pos) += 2; - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - - return value_literal_complex (arg1, arg2, exp->elts[pc + 1].type); - - case STRUCTOP_STRUCT: - tem = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - arg3 = value_struct_elt (&arg1, NULL, &exp->elts[pc + 2].string, - NULL, "structure"); - if (noside == EVAL_AVOID_SIDE_EFFECTS) - arg3 = value_zero (value_type (arg3), VALUE_LVAL (arg3)); - return arg3; +/* 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 args) +{ + CORE_ADDR responds_selector = 0; + CORE_ADDR method_selector = 0; - case STRUCTOP_PTR: - tem = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1); - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); + int struct_return = 0; - /* Check to see if operator '->' has been overloaded. If so replace - arg1 with the value returned by evaluating operator->(). */ - while (unop_user_defined_p (op, arg1)) - { - struct value *value = NULL; - try - { - value = value_x_unop (arg1, op, noside); - } + struct value *msg_send = NULL; + struct value *msg_send_stret = NULL; + int gnu_runtime = 0; - catch (const gdb_exception_error &except) - { - if (except.error == NOT_FOUND_ERROR) - break; - else - throw; - } + struct value *method = NULL; + struct value *called_method = NULL; - arg1 = value; - } + struct type *selector_type = NULL; + struct type *long_type; + struct type *type; - /* 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 = value_type (arg1); - struct type *real_type; - int full, using_enc; - LONGEST top; - struct value_print_options opts; - - get_user_print_options (&opts); - if (opts.objectprint && TYPE_TARGET_TYPE (arg_type) - && (TYPE_TARGET_TYPE (arg_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 *ret = NULL; + CORE_ADDR addr = 0; - arg3 = value_struct_elt (&arg1, NULL, &exp->elts[pc + 2].string, - NULL, "structure pointer"); - if (noside == EVAL_AVOID_SIDE_EFFECTS) - arg3 = value_zero (value_type (arg3), VALUE_LVAL (arg3)); - return arg3; + value *argvec[5]; - case STRUCTOP_MEMBER: - case STRUCTOP_MPTR: - if (op == STRUCTOP_MEMBER) - arg1 = evaluate_subexp_for_address (exp, pos, noside); - else - arg1 = evaluate_subexp (nullptr, exp, pos, noside); + long_type = builtin_type (exp->gdbarch)->builtin_long; + selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; - arg2 = evaluate_subexp (nullptr, exp, pos, noside); + if (value_as_long (target) == 0) + return value_from_longest (long_type, 0); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); + if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0).minsym) + gnu_runtime = 1; - type = check_typedef (value_type (arg2)); - switch (type->code ()) - { - case TYPE_CODE_METHODPTR: - if (noside == EVAL_AVOID_SIDE_EFFECTS) - return value_zero (TYPE_TARGET_TYPE (type), not_lval); - else - { - arg2 = cplus_method_ptr_to_value (&arg1, arg2); - gdb_assert (value_type (arg2)->code () == TYPE_CODE_PTR); - return value_ind (arg2); - } + /* 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; - case TYPE_CODE_MEMBERPTR: - /* Now, convert these values to an address. */ - arg1 = value_cast_pointers (lookup_pointer_type (TYPE_SELF_TYPE (type)), - arg1, 1); + type = lookup_function_type (type); + type = lookup_pointer_type (type); + type = lookup_function_type (type); + type = lookup_pointer_type (type); - mem_offset = value_as_long (arg2); + msg_send = find_function_in_inferior ("objc_msg_lookup", NULL); + msg_send_stret + = find_function_in_inferior ("objc_msg_lookup", NULL); - arg3 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), - value_as_long (arg1) + mem_offset); - return value_ind (arg3); + 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); + } - default: - error (_("non-pointer-to-member value used " - "in pointer-to-member construct")); - } + /* 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. */ - case TYPE_INSTANCE: - { - type_instance_flags flags - = (type_instance_flag_value) longest_to_int (exp->elts[pc + 1].longconst); - nargs = longest_to_int (exp->elts[pc + 2].longconst); - arg_types = (struct type **) alloca (nargs * sizeof (struct type *)); - for (ix = 0; ix < nargs; ++ix) - arg_types[ix] = exp->elts[pc + 2 + ix + 1].type; - - fake_method fake_expect_type (flags, nargs, arg_types); - *(pos) += 4 + nargs; - return evaluate_subexp_standard (fake_expect_type.type (), exp, pos, - noside); - } + responds_selector + = lookup_child_selector (exp->gdbarch, "respondsToSelector:"); + if (responds_selector == 0) + responds_selector + = lookup_child_selector (exp->gdbarch, "respondsTo:"); - case BINOP_CONCAT: - arg1 = evaluate_subexp_with_coercion (exp, pos, noside); - arg2 = evaluate_subexp_with_coercion (exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (binop_user_defined_p (op, arg1, arg2)) - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - else - return value_concat (arg1, arg2); - - case BINOP_ASSIGN: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - /* Special-case assignments where the left-hand-side is a - convenience variable -- in these, don't bother setting an - expected type. This avoids a weird case where re-assigning a - string or array to an internal variable could error with "Too - many array elements". */ - arg2 = evaluate_subexp (VALUE_LVAL (arg1) == lval_internalvar - ? nullptr - : value_type (arg1), - exp, pos, noside); - - if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) - return arg1; - if (binop_user_defined_p (op, arg1, arg2)) - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - else - return value_assign (arg1, arg2); - - case BINOP_ASSIGN_MODIFY: - (*pos) += 2; - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) - return arg1; - op = exp->elts[pc + 1].opcode; - if (binop_user_defined_p (op, arg1, arg2)) - return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside); - else if (op == BINOP_ADD && ptrmath_type_p (exp->language_defn, - value_type (arg1)) - && is_integral_type (value_type (arg2))) - arg2 = value_ptradd (arg1, value_as_long (arg2)); - else if (op == BINOP_SUB && ptrmath_type_p (exp->language_defn, - value_type (arg1)) - && is_integral_type (value_type (arg2))) - arg2 = value_ptradd (arg1, - value_as_long (arg2)); - else - { - struct value *tmp = arg1; + if (responds_selector == 0) + error (_("no 'respondsTo:' or 'respondsToSelector:' method")); - /* For shift and integer exponentiation operations, - only promote the first argument. */ - if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) - && is_integral_type (value_type (arg2))) - unop_promote (exp->language_defn, exp->gdbarch, &tmp); - else - binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); + method_selector + = lookup_child_selector (exp->gdbarch, "methodForSelector:"); + if (method_selector == 0) + method_selector + = lookup_child_selector (exp->gdbarch, "methodFor:"); - arg2 = value_binop (tmp, arg2, op); - } - return value_assign (arg1, arg2); + if (method_selector == 0) + error (_("no 'methodFor:' or 'methodForSelector:' method")); - case BINOP_ADD: - arg1 = evaluate_subexp_with_coercion (exp, pos, noside); - arg2 = evaluate_subexp_with_coercion (exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (binop_user_defined_p (op, arg1, arg2)) - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - else if (ptrmath_type_p (exp->language_defn, value_type (arg1)) - && is_integral_or_integral_reference (value_type (arg2))) - return value_ptradd (arg1, value_as_long (arg2)); - else if (ptrmath_type_p (exp->language_defn, value_type (arg2)) - && is_integral_or_integral_reference (value_type (arg1))) - 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); - } + /* Call the verification method, to make sure that the target + class implements the desired method. */ - case BINOP_SUB: - arg1 = evaluate_subexp_with_coercion (exp, pos, noside); - arg2 = evaluate_subexp_with_coercion (exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (binop_user_defined_p (op, arg1, arg2)) - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - else if (ptrmath_type_p (exp->language_defn, value_type (arg1)) - && ptrmath_type_p (exp->language_defn, value_type (arg2))) - { - /* FIXME -- should be ptrdiff_t */ - type = builtin_type (exp->gdbarch)->builtin_long; - return value_from_longest (type, value_ptrdiff (arg1, arg2)); - } - else if (ptrmath_type_p (exp->language_defn, value_type (arg1)) - && is_integral_or_integral_reference (value_type (arg2))) - 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); - } + 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; - case BINOP_EXP: - case BINOP_MUL: - case BINOP_DIV: - case BINOP_INTDIV: - case BINOP_REM: - case BINOP_MOD: - case BINOP_LSH: - case BINOP_RSH: - case BINOP_BITWISE_AND: - case BINOP_BITWISE_IOR: - case BINOP_BITWISE_XOR: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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; + 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}); + } - v_one = value_one (value_type (arg2)); - 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 (value_type (arg2))) - unop_promote (exp->language_defn, exp->gdbarch, &arg1); - else - binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); + /* ret should now be the selector. */ - return value_binop (arg1, arg2, op); - } - } + addr = value_as_long (ret); + if (addr) + { + struct symbol *sym = NULL; - case BINOP_SUBSCRIPT: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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. */ + /* 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 ()); - arg1 = coerce_ref (arg1); - type = check_typedef (value_type (arg1)); - 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")); - } + /* Is it a high_level symbol? */ + sym = find_pc_function (addr); + if (sym != NULL) + method = value_of_variable (sym, 0); + } - if (noside == EVAL_AVOID_SIDE_EFFECTS) - return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1)); - else - return value_subscript (arg1, value_as_long (arg2)); - } - case MULTI_SUBSCRIPT: - (*pos) += 2; - nargs = longest_to_int (exp->elts[pc + 1].longconst); - arg1 = evaluate_subexp_with_coercion (exp, pos, noside); - argvec = XALLOCAVEC (struct value *, nargs); - for (ix = 0; ix < nargs; ++ix) - argvec[ix] = evaluate_subexp_with_coercion (exp, pos, noside); - if (noside == EVAL_SKIP) - return arg1; - for (ix = 0; ix < nargs; ++ix) - { - arg2 = argvec[ix]; + /* If we found a method with symbol information, check to see + if it returns a struct. Otherwise assume it doesn't. */ - if (binop_user_defined_p (op, arg1, arg2)) - { - arg1 = value_x_binop (arg1, arg2, op, OP_NULL, noside); - } - else - { - arg1 = coerce_ref (arg1); - type = check_typedef (value_type (arg1)); + if (method) + { + CORE_ADDR funaddr; + struct type *val_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); + funaddr = find_function_addr (method, &val_type); - case BINOP_LOGICAL_AND: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - { - evaluate_subexp (nullptr, exp, pos, noside); - return eval_skip_value (exp); - } + block_for_pc (funaddr); - oldpos = *pos; - arg2 = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - *pos = oldpos; + val_type = check_typedef (val_type); - if (binop_user_defined_p (op, arg1, arg2)) - { - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - } - else + if ((val_type == NULL) + || (val_type->code () == TYPE_CODE_ERROR)) { - tem = value_logical_not (arg1); - arg2 - = evaluate_subexp (nullptr, exp, pos, (tem ? EVAL_SKIP : noside)); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, - (LONGEST) (!tem && !value_logical_not (arg2))); + if (expect_type != NULL) + val_type = expect_type; } - case BINOP_LOGICAL_OR: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - { - evaluate_subexp (nullptr, exp, pos, noside); - return eval_skip_value (exp); - } + 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)); + } - oldpos = *pos; - arg2 = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - *pos = oldpos; + /* 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 thru + 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. - if (binop_user_defined_p (op, arg1, arg2)) - { - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - } - else - { - tem = value_logical_not (arg1); - arg2 - = evaluate_subexp (nullptr, exp, pos, (!tem ? EVAL_SKIP : noside)); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, - (LONGEST) (!tem || !value_logical_not (arg2))); - } + 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. */ - case BINOP_EQUAL: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (binop_user_defined_p (op, arg1, arg2)) - { - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - } + if (method) + { + if (value_type (method)->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 (value_type (method)), + value_as_address (msg_send_stret)); else - { - binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); - tem = value_equal (arg1, arg2); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) tem); - } - - case BINOP_NOTEQUAL: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (binop_user_defined_p (op, arg1, arg2)) - { - return value_x_binop (arg1, arg2, op, OP_NULL, noside); - } + called_method + = value_from_pointer (lookup_pointer_type (value_type (method)), + value_as_address (msg_send)); + } + else + { + if (struct_return) + called_method = msg_send_stret; else - { - binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); - tem = value_equal (arg1, arg2); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) ! tem); - } + called_method = msg_send; + } - case BINOP_LESS: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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); - tem = value_less (arg1, arg2); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) tem); - } - case BINOP_GTR: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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); - tem = value_less (arg2, arg1); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) tem); - } + 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. */ - case BINOP_GEQ: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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); - tem = value_less (arg2, arg1) || value_equal (arg1, arg2); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) tem); - } + struct type *callee_type = value_type (called_method); - case BINOP_LEQ: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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); - tem = value_less (arg1, arg2) || value_equal (arg1, arg2); - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) tem); - } + if (callee_type && callee_type->code () == TYPE_CODE_PTR) + callee_type = TYPE_TARGET_TYPE (callee_type); + callee_type = TYPE_TARGET_TYPE (callee_type); - case BINOP_REPEAT: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - arg2 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - type = check_typedef (value_type (arg2)); - 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 (value_type (arg1), - longest_to_int (value_as_long (arg2))); - } - else - return value_repeat (arg1, longest_to_int (value_as_long (arg2))); - - case BINOP_COMMA: - evaluate_subexp (nullptr, exp, pos, noside); - return evaluate_subexp (nullptr, exp, pos, noside); - - case UNOP_PLUS: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (unop_user_defined_p (op, arg1)) - return value_x_unop (arg1, op, noside); - else + if (callee_type) { - unop_promote (exp->language_defn, exp->gdbarch, &arg1); - return value_pos (arg1); + if ((callee_type->code () == TYPE_CODE_ERROR) && expect_type) + return allocate_value (expect_type); + else + return allocate_value (callee_type); } - - case UNOP_NEG: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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); - } - - case UNOP_COMPLEMENT: - /* C++: check for and handle destructor names. */ + error (_("Expression of type other than " + "\"method returning ...\" used as a method")); + } - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - 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); - } + /* Now depending on whether we found a symbol for the method, + we will either call the runtime dispatcher or the method + directly. */ - case UNOP_LOGICAL_NOT: - arg1 = evaluate_subexp (nullptr, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (unop_user_defined_p (op, arg1)) - return value_x_unop (arg1, op, noside); - else - { - type = language_bool_type (exp->language_defn, exp->gdbarch); - return value_from_longest (type, (LONGEST) value_logical_not (arg1)); - } + args[0] = target; + args[1] = value_from_longest (long_type, selector); - case UNOP_IND: - if (expect_type && expect_type->code () == TYPE_CODE_PTR) - expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type)); - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - type = check_typedef (value_type (arg1)); - if (type->code () == TYPE_CODE_METHODPTR - || type->code () == TYPE_CODE_MEMBERPTR) - error (_("Attempt to dereference pointer " - "to member without an object")); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (unop_user_defined_p (op, arg1)) - return value_x_unop (arg1, op, noside); - else if (noside == EVAL_AVOID_SIDE_EFFECTS) - { - type = check_typedef (value_type (arg1)); - - /* If the type pointed to is dynamic then in order to resolve the - dynamic properties we must actually dereference the pointer. - There is a risk that this dereference will have side-effects - in the inferior, but being able to print accurate type - information seems worth the risk. */ - if ((type->code () != TYPE_CODE_PTR - && !TYPE_IS_REFERENCE (type)) - || !is_dynamic_type (TYPE_TARGET_TYPE (type))) - { - if (type->code () == TYPE_CODE_PTR - || TYPE_IS_REFERENCE (type) - /* In C you can dereference an array to get the 1st elt. */ - || type->code () == TYPE_CODE_ARRAY) - return value_zero (TYPE_TARGET_TYPE (type), - lval_memory); - else if (type->code () == TYPE_CODE_INT) - /* GDB allows dereferencing an int. */ - return value_zero (builtin_type (exp->gdbarch)->builtin_int, - lval_memory); - else - error (_("Attempt to take contents of a non-pointer value.")); - } - } + if (gnu_runtime && (method != NULL)) + { + /* Function objc_msg_lookup returns a pointer. */ + struct type *tem_type = value_type (called_method); + tem_type = lookup_pointer_type (lookup_function_type (tem_type)); + deprecated_set_value_type (called_method, tem_type); + called_method = call_function_by_hand (called_method, NULL, args); + } - /* 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, - (CORE_ADDR) value_as_address (arg1)); - return value_ind (arg1); + return call_function_by_hand (called_method, NULL, args); +} - case UNOP_ADDR: - /* C++: check for and handle pointer to members. */ +/* Helper function for MULTI_SUBSCRIPT. */ - if (noside == EVAL_SKIP) +static struct value * +eval_multi_subscript (struct type *expect_type, struct expression *exp, + enum noside noside, value *arg1, + gdb::array_view args) +{ + for (value *arg2 : args) + { + if (binop_user_defined_p (MULTI_SUBSCRIPT, arg1, arg2)) { - evaluate_subexp (nullptr, exp, pos, EVAL_SKIP); - return eval_skip_value (exp); + arg1 = value_x_binop (arg1, arg2, MULTI_SUBSCRIPT, OP_NULL, noside); } else - return evaluate_subexp_for_address (exp, pos, noside); - - case UNOP_SIZEOF: - if (noside == EVAL_SKIP) { - evaluate_subexp (nullptr, exp, pos, EVAL_SKIP); - return eval_skip_value (exp); - } - return evaluate_subexp_for_sizeof (exp, pos, noside); - - case UNOP_ALIGNOF: - { - type = value_type ( - evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS)); - /* 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); - } - - case UNOP_CAST: - (*pos) += 2; - type = exp->elts[pc + 1].type; - return evaluate_subexp_for_cast (exp, pos, noside, type); - - case UNOP_CAST_TYPE: - arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (arg1); - return evaluate_subexp_for_cast (exp, pos, noside, type); - - case UNOP_DYNAMIC_CAST: - arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (arg1); - arg1 = evaluate_subexp (type, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - return value_dynamic_cast (type, arg1); - - case UNOP_REINTERPRET_CAST: - arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (arg1); - arg1 = evaluate_subexp (type, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - return value_reinterpret_cast (type, arg1); - - case UNOP_MEMVAL: - (*pos) += 2; - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (noside == EVAL_AVOID_SIDE_EFFECTS) - return value_zero (exp->elts[pc + 1].type, lval_memory); - else - return value_at_lazy (exp->elts[pc + 1].type, - value_as_address (arg1)); - - case UNOP_MEMVAL_TYPE: - arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (arg1); - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - if (noside == EVAL_AVOID_SIDE_EFFECTS) - return value_zero (type, lval_memory); - else - return value_at_lazy (type, value_as_address (arg1)); + arg1 = coerce_ref (arg1); + struct type *type = check_typedef (value_type (arg1)); - case UNOP_PREINCREMENT: - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) - return arg1; - else if (unop_user_defined_p (op, arg1)) - { - return value_x_unop (arg1, op, noside); - } - else - { - if (ptrmath_type_p (exp->language_defn, value_type (arg1))) - arg2 = value_ptradd (arg1, 1); - else + switch (type->code ()) { - struct value *tmp = arg1; + case TYPE_CODE_PTR: + case TYPE_CODE_ARRAY: + case TYPE_CODE_STRING: + arg1 = value_subscript (arg1, value_as_long (arg2)); + break; - arg2 = value_one (value_type (arg1)); - binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); - arg2 = value_binop (tmp, arg2, BINOP_ADD); + default: + if (type->name ()) + error (_("cannot subscript something of type `%s'"), + type->name ()); + else + error (_("cannot subscript requested type")); } - - return value_assign (arg1, arg2); } + } + return (arg1); +} - case UNOP_PREDECREMENT: - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) - return arg1; - else if (unop_user_defined_p (op, arg1)) - { - return value_x_unop (arg1, op, noside); - } - else - { - if (ptrmath_type_p (exp->language_defn, value_type (arg1))) - arg2 = value_ptradd (arg1, -1); - else - { - struct value *tmp = arg1; +namespace expr +{ - arg2 = value_one (value_type (arg1)); - binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); - arg2 = value_binop (tmp, arg2, BINOP_SUB); - } +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; - return value_assign (arg1, arg2); - } + 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); - case UNOP_POSTINCREMENT: - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) - return arg1; - else if (unop_user_defined_p (op, arg1)) - { - return value_x_unop (arg1, op, noside); - } - else - { - arg3 = value_non_lval (arg1); + if (value_as_long (target) == 0) + sub_no_side = EVAL_AVOID_SIDE_EFFECTS; + else + sub_no_side = noside; + std::vector &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)); +} - if (ptrmath_type_p (exp->language_defn, value_type (arg1))) - arg2 = value_ptradd (arg1, 1); - else - { - struct value *tmp = arg1; +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 &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 ())); +} - arg2 = value_one (value_type (arg1)); - binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); - arg2 = value_binop (tmp, arg2, BINOP_ADD); - } +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_assign (arg1, arg2); - return arg3; - } + value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, + EVAL_AVOID_SIDE_EFFECTS); - case UNOP_POSTDECREMENT: - arg1 = evaluate_subexp (expect_type, exp, pos, noside); - if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) - return arg1; - else if (unop_user_defined_p (op, arg1)) + 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 + { + bool tem = value_logical_not (arg1); + if (!tem) { - return value_x_unop (arg1, op, noside); + arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); + tem = value_logical_not (arg2); } - else - { - arg3 = value_non_lval (arg1); + struct type *type = language_bool_type (exp->language_defn, + exp->gdbarch); + return value_from_longest (type, !tem); + } +} - if (ptrmath_type_p (exp->language_defn, value_type (arg1))) - arg2 = value_ptradd (arg1, -1); - else - { - struct value *tmp = arg1; +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); - arg2 = value_one (value_type (arg1)); - binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); - arg2 = value_binop (tmp, arg2, BINOP_SUB); - } + value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, + EVAL_AVOID_SIDE_EFFECTS); - value_assign (arg1, arg2); - return arg3; + 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 + { + bool tem = value_logical_not (arg1); + if (tem) + { + arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); + tem = value_logical_not (arg2); } - case OP_THIS: - (*pos) += 1; - return value_of_this (exp->language_defn); - - case OP_TYPE: - /* The value is not supposed to be used. This is here to make it - easier to accommodate expressions that contain types. */ - (*pos) += 2; - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - else if (noside == EVAL_AVOID_SIDE_EFFECTS) - return allocate_value (exp->elts[pc + 1].type); - else - error (_("Attempt to use a type name as an expression")); + struct type *type = language_bool_type (exp->language_defn, + exp->gdbarch); + return value_from_longest (type, !tem); + } +} - case OP_TYPEOF: - case OP_DECLTYPE: - if (noside == EVAL_SKIP) - { - evaluate_subexp (nullptr, exp, pos, EVAL_SKIP); - return eval_skip_value (exp); - } - else if (noside == EVAL_AVOID_SIDE_EFFECTS) - { - enum exp_opcode sub_op = exp->elts[*pos].opcode; - struct value *result; - - result = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - - /* 'decltype' has special semantics for lvalues. */ - if (op == OP_DECLTYPE - && (sub_op == BINOP_SUBSCRIPT - || sub_op == STRUCTOP_MEMBER - || sub_op == STRUCTOP_MPTR - || sub_op == UNOP_IND - || sub_op == STRUCTOP_STRUCT - || sub_op == STRUCTOP_PTR - || sub_op == OP_SCOPE)) - { - type = value_type (result); +value * +adl_func_operation::evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) +{ + std::vector &arg_ops = std::get<2> (m_storage); + std::vector 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 (SYMBOL_TYPE (symp)->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); - if (!TYPE_IS_REFERENCE (type)) - { - type = lookup_lvalue_reference_type (type); - result = allocate_value (type); - } - } +} - return result; - } - else - error (_("Attempt to use a type as an expression")); +/* This function evaluates brace-initializers (in C/C++) for + structure types. */ - case OP_TYPEID: - { - struct value *result; - enum exp_opcode sub_op = exp->elts[*pos].opcode; +struct value * +array_operation::evaluate_struct_tuple (struct value *struct_val, + struct expression *exp, + enum noside noside, int nargs) +{ + const std::vector &in_args = std::get<2> (m_storage); + struct type *struct_type = check_typedef (value_type (struct_val)); + struct type *field_type; + int fieldno = -1; - if (sub_op == OP_TYPE || sub_op == OP_DECLTYPE || sub_op == OP_TYPEOF) - result = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - else - result = evaluate_subexp (nullptr, exp, pos, noside); + int idx = 0; + while (--nargs >= 0) + { + struct value *val = NULL; + int bitpos, bitsize; + bfd_byte *addr; - if (noside != EVAL_NORMAL) - return allocate_value (cplus_typeid_type (exp->gdbarch)); + fieldno++; + /* Skip static fields. */ + while (fieldno < struct_type->num_fields () + && field_is_static (&struct_type->field (fieldno))) + 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")); - return cplus_typeid (result); - } + /* 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. */ - default: - /* Removing this case and compiling with gcc -Wall reveals that - a lot of cases are hitting this case. Some of these should - probably be removed from expression.h; others are legitimate - expressions which are (apparently) not fully implemented. + field_type = struct_type->field (fieldno).type (); + if (val == 0) + val = in_args[idx++]->evaluate (field_type, exp, noside); - If there are any cases landing here which mean a user error, - then they should be separate cases, with more descriptive - error messages. */ + /* Now actually set the field in struct_val. */ - error (_("GDB does not (yet) know how to " - "evaluate that kind of expression")); - } + /* Assign val to field fieldno. */ + if (value_type (val) != field_type) + val = value_cast (field_type, val); + + bitsize = TYPE_FIELD_BITSIZE (struct_type, fieldno); + bitpos = struct_type->field (fieldno).loc_bitpos (); + addr = value_contents_writeable (struct_val).data () + bitpos / 8; + if (bitsize) + modify_field (struct_type, addr, + value_as_long (val), bitpos % 8, bitsize); + else + memcpy (addr, value_contents (val).data (), + TYPE_LENGTH (value_type (val))); - gdb_assert_not_reached ("missed return?"); + } + return struct_val; } - -/* Evaluate a subexpression of EXP, at index *POS, - and return the address of that subexpression. - Advance *POS over the subexpression. - If the subexpression isn't an lvalue, get an error. - NOSIDE may be EVAL_AVOID_SIDE_EFFECTS; - then only the type of the result need be correct. */ -static struct value * -evaluate_subexp_for_address (struct expression *exp, int *pos, - enum noside noside) +value * +array_operation::evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) { - enum exp_opcode op; - int pc; - struct symbol *var; - struct value *x; int tem; + int tem2 = std::get<0> (m_storage); + int tem3 = std::get<1> (m_storage); + const std::vector &in_args = std::get<2> (m_storage); + int nargs = tem3 - tem2 + 1; + struct type *type = expect_type ? check_typedef (expect_type) : nullptr; + + if (expect_type != nullptr + && type->code () == TYPE_CODE_STRUCT) + { + struct value *rec = allocate_value (expect_type); - pc = (*pos); - op = exp->elts[pc].opcode; + memset (value_contents_raw (rec).data (), '\0', TYPE_LENGTH (type)); + return evaluate_struct_tuple (rec, exp, noside, nargs); + } - switch (op) + if (expect_type != nullptr + && type->code () == TYPE_CODE_ARRAY) { - case UNOP_IND: - (*pos)++; - x = evaluate_subexp (nullptr, exp, pos, noside); + struct type *range_type = type->index_type (); + struct type *element_type = TYPE_TARGET_TYPE (type); + struct value *array = allocate_value (expect_type); + int element_size = TYPE_LENGTH (check_typedef (element_type)); + LONGEST low_bound, high_bound, index; + + if (!get_discrete_bounds (range_type, &low_bound, &high_bound)) + { + low_bound = 0; + high_bound = (TYPE_LENGTH (type) / element_size) - 1; + } + index = low_bound; + memset (value_contents_raw (array).data (), 0, TYPE_LENGTH (expect_type)); + for (tem = nargs; --nargs >= 0;) + { + struct value *element; + + element = in_args[index - low_bound]->evaluate (element_type, + exp, noside); + if (value_type (element) != element_type) + element = value_cast (element_type, element); + if (index > high_bound) + /* To avoid memory corruption. */ + error (_("Too many array elements")); + memcpy (value_contents_raw (array).data () + + (index - low_bound) * element_size, + value_contents (element).data (), + element_size); + index++; + } + return array; + } - /* We can't optimize out "&*" if there's a user-defined operator*. */ - if (unop_user_defined_p (op, x)) + if (expect_type != nullptr + && type->code () == TYPE_CODE_SET) + { + struct value *set = allocate_value (expect_type); + gdb_byte *valaddr = value_contents_raw (set).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 = TYPE_TARGET_TYPE (check_type); + + if (!get_discrete_bounds (element_type, &low_bound, &high_bound)) + error (_("(power)set type with unknown size")); + memset (valaddr, '\0', TYPE_LENGTH (type)); + int idx = 0; + for (tem = 0; tem < nargs; tem++) { - x = value_x_unop (x, op, noside); - goto default_case_after_eval; - } + 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 = value_type (elem_val); + range_low = range_high = value_as_long (elem_val); + + /* Check types of elements to avoid mixture of elements from + different types. Also check if type of element is "compatible" + with element type of powerset. */ + if (range_low_type->code () == TYPE_CODE_RANGE) + range_low_type = TYPE_TARGET_TYPE (range_low_type); + if (range_high_type->code () == TYPE_CODE_RANGE) + range_high_type = TYPE_TARGET_TYPE (range_high_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; - return coerce_array (x); + 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; + } - case UNOP_MEMVAL: - (*pos) += 3; - return value_cast (lookup_pointer_type (exp->elts[pc + 1].type), - evaluate_subexp (nullptr, exp, pos, noside)); + value **argvec = XALLOCAVEC (struct value *, nargs); + for (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 (tem2, tem3, argvec); +} - case UNOP_MEMVAL_TYPE: - { - struct type *type; +} - (*pos) += 1; - x = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (x); - return value_cast (lookup_pointer_type (type), - evaluate_subexp (nullptr, exp, pos, noside)); - } + +/* Helper for evaluate_subexp_for_address. */ - case OP_VAR_VALUE: - var = exp->elts[pc + 2].symbol; +static value * +evaluate_subexp_for_address_base (struct expression *exp, enum noside noside, + value *x) +{ + if (noside == EVAL_AVOID_SIDE_EFFECTS) + { + struct type *type = check_typedef (value_type (x)); + + if (TYPE_IS_REFERENCE (type)) + return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + not_lval); + else if (VALUE_LVAL (x) == lval_memory || value_must_coerce_to_target (x)) + return value_zero (lookup_pointer_type (value_type (x)), + not_lval); + else + error (_("Attempt to take address of " + "value not located in memory.")); + } + return value_addr (x); +} - /* 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 (SYMBOL_TYPE (var))) - goto default_case; +namespace expr +{ - (*pos) += 4; - if (noside == EVAL_AVOID_SIDE_EFFECTS) - { - struct type *type = - lookup_pointer_type (SYMBOL_TYPE (var)); - enum address_class sym_class = SYMBOL_CLASS (var); +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); +} - if (sym_class == LOC_CONST - || sym_class == LOC_CONST_BYTES - || sym_class == LOC_REGISTER) - error (_("Attempt to take address of register or constant.")); +value * +operation::evaluate_for_address (struct expression *exp, enum noside noside) +{ + value *val = evaluate (nullptr, exp, noside); + return evaluate_subexp_for_address_base (exp, noside, val); +} - return - value_zero (type, not_lval); - } - else - return address_of_variable (var, exp->elts[pc + 1].block); +value * +scope_operation::evaluate_for_address (struct expression *exp, + enum noside noside) +{ + value *x = value_aggregate_elt (std::get<0> (m_storage), + std::get<1> (m_storage).c_str (), + NULL, 1, noside); + if (x == NULL) + error (_("There is no field named %s"), std::get<1> (m_storage).c_str ()); + return x; +} - case OP_VAR_MSYM_VALUE: - { - (*pos) += 4; +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); - value *val = evaluate_var_msym_value (noside, - exp->elts[pc + 1].objfile, - exp->elts[pc + 2].msymbol); - if (noside == EVAL_AVOID_SIDE_EFFECTS) - { - struct type *type = lookup_pointer_type (value_type (val)); - return value_zero (type, not_lval); - } - else - return value_addr (val); - } + /* 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 (exp, noside, x); + } - case OP_SCOPE: - tem = longest_to_int (exp->elts[pc + 2].longconst); - (*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1); - x = value_aggregate_elt (exp->elts[pc + 1].type, - &exp->elts[pc + 3].string, - NULL, 1, noside); - if (x == NULL) - error (_("There is no field named %s"), &exp->elts[pc + 3].string); - return x; + return coerce_array (x); +} - default: - default_case: - x = evaluate_subexp (nullptr, exp, pos, noside); - default_case_after_eval: - if (noside == EVAL_AVOID_SIDE_EFFECTS) - { - struct type *type = check_typedef (value_type (x)); - - if (TYPE_IS_REFERENCE (type)) - return value_zero (lookup_pointer_type (TYPE_TARGET_TYPE (type)), - not_lval); - else if (VALUE_LVAL (x) == lval_memory || value_must_coerce_to_target (x)) - return value_zero (lookup_pointer_type (value_type (x)), - not_lval); - else - error (_("Attempt to take address of " - "value not located in memory.")); - } - return value_addr (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 (value_type (val)); + return value_zero (type, not_lval); } + else + return value_addr (val); } -/* Evaluate like `evaluate_subexp' except coercing arrays to pointers. - When used in contexts where arrays will be coerced anyway, this is - equivalent to `evaluate_subexp' but much faster because it avoids - actually fetching array contents (perhaps obsolete now that we have - value_lazy()). +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)); +} - Note that we currently only do the coercion for C expressions, where - arrays are zero based and the coercion is correct. For other languages, - with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION - to decide if coercion is appropriate. */ +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 = value_type (typeval); + return value_cast (lookup_pointer_type (type), + std::get<1> (m_storage)->evaluate (nullptr, exp, noside)); +} -struct value * -evaluate_subexp_with_coercion (struct expression *exp, - int *pos, enum noside noside) +value * +var_value_operation::evaluate_for_address (struct expression *exp, + enum noside noside) { - enum exp_opcode op; - int pc; - struct value *val; - struct symbol *var; - struct type *type; + symbol *var = std::get<0> (m_storage).symbol; - pc = (*pos); - op = exp->elts[pc].opcode; + /* 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 (SYMBOL_TYPE (var))) + return operation::evaluate_for_address (exp, noside); - switch (op) + if (noside == EVAL_AVOID_SIDE_EFFECTS) { - case OP_VAR_VALUE: - var = exp->elts[pc + 2].symbol; - type = check_typedef (SYMBOL_TYPE (var)); - if (type->code () == TYPE_CODE_ARRAY - && !type->is_vector () - && CAST_IS_CONVERSION (exp->language_defn)) - { - (*pos) += 4; - val = address_of_variable (var, exp->elts[pc + 1].block); - return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), - val); - } - /* FALLTHROUGH */ + struct type *type = lookup_pointer_type (SYMBOL_TYPE (var)); + enum address_class sym_class = SYMBOL_CLASS (var); - default: - return evaluate_subexp (nullptr, exp, pos, noside); + if (sym_class == LOC_CONST + || sym_class == LOC_CONST_BYTES + || sym_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 (SYMBOL_TYPE (var)); + 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 (type)), val); } + return evaluate (nullptr, exp, noside); +} + } -/* Evaluate a subexpression of EXP, at index *POS, - and return a value for the size of that subexpression. - Advance *POS over the subexpression. If NOSIDE is EVAL_NORMAL - we allow side-effects on the operand if its type is a variable - length array. */ +/* Helper function for evaluating the size of a type. */ -static struct value * -evaluate_subexp_for_sizeof (struct expression *exp, int *pos, - enum noside noside) +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; - enum exp_opcode op; - int pc; - struct type *type; - struct value *val; + /* $5.3.3/2 of the C++ Standard (n3290 draft) says of sizeof: + "When applied to a reference or a reference type, the result is + the size of the referenced type." */ + type = check_typedef (type); + if (exp->language_defn->la_language == language_cplus + && (TYPE_IS_REFERENCE (type))) + type = check_typedef (TYPE_TARGET_TYPE (type)); + return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); +} - pc = (*pos); - op = exp->elts[pc].opcode; - - switch (op) - { - /* This case is handled specially - so that we avoid creating a value for the result type. - If the result type is very big, it's desirable not to - create a value unnecessarily. */ - case UNOP_IND: - (*pos)++; - val = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = check_typedef (value_type (val)); - if (type->code () != TYPE_CODE_PTR - && !TYPE_IS_REFERENCE (type) - && type->code () != TYPE_CODE_ARRAY) - error (_("Attempt to take contents of a non-pointer value.")); - type = TYPE_TARGET_TYPE (type); - if (is_dynamic_type (type)) - type = value_type (value_ind (val)); - return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); - - case UNOP_MEMVAL: - (*pos) += 3; - type = exp->elts[pc + 1].type; - break; - - case UNOP_MEMVAL_TYPE: - (*pos) += 1; - val = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (val); - break; +namespace expr +{ - case OP_VAR_VALUE: - type = SYMBOL_TYPE (exp->elts[pc + 2].symbol); - if (is_dynamic_type (type)) - { - val = evaluate_subexp (nullptr, exp, pos, EVAL_NORMAL); - type = value_type (val); - if (type->code () == TYPE_CODE_ARRAY) - { - 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.kind () == PROP_UNDEFINED) - return allocate_optimized_out_value (size_type); - } - } - else - (*pos) += 4; - break; +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, value_type (val)); +} - case OP_VAR_MSYM_VALUE: - { - (*pos) += 4; +value * +var_msym_value_operation::evaluate_for_sizeof (struct expression *exp, + enum noside noside) - minimal_symbol *msymbol = exp->elts[pc + 2].msymbol; - value *mval = evaluate_var_msym_value (noside, - exp->elts[pc + 1].objfile, - msymbol); +{ + const bound_minimal_symbol &b = std::get<0> (m_storage); + value *mval = evaluate_var_msym_value (noside, b.objfile, b.minsym); - type = value_type (mval); - if (type->code () == TYPE_CODE_ERROR) - error_unknown_type (msymbol->print_name ()); + struct type *type = value_type (mval); + if (type->code () == TYPE_CODE_ERROR) + error_unknown_type (b.minsym->print_name ()); - return value_from_longest (size_type, TYPE_LENGTH (type)); - } - break; - - /* Deal with the special case if NOSIDE is EVAL_NORMAL and the resulting - type of the subscript is a variable length array type. In this case we - must re-evaluate the right hand side of the subscription to allow - side-effects. */ - case BINOP_SUBSCRIPT: - if (noside == EVAL_NORMAL) - { - int npc = (*pos) + 1; + /* FIXME: This should be size_t. */ + struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; + return value_from_longest (size_type, TYPE_LENGTH (type)); +} - val = evaluate_subexp (nullptr, exp, &npc, EVAL_AVOID_SIDE_EFFECTS); - type = check_typedef (value_type (val)); +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 (value_type (val)); + if (type->code () == TYPE_CODE_ARRAY) + { + type = check_typedef (TYPE_TARGET_TYPE (type)); if (type->code () == TYPE_CODE_ARRAY) { - type = check_typedef (TYPE_TARGET_TYPE (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) { - 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_subexp (nullptr, exp, pos, EVAL_NORMAL); - return value_from_longest - (size_type, (LONGEST) TYPE_LENGTH (value_type (val))); - } + 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) TYPE_LENGTH (value_type (val))); } } } - - /* Fall through. */ - - default: - val = evaluate_subexp (nullptr, exp, pos, EVAL_AVOID_SIDE_EFFECTS); - type = value_type (val); - break; } - /* $5.3.3/2 of the C++ Standard (n3290 draft) says of sizeof: - "When applied to a reference or a reference type, the result is - the size of the referenced type." */ - type = check_typedef (type); - if (exp->language_defn->la_language == language_cplus - && (TYPE_IS_REFERENCE (type))) - type = check_typedef (TYPE_TARGET_TYPE (type)); + return 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 (value_type (val)); + 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 (type); + if (is_dynamic_type (type)) + type = value_type (value_ind (val)); + /* 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 (type)); } -/* Evaluate a subexpression of EXP, at index *POS, and return a value - for that subexpression cast to TO_TYPE. Advance *POS over the - subexpression. */ +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)); +} -static value * -evaluate_subexp_for_cast (expression *exp, int *pos, - enum noside noside, - struct type *to_type) +value * +unop_memval_type_operation::evaluate_for_sizeof (struct expression *exp, + enum noside noside) { - int pc = *pos; + value *typeval = std::get<0> (m_storage)->evaluate (nullptr, exp, + EVAL_AVOID_SIDE_EFFECTS); + return evaluate_subexp_for_sizeof_base (exp, value_type (typeval)); +} - /* Don't let symbols be evaluated with evaluate_subexp because that - throws an "unknown type" error for no-debug data symbols. - Instead, we want the cast to reinterpret the symbol. */ - if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE - || exp->elts[pc].opcode == OP_VAR_VALUE) +value * +var_value_operation::evaluate_for_sizeof (struct expression *exp, + enum noside noside) +{ + struct type *type = SYMBOL_TYPE (std::get<0> (m_storage).symbol); + if (is_dynamic_type (type)) { - (*pos) += 4; - - value *val; - if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE) + value *val = evaluate (nullptr, exp, EVAL_NORMAL); + type = value_type (val); + if (type->code () == TYPE_CODE_ARRAY) { - if (noside == EVAL_AVOID_SIDE_EFFECTS) - return value_zero (to_type, not_lval); - - val = evaluate_var_msym_value (noside, - exp->elts[pc + 1].objfile, - exp->elts[pc + 2].msymbol); + /* 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.kind () == PROP_UNDEFINED) + return allocate_optimized_out_value (size_type); } - else - val = evaluate_var_value (noside, - exp->elts[pc + 1].block, - exp->elts[pc + 2].symbol); + } + 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); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); + 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); + val = value_cast (to_type, val); - /* Don't allow e.g. '&(int)var_with_no_debug_info'. */ - if (VALUE_LVAL (val) == lval_memory) - { - if (value_lazy (val)) - value_fetch_lazy (val); - VALUE_LVAL (val) = not_lval; - } - return val; + /* Don't allow e.g. '&(int)var_with_no_debug_info'. */ + if (VALUE_LVAL (val) == lval_memory) + { + if (value_lazy (val)) + value_fetch_lazy (val); + VALUE_LVAL (val) = 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 (VALUE_LVAL (val) == lval_memory) + { + if (value_lazy (val)) + value_fetch_lazy (val); + VALUE_LVAL (val) = not_lval; } + return val; +} - value *val = evaluate_subexp (to_type, exp, pos, noside); - if (noside == EVAL_SKIP) - return eval_skip_value (exp); - return value_cast (to_type, val); } /* Parse a type expression in the string [P..P+LENGTH). */ @@ -3126,7 +2813,9 @@ parse_and_eval_type (const char *p, int length) tmp[length + 2] = '0'; tmp[length + 3] = '\0'; expression_up expr = parse_expression (tmp); - if (expr->first_opcode () != UNOP_CAST) + expr::unop_cast_operation *op + = dynamic_cast (expr->op.get ()); + if (op == nullptr) error (_("Internal error in eval_type.")); - return expr->elts[1].type; + return op->get_type (); }