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"