From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 42831 invoked by alias); 7 Sep 2018 00:41:47 -0000 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 Received: (qmail 42820 invoked by uid 89); 7 Sep 2018 00:41:46 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 spammy=pan, Pan, UD:oracle.com, value_type X-HELO: userp2120.oracle.com Received: from userp2120.oracle.com (HELO userp2120.oracle.com) (156.151.31.85) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 07 Sep 2018 00:41:44 +0000 Received: from pps.filterd (userp2120.oracle.com [127.0.0.1]) by userp2120.oracle.com (8.16.0.22/8.16.0.22) with SMTP id w870Xep6005264 for ; Fri, 7 Sep 2018 00:41:42 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : to : references : from : message-id : date : mime-version : in-reply-to : content-type : content-transfer-encoding; s=corp-2018-07-02; bh=OpX6tnkNj2JU1J/uSNEdoaZdjY0Nx8kHmxlJ4vPx50s=; b=DAWAs0E9Vp/MsEJgXDRzPL0wN4ZcgyX+AAyQmxjVtPFsHAFYu8/wdA2EkiXntOkuk3j1 RNKHHoTcqpY/f2kceiQygwM9ZSGKxR0PXniruhUawsoWGCMqhGWI4KdSty3qsRAFXYPG uQebvBgFt8tdTyb/9xq5d0VecjYszhAXRqlZEHDuvkVL+GFGRzg9ecPUXXMQKm0UJMrT EPu4BAyb8W3wimoOuWemERT1mMrL3T8IJufFRuZepAtiwK4L2FRP44/ovTmEdwR+jlPN zYqexSRqwF3RL0g8gwS3sV2MdVH3rFa8/sMQx6gqYBwpHF4PmwCIN/aMIs/gF+AquIWd ZQ== Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp2120.oracle.com with ESMTP id 2m7kdqy3c3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 07 Sep 2018 00:41:42 +0000 Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.14.4) with ESMTP id w870fgks012459 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 7 Sep 2018 00:41:42 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0121.oracle.com (8.14.4/8.13.8) with ESMTP id w870ffoH001797 for ; Fri, 7 Sep 2018 00:41:42 GMT Received: from [10.159.231.120] (/10.159.231.120) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 07 Sep 2018 00:41:41 +0000 Subject: [PING][PATCH v2 PR gdb/16841] virtual inheritance via typedef cannot find base To: "gdb-patches@sourceware.org" References: <1535058295-60173-1-git-send-email-weimin.pan@oracle.com> From: Wei-min Pan Message-ID: <7913d478-9093-7401-3b21-f9a31011ca53@oracle.com> Date: Fri, 07 Sep 2018 00:41:00 -0000 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <1535058295-60173-1-git-send-email-weimin.pan@oracle.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2018-09/txt/msg00114.txt.bz2 On 8/23/2018 2:04 PM, Weimin Pan wrote: > Finding data member in virtual base class > > This patch fixes the original problem - printing member in a virtual base, > using various expressions, do not yield the same value. A simple test case > below demonstrates the problem: > > % cat t.cc > struct base { int i; }; > typedef base tbase; > struct derived: virtual tbase { void func() { } }; > int main() { derived().func(); } > % g++ -g t.cc > % gdb a.out > (gdb) break derived::func > (gdb) run > (gdb) p i > $1 = 0 > (gdb) p base::i > $2 = 0 > (gdb) p derived::base::i > $3 = 0 > (gdb) p derived::i > $4 = 4196392 > > To fix the problem, we need to use "vptr" in the virtual class object, > which indexes to its derived class's vtable, to fetch the virtual base > offset. The offset is then added to the virtual class object to access > its member in value_struct_elt_for_reference(). > > The new function add_virtual_base_offset searches recursively for the > base class along the class hierarchy and returns the virtual base offset > for the virtual class. > > Tested on amd64-linux-gnu. No regressions. > --- > gdb/ChangeLog | 7 +++++ > gdb/testsuite/ChangeLog | 6 ++++ > gdb/testsuite/gdb.cp/virtbase2.cc | 21 +++++++++++++++ > gdb/testsuite/gdb.cp/virtbase2.exp | 50 ++++++++++++++++++++++++++++++++++++ > gdb/valops.c | 38 +++++++++++++++++++++++++++ > 5 files changed, 122 insertions(+), 0 deletions(-) > create mode 100644 gdb/testsuite/gdb.cp/virtbase2.cc > create mode 100644 gdb/testsuite/gdb.cp/virtbase2.exp > > diff --git a/gdb/ChangeLog b/gdb/ChangeLog > index c47c111..9d86f1c 100644 > --- a/gdb/ChangeLog > +++ b/gdb/ChangeLog > @@ -1,3 +1,10 @@ > +2018-08-23 Weimin Pan > + > + PR gdb/16841 > + * valops.c (add_virtual_base_offset): New function. > + (value_struct_elt_for_reference): Use it to get virtual base offset > + and add it in calculating class member address. > + > 2018-06-29 Pedro Alves > > * gdb/amd64-tdep.h (amd64_create_target_description): Add > diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog > index 93c849c..7be2e1d 100644 > --- a/gdb/testsuite/ChangeLog > +++ b/gdb/testsuite/ChangeLog > @@ -1,3 +1,9 @@ > +2018-08-23 Weimin Pan > + > + PR gdb/16841 > + * gdb.cp/virtbase2.cc: New file. > + * gdb.cp/virtbase2.exp: New file. > + > 2018-06-29 Pedro Alves > > * gdb.threads/names.exp: Adjust expected "info threads" output. > diff --git a/gdb/testsuite/gdb.cp/virtbase2.cc b/gdb/testsuite/gdb.cp/virtbase2.cc > new file mode 100644 > index 0000000..4f7631e > --- /dev/null > +++ b/gdb/testsuite/gdb.cp/virtbase2.cc > @@ -0,0 +1,21 @@ > +struct base { > + int i; double d; > + base() : i(55), d(6.6) {} > +}; > +typedef base tbase; > +struct derived: virtual tbase > +{ > + void func_d() { } > +}; > + > +struct foo: virtual derived > +{ > + void func_f() { } > +}; > + > +int main() > +{ > + derived().func_d(); > + foo().func_f(); > +} > + > diff --git a/gdb/testsuite/gdb.cp/virtbase2.exp b/gdb/testsuite/gdb.cp/virtbase2.exp > new file mode 100644 > index 0000000..c29ff1c > --- /dev/null > +++ b/gdb/testsuite/gdb.cp/virtbase2.exp > @@ -0,0 +1,50 @@ > +# Copyright 2018 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 . > + > +# Make sure printing virtual base class data member correctly (PR16841) > + > +if { [skip_cplus_tests] } { continue } > + > +standard_testfile .cc > + > +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} { > + return -1 > +} > + > +if {![runto_main]} then { > + perror "couldn't run to main" > + continue > +} > + > +gdb_breakpoint "derived::func_d" > +gdb_continue_to_breakpoint "continue to derived::func_d" > +gdb_test "print i" " = 55" "i in base class" > +gdb_test "print derived::i" " = 55" "i in base class" > +gdb_test "print derived::base::i" " = 55" "i in base class" > +gdb_test "print base::i" " = 55" "i in base class" > +gdb_test "print d" " = 6.5999999999999996" "d in base class" > +gdb_test "print derived::d" " = 6.5999999999999996" "d in base class" > +gdb_test "print derived::base::d" " = 6.5999999999999996" "d in base class" > +gdb_test "print base::d" " = 6.5999999999999996" "d in base class" > +gdb_breakpoint "foo::func_f" > +gdb_continue_to_breakpoint "continue to foo::func_f" > +gdb_test "print i" " = 55" "i in base class" > +gdb_test "print derived::i" " = 55" "i in base class" > +gdb_test "print derived::base::i" " = 55" "i in base class" > +gdb_test "print base::i" " = 55" "i in base class" > +gdb_test "print d" " = 6.5999999999999996" "d in base class" > +gdb_test "print derived::d" " = 6.5999999999999996" "d in base class" > +gdb_test "print derived::base::d" " = 6.5999999999999996" "d in base class" > +gdb_test "print base::d" " = 6.5999999999999996" "d in base class" > diff --git a/gdb/valops.c b/gdb/valops.c > index 9bdbf22..754e7d0 100644 > --- a/gdb/valops.c > +++ b/gdb/valops.c > @@ -3329,6 +3329,35 @@ compare_parameters (struct type *t1, struct type *t2, int skip_artificial) > return 0; > } > > +/* C++: Given an aggregate type VT, and a class type CLS, > + search recursively for CLS and return its offset, > + relative to VT, if it is a virtual base member. */ > + > +static int > +add_virtual_base_offset (struct type *vt, struct type *cls, > + struct value *v, int &boffs) > +{ > + for (int i = 0; i < TYPE_N_BASECLASSES (vt); i++) > + { > + struct type *ftype = TYPE_FIELD_TYPE (vt, i); > + if (check_typedef (ftype) == cls) > + { > + if (BASETYPE_VIA_VIRTUAL (vt, i)) > + { > + const gdb_byte *adr = value_contents_for_printing (v); > + boffs = baseclass_offset (vt, i, adr, value_offset (v), > + value_as_long (v), v); > + } > + return true; > + } > + > + if (add_virtual_base_offset (ftype, cls, v, boffs)) > + return true; > + } > + > + return false; > +} > + > /* C++: Given an aggregate type CURTYPE, and a member name NAME, > return the address of this member as a "pointer to member" type. > If INTYPE is non-null, then it will be the type of the member we > @@ -3393,6 +3422,15 @@ value_struct_elt_for_reference (struct type *domain, int offset, > tmp = lookup_pointer_type (TYPE_SELF_TYPE (type)); > v = value_cast_pointers (tmp, v, 1); > mem_offset = value_as_long (ptr); > + if (domain != curtype) > + { > + struct value *v2 = value_of_this_silent (current_language); > + struct type *vtype = check_typedef (value_type (v2)); > + struct type *vt = check_typedef (TYPE_TARGET_TYPE (vtype)); > + int base_offs = 0; > + if (add_virtual_base_offset (vt, curtype, v, base_offs)) > + mem_offset += base_offs; > + } > tmp = lookup_pointer_type (TYPE_TARGET_TYPE (type)); > result = value_from_pointer (tmp, > value_as_long (v) + mem_offset);