* [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* Re: [RFC] Extend existing support for evaluating expressions using overloaded operators
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
0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2012-06-04 20:53 UTC (permalink / raw)
To: Siva Chandra; +Cc: gdb-patches
>>>>> "Siva" == Siva Chandra <sivachandra@google.com> writes:
Siva> * valarith.c (value_binop): Extend to handle overloaded
Siva> binary operations on compound types.
I don't understand why value_binop must be modified.
I think in the current design it is up to the caller to check this.
(I don't necessarily think this is a good design -- but changing it
would require more changes elsewhere.)
Siva> +int
Siva> +is_compound_type (struct type *type)
Siva> +{
Siva> + enum type_code type_code;
Siva> +
Siva> + CHECK_TYPEDEF (type);
Siva> +
Siva> + type_code = TYPE_CODE (type);
Siva> + if (type_code == TYPE_CODE_STRUCT || type_code == TYPE_CODE_UNION)
It seems to me that there is other code which assumes that only
TYPE_CODE_STRUCT can be overloaded. At least binop_types_user_defined_p,
but maybe others. Those spots should be updated.
It would be nice if the test suite tested this case as well.
Siva> + TRY_CATCH (except, RETURN_MASK_ERROR)
Siva> + {
Siva> + /* Retrieve the list of methods with the name NAME. */
Siva> + fns_ptr = value_find_oload_method_list (&temp, name,
Siva> + 0, &num_fns,
Siva> + &basetype, &boffset);
Siva> + }
Siva> + if (except.reason < 0)
Siva> + fns_ptr = NULL;
I'll have to go read this in more depth; but I wonder why it is ok to
ignore exceptions here.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [RFC] Extend existing support for evaluating expressions using overloaded operators
2012-06-04 20:53 ` Tom Tromey
@ 2012-06-05 18:34 ` Siva Chandra
2012-06-08 17:41 ` Tom Tromey
0 siblings, 1 reply; 6+ messages in thread
From: Siva Chandra @ 2012-06-05 18:34 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Siva> * valarith.c (value_binop): Extend to handle overloaded
Siva> binary operations on compound types.
Tom> I don't understand why value_binop must be modified.
Tom> I think in the current design it is up to the caller to check this.
Tom> (I don't necessarily think this is a good design -- but changing it
Tom> would require more changes elsewhere.)
If we want to extend the operator overloading support into Python,
then we will have to have code to decide whether to call value_binop
or value_x_binop in the py-value.c. Another client of these two
functions is evaluate_subexp_standard, which also has code to decide
whether to call value_binop or value_x_binop. Though I did not mention
in my post, my intention is avoid such repetitive code and get all
clients to depend only on value_binop and treat value_x_binop as
'internal'. I would like to follow this patch with another patch to do
this change. Note that, only evaluate_subexp_standard calls
value_x_binop currently. Hence, replacing these calls with value_binop
should not be much work (though I have not yet come up with a way to
deal with the 'noside' argument of value_x_binop).
Siva> +int
Siva> +is_compound_type (struct type *type)
Siva> +{
Siva> + enum type_code type_code;
Siva> +
Siva> + CHECK_TYPEDEF (type);
Siva> +
Siva> + type_code = TYPE_CODE (type);
Siva> + if (type_code == TYPE_CODE_STRUCT || type_code == TYPE_CODE_UNION)
Tom> It seems to me that there is other code which assumes that only
Tom> TYPE_CODE_STRUCT can be overloaded. At least binop_types_user_defined_p,
Tom> but maybe others. Those spots should be updated.
Actually, AFAICT binop_types_user_defined_p has a copy-paste typo due
to which it is currently wrong. Even otherwise, with the change I have
in mind this function can go away I think.
Tom> It would be nice if the test suite tested this case as well.
I agree, I will add more tests after we finalize this patch.
Siva> + TRY_CATCH (except, RETURN_MASK_ERROR)
Siva> + {
Siva> + /* Retrieve the list of methods with the name NAME. */
Siva> + fns_ptr = value_find_oload_method_list (&temp, name,
Siva> + 0, &num_fns,
Siva> + &basetype, &boffset);
Siva> + }
Siva> + if (except.reason < 0)
Siva> + fns_ptr = NULL;
Tom> I'll have to go read this in more depth; but I wonder why it is ok to
Tom> ignore exceptions here.
An exception is thrown if we are trying to lookup methods of a
non-struct and non-union type. One can ask that, in such cases, why
call value_find_oload_method_list at all. My argument is, if
value_find_oload_method_list is doing the check, why should we repeat
before calling it.
Thanks,
Siva Chandra
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [RFC] Extend existing support for evaluating expressions using overloaded operators
2012-06-05 18:34 ` Siva Chandra
@ 2012-06-08 17:41 ` Tom Tromey
2012-06-08 19:18 ` Siva Chandra
0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2012-06-08 17:41 UTC (permalink / raw)
To: Siva Chandra; +Cc: gdb-patches
>>>>> "Siva" == Siva Chandra <sivachandra@google.com> writes:
Siva> If we want to extend the operator overloading support into Python,
Siva> then we will have to have code to decide whether to call value_binop
Siva> or value_x_binop in the py-value.c. Another client of these two
Siva> functions is evaluate_subexp_standard, which also has code to decide
Siva> whether to call value_binop or value_x_binop. Though I did not mention
Siva> in my post, my intention is avoid such repetitive code and get all
Siva> clients to depend only on value_binop and treat value_x_binop as
Siva> 'internal'.
I think you should start with this cleanup, then.
After the current patch it seems to me that the code would be inconsistent.
I think this idea is ok in the abstract but you have to be sure to audit
all the existing uses to make sure it does the right thing. (I don't
anticipate a problem here, but still...)
Siva> I would like to follow this patch with another patch to do
Siva> this change. Note that, only evaluate_subexp_standard calls
Siva> value_x_binop currently. Hence, replacing these calls with value_binop
Siva> should not be much work (though I have not yet come up with a way to
Siva> deal with the 'noside' argument of value_x_binop).
Letting that leak out of eval.c seems like a flaw.
Tom> It would be nice if the test suite tested this case as well.
Siva> I agree, I will add more tests after we finalize this patch.
Siva> + TRY_CATCH (except, RETURN_MASK_ERROR)
Siva> + {
Siva> + /* Retrieve the list of methods with the name NAME. */
Siva> + fns_ptr = value_find_oload_method_list (&temp, name,
Siva> + 0, &num_fns,
Siva> + &basetype, &boffset);
Siva> + }
Siva> + if (except.reason < 0)
Siva> + fns_ptr = NULL;
Tom> I'll have to go read this in more depth; but I wonder why it is ok to
Tom> ignore exceptions here.
Siva> An exception is thrown if we are trying to lookup methods of a
Siva> non-struct and non-union type. One can ask that, in such cases, why
Siva> call value_find_oload_method_list at all. My argument is, if
Siva> value_find_oload_method_list is doing the check, why should we repeat
Siva> before calling it.
Throwing and catching an exception is much more expensive, and less
clear, than just checking the type.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [RFC] Extend existing support for evaluating expressions using overloaded operators
2012-06-08 17:41 ` Tom Tromey
@ 2012-06-08 19:18 ` Siva Chandra
2012-06-18 7:30 ` Siva Chandra
0 siblings, 1 reply; 6+ messages in thread
From: Siva Chandra @ 2012-06-08 19:18 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Fri, Jun 8, 2012 at 11:11 PM, Tom Tromey <tromey@redhat.com> wrote:
> I think you should start with this cleanup, then.
> After the current patch it seems to me that the code would be inconsistent.
OK. I will stage the clean up and extension in multiple patches. Also,
that way I will get to discuss in smaller pieces as to why the code is
the way it is.
Thanks,
Siva Chandra
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC] Extend existing support for evaluating expressions using overloaded operators
2012-06-08 19:18 ` Siva Chandra
@ 2012-06-18 7:30 ` Siva Chandra
0 siblings, 0 replies; 6+ messages in thread
From: Siva Chandra @ 2012-06-18 7:30 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
[-- 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"
^ 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