Re: set print object on should affect MI varobjs (PR 13393)

xgsa
2011-12-08T08:00:18Z

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 <xgsa@yandex.ru>
>
> 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 <xgsa@yandex.ru>
>
> 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 <http://www.gnu.org/licenses/>.
> +*/
> +
> +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 <http://www.gnu.org/licenses/>.
> +
> +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)
>
>
>
>