From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2111) id 35C50385842D; Thu, 14 Dec 2023 15:19:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 35C50385842D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1702567162; bh=2MT4Y/aq9NRy7wiEat/3KY4szcpPkjdRwAfXpoGOojQ=; h=From:To:Subject:Date:From; b=c2vcBWxxpWM10dULG6BaXFQXK6Qq+Ko91o15CraYvehza2+ELiWzfPRnmv/svYrso ib4w8BeRdozFDEMMogd1TV5ez6L2B/Q3VGj3MIaqCbVHCqsB4le4CFqkPRO8qauOc+ c04GfkO/xKg0wPZknZzXa7reGw34mDENAbYVtv+0= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Hannes Domani To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Allow calling of variadic C++ functions X-Act-Checkin: binutils-gdb X-Git-Author: Hannes Domani X-Git-Refname: refs/heads/master X-Git-Oldrev: 8cb16b68584e14aade8de166c75e1d85e38507bd X-Git-Newrev: 1d2f86b6b74e6caae77951353a4c353ce9816374 Message-Id: <20231214151922.35C50385842D@sourceware.org> Date: Thu, 14 Dec 2023 15:19:22 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D1d2f86b6b74e= 6caae77951353a4c353ce9816374 commit 1d2f86b6b74e6caae77951353a4c353ce9816374 Author: Hannes Domani Date: Sun Nov 14 16:19:31 2021 +0100 Allow calling of variadic C++ functions =20 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 ``` =20 It's because all additional arguments get the TOO_FEW_PARAMS_BADNESS rank by rank_function, which disqualifies the function. =20 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 =3D 10 (gdb) print sum_vararg_int(2, 20, 30) $2 =3D 50 ``` =20 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D28589 Approved-By: Tom Tromey Diff: --- 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(-) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 4c70c9b8ae6..2580b4f19ee 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -76,6 +76,7 @@ const struct rank REFERENCE_SEE_THROUGH_BADNESS =3D {0,1}; const struct rank NULL_POINTER_CONVERSION_BADNESS =3D {2,0}; const struct rank NS_POINTER_CONVERSION_BADNESS =3D {10,0}; const struct rank NS_INTEGER_POINTER_CONVERSION_BADNESS =3D {3,0}; +const struct rank VARARG_BADNESS =3D {4, 0}; =20 /* Floatformat pairs. */ const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] =3D { @@ -4038,7 +4039,8 @@ compare_badness (const badness_vector &a, const badne= ss_vector &b) =20 badness_vector rank_function (gdb::array_view parms, - gdb::array_view args) + gdb::array_view args, + bool varargs) { /* add 1 for the length-match rank. */ badness_vector bv; @@ -4051,7 +4053,8 @@ rank_function (gdb::array_view parms, arguments and ellipsis parameter lists, we should consider those and rank the length-match more finely. */ =20 - bv.push_back ((args.size () !=3D parms.size ()) + bv.push_back ((args.size () !=3D parms.size () + && (! varargs || args.size () < parms.size ())) ? LENGTH_MISMATCH_BADNESS : EXACT_MATCH_BADNESS); =20 @@ -4064,7 +4067,7 @@ rank_function (gdb::array_view parms, =20 /* If more arguments than parameters, add dummy entries. */ for (size_t i =3D min_len; i < args.size (); i++) - bv.push_back (TOO_FEW_PARAMS_BADNESS); + bv.push_back (varargs ? VARARG_BADNESS : TOO_FEW_PARAMS_BADNESS); =20 return bv; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index eca92196364..4b563e79546 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2735,7 +2735,8 @@ extern int compare_badness (const badness_vector &, const badness_vector &); =20 extern badness_vector rank_function (gdb::array_view parms, - gdb::array_view args); + gdb::array_view args, + bool varargs =3D false); =20 extern struct rank rank_one_type (struct type *, struct type *, struct value *); diff --git a/gdb/testsuite/gdb.cp/call-c.cc b/gdb/testsuite/gdb.cp/call-c.cc index 4362bbf2143..1677755b4b9 100644 --- a/gdb/testsuite/gdb.cp/call-c.cc +++ b/gdb/testsuite/gdb.cp/call-c.cc @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . = */ =20 +#include + int func(int x) { return x; @@ -33,6 +35,29 @@ extern "C" { int foo(int); } =20 +int sum_vararg_int (int count, ...) +{ + va_list va; + int sum =3D 0; + + va_start (va, count); + for (int i =3D 0; i < count; i++) + sum +=3D 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 =3D pf; rf->func(); /* set breakpoint here */ foo(0); + sum_vararg_int (1, 5); return func(0); } diff --git a/gdb/testsuite/gdb.cp/call-c.exp b/gdb/testsuite/gdb.cp/call-c.= exp index b20bc8698ca..36c0c1e2a75 100644 --- a/gdb/testsuite/gdb.cp/call-c.exp +++ b/gdb/testsuite/gdb.cp/call-c.exp @@ -38,5 +38,18 @@ gdb_test "print foo(1)" "\\\$$decimal =3D 1" gdb_test "continue" ".*breakpoint here.*" "continue to bp" gdb_test "print rf->func()" "\\\$$decimal =3D 1" =20 +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 =3D 1" diff --git a/gdb/valops.c b/gdb/valops.c index 49ea1fd7676..a15c92bd222 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -3226,6 +3226,7 @@ find_oload_champ (gdb::array_view args, { int jj; int static_offset =3D 0; + bool varargs =3D false; std::vector parm_types; =20 if (xmethods !=3D NULL) @@ -3238,9 +3239,13 @@ find_oload_champ (gdb::array_view args, { nparms =3D TYPE_FN_FIELD_TYPE (methods, ix)->num_fields (); static_offset =3D oload_method_static_p (methods, ix); + varargs =3D TYPE_FN_FIELD_TYPE (methods, ix)->has_varargs (); } else - nparms =3D functions[ix]->type ()->num_fields (); + { + nparms =3D functions[ix]->type ()->num_fields (); + varargs =3D functions[ix]->type ()->has_varargs (); + } =20 parm_types.reserve (nparms); for (jj =3D 0; jj < nparms; jj++) @@ -3255,7 +3260,8 @@ find_oload_champ (gdb::array_view args, /* Compare parameter types to supplied argument types. Skip THIS for static methods. */ bv =3D rank_function (parm_types, - args.slice (static_offset)); + args.slice (static_offset), + varargs); =20 if (overload_debug) {