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

xgsa xgsa@yandex.ru
Mon Dec 19 20:34:00 GMT 2011


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




More information about the Gdb-patches mailing list