This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]