Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Siva Chandra <sivachandra@google.com>
To: Tom Tromey <tromey@redhat.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [RFC] Extend existing support for evaluating expressions using overloaded operators
Date: Mon, 18 Jun 2012 07:30:00 -0000	[thread overview]
Message-ID: <CAGyQ6gytckT+qW1UhcWq0moDO=qwrCby0KSx3zo2Ye-3uCN4AQ@mail.gmail.com> (raw)
In-Reply-To: <CAGyQ6gzuOgut-sONmqhPScBGqsucVJC=1dkMCtJY7jwq-Kviqg@mail.gmail.com>

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

Siva> I will stage the clean up and extension in multiple patches. Also,
Siva> that way I will get to discuss in smaller pieces as to why the code is
Siva> the way it is.

I have submitted
http://sourceware.org/ml/gdb-patches/2012-06/msg00245.html as the
first cleanup patch. Attached now is a patch which extends the
overloaded operator support. It contains a minor refactoring so that
the overloaded operator support can be extended to cases where the
first operand of a binary operation is a non-struct/non-union. Note
that this patch does not yet extend the support into Python API.

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

        Extend existing support for evaluating expressions using
        overloaded operators.
        * gdbtypes.c (is_compound_type): New function to test if a type
        is a struct or union.
        (type_can_have_methods): New function to check if a type can
        have methods defined on it.
        * gdbtypes.h (is_compound_type, type_can_have_methods): Declare.
        * valarith.c (value_user_defined_cpp_op): Make different calls
        to 'find_overload_match' based on the type of the first
        argument.
        (value_x_binop): Extend to handle binary operations which have
        either or both operands of a compound value. Pass operands as is
        to value_user_defined_op.
        (value_x_unop): Pass operand as is to value_user_defined_op.
        (binop_types_user_defined_p): Use is_compound_type to include
        unions.

        testsuite/
        * gdb.cp/operator.cc: Add test cases to test overloaded
        binary operator evaluation.
        * gdb.cp/operator.exp: Add tests to test overloaded binary
        operator evaluation.

Thanks,
Siva Chandra

[-- Attachment #2: oprovld_patch_v3.txt --]
[-- Type: text/plain, Size: 7712 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	18 Jun 2012 06:56:42 -0000
@@ -2006,6 +2006,48 @@ is_scalar_type (struct type *type)
     }
 }
 
+/* Return true if TYPE is a struct or union.  */
+
+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 is TYPE is a type which can have methods defined on it.
+   That is, if TYPE is a struct or a union, or is a pointer/reference to a
+   struct or union, then it returns true.  */
+
+int
+type_can_have_methods (struct type *type)
+{
+  if (is_compound_type (type))
+    return 1;
+  else
+    {
+      enum type_code type_code;
+
+      CHECK_TYPEDEF (type);
+      type_code = TYPE_CODE (type);
+
+      if (type_code == TYPE_CODE_PTR || type_code == TYPE_CODE_REF)
+        {
+          type = TYPE_TARGET_TYPE (type);
+          return type_can_have_methods (type);
+        }
+    }
+
+  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.167
diff -u -p -r1.167 gdbtypes.h
--- gdbtypes.h	17 Jun 2012 19:53:52 -0000	1.167
+++ gdbtypes.h	18 Jun 2012 06:56:43 -0000
@@ -1629,6 +1629,10 @@ extern int is_integral_type (struct type
 
 extern int is_scalar_type_recursive (struct type *);
 
+extern int is_compound_type (struct type *);
+
+extern int type_can_have_methods (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.104
diff -u -p -r1.104 valarith.c
--- valarith.c	9 Jun 2012 07:36:43 -0000	1.104
+++ valarith.c	18 Jun 2012 06:56:43 -0000
@@ -283,8 +283,7 @@ binop_types_user_defined_p (enum exp_opc
   if (TYPE_CODE (type2) == TYPE_CODE_REF)
     type2 = check_typedef (TYPE_TARGET_TYPE (type2));
 
-  return (TYPE_CODE (type1) == TYPE_CODE_STRUCT
-	  || TYPE_CODE (type2) == TYPE_CODE_STRUCT);
+  return (is_compound_type (type1) || is_compound_type (type2));
 }
 
 /* Check to see if either argument is a structure, or a reference to
@@ -335,22 +334,38 @@ value_user_defined_cpp_op (struct value 
   struct symbol *symp = NULL;
   struct value *valp = NULL;
 
-  find_overload_match (args, nargs, operator, BOTH /* could be method */,
-                       0 /* strict match */, &args[0], /* objp */
-                       NULL /* pass NULL symbol since symbol is unknown */,
-                       &valp, &symp, static_memfuncp, 0);
+  if (type_can_have_methods (value_type (args[0])))
+    {
+      struct value **argvec;
+      int i;
+
+      argvec = (struct value **) alloca (sizeof (struct value *) * nargs);
+      argvec[0] = value_addr (args[0]);
+      for (i = 1; i < nargs; i++)
+        argvec[i] = args[i];
+      
+      find_overload_match (argvec, nargs, operator, BOTH /* could be method */,
+                           0 /* strict match */, &argvec[0], /* objp */
+                           NULL /* pass NULL symbol since symbol is unknown */,
+                           &valp, &symp, static_memfuncp, 0);
 
-  if (valp)
-    return valp;
 
-  if (symp)
-    {
-      /* This is a non member function and does not
-         expect a reference as its first argument
-         rather the explicit structure.  */
-      args[0] = value_ind (args[0]);
-      return value_of_variable (symp, 0);
+      if (valp)
+        {
+          /* A method match was found. In such a case, the first argument
+             should actually be a pointer to 'this' (of the first arg).  */
+          args[0] = argvec[0];
+          return valp;
+        }      
     }
+  else
+    find_overload_match (args, nargs, operator, NON_METHOD,
+                         0 /* strict match */, NULL, /* objp */
+                         NULL /* pass NULL symbol since symbol is unknown */,
+                         &valp, &symp, static_memfuncp, 0);
+
+  if (symp)
+    return value_of_variable (symp, 0);
 
   error (_("Could not find %s."), operator);
 }
@@ -397,11 +412,12 @@ 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);
-  argvec[1] = value_addr (arg1);
+  argvec[1] = arg1;
   argvec[2] = arg2;
   argvec[3] = 0;
 
@@ -565,7 +581,7 @@ value_x_unop (struct value *arg1, enum e
     error (_("Can't do that unary op on that type"));	/* FIXME be explicit */
 
   argvec = (struct value **) alloca (sizeof (struct value *) * 4);
-  argvec[1] = value_addr (arg1);
+  argvec[1] = arg1;
   argvec[2] = 0;
 
   nargs = 1;
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	18 Jun 2012 06:56:44 -0000
@@ -1,7 +1,38 @@
 class A
 {
+ public:
+  int a;
+
+  A operator+ (const A &opr2);
+};
+
+union U
+{
+  int i;
+  char c;
 };
 
+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+ (const U &opr1, const A &opr2)
+{
+  return opr1.i + opr2.a;
+}
+
 int operator== (A, int)
 {
   return 11;
@@ -176,6 +207,7 @@ test x;
 int main ()
 {
   A a;
+
   a == 1;
   a == 'a';
 
@@ -207,5 +239,10 @@ int main ()
   L l;
   l == 1;
 
-  return 0;
+  A obj1 = { 10 };
+  A obj2 = { 20 };
+  int val = 1;
+  U u = { 10 };
+
+  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	18 Jun 2012 06:56:44 -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,8 @@ 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"
+gdb_test "print u + obj2" "30" "Test overloaded operator function with union arg"

      reply	other threads:[~2012-06-18  7:30 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-01 19:52 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 message]

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='CAGyQ6gytckT+qW1UhcWq0moDO=qwrCby0KSx3zo2Ye-3uCN4AQ@mail.gmail.com' \
    --to=sivachandra@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