[RFC/Patch] Call overloaded operators to perform valid Python operations on struct/class values.
Siva Chandra
sivachandra@google.com
Mon Dec 2 19:28:00 GMT 2013
Hi,
This is a follow up to this thread:
https://sourceware.org/ml/gdb/2013-11/msg00101.html
Part of Doug's response there seemed to indicate that calling
overloaded operators to perform valid Python operations has not yet
been implemented. The attached patch adds this "feature". I could not
yet think of a reason as to why adding this could be bad (as in,
leading to ambiguity or something similar).
ChangeLog
2013-12-02 Siva Chandra Reddy <sivachandra@google.com>
Call overloaded operators to perform valid Python operations on
struct/class values.
* 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.
* gdb.python/py-value-cc.exp: Add new tests.
-------------- next part --------------
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 40254b9..22c2dbc 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -762,6 +762,8 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
struct value *arg1, *arg2;
struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
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
to us as the OTHER argument, and SELF will be an entirely different
@@ -793,6 +795,7 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
CHECK_TYPEDEF (rtype);
rtype = STRIP_REFERENCE (rtype);
+ handled = 1;
if (TYPE_CODE (ltype) == TYPE_CODE_PTR
&& is_integral_type (rtype))
res_val = value_ptradd (arg1, value_as_long (arg2));
@@ -800,7 +803,10 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
&& is_integral_type (ltype))
res_val = value_ptradd (arg2, value_as_long (arg1));
else
- res_val = value_binop (arg1, arg2, BINOP_ADD);
+ {
+ handled = 0;
+ op = BINOP_ADD;
+ }
}
break;
case VALPY_SUB:
@@ -813,6 +819,7 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
CHECK_TYPEDEF (rtype);
rtype = STRIP_REFERENCE (rtype);
+ handled = 1;
if (TYPE_CODE (ltype) == TYPE_CODE_PTR
&& TYPE_CODE (rtype) == TYPE_CODE_PTR)
/* A ptrdiff_t for the target would be preferable here. */
@@ -822,38 +829,49 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
&& is_integral_type (rtype))
res_val = value_ptradd (arg1, - value_as_long (arg2));
else
- res_val = value_binop (arg1, arg2, BINOP_SUB);
+ {
+ handled = 0;
+ op = BINOP_SUB;
+ }
}
break;
case VALPY_MUL:
- res_val = value_binop (arg1, arg2, BINOP_MUL);
+ op = BINOP_MUL;
break;
case VALPY_DIV:
- res_val = value_binop (arg1, arg2, BINOP_DIV);
+ op = BINOP_DIV;
break;
case VALPY_REM:
- res_val = value_binop (arg1, arg2, BINOP_REM);
+ op = BINOP_REM;
break;
case VALPY_POW:
- res_val = value_binop (arg1, arg2, BINOP_EXP);
+ op = BINOP_EXP;
break;
case VALPY_LSH:
- res_val = value_binop (arg1, arg2, BINOP_LSH);
+ op = BINOP_LSH;
break;
case VALPY_RSH:
- res_val = value_binop (arg1, arg2, BINOP_RSH);
+ op = BINOP_RSH;
break;
case VALPY_BITAND:
- res_val = value_binop (arg1, arg2, BINOP_BITWISE_AND);
+ op = BINOP_BITWISE_AND;
break;
case VALPY_BITOR:
- res_val = value_binop (arg1, arg2, BINOP_BITWISE_IOR);
+ op = BINOP_BITWISE_IOR;
break;
case VALPY_BITXOR:
- res_val = value_binop (arg1, arg2, BINOP_BITWISE_XOR);
+ op = BINOP_BITWISE_XOR;
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)
result = value_to_value_object (res_val);
diff --git a/gdb/testsuite/gdb.python/py-value-cc.cc b/gdb/testsuite/gdb.python/py-value-cc.cc
index c010fc9..ff605c4 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.cc
+++ b/gdb/testsuite/gdb.python/py-value-cc.cc
@@ -16,8 +16,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
class A {
+ public:
+ int operator+ (const int a);
+
+ public:
+ int a_;
};
+int
+A::operator+ (const int a)
+{
+ return a + a_;
+}
+
typedef int *int_ptr;
int
@@ -35,5 +46,8 @@ int
main ()
{
A obj;
+
+ obj.a_ = 5;
+
return func (obj);
}
diff --git a/gdb/testsuite/gdb.python/py-value-cc.exp b/gdb/testsuite/gdb.python/py-value-cc.exp
index 55c3b97..026deb5 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.exp
+++ b/gdb/testsuite/gdb.python/py-value-cc.exp
@@ -34,13 +34,30 @@ if ![runto_main] {
gdb_breakpoint [gdb_get_line_number "Break here."]
gdb_continue_to_breakpoint "Break here" ".*Break here.*"
-gdb_test "python print (str(gdb.parse_and_eval(\"a\").type))" "const A &"
-gdb_test "python print (str(gdb.parse_and_eval(\"a\").referenced_value().type))" "const A"
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ref\").type))" "int &"
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ref\").referenced_value().type))" "int"
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ref\").referenced_value()))" "10"
-
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ptr_ref\").dereference().type))" "int"
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ptr_ref\").referenced_value().type))" "int_ptr"
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ptr_ref\").referenced_value().dereference()))" "10"
-gdb_test "python print (str(gdb.parse_and_eval(\"int_ptr_ref\").referenced_value().referenced_value()))" "10"
+gdb_test_no_output "python a = gdb.parse_and_eval('a')" "eval a"
+gdb_test_no_output "python int_ref = gdb.parse_and_eval('int_ref')" \
+ "eval int_ref"
+gdb_test_no_output "python int_ptr_ref = gdb.parse_and_eval('int_ptr_ref')" \
+ "eval int_ptr_ref"
+
+# Tests for gdb.Value.referenced_value()
+gdb_test "python print str(a.type)" "const A &" "a.type"
+gdb_test "python print str(a.referenced_value().type)" "const A" \
+ "a.referenced_value().type"
+gdb_test "python print str(int_ref.type)" "int &" "int_ref.type"
+gdb_test "python print str(int_ref.referenced_value().type)" "int" \
+ "int_ref.referenced_value().type"
+gdb_test "python print str(int_ref.referenced_value())" "10" \
+ "int_ref.referenced_value()"
+
+gdb_test "python print str(int_ptr_ref.dereference().type)" "int" \
+ "int_ptr_ref.dereference().type"
+gdb_test "python print str(int_ptr_ref.referenced_value().type)" "int_ptr" \
+ "int_ptr_ref.referenced_value().type"
+gdb_test "python print str(int_ptr_ref.referenced_value().dereference())" \
+ "10" "int_ptr_ref.referenced_value().dereference()"
+gdb_test "python print str(int_ptr_ref.referenced_value().referenced_value())" \
+ "10" "int_ptr_ref.referenced_value().referenced_value()"
+
+# Test overloaded operators.
+gdb_test "python print a + 5" "10" "a + 5"
More information about the Gdb-patches
mailing list