[v2] Allow calling of variadic C++ functions
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Testing passed
|
Commit Message
Currently, it's not possible to call a variadic C++ function:
```
(gdb) print sum_vararg_int(1, 10)
Cannot resolve function sum_vararg_int to any overloaded instance
(gdb) print sum_vararg_int(2, 20, 30)
Cannot resolve function sum_vararg_int to any overloaded instance
```
It's because all additional arguments get the TOO_FEW_PARAMS_BADNESS
rank by rank_function, which disqualifies the function.
To fix this, I've created the new VARARG_BADNESS rank, which is
used only for additional arguments of variadic functions, allowing
them to be called:
```
(gdb) print sum_vararg_int(1, 10)
$1 = 10
(gdb) print sum_vararg_int(2, 20, 30)
$2 = 50
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28589
---
v2:
- Fixed ranking of overloaded varargs functions, plus some tests
added for this.
---
gdb/gdbtypes.c | 9 ++++++---
gdb/gdbtypes.h | 3 ++-
gdb/testsuite/gdb.cp/call-c.cc | 26 ++++++++++++++++++++++++++
gdb/testsuite/gdb.cp/call-c.exp | 13 +++++++++++++
gdb/valops.c | 10 ++++++++--
5 files changed, 55 insertions(+), 6 deletions(-)
Comments
>>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
Hannes> To fix this, I've created the new VARARG_BADNESS rank, which is
Hannes> used only for additional arguments of variadic functions, allowing
Hannes> them to be called:
Thank you. This is ok.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
Am Mittwoch, 13. Dezember 2023, 21:09:24 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:
> >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
>
> Hannes> To fix this, I've created the new VARARG_BADNESS rank, which is
> Hannes> used only for additional arguments of variadic functions, allowing
> Hannes> them to be called:
>
> Thank you. This is ok.
> Approved-By: Tom Tromey <tom@tromey.com>
Pushed, thanks.
@@ -76,6 +76,7 @@ const struct rank REFERENCE_SEE_THROUGH_BADNESS = {0,1};
const struct rank NULL_POINTER_CONVERSION_BADNESS = {2,0};
const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0};
const struct rank NS_INTEGER_POINTER_CONVERSION_BADNESS = {3,0};
+const struct rank VARARG_BADNESS = {4, 0};
/* Floatformat pairs. */
const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = {
@@ -4038,7 +4039,8 @@ compare_badness (const badness_vector &a, const badness_vector &b)
badness_vector
rank_function (gdb::array_view<type *> parms,
- gdb::array_view<value *> args)
+ gdb::array_view<value *> args,
+ bool varargs)
{
/* add 1 for the length-match rank. */
badness_vector bv;
@@ -4051,7 +4053,8 @@ rank_function (gdb::array_view<type *> parms,
arguments and ellipsis parameter lists, we should consider those
and rank the length-match more finely. */
- bv.push_back ((args.size () != parms.size ())
+ bv.push_back ((args.size () != parms.size ()
+ && (! varargs || args.size () < parms.size ()))
? LENGTH_MISMATCH_BADNESS
: EXACT_MATCH_BADNESS);
@@ -4064,7 +4067,7 @@ rank_function (gdb::array_view<type *> parms,
/* If more arguments than parameters, add dummy entries. */
for (size_t i = min_len; i < args.size (); i++)
- bv.push_back (TOO_FEW_PARAMS_BADNESS);
+ bv.push_back (varargs ? VARARG_BADNESS : TOO_FEW_PARAMS_BADNESS);
return bv;
}
@@ -2735,7 +2735,8 @@ extern int compare_badness (const badness_vector &,
const badness_vector &);
extern badness_vector rank_function (gdb::array_view<type *> parms,
- gdb::array_view<value *> args);
+ gdb::array_view<value *> args,
+ bool varargs = false);
extern struct rank rank_one_type (struct type *, struct type *,
struct value *);
@@ -15,6 +15,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include <stdarg.h>
+
int func(int x)
{
return x;
@@ -33,6 +35,29 @@ extern "C" {
int foo(int);
}
+int sum_vararg_int (int count, ...)
+{
+ va_list va;
+ int sum = 0;
+
+ va_start (va, count);
+ for (int i = 0; i < count; i++)
+ sum += va_arg (va, int);
+ va_end (va);
+
+ return sum;
+}
+
+int vararg_func (int a, ...)
+{
+ return 1;
+}
+
+int vararg_func (int a, int b, ...)
+{
+ return 2;
+}
+
int main()
{
Foo f;
@@ -41,5 +66,6 @@ int main()
FooHandle handle = pf;
rf->func(); /* set breakpoint here */
foo(0);
+ sum_vararg_int (1, 5);
return func(0);
}
@@ -38,5 +38,18 @@ gdb_test "print foo(1)" "\\\$$decimal = 1"
gdb_test "continue" ".*breakpoint here.*" "continue to bp"
gdb_test "print rf->func()" "\\\$$decimal = 1"
+gdb_test "print sum_vararg_int(0)" "0"
+gdb_test "print sum_vararg_int(1, 10)" "10"
+gdb_test "print sum_vararg_int(2, 20, 30)" "50"
+gdb_test "print sum_vararg_int(5, 20, 30, 40, 50, 60)" "200"
+
+gdb_test "print vararg_func(1)" "1"
+gdb_test "print vararg_func(2, 3)" "2"
+gdb_test "print vararg_func(4, 5.5)" "2"
+gdb_test "print vararg_func(6, \"7\")" "1"
+gdb_test "print vararg_func(8, 9, 10)" "2"
+gdb_test "print vararg_func(11, 12, 13.5)" "2"
+gdb_test "print vararg_func(14, 15, \"16\")" "2"
+
# Regression test for method call via a typedef.
gdb_test "print handle->func()" "\\\$$decimal = 1"
@@ -3226,6 +3226,7 @@ find_oload_champ (gdb::array_view<value *> args,
{
int jj;
int static_offset = 0;
+ bool varargs = false;
std::vector<type *> parm_types;
if (xmethods != NULL)
@@ -3238,9 +3239,13 @@ find_oload_champ (gdb::array_view<value *> args,
{
nparms = TYPE_FN_FIELD_TYPE (methods, ix)->num_fields ();
static_offset = oload_method_static_p (methods, ix);
+ varargs = TYPE_FN_FIELD_TYPE (methods, ix)->has_varargs ();
}
else
- nparms = functions[ix]->type ()->num_fields ();
+ {
+ nparms = functions[ix]->type ()->num_fields ();
+ varargs = functions[ix]->type ()->has_varargs ();
+ }
parm_types.reserve (nparms);
for (jj = 0; jj < nparms; jj++)
@@ -3255,7 +3260,8 @@ find_oload_champ (gdb::array_view<value *> args,
/* Compare parameter types to supplied argument types. Skip
THIS for static methods. */
bv = rank_function (parm_types,
- args.slice (static_offset));
+ args.slice (static_offset),
+ varargs);
if (overload_debug)
{