mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 01:28:46 +00:00
Allow calling of user-defined function call operators
Currently it's not possible to call user-defined function call
operators, at least not without specifying operator() directly:
```
(gdb) l 1
1 struct S {
2 int operator() (int x) { return x + 5; }
3 };
4
5 int main () {
6 S s;
7
8 return s(23);
9 }
(gdb) p s(10)
Invalid data type for function to be called.
(gdb) p s.operator()(10)
$1 = 15
```
This now looks if an user-defined call operator is available when
trying to 'call' a struct value, and calls it instead, making this
possible:
```
(gdb) p s(10)
$1 = 15
```
The change in operation::evaluate_funcall is to make sure the type
fields are only used for function types, only they use them as the
argument types.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=12213
Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
34
gdb/eval.c
34
gdb/eval.c
@@ -588,14 +588,38 @@ evaluate_subexp_do_call (expression *exp, enum noside noside,
|
||||
{
|
||||
if (callee == NULL)
|
||||
error (_("Cannot evaluate function -- may be inlined"));
|
||||
|
||||
type *ftype = callee->type ();
|
||||
|
||||
/* If the callee is a struct, there might be a user-defined function call
|
||||
operator that should be used instead. */
|
||||
std::vector<value *> vals;
|
||||
if (overload_resolution
|
||||
&& exp->language_defn->la_language == language_cplus
|
||||
&& check_typedef (ftype)->code () == TYPE_CODE_STRUCT)
|
||||
{
|
||||
/* Include space for the `this' pointer at the start. */
|
||||
vals.resize (argvec.size () + 1);
|
||||
|
||||
vals[0] = value_addr (callee);
|
||||
for (int i = 0; i < argvec.size (); ++i)
|
||||
vals[i + 1] = argvec[i];
|
||||
|
||||
int static_memfuncp;
|
||||
find_overload_match (vals, "operator()", METHOD, &vals[0], nullptr,
|
||||
&callee, nullptr, &static_memfuncp, 0, noside);
|
||||
if (!static_memfuncp)
|
||||
argvec = vals;
|
||||
|
||||
ftype = callee->type ();
|
||||
}
|
||||
|
||||
if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||||
{
|
||||
/* If the return type doesn't look like a function type,
|
||||
call an error. This can happen if somebody tries to turn
|
||||
a variable into a function call. */
|
||||
|
||||
type *ftype = callee->type ();
|
||||
|
||||
if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION)
|
||||
{
|
||||
/* We don't know anything about what the internal
|
||||
@@ -666,9 +690,13 @@ operation::evaluate_funcall (struct type *expect_type,
|
||||
struct type *type = callee->type ();
|
||||
if (type->code () == TYPE_CODE_PTR)
|
||||
type = type->target_type ();
|
||||
/* If type is a struct, num_fields would refer to the number of
|
||||
members in the type, not the number of arguments. */
|
||||
bool type_has_arguments
|
||||
= type->code () == TYPE_CODE_FUNC || type->code () == TYPE_CODE_METHOD;
|
||||
for (int i = 0; i < args.size (); ++i)
|
||||
{
|
||||
if (i < type->num_fields ())
|
||||
if (type_has_arguments && i < type->num_fields ())
|
||||
vals[i] = args[i]->evaluate (type->field (i).type (), exp, noside);
|
||||
else
|
||||
vals[i] = args[i]->evaluate_with_coercion (exp, noside);
|
||||
|
||||
Reference in New Issue
Block a user