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]

Re: [patch] smart pointer support


On 08/09/2010 02:23 PM, Jan Kratochvil wrote:
On Mon, 09 Aug 2010 20:04:15 +0200, sami wagiaalla wrote:
+
+	      /* Check to see if the operator '->' has been overloaded.  If the operator
+	         has been overloaded replace arg2 with the value returned by the custom
+	         operator and continue evaluation.  */
+	      while (unop_user_defined_p (op, arg2))
+		{
+		  volatile struct gdb_exception except;
+		  struct value *value = NULL;
+		  TRY_CATCH (except, RETURN_MASK_ERROR)
+		    {
+		      value = value_x_unop (arg2, op, noside);
+		    }
+
+		  if (except.reason<  0)
+		    break;

What if some other error kind occurs? It would get hidden. Such as: error (_("This target does not support function calls."));

In the case you want to go with the TRY_CATCH case you should IMO specialize
the error message you want to catch to some:
     throw_error (THE_GREAT_NEW_KIND_OF_ERROR, that message);

To correctly check just that specific error kind in EXCEPT (and throw it again
otherwise).


I have created a new error type SYMBOL_NOT_FOUND_ERROR and updated the needed throw locations and the catch statements. Patch attached.
Support overloading of 'operator->'.

2010-08-16  Sami Wagiaalla  <swagiaal@redhat.com>

	 PR C++/11500:
	* valarith.c (value_x_unop): Handle STRUCTOP_PTR.
	* eval.c (evaluate_subexp_standard): Check for overload of
	'operator->'.
	* exceptions.h: New error SYMBOL_NOT_FOUND_ERROR.
	* valarith.c (value_x_binop): Throw SYMBOL_NOT_FOUND_ERROR.
	(value_x_unop): Ditto.
	* valops.c: Include "exceptions.h".
	(find_overload_match): Throw SYMBOL_NOT_FOUND_ERROR.
	(value_struct_elt): Ditto.

2010-08-16  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdb.cp/smartp.exp: New test.
	* gdb.cp/smartp.cc : New test.

diff --git a/gdb/eval.c b/gdb/eval.c
index ba75952..8b99dac 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1431,6 +1431,28 @@ evaluate_subexp_standard (struct type *expect_type,
 	  else
 	    {
 	      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+	      /* Check to see if the operator '->' has been overloaded.  If the operator
+	         has been overloaded replace arg2 with the value returned by the custom
+	         operator and continue evaluation.  */
+	      while (unop_user_defined_p (op, arg2))
+		{
+		  volatile struct gdb_exception except;
+		  struct value *value = NULL;
+		  TRY_CATCH (except, RETURN_MASK_ERROR)
+		    {
+		      value = value_x_unop (arg2, op, noside);
+		    }
+
+		  if (except.reason < 0)
+		    {
+		      if (except.error == SYMBOL_NOT_FOUND_ERROR)
+			break;
+		      else
+			throw_exception (except);
+		    }
+		  arg2 = value;
+		}
 	    }
 	  /* Now, say which argument to start evaluating from */
 	  tem = 2;
@@ -1819,6 +1841,27 @@ evaluate_subexp_standard (struct type *expect_type,
       if (noside == EVAL_SKIP)
 	goto nosideret;
 
+      /* Check to see if operator '->' has been overloaded.  If so replace
+         arg1 with the value returned by evaluating operator->().  */
+      while (unop_user_defined_p (op, arg1))
+	{
+	  volatile struct gdb_exception except;
+	  struct value *value = NULL;
+	  TRY_CATCH (except, RETURN_MASK_ERROR)
+	    {
+	      value = value_x_unop (arg1, op, noside);
+	    }
+
+	  if (except.reason < 0)
+	    {
+	      if (except.error == SYMBOL_NOT_FOUND_ERROR)
+		break;
+	      else
+		throw_exception (except);
+	    }
+	  arg1 = value;
+	}
+
       /* JYG: if print object is on we need to replace the base type
 	 with rtti type in order to continue on with successful
 	 lookup of member / method only available in the rtti type. */
diff --git a/gdb/exceptions.h b/gdb/exceptions.h
index 7d68a36..55263ed 100644
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -78,6 +78,9 @@ enum errors {
   /* Feature is not supported in this copy of GDB.  */
   UNSUPPORTED_ERROR,
 
+  /* The requested symbol was not found.  */
+  SYMBOL_NOT_FOUND_ERROR,
+
   /* Add more errors here.  */
   NR_ERRORS
 };
diff --git a/gdb/testsuite/gdb.cp/smartp.cc b/gdb/testsuite/gdb.cp/smartp.cc
new file mode 100644
index 0000000..baa8f46
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/smartp.cc
@@ -0,0 +1,163 @@
+/* This test script is part of GDB, the GNU debugger.
+
+   Copyright 1999, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   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
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   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 Type1{
+  public:
+  int foo(){
+    return 11;
+  }
+};
+
+class Type2{
+  public:
+  int foo(){
+    return 22;
+  }
+};
+
+class Type3{
+  public:
+  int foo(int){
+    return 33;
+  }
+  int foo(char){
+    return 44;
+  }
+};
+
+class Type4 {
+  public:
+    int a;
+    int b;
+};
+
+int foo (Type3, float)
+{
+  return 55;
+}
+
+class MyPointer{
+  Type1 *p;
+ public:
+  MyPointer(Type1 *pointer){
+    p = pointer;
+  }
+
+  Type1 *operator->(){
+    return p;
+  }
+};
+
+template <typename T> class SmartPointer{
+  T *p;
+ public:
+  SmartPointer(T *pointer){
+    p = pointer;
+  }
+
+  T *operator->(){
+    return p;
+  }
+};
+
+
+class A {
+ public:
+  int inta;
+  int foo() { return 66; }
+};
+
+class B {
+ public:
+  A a;
+  A* operator->(){
+    return &a;
+  }
+};
+
+class C {
+ public:
+  B b;
+  B& operator->(){
+    return b;
+  }
+};
+
+class C2 {
+ public:
+  B b;
+  B operator->(){
+    return b;
+  }
+};
+
+int main(){
+  Type1 mt1;
+  Type2 mt2;
+  Type3 mt3;
+
+  Type4 mt4;
+  mt4.a = 11;
+  mt4.b = 12;
+
+  MyPointer mp(&mt1);
+  Type1 *mtp = &mt1;
+
+  SmartPointer<Type1> sp1(&mt1);
+  SmartPointer<Type2> sp2(&mt2);
+  SmartPointer<Type3> sp3(&mt3);
+  SmartPointer<Type4> sp4(&mt4);
+
+  mp->foo();
+  mtp->foo();
+
+  sp1->foo();
+  sp2->foo();
+
+  sp3->foo(1);
+  sp3->foo('a');
+
+  sp4->a;
+  sp4->b;
+
+  Type4 *mt4p = &mt4;
+  mt4p->a;
+  mt4p->b;
+
+  A a;
+  B b;
+  C c;
+  C2 c2;
+
+  a.inta = 77;
+  b.a = a;
+  c.b = b;
+  c2.b = b;
+
+  a.foo();
+  b->foo();
+  c->foo();
+
+  b->inta = 77;
+  c->inta = 77;
+  c2->inta = 77;
+
+  return 0; // end of main
+}
+
diff --git a/gdb/testsuite/gdb.cp/smartp.exp b/gdb/testsuite/gdb.cp/smartp.exp
new file mode 100644
index 0000000..2cea473
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/smartp.exp
@@ -0,0 +1,77 @@
+# Copyright 2008 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+set testfile smartp
+set srcfile ${testfile}.cc
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug c++}] } {
+     return -1
+}
+
+############################################
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "end of main"]
+gdb_continue_to_breakpoint "end of main"
+
+# Test that overloaded arrow operator works
+gdb_test "p mp->foo()"            "= 11"
+
+# Test that regular arrow operator still works
+gdb_test "p mtp->foo()"            "= 11"
+
+# Test that normal '.' operator still works.
+gdb_test "p mt1.foo()"             "= 11"
+
+# test that gdb extension '.' for pointers still works.
+gdb_test "p mt4p.a"                "= 11"
+
+# test that gdb extension '->' for structs still works.
+gdb_test "p mt4->a"                "= 11"
+
+# Test that templated smart pointers work
+gdb_test "p sp1->foo()"            "= 11"
+gdb_test "p sp2->foo()"            "= 22"
+
+# Test that overload resolution works properly
+# with smart pointers
+gdb_test "p sp3->foo(1)"           "= 33"
+gdb_test "p sp3->foo('a')"         "= 44"
+
+# Test smart pointers work for member references
+gdb_test "p sp4->a"         "= 11"
+gdb_test "p sp4->b"         "= 12"
+
+# Test regular arrow operator still works for
+# member references
+gdb_test "p mt4p->a"         "= 11"
+gdb_test "p mt4p->b"         "= 12"
+
+# Test that incorrect use of the arrow operator
+# is still handled correctly.
+gdb_test "p mt4->fake"       "There is no member named fake."
+gdb_test "p mt4->fake()"     "Couldn't find method Type4::fake"
+
+# Test that overloading of -> works recursively
+gdb_test "p b->foo()"         "= 66"
+gdb_test "p c->foo()"         "= 66"
+gdb_test "p c->inta"          "= 77"
+
+setup_kfail "gdb/11606" "*-*-*"
+gdb_test "p c2->inta"          "= 77"
+
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 0c40905..f9ca51f 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -541,7 +541,8 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
 	}
       return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
     }
-  error (_("member function %s not found"), tstr);
+  throw_error (SYMBOL_NOT_FOUND_ERROR,
+               _("member function %s not found"), tstr);
 #ifdef lint
   return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
 #endif
@@ -616,6 +617,9 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
     case UNOP_IND:
       strcpy (ptr, "*");
       break;
+    case STRUCTOP_PTR:
+      strcpy (ptr, "->");
+      break;
     default:
       error (_("Invalid unary operation specified."));
     }
@@ -641,7 +645,9 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
 	}
       return call_function_by_hand (argvec[0], nargs, argvec + 1);
     }
-  error (_("member function %s not found"), tstr);
+  throw_error (SYMBOL_NOT_FOUND_ERROR,
+               _("member function %s not found"), tstr);
+
   return 0;			/* For lint -- never reached */
 }
 
diff --git a/gdb/valops.c b/gdb/valops.c
index f1eb041..2ac99cb 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -46,6 +46,7 @@
 #include "observer.h"
 #include "objfiles.h"
 #include "symtab.h"
+#include "exceptions.h"
 
 extern int overload_debug;
 /* Local functions.  */
@@ -2196,7 +2197,8 @@ value_struct_elt (struct value **argp, struct value **args,
     }
 
   if (!v)
-    error (_("Structure has no component named %s."), name);
+    throw_error (SYMBOL_NOT_FOUND_ERROR,
+                 _("Structure has no component named %s."), name);
   return v;
 }
 
@@ -2517,7 +2519,9 @@ find_overload_match (struct type **arg_types, int nargs,
 
   /* Did we find a match ?  */
   if (method_oload_champ == -1 && func_oload_champ == -1)
-    error (_("No symbol \"%s\" in current context."), name);
+    throw_error (SYMBOL_NOT_FOUND_ERROR,
+                 _("No symbol \"%s\" in current context."),
+                 name);
 
   /* If we have found both a method match and a function
      match, find out which one is better, and calculate match

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