Call overloaded operators to perform operations on gdb.Value objects.

* NEWS: Add entry for the new feature
	* python/py-value.c (valpy_binop): Call value_x_binop for struct
	and class values.

	testsuite/
	* gdb.python/py-value-cc.cc: Improve test case to enable testing
	operations on gdb.Value objects.
	* gdb.python/py-value-cc.exp: Add new test to test operations on
	gdb.Value objects.

	doc/
	* python.texi (Values From Inferior): Add description about the
	new feature.
This commit is contained in:
Siva Chandra
2013-12-02 06:45:09 -08:00
parent 649ebbcaef
commit f7bd0f7854
8 changed files with 88 additions and 12 deletions

View File

@ -1,3 +1,9 @@
2014-02-19 Siva Chandra Reddy <sivachandra@google.com>
* NEWS: Add entry for the new feature
* python/py-value.c (valpy_binop): Call value_x_binop for struct
and class values.
2014-02-19 Stan Shebs <stan@codesourcery.com> 2014-02-19 Stan Shebs <stan@codesourcery.com>
* MAINTAINERS: List Yao Qi as nios2 maintainer. * MAINTAINERS: List Yao Qi as nios2 maintainer.

View File

@ -82,6 +82,12 @@ qXfer:btrace:read's annex
The qXfer:btrace:read packet supports a new annex 'delta' to read The qXfer:btrace:read packet supports a new annex 'delta' to read
branch trace incrementally. branch trace incrementally.
* Python Scripting
** Valid Python operations on gdb.Value objects representing
structs/classes invoke the corresponding overloaded operators if
available.
* New targets * New targets
PowerPC64 GNU/Linux little-endian powerpc64le-*-linux* PowerPC64 GNU/Linux little-endian powerpc64le-*-linux*

View File

@ -1,3 +1,8 @@
2014-02-19 Siva Chandra Reddy <sivachandra@google.com>
* python.texi (Values From Inferior): Add description about the
new feature.
2014-02-17 Doug Evans <xdje42@gmail.com> 2014-02-17 Doug Evans <xdje42@gmail.com>
* Makefile.in (GDB_DOC_FILES): Add python.texi. * Makefile.in (GDB_DOC_FILES): Add python.texi.

View File

@ -528,7 +528,26 @@ bar = some_val + 2
@noindent @noindent
As result of this, @code{bar} will also be a @code{gdb.Value} object As result of this, @code{bar} will also be a @code{gdb.Value} object
whose values are of the same type as those of @code{some_val}. whose values are of the same type as those of @code{some_val}. Valid
Python operations can also be performed on @code{gdb.Value} objects
representing a @code{struct} or @code{class} object. For such cases,
the overloaded operator (if present), is used to perform the operation.
For example, if @code{val1} and @code{val2} are @code{gdb.Value} objects
representing instances of a @code{class} which overloads the @code{+}
operator, then one can use the @code{+} operator in their Python script
as follows:
@smallexample
val3 = val1 + val2
@end smallexample
@noindent
The result of the operation @code{val3} is also a @code{gdb.Value}
object corresponding to the value returned by the overloaded @code{+}
operator. In general, overloaded operators are invoked for the
following operations: @code{+} (binary addition), @code{-} (binary
subtraction), @code{*} (multiplication), @code{/}, @code{%}, @code{<<},
@code{>>}, @code{|}, @code{&}, @code{^}.
Inferior values that are structures or instances of some class can Inferior values that are structures or instances of some class can
be accessed using the Python @dfn{dictionary syntax}. For example, if be accessed using the Python @dfn{dictionary syntax}. For example, if

View File

@ -933,6 +933,8 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
struct value *arg1, *arg2; struct value *arg1, *arg2;
struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ()); struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
struct value *res_val = NULL; struct value *res_val = NULL;
enum exp_opcode op = OP_NULL;
int handled = 0;
/* If the gdb.Value object is the second operand, then it will be passed /* 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 different to us as the OTHER argument, and SELF will be an entirely different
@ -964,6 +966,7 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
CHECK_TYPEDEF (rtype); CHECK_TYPEDEF (rtype);
rtype = STRIP_REFERENCE (rtype); rtype = STRIP_REFERENCE (rtype);
handled = 1;
if (TYPE_CODE (ltype) == TYPE_CODE_PTR if (TYPE_CODE (ltype) == TYPE_CODE_PTR
&& is_integral_type (rtype)) && is_integral_type (rtype))
res_val = value_ptradd (arg1, value_as_long (arg2)); res_val = value_ptradd (arg1, value_as_long (arg2));
@ -971,7 +974,10 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
&& is_integral_type (ltype)) && is_integral_type (ltype))
res_val = value_ptradd (arg2, value_as_long (arg1)); res_val = value_ptradd (arg2, value_as_long (arg1));
else else
res_val = value_binop (arg1, arg2, BINOP_ADD); {
handled = 0;
op = BINOP_ADD;
}
} }
break; break;
case VALPY_SUB: case VALPY_SUB:
@ -984,6 +990,7 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
CHECK_TYPEDEF (rtype); CHECK_TYPEDEF (rtype);
rtype = STRIP_REFERENCE (rtype); rtype = STRIP_REFERENCE (rtype);
handled = 1;
if (TYPE_CODE (ltype) == TYPE_CODE_PTR if (TYPE_CODE (ltype) == TYPE_CODE_PTR
&& TYPE_CODE (rtype) == TYPE_CODE_PTR) && TYPE_CODE (rtype) == TYPE_CODE_PTR)
/* A ptrdiff_t for the target would be preferable here. */ /* A ptrdiff_t for the target would be preferable here. */
@ -993,38 +1000,49 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
&& is_integral_type (rtype)) && is_integral_type (rtype))
res_val = value_ptradd (arg1, - value_as_long (arg2)); res_val = value_ptradd (arg1, - value_as_long (arg2));
else else
res_val = value_binop (arg1, arg2, BINOP_SUB); {
handled = 0;
op = BINOP_SUB;
}
} }
break; break;
case VALPY_MUL: case VALPY_MUL:
res_val = value_binop (arg1, arg2, BINOP_MUL); op = BINOP_MUL;
break; break;
case VALPY_DIV: case VALPY_DIV:
res_val = value_binop (arg1, arg2, BINOP_DIV); op = BINOP_DIV;
break; break;
case VALPY_REM: case VALPY_REM:
res_val = value_binop (arg1, arg2, BINOP_REM); op = BINOP_REM;
break; break;
case VALPY_POW: case VALPY_POW:
res_val = value_binop (arg1, arg2, BINOP_EXP); op = BINOP_EXP;
break; break;
case VALPY_LSH: case VALPY_LSH:
res_val = value_binop (arg1, arg2, BINOP_LSH); op = BINOP_LSH;
break; break;
case VALPY_RSH: case VALPY_RSH:
res_val = value_binop (arg1, arg2, BINOP_RSH); op = BINOP_RSH;
break; break;
case VALPY_BITAND: case VALPY_BITAND:
res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND); op = BINOP_BITWISE_AND;
break; break;
case VALPY_BITOR: case VALPY_BITOR:
res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR); op = BINOP_BITWISE_IOR;
break; break;
case VALPY_BITXOR: case VALPY_BITXOR:
res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR); op = BINOP_BITWISE_XOR;
break; break;
} }
if (!handled)
{
if (binop_user_defined_p (op, arg1, arg2))
res_val = value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL);
else
res_val = value_binop (arg1, arg2, op);
}
if (res_val) if (res_val)
result = value_to_value_object (res_val); result = value_to_value_object (res_val);

View File

@ -1,3 +1,10 @@
2014-02-19 Siva Chandra Reddy <sivachandra@google.com>
* gdb.python/py-value-cc.cc: Improve test case to enable testing
operations on gdb.Value objects.
* gdb.python/py-value-cc.exp: Add new test to test operations on
gdb.Value objects.
2014-02-18 Doug Evans <dje@google.com> 2014-02-18 Doug Evans <dje@google.com>
* Makefile.in (TESTS): New variable. * Makefile.in (TESTS): New variable.

View File

@ -16,10 +16,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */ along with this program. If not, see <http://www.gnu.org/licenses/>. */
class A { class A {
public:
int operator+ (const int a1);
public: public:
int a; int a;
}; };
int
A::operator+ (const int a1)
{
return a + a1;
}
union U { union U {
int a; int a;
char c; char c;
@ -88,5 +97,7 @@ main ()
{ {
A obj; A obj;
obj.a = 5;
return func (obj); return func (obj);
} }

View File

@ -99,3 +99,7 @@ gdb_test "python print xtd\[x_fields\[1\]\]\['a'\]" "102" "xtd->a via field"
gdb_test "python print len(uu_fields)" "2" "number of fields in uu" gdb_test "python print len(uu_fields)" "2" "number of fields in uu"
gdb_test "python print uu\[uu_fields\[0\]\]\['x'\]" "1000" "uu.x via field" gdb_test "python print uu\[uu_fields\[0\]\]\['x'\]" "1000" "uu.x via field"
gdb_test "python print uu\[uu_fields\[1\]\]\['a'\]" "1000" "uu.a via field" gdb_test "python print uu\[uu_fields\[1\]\]\['a'\]" "1000" "uu.a via field"
# Test overloaded operators.
gdb_test_no_output "python a = gdb.parse_and_eval('a')" "init a"
gdb_test "python print a + 5" "10" "a + 5"