This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
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