From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31089 invoked by alias); 2 Jan 2012 02:22:33 -0000 Received: (qmail 31069 invoked by uid 22791); 2 Jan 2012 02:22:28 -0000 X-SWARE-Spam-Status: No, hits=-7.4 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_XG 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; Mon, 02 Jan 2012 02:22:07 +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.14.4/8.14.4) with ESMTP id q022M7Rp023169 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sun, 1 Jan 2012 21:22:07 -0500 Received: from host2.jankratochvil.net (ovpn-116-32.ams2.redhat.com [10.36.116.32]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q022LsYc002179 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO); Sun, 1 Jan 2012 21:21:56 -0500 Date: Mon, 02 Jan 2012 02:22:00 -0000 From: Jan Kratochvil To: xgsa Cc: Tom Tromey , gdb-patches@sourceware.org Subject: Re: set print object on should affect MI varobjs (PR mi/13393) Message-ID: <20120102022153.GA686@host2.jankratochvil.net> References: <4ED92C05.9080803@yandex.ru> <4EF22A4D.80703@yandex.ru> <20111221193630.GA28985@host2.jankratochvil.net> <4EF30389.5010008@yandex.ru> <20111223200951.GA19581@host2.jankratochvil.net> <4EF5D1C5.5010902@yandex.ru> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-2022-jp Content-Disposition: inline In-Reply-To: <4EF5D1C5.5010902@yandex.ru> User-Agent: Mutt/1.5.21 (2010-09-15) 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: 2012-01/txt/msg00010.txt.bz2 On Sat, 24 Dec 2011 14:21:09 +0100, xgsa wrote: > gdb/ChangeLog: The ChangeLog order did not fully match the patch order, it is difficult to follow it a bit. > 2011-12-02 Anton Gorenkov > > PR mi/13393 > > * gdb/valops.c (value_ind): Extract value type and enclosing type > setting to a separate function readjust_value_type. valops.c already has an entry above (below after reordering it); but that corresponds to the problem the entries are not in the patch order. All the files are already in gdb/ChangeLog so they should be written as valops.c, not gdb/valops.c. > * gdb/valops.c (value_rtti_target_type): Replaced with > value_rtti_indirect_type. > (value_rtti_indirect_type): New function. The same as > value_rtti_target_type, but return a reference or pointer type (because > every caller do it after call that leads to code duplication). http://www.gnu.org/prep/standards/standards.html#Change-Log-Concepts "There’s no need to describe the full purpose of the changes or how they work together." Therefore: (value_rtti_target_type): Rename to ... (value_rtti_indirect_type): ... here. is enough. That change to value_rtti_indirect_type would be easier to read if it was a separate patch. > * gdb/c-valprint.c (c_value_print): Use value_rtti_indirect_type > instead of value_rtti_target_type. > * gdb/eval.c (evaluate_subexp_standard): Use value_rtti_indirect_type > instead of value_rtti_target_type. > * gdb/typeprint.c: Use value_rtti_indirect_type instead of > value_rtti_target_type. > * gdb/value.c (value_actual_type): New function. > (value_rtti_indirect_type): New function. Here probably should have been readjust_value_type, not value_rtti_indirect_type. > (coerce_ref): Support for enclosing type setting for references > with readjust_value_type. > * gdb/value.h (value_actual_type): Add prototype. > (readjust_value_type): Add prototype. Missing: (value_rtti_target_type): Rename to ... (value_rtti_indirect_type): ... here. > * gdb/varobj.c (varobj_create): Call value_actual_type if necessary. > (create_child_with_value): Call value_actual_type. > (value_of_root): Support for type change if the value changed and RTTI > is used to determine type. > (adjust_value_for_child_access): Extended with a new parameter and cast > given value to enclosing type is necessary. > (c_number_of_children): Updated for extended Missing/adjust: (c_number_of_children, c_describe_child): Updated for extended > adjust_value_for_child_access. > (cplus_number_of_children): Send a value as parameter if RTTI should be > used to determine type. > (cplus_describe_child): Determine whether RTTI type should be used. > > gdb/testsuite/ChangeLog: > > 2011-12-02 Anton Gorenkov > > PR mi/13393 > > * gdb.mi/mi-var-rtti.cc: New file. > * gdb.mi/mi-var-rtti.exp: New file. The testcase names should be unique so that one can find one if some FAILs, they are not unique: 5 gdb.mi/mi-var-rtti.exp: -interpreter-exec console "set print object on" 5 gdb.mi/mi-var-rtti.exp: -interpreter-exec console "set print object off" 4 gdb.mi/mi-var-rtti.exp: list children of ptr.public (without RTTI) 4 gdb.mi/mi-var-rtti.exp: list children of ptr (without RTTI) 2 gdb.mi/mi-var-rtti.exp: update ptr 2 gdb.mi/mi-var-rtti.exp: list children of ptr.public (with RTTI) 2 gdb.mi/mi-var-rtti.exp: list children of ptr.Base.public (with RTTI) 2 gdb.mi/mi-var-rtti.exp: list children of ptr.Base (with RTTI) 2 gdb.mi/mi-var-rtti.exp: list children of ptr (with RTTI) 2 gdb.mi/mi-var-rtti.exp: delete varobj for ptr 2 gdb.mi/mi-var-rtti.exp: create varobj for ptr 2 gdb.mi/mi-var-rtti.exp: check ptr->C (with RTTI) 2 gdb.mi/mi-var-rtti.exp: check ptr->B (with RTTI) 2 gdb.mi/mi-var-rtti.exp: check ptr->A (without RTTI) 2 gdb.mi/mi-var-rtti.exp: check ptr->A (with RTTI) > > diff --git a/gdb/valops.c b/gdb/valops.c > index cb39677..b4ebe36 100644 > --- a/gdb/valops.c > +++ b/gdb/valops.c > @@ -1774,15 +1774,7 @@ value_ind (struct value *arg1) > (value_as_address (arg1) > - value_pointed_to_offset (arg1))); > > - /* Re-adjust type. */ > - deprecated_set_value_type (arg2, TYPE_TARGET_TYPE (base_type)); > - /* Add embedding info. */ > - set_value_enclosing_type (arg2, enc_type); > - set_value_embedded_offset (arg2, value_pointed_to_offset (arg1)); > - > - /* We may be pointing to an object of some derived type. */ > - arg2 = value_full_object (arg2, NULL, 0, 0, 0); > - return arg2; > + return readjust_value_type (arg2, enc_type, base_type, arg1); > } > > error (_("Attempt to take contents of a non-pointer value.")); > @@ -3528,23 +3520,48 @@ value_maybe_namespace_elt (const struct type *curtype, > return result; > } > > -/* Given a pointer value V, find the real (RTTI) type of the object it > - points to. > +/* Given a pointer or a reference value V, find its real (RTTI) type. > > Other parameters FULL, TOP, USING_ENC as with value_rtti_type() > and refer to the values computed for the object pointed to. */ > > struct type * > -value_rtti_target_type (struct value *v, int *full, > - int *top, int *using_enc) > +value_rtti_indirect_type (struct value *v, int *full, > + int *top, int *using_enc) > { > struct value *target; > + struct type *type, *real_type, *target_type; > + > + type = value_type (v); > + type = check_typedef (type); > + if (TYPE_CODE (type) == TYPE_CODE_REF) > + target = coerce_ref (v); > + else if (TYPE_CODE (type) == TYPE_CODE_PTR) > + target = value_ind (v); > + else > + return NULL; > > - target = value_ind (v); > + real_type = value_rtti_type (target, full, top, using_enc); > > - return value_rtti_type (target, full, top, using_enc); > + if (real_type) > + { > + /* Copy qualifiers to the referenced object. */ > + target_type = value_type (target); > + real_type = make_cv_type (TYPE_CONST (target_type), > + TYPE_VOLATILE (target_type), real_type, NULL); Use tabs, not spaces. http://www.gnu.org/prep/standards/standards.html#Formatting GNU indent options > + if (TYPE_CODE (type) == TYPE_CODE_REF) > + real_type = lookup_reference_type (real_type); > + else if (TYPE_CODE (type) == TYPE_CODE_PTR) > + real_type = lookup_pointer_type (real_type); Either remove "if (TYPE_CODE (type) == TYPE_CODE_PTR)" as it must be always true here anyway, either else /* TYPE_CODE (type) == TYPE_CODE_PTR */ real_type = lookup_pointer_type (real_type); or: else if (TYPE_CODE (type) == TYPE_CODE_PTR) real_type = lookup_pointer_type (real_type); else internal_error (...); Empty line before a comment. > + /* Copy qualifiers to the pointer/reference. */ > + real_type = make_cv_type (TYPE_CONST (type), TYPE_VOLATILE (type), > + real_type, NULL); > + } > + > + return real_type; > } > > + Excessive newline. > /* Given a value pointed to by ARGP, check its real run-time type, and > if that is different from the enclosing type, create a new value > using the real run-time type as the enclosing type (and of the same > diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c > index 3461b08..d81d07d 100644 > --- a/gdb/c-valprint.c > +++ b/gdb/c-valprint.c > @@ -698,22 +698,12 @@ c_value_print (struct value *val, struct ui_file *stream, > > if (value_entirely_available (val)) > { > - real_type = value_rtti_target_type (val, &full, &top, &using_enc); > + real_type = value_rtti_indirect_type (val, &full, &top, &using_enc); More than 80 characters. > if (real_type) > { > /* RTTI entry found. */ > - if (TYPE_CODE (type) == TYPE_CODE_PTR) > - { > - /* Create a pointer type pointing to the real > - type. */ > - type = lookup_pointer_type (real_type); > - } > - else > - { > - /* Create a reference type referencing the real > - type. */ > - type = lookup_reference_type (real_type); > - } > + type = real_type; > + > /* Need to adjust pointer value. */ > val = value_from_pointer (type, value_as_address (val) - top); > > diff --git a/gdb/eval.c b/gdb/eval.c > index 5d758d1..3d23d0f 100644 > --- a/gdb/eval.c > +++ b/gdb/eval.c > @@ -1990,16 +1990,9 @@ evaluate_subexp_standard (struct type *expect_type, > if (opts.objectprint && TYPE_TARGET_TYPE(type) > && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS)) > { > - real_type = value_rtti_target_type (arg1, &full, &top, &using_enc); > + real_type = value_rtti_indirect_type (arg1, &full, &top, &using_enc); More than 80 characters. > if (real_type) > - { > - if (TYPE_CODE (type) == TYPE_CODE_PTR) > - real_type = lookup_pointer_type (real_type); > - else > - real_type = lookup_reference_type (real_type); > - > arg1 = value_cast (real_type, arg1); > - } > } > } > > diff --git a/gdb/testsuite/gdb.mi/mi-var-rtti.cc b/gdb/testsuite/gdb.mi/mi-var-rtti.cc > new file mode 100644 > index 0000000..3622f3b > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/mi-var-rtti.cc > @@ -0,0 +1,184 @@ > +/* Copyright 2011 Free Software Foundation, Inc. Just a reminder to update the year for the final commit. > + > + 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 . > +*/ > + > +struct Base { > + Base() : A(1) {} > + virtual ~Base() {} // Enforce type to have vtable > + int A; > +}; > + > +struct Derived : public Base { It would be nice to test also multiple inheritance where non-zero EMBEDDED_OFFSET gets involved with value_enclosing_type, that is some struct Derived : public First, public Base { But your code probably works with it during some quick tests. > + Derived() : B(2), C(3) {} > + int B; > + int C; > +}; > + > + > +void use_rtti_for_ptr_test () > +{ > + /*: BEGIN: use_rtti_for_ptr :*/ > + Derived d; > + Base* ptr = &d; > + const Base* constPtr = &d; > + Base* const ptrConst = &d; > + Base const* const constPtrConst = &d; > + /*: > + mi_var_rtti__set_print_object off > + mi_var_rtti__check_derived_class_without_rtti ptr {Base \*} > + mi_var_rtti__check_derived_class_without_rtti constPtr {const Base \*} > + mi_var_rtti__check_derived_class_without_rtti ptrConst {Base \* const} > + mi_var_rtti__check_derived_class_without_rtti constPtrConst {const Base \* const} > + > + mi_var_rtti__set_print_object on > + mi_var_rtti__check_derived_class_with_rtti ptr {Derived \*} > + mi_var_rtti__check_derived_class_with_rtti constPtr {const Derived \*} > + mi_var_rtti__check_derived_class_with_rtti ptrConst {Derived \* const} > + mi_var_rtti__check_derived_class_with_rtti constPtrConst {const Derived \* const} > + :*/ > + return; > + /*: END: use_rtti_for_ptr :*/ > +} > + > + > +void use_rtti_for_ref_test () > +{ > + /*: BEGIN: use_rtti_for_ref :*/ > + Derived d; > + Base& ref = d; > + const Base& constRef = d; > + /*: > + mi_var_rtti__set_print_object off > + mi_var_rtti__check_derived_class_without_rtti ref {Base \&} > + mi_var_rtti__check_derived_class_without_rtti constRef {const Base \&} > + > + mi_var_rtti__set_print_object on > + mi_var_rtti__check_derived_class_with_rtti ref {Derived \&} > + mi_var_rtti__check_derived_class_with_rtti constRef {const Derived \&} > + :*/ > + return; > + /*: END: use_rtti_for_ref :*/ > +} > + > + > +void use_rtti_for_ptr_child_test () > +{ > + /*: BEGIN: use_rtti_for_ptr_child :*/ > + Derived d; > + struct S { > + Base* ptr; > + const Base* constPtr; > + Base* const ptrConst; > + Base const* const constPtrConst; > + S ( Base* v ) : > + ptr ( v ), > + constPtr ( v ), > + ptrConst ( v ), > + constPtrConst ( v ) {} > + } s ( &d ); > + /*: > + mi_var_rtti__set_print_object off > + mi_var_rtti__check_derived_class_without_rtti s.ptr {Base \*} > + mi_var_rtti__check_derived_class_without_rtti s.constPtr {const Base \*} > + mi_var_rtti__check_derived_class_without_rtti s.ptrConst {Base \* const} > + mi_var_rtti__check_derived_class_without_rtti s.constPtrConst {const Base \* const} > + > + mi_var_rtti__set_print_object on > + mi_var_rtti__check_derived_class_with_rtti s.ptr {Derived \*} > + mi_var_rtti__check_derived_class_with_rtti s.constPtr {const Derived \*} > + mi_var_rtti__check_derived_class_with_rtti s.ptrConst {Derived \* const} > + mi_var_rtti__check_derived_class_with_rtti s.constPtrConst {const Derived \* const} > + :*/ > + return; > + /*: END: use_rtti_for_ptr_child :*/ > +} > + > + > +void use_rtti_for_ref_child_test () > +{ > + /*: BEGIN: use_rtti_for_ref_child :*/ > + Derived d; > + struct S { > + Base& ref; > + const Base& constRef; > + S ( Base& v ) : > + ref ( v ), > + constRef ( v ) {} > + } s ( d ); > + /*: > + mi_var_rtti__set_print_object off > + mi_var_rtti__check_derived_class_without_rtti s.ref {Base \&} > + mi_var_rtti__check_derived_class_without_rtti s.constRef {const Base \&} > + > + mi_var_rtti__set_print_object on > + mi_var_rtti__check_derived_class_with_rtti s.ref {Derived \&} > + mi_var_rtti__check_derived_class_with_rtti s.constRef {const Derived \&} > + :*/ > + return; > + /*: END: use_rtti_for_ref_child :*/ > +} > + > +void type_update_when_use_rtti_test () > +{ > + /*: BEGIN: type_update_when_use_rtti :*/ > + Derived d; > + /*: > + mi_var_rtti__set_print_object on > + mi_create_varobj_checked VAR ptr {Base \*} "create varobj for ptr" > + mi_var_rtti__check_derived_children_without_rtti ptr > + :*/ > + > + Base* ptr = &d; > + /*: > + mi_varobj_update_with_type_change VAR {Derived \*} 2 "update ptr" > + mi_var_rtti__check_derived_children_with_rtti ptr > + mi_var_rtti__check_derived_content_with_rtti ptr > + mi_delete_varobj VAR "delete varobj for ptr" > + :*/ > + return; > + /*: END: type_update_when_use_rtti :*/ > +} > + > +void skip_type_update_when_not_use_rtti_test () > +{ > + /*: BEGIN: skip_type_update_when_not_use_rtti :*/ > + Derived d; > + /*: > + mi_var_rtti__set_print_object off > + mi_create_varobj_checked VAR ptr {Base \*} "create varobj for ptr" > + mi_var_rtti__check_derived_children_without_rtti ptr > + :*/ > + > + Base* ptr = &d; > + /*: > + mi_varobj_update VAR {} "update ptr" > + mi_var_rtti__check_derived_children_without_rtti ptr > + mi_var_rtti__check_derived_content_without_rtti ptr > + mi_delete_varobj VAR "delete varobj for ptr" > + :*/ > + return; > + /*: END: skip_type_update_when_not_use_rtti :*/ > +} > + > +int main () > +{ > + use_rtti_for_ptr_test(); > + use_rtti_for_ref_test(); > + use_rtti_for_ptr_child_test(); > + use_rtti_for_ref_child_test(); > + type_update_when_use_rtti_test(); > + skip_type_update_when_not_use_rtti_test(); > + return 0; > +} > diff --git a/gdb/testsuite/gdb.mi/mi-var-rtti.exp b/gdb/testsuite/gdb.mi/mi-var-rtti.exp > new file mode 100644 > index 0000000..177b63c > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/mi-var-rtti.exp > @@ -0,0 +1,108 @@ > +# Copyright 2011 Free Software Foundation, Inc. Just a reminder to update the year for the final commit. > + > +# 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 { [skip_cplus_tests] } { continue } > + > +load_lib mi-support.exp > +set MIFLAGS "-i=mi" > + > +gdb_exit > +if [mi_gdb_start] { > + continue > +} > + > +set testfile mi-var-rtti > +set srcfile "$testfile.cc" > +set binfile $objdir/$subdir/$testfile > + > +if [get_compiler_info ${binfile} "c++"] { > + return -1; > +} > + > +if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable {debug c++}] != ""} { > + untested $testfile.exp > + return -1 > +} build_executable is preferred nowadays. > + > +mi_gdb_load ${binfile} > + > +mi_prepare_inline_tests $srcfile > + > +# Enable using RTTI to determine real types of the objects > +proc mi_var_rtti__set_print_object {state} { > + mi_gdb_test "-interpreter-exec console \"set print object ${state}\"" \ > + {\^done} \ > + "-interpreter-exec console \"set print object ${state}\"" > +} > + > +proc mi_var_rtti__check_derived_children_without_rtti {var_name} { > + mi_list_varobj_children VAR { > + { VAR.public public 1 } > + } "list children of ${var_name} (without RTTI)" > + mi_list_varobj_children "VAR.public" { > + { VAR.public.A A 0 int } > + } "list children of ${var_name}.public (without RTTI)" > +} > + > +proc mi_var_rtti__check_derived_content_without_rtti {var_name} { > + mi_check_varobj_value VAR.public.A 1 "check ${var_name}->A (without RTTI)" > +} > + > +proc mi_var_rtti__check_derived_class_without_rtti {var_name var_type} { > + mi_create_varobj_checked VAR ${var_name} ${var_type} "create varobj for ${var_name} (without RTTI)" > + mi_var_rtti__check_derived_children_without_rtti ${var_name} > + mi_var_rtti__check_derived_content_without_rtti ${var_name} > + mi_delete_varobj VAR "delete varobj for ${var_name} (without RTTI)" > +} > + > +proc mi_var_rtti__check_derived_children_with_rtti {var_name} { > + mi_list_varobj_children VAR { > + { VAR.Base Base 1 Base } > + { VAR.public public 2 } > + } "list children of ${var_name} (with RTTI)" > + mi_list_varobj_children "VAR.Base" { > + { VAR.Base.public public 1 } > + } "list children of ${var_name}.Base (with RTTI)" > + mi_list_varobj_children "VAR.Base.public" { > + { VAR.Base.public.A A 0 int } > + } "list children of ${var_name}.Base.public (with RTTI)" > + mi_list_varobj_children "VAR.public" { > + { VAR.public.B B 0 int } > + { VAR.public.C C 0 int } > + } "list children of ${var_name}.public (with RTTI)" > +} > + > +proc mi_var_rtti__check_derived_content_with_rtti {var_name} { > + mi_check_varobj_value VAR.Base.public.A 1 "check ${var_name}->A (with RTTI)" > + mi_check_varobj_value VAR.public.B 2 "check ${var_name}->B (with RTTI)" > + mi_check_varobj_value VAR.public.C 3 "check ${var_name}->C (with RTTI)" > +} > + > +proc mi_var_rtti__check_derived_class_with_rtti {var_name var_type} { > + mi_create_varobj_checked VAR ${var_name} ${var_type} "create varobj for ${var_name} (with RTTI)" > + mi_var_rtti__check_derived_children_with_rtti ${var_name} > + mi_var_rtti__check_derived_content_with_rtti ${var_name} > + mi_delete_varobj VAR "delete varobj for ${var_name} (with RTTI)" > +} > + > +mi_run_inline_test use_rtti_for_ptr > +mi_run_inline_test use_rtti_for_ref > +mi_run_inline_test use_rtti_for_ptr_child > +mi_run_inline_test use_rtti_for_ref_child > +mi_run_inline_test type_update_when_use_rtti > +mi_run_inline_test skip_type_update_when_not_use_rtti > + > +mi_gdb_exit > +return 0 > diff --git a/gdb/typeprint.c b/gdb/typeprint.c > index cf4158d..6546c98 100644 > --- a/gdb/typeprint.c > +++ b/gdb/typeprint.c > @@ -140,16 +140,7 @@ whatis_exp (char *exp, int show) > if (((TYPE_CODE (type) == TYPE_CODE_PTR) > || (TYPE_CODE (type) == TYPE_CODE_REF)) > && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS)) > - { > - real_type = value_rtti_target_type (val, &full, &top, &using_enc); > - if (real_type) > - { > - if (TYPE_CODE (type) == TYPE_CODE_PTR) > - real_type = lookup_pointer_type (real_type); > - else > - real_type = lookup_reference_type (real_type); > - } > - } > + real_type = value_rtti_indirect_type (val, &full, &top, &using_enc); > else if (TYPE_CODE (type) == TYPE_CODE_CLASS) > real_type = value_rtti_type (val, &full, &top, &using_enc); > } > diff --git a/gdb/value.c b/gdb/value.c > index d263d0c..15726c0 100644 > --- a/gdb/value.c > +++ b/gdb/value.c > @@ -821,6 +821,35 @@ value_enclosing_type (struct value *value) > return value->enclosing_type; > } > > +/* Look at value.h for description. */ Empty line after function comment. > +struct type * > +value_actual_type (struct value *value, int resolve_simple_types) > +{ > + struct value_print_options opts; > + struct value *target; > + struct type *result; > + > + get_user_print_options (&opts); > + > + result = value_type (value); > + if (opts.objectprint) > + { This block should be indented by 2 more characters right. > + if (TYPE_CODE (result) == TYPE_CODE_PTR > + || TYPE_CODE (result) == TYPE_CODE_REF) Use tabs, not spaces. > + { This block should be indented by 2 more characters right. > + struct type *real_type; > + > + real_type = value_rtti_indirect_type (value, 0, 0, 0); real_type = value_rtti_indirect_type (value, NULL, NULL, NULL); (I am aware, it is compatible.) > + if (real_type) > + result = real_type; Use tabs, not spaces. > + } > + else if (resolve_simple_types) > + result = value_enclosing_type (value); > + } > + > + return result; > +} > + > static void > require_not_optimized_out (const struct value *value) > { > @@ -3110,10 +3139,26 @@ coerce_ref_if_computed (const struct value *arg) > } > Missing the comment: /* Look at value.h for description. */ > struct value * > +readjust_value_type (struct value *value, struct type *enc_type, > + struct type *original_type, struct value *original_value) > +{ > + /* Re-adjust type. */ > + deprecated_set_value_type (value, TYPE_TARGET_TYPE (original_type)); > + > + /* Add embedding info. */ > + set_value_enclosing_type (value, enc_type); > + set_value_embedded_offset (value, value_pointed_to_offset (original_value)); > + > + /* We may be pointing to an object of some derived type. */ > + return value_full_object (value, NULL, 0, 0, 0); > +} > + > +struct value * > coerce_ref (struct value *arg) > { > struct type *value_type_arg_tmp = check_typedef (value_type (arg)); > struct value *retval; > + struct type *enc_type; > > retval = coerce_ref_if_computed (arg); > if (retval) > @@ -3122,9 +3167,13 @@ coerce_ref (struct value *arg) > if (TYPE_CODE (value_type_arg_tmp) != TYPE_CODE_REF) > return arg; > > - return value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp), > - unpack_pointer (value_type (arg), > - value_contents (arg))); > + enc_type = check_typedef (value_enclosing_type (arg)); > + enc_type = TYPE_TARGET_TYPE (enc_type); > + > + retval = value_at_lazy (enc_type, > + unpack_pointer (value_type (arg), > + value_contents (arg))); > + return readjust_value_type (retval, enc_type, value_type_arg_tmp, arg); > } > > struct value * > diff --git a/gdb/value.h b/gdb/value.h > index d2c58ec..7345c71 100644 > --- a/gdb/value.h > +++ b/gdb/value.h > @@ -139,6 +139,16 @@ extern struct type *value_enclosing_type (struct value *); > extern void set_value_enclosing_type (struct value *val, > struct type *new_type); > > +/* Returns value_type or value_enclosing_type depending on > + value_print_options.objectprint. > + > + If RESOLVE_SIMPLE_TYPES is 0 the enclosing type will be resolved > + only for pointers and references, else it will be returned > + for all the types (e.g. structures). This option is useful > + to prevent retrieving enclosing type for the base classes fields. */ > + > +extern struct type *value_actual_type (struct value *value, int resolve_simple_types); More than 80 characters. > + > extern int value_pointed_to_offset (struct value *value); > extern void set_value_pointed_to_offset (struct value *value, int val); > extern int value_embedded_offset (struct value *value); > @@ -353,6 +363,13 @@ extern short *deprecated_value_regnum_hack (struct value *); > > extern struct value *coerce_ref_if_computed (const struct value *arg); > > +/* Setup a new value type and enclosing value type for dereferenced value. > + It is a common implementation for coerce_ref and value_ind. */ > + > +extern struct value * > +readjust_value_type (struct value *value, struct type *enc_type, > + struct type *original_type, struct value *original_value); Use tabs, not spaces. The function name should be more specific, such as readjust_indirect_value_type. Missing comment on the parameters. Comment that VALUE will will be modified by this function. > + > /* Convert a REF to the object referenced. */ > > extern struct value *coerce_ref (struct value *value); > @@ -617,8 +634,8 @@ extern struct value *value_primitive_field (struct value *arg1, int offset, > struct type *arg_type); > > > -extern struct type *value_rtti_target_type (struct value *, int *, int *, > - int *); > +extern struct type *value_rtti_indirect_type (struct value *, int *, int *, > + int *); > > extern struct value *value_full_object (struct value *, struct type *, int, > int, int); > diff --git a/gdb/varobj.c b/gdb/varobj.c > index 7c68a93..dfeb71b 100644 > --- a/gdb/varobj.c > +++ b/gdb/varobj.c > @@ -659,8 +659,18 @@ varobj_create (char *objname, > > var->type = value_type (type_only_value); > } > - else > - var->type = value_type (value); > + else > + { This block should be indented by 2 more characters right. > + struct type *enclosing_type; > + > + var->type = value_type (value); > + enclosing_type = value_actual_type (value, 0); > + if (check_typedef (enclosing_type) != check_typedef (var->type)) As noted by Tom, I would extend it that maybe value_actual_type should return whether it did any action as that check_typedef != check_typedef check is fragile in general, the same type has multiple instances. > + { > + var->type = enclosing_type; > + value = value_cast (enclosing_type, value); > + } > + } > > install_new_value (var, value, 1 /* Initial assignment */); > > @@ -2194,7 +2204,7 @@ create_child_with_value (struct varobj *parent, int index, const char *name, > if (value != NULL) > /* If the child had no evaluation errors, var->value > will be non-NULL and contain a valid type. */ > - child->type = value_type (value); > + child->type = value_actual_type (value, 0); > else > /* Otherwise, we must compute the type. */ > child->type = (*child->root->lang->type_of_child) (child->parent, > @@ -2480,6 +2490,7 @@ static struct value * > value_of_root (struct varobj **var_handle, int *type_changed) > { > struct varobj *var; > + struct value_print_options opts; > > if (var_handle == NULL) > return NULL; > @@ -2492,7 +2503,8 @@ value_of_root (struct varobj **var_handle, int *type_changed) > if (!is_root_p (var)) > return NULL; > > - if (var->root->floating) > + get_user_print_options (&opts); > + if (var->root->floating || opts.objectprint) > { > struct varobj *tmp_var; > char *old_type, *new_type; > @@ -2781,6 +2793,10 @@ varobj_floating_p (struct varobj *var) > to all types and dereferencing pointers to > structures. > > + If LOOKUP_ACTUAL_TYPE is set the enclosing type of the > + value will be fetched and if it differs from static type > + the value will be casted to it. > + > Both TYPE and *TYPE should be non-null. VALUE > can be null if we want to only translate type. > *VALUE can be null as well -- if the parent > @@ -2792,7 +2808,8 @@ varobj_floating_p (struct varobj *var) > static void > adjust_value_for_child_access (struct value **value, > struct type **type, > - int *was_ptr) > + int *was_ptr, > + int lookup_actual_type) > { > gdb_assert (type && *type); > > @@ -2832,6 +2849,19 @@ adjust_value_for_child_access (struct value **value, > /* The 'get_target_type' function calls check_typedef on > result, so we can immediately check type code. No > need to call check_typedef here. */ > + > + /* Access a real type of the value (if necessary and possible). */ > + if (value && *value && lookup_actual_type) > + { > + struct type *enclosing_type; > + > + enclosing_type = value_actual_type (*value, 1); > + if (check_typedef (enclosing_type) != check_typedef (*type)) The same check_typedef != check_typedef and value_actual_type comment like above. > + { > + *type = enclosing_type; > + *value = value_cast (enclosing_type, *value); > + } > + } > } > > /* C */ > @@ -2842,7 +2872,7 @@ c_number_of_children (struct varobj *var) > int children = 0; > struct type *target; > > - adjust_value_for_child_access (NULL, &type, NULL); > + adjust_value_for_child_access (NULL, &type, NULL, 0); > target = get_target_type (type); > > switch (TYPE_CODE (type)) > @@ -2957,7 +2987,7 @@ c_describe_child (struct varobj *parent, int index, > *cfull_expression = NULL; > parent_expression = varobj_get_path_expr (parent); > } > - adjust_value_for_child_access (&value, &type, &was_ptr); > + adjust_value_for_child_access (&value, &type, &was_ptr, 0); > > switch (TYPE_CODE (type)) > { > @@ -3223,16 +3253,28 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format) > static int > cplus_number_of_children (struct varobj *var) > { > + struct value *value = 0; Please use: struct value *value = NULL; > struct type *type; > int children, dont_know; > + int lookup_actual_type = 0; > + struct value_print_options opts; > > dont_know = 1; > children = 0; > > + get_user_print_options (&opts); > + > if (!CPLUS_FAKE_CHILD (var)) > { > type = get_value_type (var); > - adjust_value_for_child_access (NULL, &type, NULL); Empty line before comment. > + /* It is necessary to access a real type (via RTTI). */ > + if (opts.objectprint) > + { > + value = var->value; > + lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF > + || TYPE_CODE (var->type) == TYPE_CODE_PTR); Use tabs, not spaces. > + } > + adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type); > > if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || > ((TYPE_CODE (type)) == TYPE_CODE_UNION)) > @@ -3259,7 +3301,15 @@ cplus_number_of_children (struct varobj *var) > int kids[3]; > > type = get_value_type (var->parent); > - adjust_value_for_child_access (NULL, &type, NULL); > + > + /* It is necessary to access a real type (via RTTI). */ > + if (opts.objectprint) > + { > + value = var->parent->value; > + lookup_actual_type = (TYPE_CODE (var->parent->type) == TYPE_CODE_REF > + || TYPE_CODE (var->parent->type) == TYPE_CODE_PTR); More than 80 characters. > + } > + adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type); > > cplus_class_num_children (type, kids); > if (strcmp (var->name, "public") == 0) > @@ -3341,7 +3391,10 @@ cplus_describe_child (struct varobj *parent, int index, > struct value *value; > struct type *type; > int was_ptr; > + int lookup_actual_type = 0; > char *parent_expression = NULL; > + struct varobj *var; > + struct value_print_options opts; > > if (cname) > *cname = NULL; > @@ -3352,22 +3405,18 @@ cplus_describe_child (struct varobj *parent, int index, > if (cfull_expression) > *cfull_expression = NULL; > > - if (CPLUS_FAKE_CHILD (parent)) > - { > - value = parent->parent->value; > - type = get_value_type (parent->parent); > - if (cfull_expression) > - parent_expression = varobj_get_path_expr (parent->parent); > - } > - else > - { > - value = parent->value; > - type = get_value_type (parent); > - if (cfull_expression) > - parent_expression = varobj_get_path_expr (parent); > - } > + get_user_print_options (&opts); > + > + var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent; > + if (opts.objectprint) > + lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF > + || TYPE_CODE (var->type) == TYPE_CODE_PTR); > + value = var->value; > + type = get_value_type (var); > + if (cfull_expression) > + parent_expression = varobj_get_path_expr (var); > > - adjust_value_for_child_access (&value, &type, &was_ptr); > + adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type); > > if (TYPE_CODE (type) == TYPE_CODE_STRUCT > || TYPE_CODE (type) == TYPE_CODE_UNION) Thanks, Jan