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>
Cc: Tom Tromey <tromey@redhat.com>, Doug Evans <dje@google.com>
Subject: Re: [RFC/Patch] Call overloaded operators to perform valid Python operations on struct/class values.
Date: Fri, 20 Dec 2013 22:29:00 -0000	[thread overview]
Message-ID: <CAGyQ6gzMxiWMCYxYDvyWDfXVxfe3_Yy=6uzOyVyJ9XO+8QU5YA@mail.gmail.com> (raw)
In-Reply-To: <CAGyQ6gzYoyct9VwjsTgVR0tcq_u3=abyfdSAQwssqQk09yYdZA@mail.gmail.com>

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

I do not think there was an agreement on whether to have this feature
or not. Based on the points raised by Doug, my personal opinion is
that we should have this feature along with the facility (which in my
opinion is a cool fallback when no other Pythonic way works) suggested
by Doug.  To keep the discussion moving for both the ideas, I am
sending a patch which addresses the nits pointed out by Doug on my
first patch.  I will hopefully find time during the holidays to work
on the feature suggested by Doug.

2013-12-20  Siva Chandra Reddy  <sivachandra@google.com>

        Call overloaded operators to perform valid Python operations on
        struct/class values.
        * NEWS (Python Scripting): Add entry for this 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/
        * gdb.texinfo (Values From Inferior): Add description about
        performing valid Python operations on gdb.Value objects.

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

diff --git a/gdb/NEWS b/gdb/NEWS
index e4baf50..b712fdd 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -42,6 +42,9 @@
   ** Line tables representation has been added.
   ** New attribute 'parent_type' for gdb.Field objects.
   ** gdb.Field objects can be used as subscripts on gdb.Value objects.
+  ** Valid Python operations on gdb.Value objects representing
+     structs/classes invokes the corresponding overloaded operators if
+     available.
 
 * New targets
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b7551c2..0ca0880 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23974,7 +23974,23 @@ bar = some_val + 2
 
 @noindent
 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 @code{struct}s/@code{class}es.  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 has an overloaded
+operator defined for 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.
 
 Inferior values that are structures or instances of some class can
 be accessed using the Python @dfn{dictionary syntax}.  For example, if
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index df25179..6c2458c 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -884,6 +884,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
@@ -915,6 +917,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));
@@ -922,7 +925,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:
@@ -935,6 +941,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.  */
@@ -944,38 +951,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 80094ec..60c2182 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.cc
+++ b/gdb/testsuite/gdb.python/py-value-cc.cc
@@ -17,9 +17,18 @@
 
 class A {
  public:
+  int operator+ (const int a1);
+
+ public:
   int a;
 };
 
+int
+A::operator+ (const int a1)
+{
+  return a + a1;
+}
+
 union U {
   int a;
   char c;
@@ -65,5 +74,7 @@ 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 eacaf2e..fb1176d 100644
--- a/gdb/testsuite/gdb.python/py-value-cc.exp
+++ b/gdb/testsuite/gdb.python/py-value-cc.exp
@@ -79,3 +79,7 @@ gdb_test "python print(b_td\[b_fields\[0\]\]\['a'\])" "100" \
 
 gdb_test "python print(u\[u_fields\[0\]\])" "99.*" "u's first field via field"
 gdb_test "python print(u\[u_fields\[1\]\])" "99.*" "u's second field 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"

  reply	other threads:[~2013-12-20 22:29 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-02 19:28 Siva Chandra
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 [this message]
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='CAGyQ6gzMxiWMCYxYDvyWDfXVxfe3_Yy=6uzOyVyJ9XO+8QU5YA@mail.gmail.com' \
    --to=sivachandra@google.com \
    --cc=dje@google.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tromey@redhat.com \
    /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).