This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit] Fix a C++ operator* bug
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Tue, 25 Jul 2006 00:27:02 -0400
- Subject: [commit] Fix a C++ operator* bug
Chris sent me a testcase a year and a half ago and I've only just
now found time to look at it. We were failing to evaluate this
expression:
(*B).dump ();
The problem was that the class of B had an operator* which returned a
different type. We evaluated &(*B) to get "this", and optimized out
the &* sequence, so we got the type of B instead of the type returned
by its operator*. And that type didn't have a member function named
dump.
Fix checked in.
--
Daniel Jacobowitz
CodeSourcery
2006-07-25 Daniel Jacobowitz <dan@codesourcery.com>
* eval.c (evaluate_subexp_for_address): Don't incorrectly discard
calls to C++ operator*.
2006-07-25 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.cp/userdef.cc, gdb.cp/userdef.exp: New tests for unary
operator*.
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.62
diff -u -p -r1.62 eval.c
--- eval.c 20 Jul 2006 22:50:07 -0000 1.62
+++ eval.c 25 Jul 2006 04:01:52 -0000
@@ -2132,6 +2132,7 @@ evaluate_subexp_for_address (struct expr
enum exp_opcode op;
int pc;
struct symbol *var;
+ struct value *x;
pc = (*pos);
op = exp->elts[pc].opcode;
@@ -2140,7 +2141,24 @@ evaluate_subexp_for_address (struct expr
{
case UNOP_IND:
(*pos)++;
- return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ /* We can't optimize out "&*" if there's a user-defined operator*. */
+ if (unop_user_defined_p (op, x))
+ {
+ x = value_x_unop (x, op, noside);
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ if (VALUE_LVAL (x) == lval_memory)
+ return value_zero (lookup_pointer_type (value_type (x)),
+ not_lval);
+ else
+ error (_("Attempt to take address of non-lval"));
+ }
+ return value_addr (x);
+ }
+
+ return x;
case UNOP_MEMVAL:
(*pos) += 3;
@@ -2179,16 +2197,16 @@ evaluate_subexp_for_address (struct expr
default:
default_case:
+ x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
- struct value *x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (VALUE_LVAL (x) == lval_memory)
return value_zero (lookup_pointer_type (value_type (x)),
not_lval);
else
error (_("Attempt to take address of non-lval"));
}
- return value_addr (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ return value_addr (x);
}
}
Index: testsuite/gdb.cp/userdef.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/userdef.cc,v
retrieving revision 1.4
diff -u -p -r1.4 userdef.cc
--- testsuite/gdb.cp/userdef.cc 27 Apr 2005 16:35:15 -0000 1.4
+++ testsuite/gdb.cp/userdef.cc 25 Jul 2006 04:01:52 -0000
@@ -1,6 +1,6 @@
/* This test script is part of GDB, the GNU debugger.
- Copyright 1999, 2002, 2003, 2004, 2005
+ Copyright 1999, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -306,12 +306,31 @@ A2 A2::operator+()
return A2 ();
}
+class Member
+{
+public:
+ int z;
+};
+
+class Container
+{
+public:
+ Member m;
+
+ Member& operator* ();
+};
+
+Member& Container::operator* ()
+{
+ return this->m;
+}
int main (void)
{
A1 one(2,3);
A1 two(4,5);
A1 three(0,0);
+ Container c;
int val;
marker1(); // marker1-returns-here
@@ -379,6 +398,8 @@ int main (void)
++three;
cout << "preinc " << three;
+ (*c).z = 1;
+
return 0;
}
Index: testsuite/gdb.cp/userdef.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/userdef.exp,v
retrieving revision 1.4
diff -u -p -r1.4 userdef.exp
--- testsuite/gdb.cp/userdef.exp 27 Apr 2005 16:35:15 -0000 1.4
+++ testsuite/gdb.cp/userdef.exp 25 Jul 2006 04:01:52 -0000
@@ -1,5 +1,6 @@
# Tests of overloaded operators resolution.
-# Copyright 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+# Copyright 1998, 1999, 2002, 2004, 2005, 2006
+# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -143,5 +144,11 @@ gdb_test "print two = one" "\\\$\[0-9\]*
gdb_test "break A2::'operator+'" ".*Breakpoint $decimal at.*"
gdb_test "break A2::'operator +'" ".*Breakpoint $decimal at.*"
+# Check that GDB handles operator* correctly.
+gdb_test "print c" "\\\$\[0-9\]* = {m = {z = .*}}"
+gdb_test "print *c" "\\\$\[0-9\]* = \\(Member &\\) @$hex: {z = .*}"
+gdb_test "print &*c" "\\\$\[0-9\]* = \\(Member \\*\\) $hex"
+gdb_test "ptype &*c" "type = struct Member {\[\r\n \]+int z;\[\r\n\]+} &\\*"
+
gdb_exit
return 0