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