From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3795 invoked by alias); 20 Jul 2010 15:58:13 -0000 Received: (qmail 3782 invoked by uid 22791); 20 Jul 2010 15:58:11 -0000 X-SWARE-Spam-Status: No, hits=-6.0 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_CP,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 20 Jul 2010 15:58:04 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6KFw3cp010063 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 20 Jul 2010 11:58:03 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6KFw2re020269 for ; Tue, 20 Jul 2010 11:58:02 -0400 Received: from [10.15.16.129] (dhcp-10-15-16-129.yyz.redhat.com [10.15.16.129]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id o6KFw2bS010037 for ; Tue, 20 Jul 2010 11:58:02 -0400 Message-ID: <4C45C78A.9080904@redhat.com> Date: Tue, 20 Jul 2010 15:58:00 -0000 From: sami wagiaalla User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100621 Fedora/3.0.5-1.fc13 Thunderbird/3.0.5 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [patch] smart pointer support Content-Type: multipart/mixed; boundary="------------020504050002030201000906" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-07/txt/msg00304.txt.bz2 This is a multi-part message in MIME format. --------------020504050002030201000906 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 735 The '->' operator can be overloaded in C++ and when overloaded it forwards the function call or member reference to the return type. Example: template < typename Type> class SmartPointer{ Type* p; public: SmartPointer(Type *pointer){ p = pointer; } Type* operator->(){ return p; } }; class MyType{ public: void foo(){ printf("I am foo\n"); } }; int main(){ MyType mt; SmartPointer sp(&mt); sp->foo(); return 0; } Here sp->foo() really means (sp->)->foo() This patch adds support for that in gdb This patch adds a test to the test suite to test for the functionality above and was regression tested by running the test suite on Fedora 13 on x8664 with gcc 444 --------------020504050002030201000906 Content-Type: text/plain; name="smart_pointer.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="smart_pointer.patch" Content-length: 6019 Support overloading of 'operator->'. 2010-07-20 Sami Wagiaalla PR C++/11500: * valarith.c (value_x_unop): Handle STRUCTOP_PTR. * eval.c (evaluate_subexp_standard): Check for overload of 'operator->'. 2010-07-20 Sami Wagiaalla * gdb.cp/smartp.exp: New test. * gdb.cp/smartp.cc : New test. diff --git a/gdb/eval.c b/gdb/eval.c index ea3d8a0..5f4ab2f 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -1431,6 +1431,20 @@ evaluate_subexp_standard (struct type *expect_type, else { arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside); + + /* For C++ 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. */ + if (exp->language_defn->la_language == language_cplus) + { + struct type *arg_type = value_type (arg2); + if (arg_type && TYPE_CODE (arg_type) == TYPE_CODE_STRUCT) + { + struct value *value = value_x_unop (arg2, op, noside); + if (value) + arg2 = value; + } + } } /* Now, say which argument to start evaluating from */ tem = 2; @@ -1818,6 +1832,20 @@ evaluate_subexp_standard (struct type *expect_type, if (noside == EVAL_SKIP) goto nosideret; + /* For C++ check to see if operator '->' has been overloaded. + If so replace arg1 with the value returned by evaluating + operator->(). */ + if (exp->language_defn->la_language == language_cplus) + { + struct type *arg_type = value_type (arg1); + + if (arg_type && TYPE_CODE (arg_type) == TYPE_CODE_STRUCT) + { + struct value *value = value_x_unop (arg1, op, noside); + if (value) + 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..a42db6f --- /dev/null +++ b/gdb/testsuite/gdb.cp/smartp.cc @@ -0,0 +1,95 @@ +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 class SmartPointer{ + T* p; + public: + SmartPointer(T *pointer){ + p = pointer; + } + + T *operator->(){ + return p; + } +}; + +int main(){ + Type1 mt1; + Type2 mt2; + Type3 mt3; + + Type4 mt4; + mt4.a = 11; + mt4.b = 12; + + MyPointer mp(&mt1); + Type1 *mtp = &mt1; + + SmartPointer sp1(&mt1); + SmartPointer sp2(&mt2); + SmartPointer sp3(&mt3); + SmartPointer 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; + + 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..335ecf8 --- /dev/null +++ b/gdb/testsuite/gdb.cp/smartp.exp @@ -0,0 +1,68 @@ +# 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 . + +if $tracelevel then { + strace $tracelevel +} + +set testfile smartp +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +############################################ + +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 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" + 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.")); } --------------020504050002030201000906--