Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC] Extend existing support for evaluating expressions using overloaded operators
@ 2012-06-01 19:52 Siva Chandra
  2012-06-04 20:53 ` Tom Tromey
  0 siblings, 1 reply; 6+ messages in thread
From: Siva Chandra @ 2012-06-01 19:52 UTC (permalink / raw)
  To: gdb-patches

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

Hello,

The attached patch extends the existing support for evaluating
expressions using overloaded operators defined in C++ source. For
example, currently we do not support evaluation of a binary operation
if the first operand is a non-struct and the second operand is a
struct. To illustrate, if in C++ source we have

<code>
class Integer
{
...
};

int
operator+ (const int a, const Interger &b)
{
...
}

int an_int;
Integer an_integer;
</code>

then, at GDB prompt, we cannot do this

(gdb) p an_int + an_integer

The attached patch adds this support.

2012-06-01  Siva Chandra Reddy  <sivachandra@google.com>

        Extend existing support for evaluating expressions using
        overloaded operators.
        * gdtypes.c (is_scalar_type): Make the function non-static.
        (is_compound_type): New function to test if a type is a compound
        type.
        * gdbtypes.h (is_scalar_type, is_compound_type): Add
        declarations for these functions.
        * valarith.c (value_binop): Extend to handle overloaded
        binary operations on compound types.
        (value_x_binop): Extend to handle binary operations which have
        atleast one compound value operand.
        * valops.c (find_overload_match): Lookup overloaded operator
        function when lookup for overloaded operator method throws an
        exception.

        testsuite/
        * gdb.cp/operator.cc: Add test cases to test overloaded
        binary operator evaluation.
        * gdb.python/py-value.cc: Likewise
        * gdb.cp/operator.exp: Add tests to test overloaded binary
        operator evaluation.
        * gdb.python/py-value-cc.exp: Likewise
        * gdb.python/py-value.exp: Fix a test case to align it with the
        new error message.

Thanks,
Siva Chandra

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

Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.230
diff -u -p -r1.230 gdbtypes.c
--- gdbtypes.c	23 May 2012 23:45:09 -0000	1.230
+++ gdbtypes.c	1 Jun 2012 19:00:32 -0000
@@ -1987,7 +1987,7 @@ is_integral_type (struct type *t)
 
 /* Return true if TYPE is scalar.  */
 
-static int
+int
 is_scalar_type (struct type *type)
 {
   CHECK_TYPEDEF (type);
@@ -2006,6 +2006,20 @@ is_scalar_type (struct type *type)
     }
 }
 
+int
+is_compound_type (struct type *type)
+{
+  enum type_code type_code;
+
+  CHECK_TYPEDEF (type);
+
+  type_code = TYPE_CODE (type);
+  if (type_code == TYPE_CODE_STRUCT || type_code == TYPE_CODE_UNION)
+    return 1;
+  else
+    return 0;
+}
+
 /* Return true if T is scalar, or a composite type which in practice has
    the memory layout of a scalar type.  E.g., an array or struct with only
    one scalar element inside it, or a union with only scalar elements.  */
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.165
diff -u -p -r1.165 gdbtypes.h
--- gdbtypes.h	18 Apr 2012 06:46:46 -0000	1.165
+++ gdbtypes.h	1 Jun 2012 19:00:33 -0000
@@ -1603,8 +1603,12 @@ extern int can_dereference (struct type 
 
 extern int is_integral_type (struct type *);
 
+extern int is_scalar_type (struct type *);
+
 extern int is_scalar_type_recursive (struct type *);
 
+extern int is_compound_type (struct type *);
+
 extern void maintenance_print_type (char *, int);
 
 extern htab_t create_copied_types_hash (struct objfile *objfile);
Index: valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.103
diff -u -p -r1.103 valarith.c
--- valarith.c	18 May 2012 21:02:50 -0000	1.103
+++ valarith.c	1 Jun 2012 19:00:33 -0000
@@ -397,7 +397,8 @@ value_x_binop (struct value *arg1, struc
   /* now we know that what we have to do is construct our
      arg vector and find the right function to call it with.  */
 
-  if (TYPE_CODE (check_typedef (value_type (arg1))) != TYPE_CODE_STRUCT)
+  if (!is_compound_type (check_typedef (value_type (arg1)))
+      && !is_compound_type (check_typedef (value_type (arg2))))
     error (_("Can't do that binary op on that type"));	/* FIXME be explicit */
 
   argvec = (struct value **) alloca (sizeof (struct value *) * 4);
@@ -1447,24 +1448,27 @@ value_binop (struct value *arg1, struct 
   int t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY
 		   && TYPE_VECTOR (type2));
 
-  if (!t1_is_vec && !t2_is_vec)
+  if (is_scalar_type (type1) && is_scalar_type (type2))
     val = scalar_binop (arg1, arg2, op);
   else if (t1_is_vec && t2_is_vec)
     val = vector_binop (arg1, arg2, op);
-  else
+  else if ((is_scalar_type (type1) && t2_is_vec)
+           || (is_scalar_type (type2) && t1_is_vec))
     {
       /* Widen the scalar operand to a vector.  */
       struct value **v = t1_is_vec ? &arg2 : &arg1;
       struct type *t = t1_is_vec ? type2 : type1;
-      
-      if (TYPE_CODE (t) != TYPE_CODE_FLT
-	  && TYPE_CODE (t) != TYPE_CODE_DECFLOAT
-	  && !is_integral_type (t))
-	error (_("Argument to operation not a number or boolean."));
+
+      if (TYPE_CODE (t) == TYPE_CODE_PTR)
+	error (_("Argument to arithmetic operation not of valid type."));
 
       *v = value_cast (t1_is_vec ? type1 : type2, *v);
       val = vector_binop (arg1, arg2, op);
     }
+  else if (is_compound_type (type1) || is_compound_type (type2))
+    val = value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL);
+  else
+    error (_("Arguments to arithmetic operation not of valid type."));
 
   return val;
 }
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.294
diff -u -p -r1.294 valops.c
--- valops.c	21 May 2012 19:47:53 -0000	1.294
+++ valops.c	1 Jun 2012 19:00:35 -0000
@@ -2589,6 +2589,7 @@ find_overload_match (struct value **args
 		     struct value **valp, struct symbol **symp, 
 		     int *staticp, const int no_adl)
 {
+  struct gdb_exception except;
   struct value *obj = (objp ? *objp : NULL);
   struct type *obj_type = obj ? value_type (obj) : NULL;
   /* Index of best overloaded function.  */
@@ -2642,10 +2643,16 @@ find_overload_match (struct value **args
 	    }
 	}
 
-      /* Retrieve the list of methods with the name NAME.  */
-      fns_ptr = value_find_oload_method_list (&temp, name, 
-					      0, &num_fns, 
-					      &basetype, &boffset);
+      TRY_CATCH (except, RETURN_MASK_ERROR)
+        {
+          /* Retrieve the list of methods with the name NAME.  */
+          fns_ptr = value_find_oload_method_list (&temp, name, 
+	                                          0, &num_fns, 
+                                                  &basetype, &boffset);
+        }
+      if (except.reason < 0)
+        fns_ptr = NULL;
+
       /* If this is a method only search, and no methods were found
          the search has faild.  */
       if (method == METHOD && (!fns_ptr || !num_fns))
Index: testsuite/gdb.cp/operator.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/operator.cc,v
retrieving revision 1.2
diff -u -p -r1.2 operator.cc
--- testsuite/gdb.cp/operator.cc	25 Jun 2010 18:05:30 -0000	1.2
+++ testsuite/gdb.cp/operator.cc	1 Jun 2012 19:00:36 -0000
@@ -1,7 +1,26 @@
 class A
 {
+ public:
+  int a;
+
+  A operator+ (const A &opr2);
 };
 
+A
+A::operator+ (const A &opr2)
+{
+  A new_a;
+  new_a.a = a + opr2.a;
+
+  return new_a;
+}
+
+int
+operator+ (const int opr1, const A &opr2)
+{
+  return opr1 + opr2.a;
+}
+
 int operator== (A, int)
 {
   return 11;
@@ -176,6 +195,7 @@ test x;
 int main ()
 {
   A a;
+
   a == 1;
   a == 'a';
 
@@ -207,5 +227,9 @@ int main ()
   L l;
   l == 1;
 
-  return 0;
+  A obj1 = { 10 };
+  A obj2 = { 20 };
+  int val = 1;
+
+  return 0; /* Break here.  */
 }
Index: testsuite/gdb.cp/operator.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/operator.exp,v
retrieving revision 1.4
diff -u -p -r1.4 operator.exp
--- testsuite/gdb.cp/operator.exp	4 Jan 2012 08:17:47 -0000	1.4
+++ testsuite/gdb.cp/operator.exp	1 Jun 2012 19:00:36 -0000
@@ -26,6 +26,9 @@ if ![runto_main] then {
     continue
 }
 
+gdb_breakpoint [gdb_get_line_number "Break here."]
+gdb_continue_to_breakpoint "Break here" ".*Break here.*"
+
 # Test global operator
 gdb_test "p a == 1" "= 11" "global operator"
 gdb_test "p a == 'a'" "= 12" "global operator overload"
@@ -59,3 +62,7 @@ gdb_test "p l == 1" "= 88"
 
 # Test that we don't fall into an import loop
 gdb_test {p x[0]} {No symbol "operator\[\]" in current context.}
+
+# Test + operators
+gdb_test "print val + obj1" "11" "Test overloaded operator function"
+gdb_test "print (obj1 + obj2).a" "30" "Test overloaded operator method"
Index: testsuite/gdb.python/py-value-cc.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-value-cc.exp,v
retrieving revision 1.1
diff -u -p -r1.1 py-value-cc.exp
--- testsuite/gdb.python/py-value-cc.exp	22 Mar 2012 08:10:44 -0000	1.1
+++ testsuite/gdb.python/py-value-cc.exp	1 Jun 2012 19:00:37 -0000
@@ -36,6 +36,12 @@ if ![runto_main] {
 gdb_breakpoint [gdb_get_line_number "Break here."]
 gdb_continue_to_breakpoint "Break here" ".*Break here.*"
 
+gdb_py_test_silent_cmd "python val = gdb.parse_and_eval('val')" "Create an integer value" 0
+gdb_py_test_silent_cmd "python a = gdb.parse_and_eval('a')" "Create a value for 'a'" 0
+gdb_py_test_silent_cmd "python local_a = gdb.parse_and_eval('local_a')" "Create a value for 'local_a'" 0
+gdb_py_test_silent_cmd "python new1 = val + local_a" "Excercise operator+(int, A)" 0
+gdb_py_test_silent_cmd "python new2 = a + local_a" "Excercise A::operator+(A)" 0
+
 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 &"
@@ -46,3 +52,6 @@ gdb_test "python print str(gdb.parse_and
 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 "python print new1" "20" "Test overloaded operator function"
+gdb_test "python print new2\['a'\]" "20" "Test overlaoded operator method"
Index: testsuite/gdb.python/py-value.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-value.cc,v
retrieving revision 1.1
diff -u -p -r1.1 py-value.cc
--- testsuite/gdb.python/py-value.cc	22 Mar 2012 08:10:44 -0000	1.1
+++ testsuite/gdb.python/py-value.cc	1 Jun 2012 19:00:37 -0000
@@ -15,14 +15,35 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-class A {
+class A
+{
+ public:
+  int a;
+
+  A operator+ (const A &opr2);
 };
 
+A
+A::operator+ (const A &opr2)
+{
+  A new_a;
+  new_a.a = a + opr2.a;
+
+  return new_a;
+}
+
+int
+operator+ (const int opr1, const A &opr2)
+{
+  return opr1 + opr2.a;
+}
+
 typedef int *int_ptr;
 
 int
 func (const A &a)
 {
+  A local_a = { 10 };
   int val = 10;
   int &int_ref = val;
   int_ptr ptr = &val;
@@ -34,6 +55,7 @@ func (const A &a)
 int
 main ()
 {
-  A obj;
+  A obj = { 10 };
+
   return func (obj);
 }
Index: testsuite/gdb.python/py-value.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-value.exp,v
retrieving revision 1.27
diff -u -p -r1.27 py-value.exp
--- testsuite/gdb.python/py-value.exp	16 Jan 2012 16:21:52 -0000	1.27
+++ testsuite/gdb.python/py-value.exp	1 Jun 2012 19:00:37 -0000
@@ -109,7 +109,7 @@ proc test_value_numeric_ops {} {
   # Test some invalid operations.
 
   gdb_test_multiple "python print 'result = ' + str(i+'foo')" "catch error in python type conversion" {
-      -re "Argument to arithmetic operation not a number or boolean.*$gdb_prompt $"   {pass "catch error in python type conversion"}
+      -re "Arguments to arithmetic operation not of valid type.*$gdb_prompt $"   {pass "catch error in python type conversion"}
       -re "result = .*$gdb_prompt $"		      {fail "catch error in python type conversion"}
       -re "$gdb_prompt $"			      {fail "catch error in python type conversion"}
   }

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-06-18  7:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-01 19:52 [RFC] Extend existing support for evaluating expressions using overloaded operators Siva Chandra
2012-06-04 20:53 ` Tom Tromey
2012-06-05 18:34   ` Siva Chandra
2012-06-08 17:41     ` Tom Tromey
2012-06-08 19:18       ` Siva Chandra
2012-06-18  7:30         ` Siva Chandra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox