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

xgsa
2012-02-19T16:42:03Z

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

As the first patch was approved (not checked in though cause my account
hasn't been created yet) here is the second part of the changes. Note,
that this patch relies on changes from the previous one.

Thanks,
Anton

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.

gdb/ChangeLog:

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

PR mi/13393

* value.c (value_actual_type): New function.
* value.h (value_actual_type): New declaration.
* varobj.c (varobj_create): Call value_actual_type instead of
value_type.
(create_child_with_value): Call value_actual_type instead of
value_type.
(value_of_root): Support for type change if the value changed
and RTTI
is used to determine the type.
(adjust_value_for_child_access): Extended with a new parameter
and cast
given value to enclosing type if it is set.
(c_number_of_children): Updated for extended
adjust_value_for_child_access.
(c_describe_child): Updated for extended
adjust_value_for_child_access.
(cplus_number_of_children): Updated for extended
adjust_value_for_child_access.
(cplus_describe_child): Updated for extended
adjust_value_for_child_access.

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

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..d85af37
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-rtti.cc
@@ -0,0 +1,258 @@
+/* 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_test
+ set_print_object off $testname
+ check_derived_class_without_rtti ptr {Base \*} $testname
+ check_derived_class_without_rtti constPtr {const Base \*} $testname
+ check_derived_class_without_rtti ptrConst {Base \* const} $testname
+ check_derived_class_without_rtti constPtrConst {const Base \* const} \
+ $testname
+
+ set_print_object on $testname
+ check_derived_class_with_rtti ptr {Derived \*} $testname
+ check_derived_class_with_rtti constPtr {const Derived \*} $testname
+ check_derived_class_with_rtti ptrConst {Derived \* const} $testname
+ check_derived_class_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_test
+ set_print_object off $testname
+ check_derived_class_without_rtti ref {Base \&} $testname
+ check_derived_class_without_rtti constRef {const Base \&} $testname
+
+ set_print_object on $testname
+ check_derived_class_with_rtti ref {Derived \&} $testname
+ check_derived_class_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_test
+ set_print_object off $testname
+ check_derived_class_without_rtti s.ptr {Base \*} $testname
+ check_derived_class_without_rtti s.constPtr {const Base \*} $testname
+ check_derived_class_without_rtti s.ptrConst {Base \* const} $testname
+ check_derived_class_without_rtti s.constPtrConst {const Base \* const} \
+ $testname
+
+ set_print_object on $testname
+ check_derived_class_with_rtti s.ptr {Derived \*} $testname
+ check_derived_class_with_rtti s.constPtr {const Derived \*} $testname
+ check_derived_class_with_rtti s.ptrConst {Derived \* const} $testname
+ check_derived_class_with_rtti s.constPtrConst {const Derived \* const} \
+ $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_test
+ set_print_object off $testname
+ check_derived_class_without_rtti s.ref {Base \&} $testname
+ check_derived_class_without_rtti s.constRef {const Base \&} $testname
+
+ set_print_object on $testname
+ check_derived_class_with_rtti s.ref {Derived \&} $testname
+ check_derived_class_with_rtti s.constRef {const Derived \&} $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_derived_class_without_rtti ptr {Base \*} $testname
+ check_derived_class_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_test
+ set_print_object on $testname
+ mi_create_varobj_checked VAR ptr {Base \*} \
+ "create varobj for ptr in $testname"
+ check_derived_children_without_rtti ptr $testname
+ :*/
+
+ Base* ptr = &d;
+ /*:
+ mi_varobj_update_with_type_change VAR {Derived \*} 2 \
+ "update ptr in $testname"
+ check_derived_children_with_rtti ptr $testname
+ check_derived_content_with_rtti ptr $testname
+ mi_delete_varobj VAR "delete varobj for ptr 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_test
+ set_print_object off $testname
+ mi_create_varobj_checked VAR ptr {Base \*} \
+ "create varobj for ptr in $testname"
+ check_derived_children_without_rtti ptr $testname
+ :*/
+
+ Base* ptr = &d;
+ /*:
+ mi_varobj_update VAR {} "update ptr in $testname"
+ check_derived_children_without_rtti ptr $testname
+ check_derived_content_without_rtti ptr $testname
+ mi_delete_varobj VAR "delete varobj for ptr 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;
+}
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..c4597ce
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-rtti.exp
@@ -0,0 +1,114 @@
+# 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 {var_name testname} {
+ mi_list_varobj_children VAR {
+ { VAR.public public 1 }
+ } "list children of ${var_name} (without RTTI) in $testname"
+ mi_list_varobj_children "VAR.public" {
+ { VAR.public.A A 0 int }
+ } "list children of ${var_name}.public (without RTTI) in $testname"
+}
+
+proc check_derived_content_without_rtti {var_name testname} {
+ mi_check_varobj_value VAR.public.A 1 \
+ "check ${var_name}->A (without RTTI) in $testname"
+}
+
+proc check_derived_class_without_rtti {var_name var_type testname} {
+ mi_create_varobj_checked VAR ${var_name} ${var_type} \
+ "create varobj for ${var_name} (without RTTI) in ${testname}"
+ check_derived_children_without_rtti ${var_name} ${testname}
+ check_derived_content_without_rtti ${var_name} ${testname}
+ mi_delete_varobj VAR \
+ "delete varobj for ${var_name} (without RTTI) in ${testname}"
+}
+
+proc check_derived_children_with_rtti {var_name testname} {
+ mi_list_varobj_children VAR {
+ { VAR.Base Base 1 Base }
+ { VAR.public public 2 }
+ } "list children of ${var_name} (with RTTI) in $testname"
+ mi_list_varobj_children "VAR.Base" {
+ { VAR.Base.public public 1 }
+ } "list children of ${var_name}.Base (with RTTI) in $testname"
+ mi_list_varobj_children "VAR.Base.public" {
+ { VAR.Base.public.A A 0 int }
+ } "list children of ${var_name}.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 ${var_name}.public (with RTTI) in $testname"
+}
+
+proc check_derived_content_with_rtti {var_name testname} {
+ mi_check_varobj_value VAR.Base.public.A 1 \
+ "check ${var_name}->A (with RTTI) in $testname"
+ mi_check_varobj_value VAR.public.B 2 \
+ "check ${var_name}->B (with RTTI) in $testname"
+ mi_check_varobj_value VAR.public.C 3 \
+ "check ${var_name}->C (with RTTI) in $testname"
+}
+
+proc check_derived_class_with_rtti {var_name var_type testname} {
+ mi_create_varobj_checked VAR ${var_name} ${var_type} \
+ "create varobj for ${var_name} (with RTTI) in $testname"
+ check_derived_children_with_rtti ${var_name} $testname
+ check_derived_content_with_rtti ${var_name} $testname
+ mi_delete_varobj VAR \
+ "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
diff --git a/gdb/value.c b/gdb/value.c
index 85ea970..77e547e 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -825,6 +825,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)
{
diff --git a/gdb/value.h b/gdb/value.h
index d4c4a83..71b5140 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -137,6 +137,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);
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 8855ce3..d55b082 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -672,8 +672,15 @@ 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);
+ }

install_new_value (var, value, 1 /* Initial assignment */);

@@ -2280,7 +2287,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,
@@ -2566,6 +2573,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;
@@ -2578,7 +2586,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;
@@ -2867,6 +2876,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
@@ -2878,7 +2891,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);

@@ -2923,6 +2937,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);
+ }
+ }
}

/* C */
@@ -2933,7 +2961,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))
@@ -3049,7 +3077,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))
{
@@ -3350,16 +3378,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))
@@ -3386,7 +3427,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)
@@ -3468,7 +3519,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;
@@ -3479,24 +3533,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);
+
+ 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);
+ 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)