aboutsummaryrefslogtreecommitdiff
path: root/gdb/eval.c
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2021-06-21 23:33:11 +0100
committerAndrew Burgess <andrew.burgess@embecosm.com>2021-06-25 20:43:05 +0100
commit79bd4d34f0583f1c1cea60fa94986e222ade33b8 (patch)
treec1a646ab831a8496764718f5dbe8e76f3af525da /gdb/eval.c
parent3da4c6449b1ce57accfb1b9fa8415ad1cf42039b (diff)
downloadgdb-79bd4d34f0583f1c1cea60fa94986e222ade33b8.zip
gdb-79bd4d34f0583f1c1cea60fa94986e222ade33b8.tar.gz
gdb-79bd4d34f0583f1c1cea60fa94986e222ade33b8.tar.bz2
gdb: fix regression in evaluate_funcall for non C++ like cases
This regression, as it is exposed by the test added in this commit, first became noticable with this commit: commit d182f2797922a305fbd1ef6a483cc39a56b43e02 Date: Mon Mar 8 07:27:57 2021 -0700 Convert c-exp.y to use operations But, this commit only added converted the C expression parser to make use of code that was added in this commit: commit a00b7254fb614af557de7ae7cc0eb39a0ce0e408 Date: Mon Mar 8 07:27:57 2021 -0700 Implement function call operations And it was this second commit that actually introduced the bugs (there are two). In structop_base_operation::evaluate_funcall we build up an argument list in the vector vals. Later in this function the argument list might be passed to value_struct_elt. Prior to commit a00b7254fb614 the vals vector (or argvec as it used to be called) stored the value for the function callee in the argvec at index 0. This 'callee' value is what ends up being passed to evaluate_subexp_do_call, and represents the function to be called, the value contents are the address of the function, and the value type is the function signature. The remaining items held in the argvec were the values to pass to the function. For a non-static member function the `this' pointer would be at index 1 in the array. After commit a00b7254fb614 this callee value is now held in a separate variable, not the vals array. So, for non-static member functions, the `this' pointer is now at index 0, with any other arguments after that. What this means is that previous, when we called value_struct_elt we would pass the address of argvec[1] as this was the first argument. But now we should be passing the address of vals[0]. Unfortunately, we are still passing vals[1], effectively skipping the first argument. The second issue is that, prior to commit a00b7254fb614, the argvec array was NULL terminated. This is required as value_struct_elt calls search_struct_method, which calls typecmp, and typecmp requires that the array have a NULL at the end. After commit a00b7254fb614 this NULL has been lost, and we are therefore violating the API requirements of typecmp. This commit fixes both of these regressions. I also extended the header comments on search_struct_method and value_struct_elt to make it clearer that the array required a NULL marker at the end. You will notice in the test attached to this commit that I test calling a non-static member function, but not calling a static member function. The reason for this is that calling static member functions is currently broken due to a different bug. That will be fixed in a later patch in this series, at which time I'll add a test for calling a static member function. gdb/ChangeLog: PR gdb/27994 * eval.c (structop_base_operation::evaluate_funcall): Add a nullptr to the end of the args array, which should not be included in the argument array_view. Pass all the arguments through to value_struct_elt. * valops.c (search_struct_method): Update header comment. (value_struct_elt): Likewise. gdb/testsuite/ChangeLog: PR gdb/27994 * gdb.cp/method-call-in-c.cc: New file. * gdb.cp/method-call-in-c.exp: New file.
Diffstat (limited to 'gdb/eval.c')
-rw-r--r--gdb/eval.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/gdb/eval.c b/gdb/eval.c
index 659493c..ab070a3 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -872,7 +872,9 @@ structop_base_operation::evaluate_funcall
(struct type *expect_type, struct expression *exp, enum noside noside,
const std::vector<operation_up> &args)
{
- std::vector<value *> vals (args.size () + 1);
+ /* Allocate space for the function call arguments. Include space for a
+ `this' pointer at the start, and a trailing nullptr. */
+ std::vector<value *> vals (args.size () + 2);
/* First, evaluate the structure into vals[0]. */
enum exp_opcode op = opcode ();
if (op == STRUCTOP_STRUCT)
@@ -918,9 +920,16 @@ structop_base_operation::evaluate_funcall
}
}
+ /* Evaluate the arguments, and add the trailing nullptr. 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);
- gdb::array_view<value *> arg_view = vals;
+ vals[args.size () + 1] = nullptr;
+
+ /* The array view includes the `this' pointer, but not the trailing
+ nullptr. */
+ gdb::array_view<value *> arg_view
+ = gdb::make_array_view (&vals[0], args.size () + 1);
int static_memfuncp;
value *callee;
@@ -941,7 +950,7 @@ structop_base_operation::evaluate_funcall
{
struct value *temp = vals[0];
- callee = value_struct_elt (&temp, &vals[1], tstr,
+ callee = value_struct_elt (&temp, &vals[0], tstr,
&static_memfuncp,
op == STRUCTOP_STRUCT
? "structure" : "structure pointer");