public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Siva Chandra <sivachandra@google.com>
To: gdb-patches <gdb-patches@sourceware.org>
Subject: [RFC/Patch] Call overloaded operators to perform valid Python operations on struct/class values.
Date: Mon, 02 Dec 2013 19:28:00 -0000	[thread overview]
Message-ID: <CAGyQ6gxk9zcLKQ1Ef2XhgUMCyB8MB1v=6tA4jsfPyEFgxR8bNw@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 803 bytes --]

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.

[-- Attachment #2: python_op_patch_v1.txt --]
[-- Type: text/plain, Size: 6393 bytes --]

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"

             reply	other threads:[~2013-12-02 19:28 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-02 19:28 Siva Chandra [this message]
2013-12-06  6:25 ` Doug Evans
2013-12-06 14:20   ` Siva Chandra
2013-12-11 20:18     ` Tom Tromey
2013-12-11 20:17   ` Tom Tromey
2013-12-16  7:48     ` Doug Evans
2013-12-16 22:24       ` Siva Chandra
2013-12-18 16:37         ` Doug Evans
2013-12-18 23:15           ` Siva Chandra
2013-12-19 14:11             ` Doug Evans
2013-12-19 17:50               ` Siva Chandra
2013-12-20 22:29                 ` Siva Chandra
2013-12-21  8:21                   ` Eli Zaretskii
2013-12-30 14:40                     ` Siva Chandra
2013-12-30 17:57                       ` Eli Zaretskii
2014-01-22 21:39                       ` Siva Chandra
2014-01-25 18:45                         ` Doug Evans

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAGyQ6gxk9zcLKQ1Ef2XhgUMCyB8MB1v=6tA4jsfPyEFgxR8bNw@mail.gmail.com' \
    --to=sivachandra@google.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).