gdb/doc/ChangeLog:
2012-04-14 Anton Gorenkov <xgsa@yandex.ru> PR mi/13393 * gdb.texinfo (Print Settings): Extend the description for "set print object". (GDB/MI Variable Objects): Extend the description for -var-create and -var-list-children. gdb/testsuite/ChangeLog: 2012-04-14 Anton Gorenkov <xgsa@yandex.ru> PR mi/13393 * gdb.mi/mi-var-rtti.cc: New file. * gdb.mi/mi-var-rtti.exp: New file. * lib/mi-support.exp (mi_varobj_update_with_child_type_change): New function. (mi_varobj_update_with_type_change): updated to avoid code duplication. gdb/ChangeLog: 2012-04-14 Anton Gorenkov <xgsa@yandex.ru> PR mi/13393 * value.c (value_actual_type): New function. * value.h (value_actual_type): New declaration. * varobj.c (update_type_if_necessary): New function. (varobj_create): Call value_actual_type instead of value_type. (install_dynamic_child): distinct changed and type changed MI variable objects. (update_dynamic_varobj_children): Updated for install_dynamic_child change. All callers updated. (varobj_update): Support for MI variable object type change if the value changed and RTTI is used to determine the type. (create_child_with_value): Call value_actual_type instead of value_type. (adjust_value_for_child_access): Extended with a new parameter which specify whether the given value should be casted to enclosing type. All callers updated.
This commit is contained in:
parent
5f18041e78
commit
8264ba82b7
10 changed files with 742 additions and 42 deletions
|
@ -1,3 +1,23 @@
|
|||
2012-04-14 Anton Gorenkov <xgsa@yandex.ru>
|
||||
|
||||
PR mi/13393
|
||||
* value.c (value_actual_type): New function.
|
||||
* value.h (value_actual_type): New declaration.
|
||||
* varobj.c (update_type_if_necessary): New function.
|
||||
(varobj_create): Call value_actual_type instead of
|
||||
value_type.
|
||||
(install_dynamic_child): distinct changed and type changed MI variable
|
||||
objects.
|
||||
(update_dynamic_varobj_children): Updated for install_dynamic_child
|
||||
change. All callers updated.
|
||||
(varobj_update): Support for MI variable object type change if
|
||||
the value changed and RTTI is used to determine the type.
|
||||
(create_child_with_value): Call value_actual_type instead of
|
||||
value_type.
|
||||
(adjust_value_for_child_access): Extended with a new parameter which
|
||||
specify whether the given value should be casted to enclosing type.
|
||||
All callers updated.
|
||||
|
||||
2012-04-14 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
Import gnulib module inttypes from git
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2012-04-14 Anton Gorenkov <xgsa@yandex.ru>
|
||||
|
||||
PR mi/13393
|
||||
* gdb.texinfo (Print Settings): Extend the description for "set print
|
||||
object".
|
||||
(GDB/MI Variable Objects): Extend the description for -var-create and
|
||||
-var-list-children.
|
||||
|
||||
2012-04-11 Siva Chandra Reddy <sivachandra@google.com>
|
||||
|
||||
* gdb.texinfo (Examining Data): Document the 'explore' command.
|
||||
|
|
|
@ -8666,7 +8666,8 @@ When displaying a pointer to an object, identify the @emph{actual}
|
|||
the virtual function table. Note that the virtual function table is
|
||||
required---this feature can only work for objects that have run-time
|
||||
type identification; a single virtual method in the object's declared
|
||||
type is sufficient.
|
||||
type is sufficient. Note that this setting is also taken into account when
|
||||
working with variable objects via MI (@pxref{GDB/MI}).
|
||||
|
||||
@item set print object off
|
||||
Display only the declared type of objects, without reference to the
|
||||
|
@ -29103,7 +29104,10 @@ will not be interesting.
|
|||
|
||||
@item type
|
||||
The varobj's type. This is a string representation of the type, as
|
||||
would be printed by the @value{GDBN} CLI.
|
||||
would be printed by the @value{GDBN} CLI. If @samp{print object}
|
||||
(@pxref{Print Settings, set print object}) is set to @code{on}, the
|
||||
@emph{actual} (derived) type of the object is shown rather than the
|
||||
@emph{declared} one.
|
||||
|
||||
@item thread-id
|
||||
If a variable object is bound to a specific thread, then this is the
|
||||
|
@ -29274,7 +29278,10 @@ Number of children this child has. For a dynamic varobj, this will be
|
|||
0.
|
||||
|
||||
@item type
|
||||
The type of the child.
|
||||
The type of the child. If @samp{print object}
|
||||
(@pxref{Print Settings, set print object}) is set to @code{on}, the
|
||||
@emph{actual} (derived) type of the object is shown rather than the
|
||||
@emph{declared} one.
|
||||
|
||||
@item value
|
||||
If values were requested, this is the value.
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2012-04-14 Anton Gorenkov <xgsa@yandex.ru>
|
||||
|
||||
PR mi/13393
|
||||
* gdb.mi/mi-var-rtti.cc: New file.
|
||||
* gdb.mi/mi-var-rtti.exp: New file.
|
||||
* lib/mi-support.exp (mi_varobj_update_with_child_type_change): New
|
||||
function.
|
||||
(mi_varobj_update_with_type_change): updated to avoid code duplication.
|
||||
|
||||
2012-04-11 Siva Chandra Reddy <sivachandra@google.com>
|
||||
|
||||
* gdb.python/Makefile.in: Add py-explore and py-explore-cc to
|
||||
|
|
360
gdb/testsuite/gdb.mi/mi-var-rtti.cc
Normal file
360
gdb/testsuite/gdb.mi/mi-var-rtti.cc
Normal file
|
@ -0,0 +1,360 @@
|
|||
/* Copyright 2012 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;
|
||||
/*:
|
||||
set testname use_rtti_for_ptr
|
||||
set_print_object off $testname
|
||||
check_new_derived_without_rtti ptr {Base \*} $testname
|
||||
check_new_derived_without_rtti constPtr {const Base \*} $testname
|
||||
check_new_derived_without_rtti ptrConst {Base \* const} $testname
|
||||
check_new_derived_without_rtti constPtrConst {const Base \* const} \
|
||||
$testname
|
||||
|
||||
set_print_object on $testname
|
||||
check_new_derived_with_rtti ptr {Derived \*} $testname
|
||||
check_new_derived_with_rtti constPtr {const Derived \*} $testname
|
||||
check_new_derived_with_rtti ptrConst {Derived \* const} $testname
|
||||
check_new_derived_with_rtti constPtrConst {const Derived \* const} \
|
||||
$testname
|
||||
:*/
|
||||
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;
|
||||
/*:
|
||||
set testname use_rtti_for_ref
|
||||
set_print_object off $testname
|
||||
check_new_derived_without_rtti ref {Base \&} $testname
|
||||
check_new_derived_without_rtti constRef {const Base \&} $testname
|
||||
|
||||
set_print_object on $testname
|
||||
check_new_derived_with_rtti ref {Derived \&} $testname
|
||||
check_new_derived_with_rtti constRef {const Derived \&} $testname
|
||||
:*/
|
||||
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 );
|
||||
/*:
|
||||
set testname use_rtti_for_ptr_child
|
||||
|
||||
set_print_object off $testname
|
||||
mi_create_varobj VAR s "create varobj for s (without RTTI) in $testname"
|
||||
mi_list_varobj_children VAR {
|
||||
{ VAR.public public 4 }
|
||||
} "list children of s (without RTTI) in $testname"
|
||||
mi_list_varobj_children VAR.public {
|
||||
{ VAR.public.ptr ptr 1 {Base \*} }
|
||||
{ VAR.public.constPtr constPtr 1 {const Base \*} }
|
||||
{ VAR.public.ptrConst ptrConst 1 {Base \* const} }
|
||||
{ VAR.public.constPtrConst constPtrConst 1 {const Base \* const} }
|
||||
} "list children of s.public (without RTTI) in $testname"
|
||||
check_derived_without_rtti VAR.public.ptr s.ptr $testname
|
||||
check_derived_without_rtti VAR.public.constPtr s.constPtr $testname
|
||||
check_derived_without_rtti VAR.public.ptrConst s.ptrConst $testname
|
||||
check_derived_without_rtti VAR.public.constPtrConst s.constPtrConst \
|
||||
$testname
|
||||
mi_delete_varobj VAR "delete varobj for s (without RTTI) in $testname"
|
||||
|
||||
set_print_object on $testname
|
||||
mi_create_varobj VAR s "create varobj for s (with RTTI) in $testname"
|
||||
mi_list_varobj_children VAR {
|
||||
{ VAR.public public 4 }
|
||||
} "list children of s (with RTTI) in $testname"
|
||||
mi_list_varobj_children VAR.public {
|
||||
{ VAR.public.ptr ptr 2 {Derived \*} }
|
||||
{ VAR.public.constPtr constPtr 2 {const Derived \*} }
|
||||
{ VAR.public.ptrConst ptrConst 2 {Derived \* const} }
|
||||
{ VAR.public.constPtrConst constPtrConst 2 {const Derived \* const}}
|
||||
} "list children of s.public (with RTTI) in $testname"
|
||||
check_derived_with_rtti VAR.public.ptr s.ptr $testname
|
||||
check_derived_with_rtti VAR.public.constPtr s.constPtr $testname
|
||||
check_derived_with_rtti VAR.public.ptrConst s.ptrConst $testname
|
||||
check_derived_with_rtti VAR.public.constPtrConst s.constPtrConst \
|
||||
$testname
|
||||
mi_delete_varobj VAR "delete varobj for s (with RTTI) in $testname"
|
||||
:*/
|
||||
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 );
|
||||
/*:
|
||||
set testname use_rtti_for_ref_child
|
||||
|
||||
set_print_object off $testname
|
||||
mi_create_varobj VAR s "create varobj for s (without RTTI) in $testname"
|
||||
mi_list_varobj_children VAR {
|
||||
{ VAR.public public 2 }
|
||||
} "list children of s (without RTTI) in $testname"
|
||||
mi_list_varobj_children VAR.public {
|
||||
{ VAR.public.ref ref 1 {Base \&} }
|
||||
{ VAR.public.constRef constRef 1 {const Base \&} }
|
||||
} "list children of s.public (without RTTI) in $testname"
|
||||
check_derived_without_rtti VAR.public.ref s.ref $testname
|
||||
check_derived_without_rtti VAR.public.constRef s.constRef $testname
|
||||
mi_delete_varobj VAR "delete varobj for s (without RTTI) in $testname"
|
||||
|
||||
set_print_object on $testname
|
||||
mi_create_varobj VAR s "create varobj for s (with RTTI) in $testname"
|
||||
mi_list_varobj_children VAR {
|
||||
{ VAR.public public 2 }
|
||||
} "list children of s (with RTTI) in $testname"
|
||||
mi_list_varobj_children VAR.public {
|
||||
{ VAR.public.ref ref 2 {Derived \&} }
|
||||
{ VAR.public.constRef constRef 2 {const Derived \&} }
|
||||
} "list children of s.public (with RTTI) in $testname"
|
||||
check_derived_with_rtti VAR.public.ref s.ref $testname
|
||||
check_derived_with_rtti VAR.public.constRef s.constRef $testname
|
||||
mi_delete_varobj VAR "delete varobj for s (with RTTI) in $testname"
|
||||
:*/
|
||||
return;
|
||||
/*: END: use_rtti_for_ref_child :*/
|
||||
}
|
||||
|
||||
|
||||
struct First {
|
||||
First() : F(-1) {}
|
||||
int F;
|
||||
};
|
||||
|
||||
|
||||
struct MultipleDerived : public First, Base {
|
||||
MultipleDerived() : B(2), C(3) {}
|
||||
int B;
|
||||
int C;
|
||||
};
|
||||
|
||||
|
||||
void use_rtti_with_multiple_inheritence_test ()
|
||||
{
|
||||
/*: BEGIN: use_rtti_with_multiple_inheritence :*/
|
||||
MultipleDerived d;
|
||||
Base* ptr = &d;
|
||||
Base& ref = d;
|
||||
/*:
|
||||
set testname use_rtti_with_multiple_inheritence
|
||||
set_print_object off $testname
|
||||
check_new_derived_without_rtti ptr {Base \*} $testname
|
||||
check_new_derived_without_rtti ref {Base \&} $testname
|
||||
|
||||
set_print_object on $testname
|
||||
mi_create_varobj_checked VAR ptr {MultipleDerived \*} \
|
||||
"create varobj for ptr (with RTTI) in $testname"
|
||||
mi_list_varobj_children VAR {
|
||||
{ VAR.First First 1 First }
|
||||
{ VAR.Base Base 1 Base }
|
||||
{ VAR.public public 2 }
|
||||
} "list children of ptr (with RTTI) in $testname"
|
||||
mi_list_varobj_children "VAR.First" {
|
||||
{ VAR.First.public public 1 }
|
||||
} "list children of ptr.First (with RTTI) in $testname"
|
||||
mi_list_varobj_children "VAR.First.public" {
|
||||
{ VAR.First.public.F F 0 int }
|
||||
} "list children of ptr.Base.public (with RTTI) in $testname"
|
||||
mi_list_varobj_children "VAR.Base" {
|
||||
{ VAR.Base.public public 1 }
|
||||
} "list children of ptr.Base (with RTTI) in $testname"
|
||||
mi_list_varobj_children "VAR.Base.public" {
|
||||
{ VAR.Base.public.A A 0 int }
|
||||
} "list children of ptr.Base.public (with RTTI) in $testname"
|
||||
mi_list_varobj_children "VAR.public" {
|
||||
{ VAR.public.B B 0 int }
|
||||
{ VAR.public.C C 0 int }
|
||||
} "list children of ptr.public (with RTTI) in $testname"
|
||||
|
||||
mi_delete_varobj VAR \
|
||||
"delete varobj for ptr (with RTTI) in $testname"
|
||||
:*/
|
||||
return;
|
||||
/*: END: use_rtti_with_multiple_inheritence :*/
|
||||
}
|
||||
|
||||
|
||||
void type_update_when_use_rtti_test ()
|
||||
{
|
||||
/*: BEGIN: type_update_when_use_rtti :*/
|
||||
Derived d;
|
||||
/*:
|
||||
set testname type_update_when_use_rtti
|
||||
|
||||
set_print_object on $testname
|
||||
mi_create_varobj_checked PTR ptr {Base \*} \
|
||||
"create varobj for ptr in $testname"
|
||||
check_derived_children_without_rtti PTR ptr $testname
|
||||
|
||||
mi_create_varobj S s "create varobj for S in $testname"
|
||||
mi_list_varobj_children S {
|
||||
{ S.public public 1 }
|
||||
} "list children of s in $testname"
|
||||
mi_list_varobj_children S.public {
|
||||
{ S.public.ptr ptr 1 {Base \*} }
|
||||
} "list children of s.public in $testname"
|
||||
check_derived_children_without_rtti S.public.ptr s.ptr $testname
|
||||
:*/
|
||||
|
||||
Base* ptr = &d;
|
||||
struct S {
|
||||
Base* ptr;
|
||||
S ( Base* v ) :
|
||||
ptr ( v ) {}
|
||||
} s ( &d );
|
||||
/*:
|
||||
mi_varobj_update_with_type_change PTR {Derived \*} 2 \
|
||||
"update ptr to derived in $testname"
|
||||
check_derived_with_rtti PTR ptr $testname
|
||||
|
||||
mi_varobj_update_with_child_type_change S S.public.ptr {Derived \*} 2 \
|
||||
"update s.ptr to derived in $testname"
|
||||
check_derived_with_rtti S.public.ptr s.ptr $testname
|
||||
:*/
|
||||
|
||||
ptr = 0;
|
||||
s.ptr = 0;
|
||||
/*:
|
||||
mi_varobj_update_with_type_change PTR {Base \*} 1 \
|
||||
"update ptr back to base type in $testname"
|
||||
mi_delete_varobj PTR "delete varobj for ptr in $testname"
|
||||
|
||||
mi_varobj_update_with_child_type_change S S.public.ptr {Base \*} 1 \
|
||||
"update s.ptr back to base type in $testname"
|
||||
mi_delete_varobj S "delete varobj for s in $testname"
|
||||
:*/
|
||||
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;
|
||||
/*:
|
||||
set testname skip_type_update_when_not_use_rtti
|
||||
|
||||
set_print_object off $testname
|
||||
mi_create_varobj_checked PTR ptr {Base \*} \
|
||||
"create varobj for ptr in $testname"
|
||||
check_derived_children_without_rtti PTR ptr $testname
|
||||
|
||||
mi_create_varobj S s "create varobj for S in $testname"
|
||||
mi_list_varobj_children S {
|
||||
{ S.public public 1 }
|
||||
} "list children of s in $testname"
|
||||
mi_list_varobj_children S.public {
|
||||
{ S.public.ptr ptr 1 {Base \*} }
|
||||
} "list children of s.public in $testname"
|
||||
check_derived_children_without_rtti S.public.ptr s.ptr $testname
|
||||
:*/
|
||||
|
||||
Base* ptr = &d;
|
||||
struct S {
|
||||
Base* ptr;
|
||||
S ( Base* v ) :
|
||||
ptr ( v ) {}
|
||||
} s ( &d );
|
||||
/*:
|
||||
mi_varobj_update PTR {PTR PTR.public.A} \
|
||||
"update ptr to derived type in $testname"
|
||||
check_derived_without_rtti PTR ptr $testname
|
||||
|
||||
mi_varobj_update S {S.public.ptr S.public.ptr.public.A} \
|
||||
"update s to derived type in $testname"
|
||||
check_derived_without_rtti S.public.ptr s.ptr $testname
|
||||
:*/
|
||||
|
||||
ptr = 0;
|
||||
s.ptr = 0;
|
||||
/*:
|
||||
mi_varobj_update PTR {PTR PTR.public.A} \
|
||||
"update ptr back to base type in $testname"
|
||||
mi_delete_varobj PTR "delete varobj for ptr in $testname"
|
||||
|
||||
mi_varobj_update S {S.public.ptr S.public.ptr.public.A} \
|
||||
"update s back to base type in $testname"
|
||||
mi_delete_varobj S "delete varobj for s in $testname"
|
||||
:*/
|
||||
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();
|
||||
use_rtti_with_multiple_inheritence_test();
|
||||
type_update_when_use_rtti_test();
|
||||
skip_type_update_when_not_use_rtti_test();
|
||||
return 0;
|
||||
}
|
124
gdb/testsuite/gdb.mi/mi-var-rtti.exp
Normal file
124
gdb/testsuite/gdb.mi/mi-var-rtti.exp
Normal file
|
@ -0,0 +1,124 @@
|
|||
# Copyright 2012 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 executable ${testfile}
|
||||
set binfile $objdir/$subdir/$testfile
|
||||
set opts {debug c++}
|
||||
|
||||
if [build_executable $testfile.exp $executable $srcfile $opts] {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mi_gdb_load ${binfile}
|
||||
|
||||
mi_prepare_inline_tests $srcfile
|
||||
|
||||
# Enable using RTTI to determine real types of the objects
|
||||
proc set_print_object {state testname} {
|
||||
mi_gdb_test "-interpreter-exec console \"set print object ${state}\"" \
|
||||
{\^done} \
|
||||
"-interpreter-exec console \"set print object ${state}\" in $testname"
|
||||
}
|
||||
|
||||
proc check_derived_children_without_rtti {varobj_name var_name testname} {
|
||||
mi_list_varobj_children ${varobj_name} "
|
||||
{ ${varobj_name}.public public 1 }
|
||||
" "list children of ${var_name} (without RTTI) in $testname"
|
||||
mi_list_varobj_children "${varobj_name}.public" "
|
||||
{ ${varobj_name}.public.A A 0 int }
|
||||
" "list children of ${var_name}.public (without RTTI) in $testname"
|
||||
}
|
||||
|
||||
proc check_derived_content_without_rtti {varobj_name var_name testname} {
|
||||
mi_check_varobj_value ${varobj_name}.public.A 1 \
|
||||
"check ${var_name}->A (without RTTI) in $testname"
|
||||
}
|
||||
|
||||
proc check_derived_without_rtti {varobj_name var_name testname} {
|
||||
check_derived_children_without_rtti ${varobj_name} ${var_name} ${testname}
|
||||
check_derived_content_without_rtti ${varobj_name} ${var_name} ${testname}
|
||||
}
|
||||
|
||||
proc check_new_derived_without_rtti {var_name var_type testname} {
|
||||
set varobj_name VAR
|
||||
mi_create_varobj_checked ${varobj_name} ${var_name} ${var_type} \
|
||||
"create varobj for ${var_name} (without RTTI) in ${testname}"
|
||||
check_derived_without_rtti ${varobj_name} ${var_name} ${testname}
|
||||
mi_delete_varobj ${varobj_name} \
|
||||
"delete varobj for ${var_name} (without RTTI) in ${testname}"
|
||||
}
|
||||
|
||||
proc check_derived_children_with_rtti {varobj_name var_name testname} {
|
||||
mi_list_varobj_children ${varobj_name} "
|
||||
{ ${varobj_name}.Base Base 1 Base }
|
||||
{ ${varobj_name}.public public 2 }
|
||||
" "list children of ${var_name} (with RTTI) in $testname"
|
||||
mi_list_varobj_children "${varobj_name}.Base" "
|
||||
{ ${varobj_name}.Base.public public 1 }
|
||||
" "list children of ${var_name}.Base (with RTTI) in $testname"
|
||||
mi_list_varobj_children "${varobj_name}.Base.public" "
|
||||
{ ${varobj_name}.Base.public.A A 0 int }
|
||||
" "list children of ${var_name}.Base.public (with RTTI) in $testname"
|
||||
mi_list_varobj_children "${varobj_name}.public" "
|
||||
{ ${varobj_name}.public.B B 0 int }
|
||||
{ ${varobj_name}.public.C C 0 int }
|
||||
" "list children of ${var_name}.public (with RTTI) in $testname"
|
||||
}
|
||||
|
||||
proc check_derived_content_with_rtti {varobj_name var_name testname} {
|
||||
mi_check_varobj_value ${varobj_name}.Base.public.A 1 \
|
||||
"check ${var_name}->A (with RTTI) in $testname"
|
||||
mi_check_varobj_value ${varobj_name}.public.B 2 \
|
||||
"check ${var_name}->B (with RTTI) in $testname"
|
||||
mi_check_varobj_value ${varobj_name}.public.C 3 \
|
||||
"check ${var_name}->C (with RTTI) in $testname"
|
||||
}
|
||||
|
||||
proc check_derived_with_rtti {varobj_name var_name testname} {
|
||||
check_derived_children_with_rtti ${varobj_name} ${var_name} $testname
|
||||
check_derived_content_with_rtti ${varobj_name} ${var_name} $testname
|
||||
}
|
||||
|
||||
proc check_new_derived_with_rtti {var_name var_type testname} {
|
||||
set varobj_name VAR
|
||||
mi_create_varobj_checked ${varobj_name} ${var_name} ${var_type} \
|
||||
"create varobj for ${var_name} (with RTTI) in $testname"
|
||||
check_derived_with_rtti ${varobj_name} ${var_name} $testname
|
||||
mi_delete_varobj ${varobj_name} \
|
||||
"delete varobj for ${var_name} (with RTTI) in $testname"
|
||||
}
|
||||
|
||||
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 use_rtti_with_multiple_inheritence
|
||||
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
|
|
@ -1298,13 +1298,17 @@ proc mi_varobj_update { name expected testname } {
|
|||
mi_gdb_test "-var-update $name" $er $testname
|
||||
}
|
||||
|
||||
proc mi_varobj_update_with_type_change { name new_type new_children testname } {
|
||||
set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\",has_more=\".\"}"
|
||||
proc mi_varobj_update_with_child_type_change { name child_name new_type new_children testname } {
|
||||
set v "{name=\"$child_name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\",has_more=\".\"}"
|
||||
set er "\\^done,changelist=\\\[$v\\\]"
|
||||
verbose -log "Expecting: $er"
|
||||
mi_gdb_test "-var-update $name" $er $testname
|
||||
}
|
||||
|
||||
proc mi_varobj_update_with_type_change { name new_type new_children testname } {
|
||||
mi_varobj_update_with_child_type_change $name $name $new_type $new_children $testname
|
||||
}
|
||||
|
||||
# A helper that turns a key/value list into a regular expression
|
||||
# matching some MI output.
|
||||
proc mi_varobj_update_kv_helper {list} {
|
||||
|
|
41
gdb/value.c
41
gdb/value.c
|
@ -834,6 +834,47 @@ 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,
|
||||
int *real_type_found)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
struct value *target;
|
||||
struct type *result;
|
||||
|
||||
get_user_print_options (&opts);
|
||||
|
||||
if (real_type_found)
|
||||
*real_type_found = 0;
|
||||
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, NULL, NULL, NULL);
|
||||
if (real_type)
|
||||
{
|
||||
if (real_type_found)
|
||||
*real_type_found = 1;
|
||||
result = real_type;
|
||||
}
|
||||
}
|
||||
else if (resolve_simple_types)
|
||||
{
|
||||
if (real_type_found)
|
||||
*real_type_found = 1;
|
||||
result = value_enclosing_type (value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
require_not_optimized_out (const struct value *value)
|
||||
{
|
||||
|
|
16
gdb/value.h
16
gdb/value.h
|
@ -138,6 +138,22 @@ 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.
|
||||
|
||||
REAL_TYPE_FOUND is used to inform whether the real type was found
|
||||
(or just static type was used). The NULL may be passed if it is not
|
||||
necessary. */
|
||||
|
||||
extern struct type *value_actual_type (struct value *value,
|
||||
int resolve_simple_types,
|
||||
int *real_type_found);
|
||||
|
||||
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);
|
||||
|
|
185
gdb/varobj.c
185
gdb/varobj.c
|
@ -270,6 +270,9 @@ static void cppush (struct cpstack **pstack, char *name);
|
|||
|
||||
static char *cppop (struct cpstack **pstack);
|
||||
|
||||
static int update_type_if_necessary (struct varobj *var,
|
||||
struct value *new_value);
|
||||
|
||||
static int install_new_value (struct varobj *var, struct value *value,
|
||||
int initial);
|
||||
|
||||
|
@ -716,8 +719,14 @@ varobj_create (char *objname,
|
|||
|
||||
var->type = value_type (type_only_value);
|
||||
}
|
||||
else
|
||||
var->type = value_type (value);
|
||||
else
|
||||
{
|
||||
int real_type_found = 0;
|
||||
|
||||
var->type = value_actual_type (value, 0, &real_type_found);
|
||||
if (real_type_found)
|
||||
value = value_cast (var->type, value);
|
||||
}
|
||||
|
||||
/* Set language info */
|
||||
lang = variable_language (var);
|
||||
|
@ -1005,6 +1014,7 @@ restrict_range (VEC (varobj_p) *children, int *from, int *to)
|
|||
static void
|
||||
install_dynamic_child (struct varobj *var,
|
||||
VEC (varobj_p) **changed,
|
||||
VEC (varobj_p) **type_changed,
|
||||
VEC (varobj_p) **new,
|
||||
VEC (varobj_p) **unchanged,
|
||||
int *cchanged,
|
||||
|
@ -1027,12 +1037,18 @@ install_dynamic_child (struct varobj *var,
|
|||
{
|
||||
varobj_p existing = VEC_index (varobj_p, var->children, index);
|
||||
|
||||
int type_updated = update_type_if_necessary (existing, value);
|
||||
if (type_updated)
|
||||
{
|
||||
if (type_changed)
|
||||
VEC_safe_push (varobj_p, *type_changed, existing);
|
||||
}
|
||||
if (install_new_value (existing, value, 0))
|
||||
{
|
||||
if (changed)
|
||||
if (!type_updated && changed)
|
||||
VEC_safe_push (varobj_p, *changed, existing);
|
||||
}
|
||||
else if (unchanged)
|
||||
else if (!type_updated && unchanged)
|
||||
VEC_safe_push (varobj_p, *unchanged, existing);
|
||||
}
|
||||
}
|
||||
|
@ -1055,6 +1071,7 @@ dynamic_varobj_has_child_method (struct varobj *var)
|
|||
static int
|
||||
update_dynamic_varobj_children (struct varobj *var,
|
||||
VEC (varobj_p) **changed,
|
||||
VEC (varobj_p) **type_changed,
|
||||
VEC (varobj_p) **new,
|
||||
VEC (varobj_p) **unchanged,
|
||||
int *cchanged,
|
||||
|
@ -1190,6 +1207,7 @@ update_dynamic_varobj_children (struct varobj *var,
|
|||
if (v == NULL)
|
||||
gdbpy_print_stack ();
|
||||
install_dynamic_child (var, can_mention ? changed : NULL,
|
||||
can_mention ? type_changed : NULL,
|
||||
can_mention ? new : NULL,
|
||||
can_mention ? unchanged : NULL,
|
||||
can_mention ? cchanged : NULL, i, name, v);
|
||||
|
@ -1245,7 +1263,7 @@ varobj_get_num_children (struct varobj *var)
|
|||
|
||||
/* If we have a dynamic varobj, don't report -1 children.
|
||||
So, try to fetch some children first. */
|
||||
update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy,
|
||||
update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL, &dummy,
|
||||
0, 0, 0);
|
||||
}
|
||||
else
|
||||
|
@ -1271,8 +1289,8 @@ varobj_list_children (struct varobj *var, int *from, int *to)
|
|||
/* This, in theory, can result in the number of children changing without
|
||||
frontend noticing. But well, calling -var-list-children on the same
|
||||
varobj twice is not something a sane frontend would do. */
|
||||
update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed,
|
||||
0, 0, *to);
|
||||
update_dynamic_varobj_children (var, NULL, NULL, NULL, NULL,
|
||||
&children_changed, 0, 0, *to);
|
||||
restrict_range (var->children, from, to);
|
||||
return var->children;
|
||||
}
|
||||
|
@ -1619,6 +1637,43 @@ install_new_value_visualizer (struct varobj *var)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* When using RTTI to determine variable type it may be changed in runtime when
|
||||
the variable value is changed. This function checks whether type of varobj
|
||||
VAR will change when a new value NEW_VALUE is assigned and if it is so
|
||||
updates the type of VAR. */
|
||||
|
||||
static int
|
||||
update_type_if_necessary (struct varobj *var, struct value *new_value)
|
||||
{
|
||||
if (new_value)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
get_user_print_options (&opts);
|
||||
if (opts.objectprint)
|
||||
{
|
||||
struct type *new_type;
|
||||
char *curr_type_str, *new_type_str;
|
||||
|
||||
new_type = value_actual_type (new_value, 0, 0);
|
||||
new_type_str = type_to_string (new_type);
|
||||
curr_type_str = varobj_get_type (var);
|
||||
if (strcmp (curr_type_str, new_type_str) != 0)
|
||||
{
|
||||
var->type = new_type;
|
||||
|
||||
/* This information may be not valid for a new type. */
|
||||
varobj_delete (var, NULL, 1);
|
||||
VEC_free (varobj_p, var->children);
|
||||
var->num_children = -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assign a new value to a variable object. If INITIAL is non-zero,
|
||||
this is the first assignement after the variable object was just
|
||||
created, or changed type. In that case, just assign the value
|
||||
|
@ -1948,8 +2003,9 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
value_of_root variable dispose of the varobj if the type
|
||||
has changed. */
|
||||
new = value_of_root (varp, &type_changed);
|
||||
if (update_type_if_necessary(*varp, new))
|
||||
type_changed = 1;
|
||||
r.varobj = *varp;
|
||||
|
||||
r.type_changed = type_changed;
|
||||
if (install_new_value ((*varp), new, type_changed))
|
||||
r.changed = 1;
|
||||
|
@ -1990,6 +2046,8 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
struct type *new_type;
|
||||
|
||||
new = value_of_child (v->parent, v->index);
|
||||
if (update_type_if_necessary(v, new))
|
||||
r.type_changed = 1;
|
||||
if (new)
|
||||
new_type = value_type (new);
|
||||
else
|
||||
|
@ -2019,7 +2077,8 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
invoked. */
|
||||
if (v->pretty_printer)
|
||||
{
|
||||
VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0;
|
||||
VEC (varobj_p) *changed = 0, *type_changed = 0, *unchanged = 0;
|
||||
VEC (varobj_p) *new = 0;
|
||||
int i, children_changed = 0;
|
||||
|
||||
if (v->frozen)
|
||||
|
@ -2037,7 +2096,7 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
it. */
|
||||
if (!varobj_has_more (v, 0))
|
||||
{
|
||||
update_dynamic_varobj_children (v, NULL, NULL, NULL,
|
||||
update_dynamic_varobj_children (v, NULL, NULL, NULL, NULL,
|
||||
&dummy, 0, 0, 0);
|
||||
if (varobj_has_more (v, 0))
|
||||
r.changed = 1;
|
||||
|
@ -2051,8 +2110,8 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
|
||||
/* If update_dynamic_varobj_children returns 0, then we have
|
||||
a non-conforming pretty-printer, so we skip it. */
|
||||
if (update_dynamic_varobj_children (v, &changed, &new, &unchanged,
|
||||
&children_changed, 1,
|
||||
if (update_dynamic_varobj_children (v, &changed, &type_changed, &new,
|
||||
&unchanged, &children_changed, 1,
|
||||
v->from, v->to))
|
||||
{
|
||||
if (children_changed || new)
|
||||
|
@ -2064,6 +2123,18 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
popped from the work stack first, and so will be
|
||||
added to result first. This does not affect
|
||||
correctness, just "nicer". */
|
||||
for (i = VEC_length (varobj_p, type_changed) - 1; i >= 0; --i)
|
||||
{
|
||||
varobj_p tmp = VEC_index (varobj_p, type_changed, i);
|
||||
varobj_update_result r = {0};
|
||||
|
||||
/* Type may change only if value was changed. */
|
||||
r.varobj = tmp;
|
||||
r.changed = 1;
|
||||
r.type_changed = 1;
|
||||
r.value_installed = 1;
|
||||
VEC_safe_push (varobj_update_result, stack, &r);
|
||||
}
|
||||
for (i = VEC_length (varobj_p, changed) - 1; i >= 0; --i)
|
||||
{
|
||||
varobj_p tmp = VEC_index (varobj_p, changed, i);
|
||||
|
@ -2090,9 +2161,10 @@ varobj_update (struct varobj **varp, int explicit)
|
|||
if (r.changed || r.children_changed)
|
||||
VEC_safe_push (varobj_update_result, result, &r);
|
||||
|
||||
/* Free CHANGED and UNCHANGED, but not NEW, because NEW
|
||||
has been put into the result vector. */
|
||||
/* Free CHANGED, TYPE_CHANGED and UNCHANGED, but not NEW,
|
||||
because NEW has been put into the result vector. */
|
||||
VEC_free (varobj_p, changed);
|
||||
VEC_free (varobj_p, type_changed);
|
||||
VEC_free (varobj_p, unchanged);
|
||||
|
||||
continue;
|
||||
|
@ -2367,7 +2439,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, NULL);
|
||||
else
|
||||
/* Otherwise, we must compute the type. */
|
||||
child->type = (*child->root->lang->type_of_child) (child->parent,
|
||||
|
@ -2948,6 +3020,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
|
||||
|
@ -2959,7 +3035,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);
|
||||
|
||||
|
@ -3004,6 +3081,20 @@ 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;
|
||||
int real_type_found = 0;
|
||||
|
||||
enclosing_type = value_actual_type (*value, 1, &real_type_found);
|
||||
if (real_type_found)
|
||||
{
|
||||
*type = enclosing_type;
|
||||
*value = value_cast (enclosing_type, *value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement the "value_is_changeable_p" varobj callback for most
|
||||
|
@ -3044,7 +3135,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))
|
||||
|
@ -3160,7 +3251,7 @@ c_describe_child (struct varobj *parent, int index,
|
|||
*cfull_expression = NULL;
|
||||
parent_expression = varobj_get_path_expr (get_path_expr_parent (parent));
|
||||
}
|
||||
adjust_value_for_child_access (&value, &type, &was_ptr);
|
||||
adjust_value_for_child_access (&value, &type, &was_ptr, 0);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
|
@ -3456,16 +3547,29 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
|
|||
static int
|
||||
cplus_number_of_children (struct varobj *var)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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))
|
||||
|
@ -3492,7 +3596,17 @@ 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)
|
||||
{
|
||||
struct varobj *parent = var->parent;
|
||||
|
||||
value = parent->value;
|
||||
lookup_actual_type = (TYPE_CODE (parent->type) == TYPE_CODE_REF
|
||||
|| TYPE_CODE (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)
|
||||
|
@ -3574,7 +3688,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;
|
||||
|
@ -3585,24 +3702,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 (get_path_expr_parent (parent->parent));
|
||||
}
|
||||
else
|
||||
{
|
||||
value = parent->value;
|
||||
type = get_value_type (parent);
|
||||
if (cfull_expression)
|
||||
parent_expression
|
||||
= varobj_get_path_expr (get_path_expr_parent (parent));
|
||||
}
|
||||
get_user_print_options (&opts);
|
||||
|
||||
adjust_value_for_child_access (&value, &type, &was_ptr);
|
||||
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 (get_path_expr_parent (var));
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue