+/* Helper for evaluating an OP_VAR_MSYM_VALUE. */
+
+value *
+evaluate_var_msym_value (enum noside noside,
+ struct objfile *objfile, minimal_symbol *msymbol)
+{
+ CORE_ADDR address;
+ type *the_type = find_minsym_type_and_address (msymbol, objfile, &address);
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS && !TYPE_GNU_IFUNC (the_type))
+ return value_zero (the_type, not_lval);
+ else
+ 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);
+}
+
+/* Evaluate a function call. The function to be called is in
+ ARGVEC[0] and the arguments passed to the function are in
+ ARGVEC[1..NARGS]. FUNCTION_NAME is the name of the function, if
+ known. DEFAULT_RETURN_TYPE is used as the function's return type
+ if the return type is unknown. */
+
+static value *
+eval_call (expression *exp, enum noside noside,
+ int nargs, value **argvec,
+ const char *function_name,
+ type *default_return_type)
+{
+ if (argvec[0] == NULL)
+ error (_("Cannot evaluate function -- may be inlined"));
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type,
+ call an error. This can happen if somebody tries to turn
+ a variable into a function call. */
+
+ type *ftype = value_type (argvec[0]);
+
+ if (TYPE_CODE (ftype) == TYPE_CODE_INTERNAL_FUNCTION)
+ {
+ /* We don't know anything about what the internal
+ function might return, but we have to return
+ something. */
+ return value_zero (builtin_type (exp->gdbarch)->builtin_int,
+ not_lval);
+ }
+ else if (TYPE_CODE (ftype) == TYPE_CODE_XMETHOD)
+ {
+ type *return_type
+ = result_type_of_xmethod (argvec[0],
+ gdb::make_array_view (argvec + 1,
+ nargs));
+
+ if (return_type == NULL)
+ error (_("Xmethod is missing return type."));
+ return value_zero (return_type, not_lval);
+ }
+ else if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+ || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+ if (TYPE_GNU_IFUNC (ftype))
+ {
+ CORE_ADDR address = value_address (argvec[0]);
+ type *resolved_type = find_gnu_ifunc_target_type (address);
+
+ if (resolved_type != NULL)
+ ftype = resolved_type;
+ }
+
+ type *return_type = TYPE_TARGET_TYPE (ftype);
+
+ if (return_type == NULL)
+ return_type = default_return_type;
+
+ if (return_type == NULL)
+ error_call_unknown_return_type (function_name);
+
+ return allocate_value (return_type);
+ }
+ else
+ error (_("Expression of type other than "
+ "\"Function returning ...\" used as function"));
+ }
+ switch (TYPE_CODE (value_type (argvec[0])))
+ {
+ case TYPE_CODE_INTERNAL_FUNCTION:
+ return call_internal_function (exp->gdbarch, exp->language_defn,
+ argvec[0], nargs, argvec + 1);
+ case TYPE_CODE_XMETHOD:
+ return call_xmethod (argvec[0], gdb::make_array_view (argvec + 1, nargs));
+ default:
+ return call_function_by_hand (argvec[0], default_return_type,
+ gdb::make_array_view (argvec + 1, nargs));
+ }
+}
+
+/* Helper for evaluating an OP_FUNCALL. */
+
+static value *
+evaluate_funcall (type *expect_type, expression *exp, int *pos,
+ enum noside noside)
+{
+ 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;
+
+ 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)
+ {
+ /* First, evaluate the structure into arg2. */
+ pc2 = (*pos)++;
+
+ if (op == STRUCTOP_MEMBER)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+
+ /* If the function is a virtual function, then the aggregate
+ value (providing the structure) plays its part by providing
+ the vtable. Otherwise, it is just along for the ride: call
+ the function directly. */
+
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ 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 (TYPE_CODE (a1_type) == 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);
+
+ /* Now, say which argument to start evaluating from. */
+ nargs++;
+ tem = 2;
+ argvec[1] = arg2;
+ }
+ else if (TYPE_CODE (a1_type) == 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));
+
+ /* Now, convert these values to an address. */
+ arg2 = value_cast (type_ptr, arg2);
+
+ long mem_offset = value_as_long (arg1);
+
+ 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"));
+ }
+ else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ /* 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);
+
+ 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 (NULL_TYPE, exp, pos, noside);
+
+ /* 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);
+ }
+
+ catch (const gdb_exception_error &except)
+ {
+ if (except.error == NOT_FOUND_ERROR)
+ break;
+ else
+ throw;
+ }
+
+ 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) == TYPE_CODE_NAMESPACE)
+ {
+ function = cp_lookup_symbol_namespace (TYPE_NAME (type),
+ name,
+ get_selected_block (0),
+ VAR_DOMAIN).symbol;
+ if (function == NULL)
+ error (_("No symbol \"%s\" in namespace \"%s\"."),
+ name, TYPE_NAME (type));
+
+ tem = 1;
+ /* arg2 is left as NULL on purpose. */
+ }
+ else
+ {
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION);
+ function_name = name;
+
+ /* We need a properly typed value for method lookup. For
+ static methods arg2 is otherwise unused. */
+ arg2 = value_zero (type, lval_memory);
+ ++nargs;
+ tem = 2;
+ }
+ }
+ else if (op == OP_ADL_FUNC)
+ {
+ /* Save the function position and move pos so that the arguments
+ can be evaluated. */
+ int func_name_len;
+
+ save_pos1 = *pos;
+ tem = 1;
+
+ func_name_len = longest_to_int (exp->elts[save_pos1 + 3].longconst);
+ (*pos) += 6 + BYTES_TO_EXP_ELEM (func_name_len + 1);
+ }
+ else
+ {
+ /* 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;
+ }
+ 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 ();
+ }
+
+ argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside);
+ type *type = value_type (argvec[0]);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ if (type && TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
+ {
+ argvec[tem] = evaluate_subexp (TYPE_FIELD_TYPE (type,
+ tem - 1),
+ exp, pos, noside);
+ }
+ }
+ }
+ }
+
+ /* Evaluate arguments (if not already done, e.g., namespace::func()
+ and overload-resolution is off). */
+ for (; tem <= nargs; tem++)
+ {
+ /* Ensure that array expressions are coerced into pointer
+ objects. */
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ }
+
+ /* Signal end of arglist. */
+ argvec[tem] = 0;
+
+ if (noside == EVAL_SKIP)
+ return eval_skip_value (exp);
+
+ 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);
+
+ 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);
+
+ /* Now fix the expression being evaluated. */
+ exp->elts[save_pos1 + 2].symbol = symp;
+ argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
+ }
+
+ if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR
+ || (op == OP_SCOPE && function_name != NULL))
+ {
+ int static_memfuncp;
+ char *tstr;
+
+ /* Method invocation: stuff "this" as first parameter. If the
+ method turns out to be static we undo this below. */
+ argvec[1] = arg2;
+
+ if (op != OP_SCOPE)
+ {
+ /* 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)
+ {
+ /* For the time being, we don't handle this. */
+ error (_("Call to overloaded function %s requires "
+ "`this' pointer"),
+ function_name);
+ }
+ 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++;
+ }
+ }
+ 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;
+
+ if (op == OP_VAR_VALUE)
+ function = exp->elts[save_pos1+2].symbol;
+
+ (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. */
+ }
+ }
+ else
+ {
+ /* It is probably a C-style function. */
+ /* Nothing to be done; argvec already correctly set up. */
+ }
+
+ return eval_call (exp, noside, nargs, argvec, var_func_name, expect_type);
+}
+
+/* Helper for skipping all the arguments in an undetermined argument list.
+ This function was designed for use in the OP_F77_UNDETERMINED_ARGLIST
+ case of evaluate_subexp_standard as multiple, but not all, code paths
+ require a generic skip. */
+
+static void
+skip_undetermined_arglist (int nargs, struct expression *exp, int *pos,
+ enum noside noside)
+{
+ for (int i = 0; i < nargs; ++i)
+ evaluate_subexp (NULL_TYPE, exp, pos, noside);