mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-06 12:09:26 +08:00
Allow calling of variadic C++ functions
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 Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
parent
8cb16b6858
commit
1d2f86b6b7
@ -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"
|
||||
|
10
gdb/valops.c
10
gdb/valops.c
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user