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

xgsa
2011-12-19T20:02:23Z

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 <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)
>>
>>
>>
>>
>
>