commit 3a019f3ba61bde5320419f5782d8f2554ac55ace Author: Jonathan Wakely Date: Tue Sep 20 10:38:35 2016 +0100 gdb: Implement floordiv operator for gdb.Value gdb/ChangeLog: 2016-09-20 Jonathan Wakely PR python/20624 * python/py-value.c (VALPY_FLOORDIV): Define new enumerator. (valpy_binop_throw): Handle VALPY_FLOORDIV. (valpy_floordiv): New function. (value_object_as_number): Set valpy_floordiv in relevant slot. gdb/testsuite/ChangeLog: 2016-09-20 Jonathan Wakely PR python/20624 * gdb.python/py-value.exp: Test floor division. diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 21e9247..f6a6c11 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -1011,7 +1011,8 @@ enum valpy_opcode VALPY_RSH, VALPY_BITAND, VALPY_BITOR, - VALPY_BITXOR + VALPY_BITXOR, + VALPY_FLOORDIV }; /* If TYPE is a reference, return the target; otherwise return TYPE. */ @@ -1032,6 +1033,7 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other) struct value *res_val = NULL; enum exp_opcode op = OP_NULL; int handled = 0; + bool floor_it = false; /* If the gdb.Value object is the second operand, then it will be passed to us as the OTHER argument, and SELF will be an entirely @@ -1113,6 +1115,22 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other) case VALPY_REM: op = BINOP_REM; break; + case VALPY_FLOORDIV: + { + struct type *ltype = value_type (arg1); + struct type *rtype = value_type (arg2); + ltype = check_typedef (ltype); + rtype = check_typedef (rtype); + if (TYPE_CODE (ltype) == TYPE_CODE_FLT + || TYPE_CODE (rtype) == TYPE_CODE_FLT) + { + op = BINOP_DIV; + floor_it = true; + } + else + op = BINOP_INTDIV; + } + break; case VALPY_POW: op = BINOP_EXP; break; @@ -1142,7 +1160,15 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other) } if (res_val) - result = value_to_value_object (res_val); + { + if (floor_it) + { + double d = value_as_double (res_val); + d = floor (d); + res_val = value_from_double (value_type (res_val), d); + } + result = value_to_value_object (res_val); + } do_cleanups (cleanup); return result; @@ -1200,6 +1226,12 @@ valpy_remainder (PyObject *self, PyObject *other) } static PyObject * +valpy_floordiv (PyObject *self, PyObject *other) +{ + return valpy_binop (VALPY_FLOORDIV, self, other); +} + +static PyObject * valpy_power (PyObject *self, PyObject *other, PyObject *unused) { /* We don't support the ternary form of pow. I don't know how to express @@ -1837,7 +1869,7 @@ static PyNumberMethods value_object_as_number = { NULL, /* nb_inplace_and */ NULL, /* nb_inplace_xor */ NULL, /* nb_inplace_or */ - NULL, /* nb_floor_divide */ + valpy_floordiv, /* nb_floor_divide */ valpy_divide, /* nb_true_divide */ NULL, /* nb_inplace_floor_divide */ NULL, /* nb_inplace_true_divide */ diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp index 57a9ba1..81837e9 100644 --- a/gdb/testsuite/gdb.python/py-value.exp +++ b/gdb/testsuite/gdb.python/py-value.exp @@ -87,6 +87,8 @@ proc test_value_numeric_ops {} { gdb_test "python print ('result = ' + str(f/g))" " = 0.5" "divide two double values" gdb_test "python print ('result = ' + str(i%j))" " = 1" "take remainder of two integer values" # Remainder of float is implemented in Python but not in GDB's value system. + gdb_test "python print ('result = ' + str(i//j))" " = 2" "floor-divide two integer values" + gdb_test "python print ('result = ' + str(f//g))" " = 0" "floor-divide two double values" gdb_test "python print ('result = ' + str(i**j))" " = 25" "integer value raised to the power of another integer value" gdb_test "python print ('result = ' + str(g**j))" " = 6.25" "double value raised to the power of integer value"