From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19333 invoked by alias); 19 Dec 2011 20:02:23 -0000 Received: (qmail 19321 invoked by uid 22791); 19 Dec 2011 20:02:19 -0000 X-SWARE-Spam-Status: No, hits=0.4 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_SORBS_WEB X-Spam-Check-By: sourceware.org Received: from forward6.mail.yandex.net (HELO forward6.mail.yandex.net) (77.88.60.125) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 19 Dec 2011 20:01:37 +0000 Received: from smtp6.mail.yandex.net (smtp6.mail.yandex.net [77.88.61.56]) by forward6.mail.yandex.net (Yandex) with ESMTP id 06B51F8023B for ; Tue, 20 Dec 2011 00:01:34 +0400 (MSK) Received: from smtp6.mail.yandex.net (localhost [127.0.0.1]) by smtp6.mail.yandex.net (Yandex) with ESMTP id D91FE16404F6 for ; Tue, 20 Dec 2011 00:01:34 +0400 (MSK) Received: from kts.bestnet.kharkov.ua (kts.bestnet.kharkov.ua [80.92.226.138]) by smtp6.mail.yandex.net (nwsmtp/Yandex) with ESMTP id 1X6C24cl-1Y6aO9wt; Tue, 20 Dec 2011 00:01:34 +0400 X-Yandex-Spam: 1 Message-ID: <4EEF985B.6080208@yandex.ru> Date: Mon, 19 Dec 2011 20:34:00 -0000 From: xgsa User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.23) Gecko/20110921 Thunderbird/3.1.15 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: Re: set print object on should affect MI varobjs (PR 13393) References: <4ED92C05.9080803@yandex.ru> <4EE06E81.8000606@yandex.ru> In-Reply-To: <4EE06E81.8000606@yandex.ru> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit 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: 2011-12/txt/msg00650.txt.bz2 Just a reminder: please, review this patch. Thanks, Anton -------- Original message -------- > Hi, > > I have sent my patch some time ago, but have not receive any response. > Can somebody review and comment it? Are there any chances to get it in > gdb 7.4? > > Thanks, > Anton > > -------- Original message -------- >> Hi, >> >> (it seems that my previous message about this patch was lost somehow, >> so I resend it again; sorry, if I sent it twice) >> >> The CLI "print" command shows user runtime type of C++ variable based >> on RTTI if "set print object" is "on". So gdb can show "real" type >> name for the objects that are stored by the interfaces and show their >> internals. Unfortunately, this information is not available via MI, >> so a lot of GUI tools that use it (e.g. Eclipse CDT) cann't access it. >> >> Here is an example that demonstrates the case described above: >> >> struct Base { >> Base() : a(1) {} >> virtual ~Base() {} // Enforce type to have RTTI >> int a; >> }; >> >> struct Derived : public Base { >> Derived() : b(2) {} >> int b; >> }; >> >> int main() { >> Derived b; >> Base* aPtr = &b; // aPtr should has Derived* type >> return 0; >> } >> >> This patch fixes this issue and also a few problems in gdb that are >> directly connected to the described above: >> - currently gdb loses cv-qualifiers after RTTI type access (e.g. if >> aPtr in the example above will be declared as "const Base*" then >> "print aPtr" in CLI with "set print object on" will return "Derived*" >> instead of "const Derived*". >> - "whatis" CLI command does not work for C++ references. >> >> See also more details here: >> http://sourceware.org/bugzilla/show_bug.cgi?id=13393 >> >> A few tests on this feature are also added to gdb.mi test suite. >> There is no regressions on gdb.mi & gdb.cp test suites (on >> x86-ubuntu-linux platform). >> >> >> Thanks, >> Anton >> >> >> gdb/ChangeLog: >> >> 2011-12-02 Anton Gorenkov >> >> PR 13393 >> * gdb/valops.c (value_rtti_target_type): add support for references. >> Return also a reference or pointer type (because every caller do >> it after call that leads to code duplication) >> * gdb/c-valprint.c (c_value_print): updated for >> value_rtti_target_type() change. >> * gdb/eval.c (evaluate_subexp_standard): updated for >> value_rtti_target_type() change. >> * gdb/typeprint.c: updated for value_rtti_target_type() change. >> * gdb/gdbtypes.c: make make_qualified_type() available for >> value_rtti_target_type() from gdb/valops.c. >> * gdb/gdbtypes.h: declaraion of make_qualified_type() was added. >> * gdb/value.c(actual_type): new function. >> (coerce_ref): support for enclosing type setting for references >> (as it is done for pointers in value_ind()) >> * gdb/value.h(actual_type): add prototype. >> * gdb/varobj.c(varobj_create): call actual_type() if necessary >> (create_child_with_value): call 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): update 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 13393 >> * gdb.mi/mi-var-rtti.cc:: New file. >> * gdb.mi/mi-var-rtti.exp:: New file. >> >> >> diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c >> index 3461b08..bfb3227 100644 >> --- a/gdb/c-valprint.c >> +++ b/gdb/c-valprint.c >> @@ -702,18 +702,8 @@ c_value_print (struct value *val, struct ui_file >> *stream, >> 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..7e6a6c5 100644 >> --- a/gdb/eval.c >> +++ b/gdb/eval.c >> @@ -1992,14 +1992,7 @@ evaluate_subexp_standard (struct type >> *expect_type, >> { >> real_type = value_rtti_target_type (arg1, &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); >> - >> arg1 = value_cast (real_type, arg1); >> - } >> } >> } >> >> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c >> index 614b813..52105e8 100644 >> --- a/gdb/gdbtypes.c >> +++ b/gdb/gdbtypes.c >> @@ -508,7 +508,7 @@ address_space_int_to_name (struct gdbarch >> *gdbarch, int space_flag) >> If STORAGE is non-NULL, create the new type instance there. >> STORAGE must be in the same obstack as TYPE. */ >> >> -static struct type * >> +struct type * >> make_qualified_type (struct type *type, int new_flags, >> struct type *storage) >> { >> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h >> index 69f6b46..1192a4b 100644 >> --- a/gdb/gdbtypes.h >> +++ b/gdb/gdbtypes.h >> @@ -1440,6 +1440,9 @@ extern int address_space_name_to_int (struct >> gdbarch *, char *); >> >> extern const char *address_space_int_to_name (struct gdbarch *, int); >> >> +extern struct type * make_qualified_type (struct type *type, int >> new_flags, >> + struct type *storage); >> + >> extern struct type *make_type_with_address_space (struct type *type, >> int space_identifier); >> >> 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. >> + >> + 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 { >> + 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..2999e87 >> --- /dev/null >> +++ b/gdb/testsuite/gdb.mi/mi-var-rtti.exp >> @@ -0,0 +1,108 @@ >> +# Copyright 2006, 2007, 2008, 2009, 2010, 2011 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 { [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 >> +} >> + >> +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..8170e14 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_target_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/valops.c b/gdb/valops.c >> index cb39677..8f38cba 100644 >> --- a/gdb/valops.c >> +++ b/gdb/valops.c >> @@ -3528,8 +3528,7 @@ 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. */ >> @@ -3539,12 +3538,35 @@ value_rtti_target_type (struct value *v, int >> *full, >> int *top, int *using_enc) >> { >> struct value *target; >> + struct type *type, *real_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 0; >> + >> + real_type = value_rtti_type (target, full, top, using_enc); >> >> - target = value_ind (v); >> + if (real_type) >> + { >> + // Copy qualifiers to the referenced object >> + real_type = make_qualified_type (real_type, >> TYPE_INSTANCE_FLAGS (value_type(target)), NULL); >> + 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); >> + // Copy qualifiers to the pointer/reference >> + real_type = make_qualified_type (real_type, >> TYPE_INSTANCE_FLAGS (type), NULL); >> + } >> >> - return value_rtti_type (target, full, top, using_enc); >> + return real_type; >> } >> >> + >> /* 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/value.c b/gdb/value.c >> index d263d0c..a61df8e 100644 >> --- a/gdb/value.c >> +++ b/gdb/value.c >> @@ -821,6 +821,32 @@ value_enclosing_type (struct value *value) >> return value->enclosing_type; >> } >> >> +struct type * >> +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) >> + { >> + if ((TYPE_CODE (result) == TYPE_CODE_PTR) || (TYPE_CODE (result) >> == TYPE_CODE_REF)) >> + { >> + struct type *real_type; >> + real_type = value_rtti_target_type ( value, 0, 0, 0 ); >> + if (real_type) >> + result = real_type; >> + } >> + else if (resolve_simple_types) >> + result = value_enclosing_type (value); >> + } >> + >> + return result; >> +} >> + >> static void >> require_not_optimized_out (const struct value *value) >> { >> @@ -3114,6 +3140,7 @@ 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 +3149,23 @@ 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), >> + 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))); >> + /* Re-adjust type. */ >> + deprecated_set_value_type (retval, TYPE_TARGET_TYPE >> (value_type_arg_tmp)); >> + >> + /* Add embedding info. */ >> + set_value_enclosing_type (retval, enc_type); >> + set_value_embedded_offset (retval, value_pointed_to_offset (arg)); >> + >> + /* We may be pointing to an object of some derived type. */ >> + retval = value_full_object (retval, NULL, 0, 0, 0); >> + >> + return retval; >> } >> >> struct value * >> diff --git a/gdb/value.h b/gdb/value.h >> index d2c58ec..57130e4 100644 >> --- a/gdb/value.h >> +++ b/gdb/value.h >> @@ -139,6 +139,15 @@ 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 also >> + all the types (e.g. for structures). This option is useful >> + to prevent retrieving enclosing type for the base classes fields */ >> +extern struct type *actual_type (struct value *value, int >> resolve_simple_types); >> + >> 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); >> diff --git a/gdb/varobj.c b/gdb/varobj.c >> index 7c68a93..22c045b 100644 >> --- a/gdb/varobj.c >> +++ b/gdb/varobj.c >> @@ -660,7 +660,16 @@ varobj_create (char *objname, >> var->type = value_type (type_only_value); >> } >> else >> - var->type = value_type (value); >> + { >> + struct type *enclosing_type; >> + var->type = value_type (value); >> + enclosing_type = actual_type(value, 0); >> + if (check_typedef (enclosing_type) != check_typedef (var->type)) >> + { >> + var->type = enclosing_type; >> + value = value_cast (enclosing_type, value); >> + } >> + } >> >> install_new_value (var, value, 1 /* Initial assignment */); >> >> @@ -2194,7 +2203,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 = actual_type (value, 0); >> else >> /* Otherwise, we must compute the type. */ >> child->type = (*child->root->lang->type_of_child) (child->parent, >> @@ -2480,6 +2489,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 +2502,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 +2792,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,8 +2807,10 @@ 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) >> { >> + struct type *enclosing_type; >> gdb_assert (type && *type); >> >> if (was_ptr) >> @@ -2832,6 +2849,17 @@ 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) >> + { >> + enclosing_type = actual_type(*value, 1); >> + if (check_typedef (enclosing_type) != check_typedef (*type)) >> + { >> + *type = enclosing_type; >> + *value = value_cast (enclosing_type, *value); >> + } >> + } >> } >> >> /* C */ >> @@ -2842,7 +2870,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 +2985,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 +3251,27 @@ 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; >> 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); >> + // 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; >> + } >> + 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 +3298,13 @@ 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; >> + } >> + 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 +3386,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 +3400,17 @@ 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) >> >> >> >> > >