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

xgsa
2011-12-24T13:21:22Z

[-- Attachment #1: Type: text/plain, Size: 2133 bytes --]

I have used 4 spaces for tabs in ChangeLog, sorry. Fixed.

Thanks,
Anton

gdb/ChangeLog:

2011-12-02 Anton Gorenkov <xgsa@yandex.ru>

PR mi/13393

* 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).
* 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.
(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.
* gdb/valops.c (value_ind): Extract value type and enclosing type
setting to a separate function readjust_value_type.
* 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
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 mi/13393

* gdb.mi/mi-var-rtti.cc: New file.
* gdb.mi/mi-var-rtti.exp: New file.

[-- Attachment #2: gdb_mi4.patch --]
[-- Type: text/x-diff, Size: 26366 bytes --]

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);
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);
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.
+
+ 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..177b63c
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-rtti.exp
@@ -0,0 +1,108 @@
+# 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/>.
+
+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..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/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);
+ 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_cv_type (TYPE_CONST (type), TYPE_VOLATILE (type),
+ real_type, NULL);
+ }
+
+ 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..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. */
+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)
+ {
+ if (TYPE_CODE (result) == TYPE_CODE_PTR
+ || TYPE_CODE (result) == TYPE_CODE_REF)
+ {
+ struct type *real_type;
+
+ real_type = value_rtti_indirect_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)
{
@@ -3110,10 +3139,26 @@ coerce_ref_if_computed (const struct value *arg)
}

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);
+
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);
+
/* 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
+ {
+ 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))
+ {
+ 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))
+ {
+ *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;
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 +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);
+ }
+ 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)