From: sami wagiaalla <swagiaal@redhat.com>
To: gdb-patches@sourceware.org
Subject: Re: [patch] smart pointer support
Date: Mon, 09 Aug 2010 15:59:00 -0000 [thread overview]
Message-ID: <4C6025EF.5080509@redhat.com> (raw)
In-Reply-To: <m3hbj7qt7w.fsf@fleche.redhat.com>
[-- Attachment #1: Type: text/plain, Size: 502 bytes --]
> Sami> + struct value *value = value_x_unop (arg2, op, noside);
> Sami> + if (value)
> Sami> + arg2 = value;
>
> This seems strange. When can the result here be NULL? And what does
> that mean? It seems like this either ought to be impossible, or it
> should be an error of some kind.
>
Yes this is incorrect. value_x_unop never returns null. If the operator
is not found it throws an error. I added a try catch statement and tests
for the failing case.
New patch attached.
[-- Attachment #2: smart_pointer.patch --]
[-- Type: text/plain, Size: 7691 bytes --]
Support overloading of 'operator->'.
2010-08-09 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->'.
2010-08-09 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..9786c1e 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1431,6 +1431,24 @@ 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)
+ break;
+
+ arg2 = value;
+ }
}
/* Now, say which argument to start evaluating from */
tem = 2;
@@ -1819,6 +1837,23 @@ 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)
+ break;
+
+ 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/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..01c8a11
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/smartp.exp
@@ -0,0 +1,74 @@
+# 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 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..91f9c0c 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -616,6 +616,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."));
}
next prev parent reply other threads:[~2010-08-09 15:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-20 15:58 sami wagiaalla
2010-07-23 23:37 ` Tom Tromey
2010-08-05 18:46 ` sami wagiaalla
2010-08-05 22:57 ` Ulrich Weigand
2010-08-06 16:23 ` sami wagiaalla
2010-08-06 16:48 ` Ulrich Weigand
2010-08-06 17:29 ` Tom Tromey
2010-08-08 15:01 ` Ulrich Weigand
2010-08-06 21:33 ` sami wagiaalla
2010-08-06 22:20 ` Tom Tromey
2010-08-09 15:59 ` sami wagiaalla [this message]
2010-08-09 17:35 ` Tom Tromey
2010-08-09 18:04 ` sami wagiaalla
2010-08-09 18:23 ` Jan Kratochvil
2010-08-16 20:31 ` sami wagiaalla
2010-08-16 20:59 ` Pedro Alves
2010-08-17 16:16 ` sami wagiaalla
2010-08-17 17:15 ` Tom Tromey
2010-10-19 20:55 ` sami wagiaalla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C6025EF.5080509@redhat.com \
--to=swagiaal@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).