This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On Sat, 24 Dec 2011 14:21:09 +0100, xgsa wrote:
> gdb/ChangeLog:

The ChangeLog order did not fully match the patch order, it is difficult to
follow it a bit.


> 2011-12-02  Anton Gorenkov <xgsa@yandex.ru>
> 
>         PR mi/13393
> 

>         * gdb/valops.c (value_ind): Extract value type and enclosing type
>         setting to a separate function readjust_value_type.

valops.c already has an entry above (below after reordering it); but that
corresponds to the problem the entries are not in the patch order.

All the files are already in gdb/ChangeLog so they should be written as
valops.c, not gdb/valops.c.


>         * gdb/valops.c (value_rtti_target_type): Replaced with
>         value_rtti_indirect_type.
>         (value_rtti_indirect_type): New function.  The same as
>         value_rtti_target_type, but return a reference or pointer type (because
>         every caller do it after call that leads to code duplication).

http://www.gnu.org/prep/standards/standards.html#Change-Log-Concepts
"There’s no need to describe the full purpose of the changes or how they work
together."

Therefore:
	  (value_rtti_target_type): Rename to ...
	  (value_rtti_indirect_type): ... here.
is enough.

That change to value_rtti_indirect_type would be easier to read if it was
a separate patch.


>         * gdb/c-valprint.c (c_value_print): Use value_rtti_indirect_type
>         instead of value_rtti_target_type.
>         * gdb/eval.c (evaluate_subexp_standard): Use value_rtti_indirect_type
>         instead of value_rtti_target_type.
>         * gdb/typeprint.c: Use value_rtti_indirect_type instead of
>         value_rtti_target_type.
>         * gdb/value.c (value_actual_type): New function.

>         (value_rtti_indirect_type): New function.

Here probably should have been readjust_value_type, not
value_rtti_indirect_type.


>         (coerce_ref): Support for enclosing type setting for references
>         with readjust_value_type.
>         * gdb/value.h (value_actual_type): Add prototype.
>         (readjust_value_type): Add prototype.

Missing:
	  (value_rtti_target_type): Rename to ...
	  (value_rtti_indirect_type): ... here.


>         * gdb/varobj.c (varobj_create): Call value_actual_type if necessary.
>         (create_child_with_value): Call value_actual_type.
>         (value_of_root): Support for type change if the value changed and RTTI
>         is used to determine type.
>         (adjust_value_for_child_access): Extended with a new parameter and cast
>         given value to enclosing type is necessary.
>         (c_number_of_children): Updated for extended

Missing/adjust:
          (c_number_of_children, c_describe_child): Updated for extended

>         adjust_value_for_child_access.
>         (cplus_number_of_children): Send a value as parameter if RTTI should be
>         used to determine type.
>         (cplus_describe_child): Determine whether RTTI type should be used.
> 
> gdb/testsuite/ChangeLog:
> 
> 2011-12-02  Anton Gorenkov <xgsa@yandex.ru>
> 
>         PR mi/13393
> 
>         * gdb.mi/mi-var-rtti.cc: New file.
>         * gdb.mi/mi-var-rtti.exp: New file.

The testcase names should be unique so that one can find one if some FAILs,
they are not unique:
      5 gdb.mi/mi-var-rtti.exp: -interpreter-exec console "set print object on"
      5 gdb.mi/mi-var-rtti.exp: -interpreter-exec console "set print object off"
      4 gdb.mi/mi-var-rtti.exp: list children of ptr.public (without RTTI)
      4 gdb.mi/mi-var-rtti.exp: list children of ptr (without RTTI)
      2 gdb.mi/mi-var-rtti.exp: update ptr
      2 gdb.mi/mi-var-rtti.exp: list children of ptr.public (with RTTI)
      2 gdb.mi/mi-var-rtti.exp: list children of ptr.Base.public (with RTTI)
      2 gdb.mi/mi-var-rtti.exp: list children of ptr.Base (with RTTI)
      2 gdb.mi/mi-var-rtti.exp: list children of ptr (with RTTI)
      2 gdb.mi/mi-var-rtti.exp: delete varobj for ptr
      2 gdb.mi/mi-var-rtti.exp: create varobj for ptr
      2 gdb.mi/mi-var-rtti.exp: check ptr->C (with RTTI)
      2 gdb.mi/mi-var-rtti.exp: check ptr->B (with RTTI)
      2 gdb.mi/mi-var-rtti.exp: check ptr->A (without RTTI)
      2 gdb.mi/mi-var-rtti.exp: check ptr->A (with RTTI) 


> 

> diff --git a/gdb/valops.c b/gdb/valops.c
> index cb39677..b4ebe36 100644
> --- a/gdb/valops.c
> +++ b/gdb/valops.c
> @@ -1774,15 +1774,7 @@ value_ind (struct value *arg1)
>  			      (value_as_address (arg1)
>  			       - value_pointed_to_offset (arg1)));
>  
> -      /* Re-adjust type.  */
> -      deprecated_set_value_type (arg2, TYPE_TARGET_TYPE (base_type));
> -      /* Add embedding info.  */
> -      set_value_enclosing_type (arg2, enc_type);
> -      set_value_embedded_offset (arg2, value_pointed_to_offset (arg1));
> -
> -      /* We may be pointing to an object of some derived type.  */
> -      arg2 = value_full_object (arg2, NULL, 0, 0, 0);
> -      return arg2;
> +      return readjust_value_type (arg2, enc_type, base_type, arg1);
>      }
>  
>    error (_("Attempt to take contents of a non-pointer value."));
> @@ -3528,23 +3520,48 @@ value_maybe_namespace_elt (const struct type *curtype,
>    return result;
>  }
>  
> -/* Given a pointer value V, find the real (RTTI) type of the object it
> -   points to.
> +/* Given a pointer or a reference value V, find its real (RTTI) type.
>  
>     Other parameters FULL, TOP, USING_ENC as with value_rtti_type()
>     and refer to the values computed for the object pointed to.  */
>  
>  struct type *
> -value_rtti_target_type (struct value *v, int *full, 
> -			int *top, int *using_enc)
> +value_rtti_indirect_type (struct value *v, int *full, 
> +			  int *top, int *using_enc)
>  {
>    struct value *target;
> +  struct type *type, *real_type, *target_type;
> +
> +  type = value_type (v);
> +  type = check_typedef (type);
> +  if (TYPE_CODE (type) == TYPE_CODE_REF)
> +    target = coerce_ref (v);
> +  else if (TYPE_CODE (type) == TYPE_CODE_PTR)
> +    target = value_ind (v);
> +  else
> +    return NULL;
>  
> -  target = value_ind (v);
> +  real_type = value_rtti_type (target, full, top, using_enc);
>  
> -  return value_rtti_type (target, full, top, using_enc);
> +  if (real_type)
> +    {
> +      /* Copy qualifiers to the referenced object.  */
> +      target_type = value_type (target);
> +      real_type = make_cv_type (TYPE_CONST (target_type),
> +                                TYPE_VOLATILE (target_type), real_type, NULL);

Use tabs, not spaces.
http://www.gnu.org/prep/standards/standards.html#Formatting
GNU indent options


> +      if (TYPE_CODE (type) == TYPE_CODE_REF)
> +        real_type = lookup_reference_type (real_type);
> +      else if (TYPE_CODE (type) == TYPE_CODE_PTR)
> +        real_type = lookup_pointer_type (real_type);

Either remove "if (TYPE_CODE (type) == TYPE_CODE_PTR)" as it must be always
true here anyway, either
	else /* TYPE_CODE (type) == TYPE_CODE_PTR */
          real_type = lookup_pointer_type (real_type);
or:
	else if (TYPE_CODE (type) == TYPE_CODE_PTR)
          real_type = lookup_pointer_type (real_type);
	else
	  internal_error (...);


Empty line before a comment.

> +      /* Copy qualifiers to the pointer/reference.  */
> +      real_type = make_cv_type (TYPE_CONST (type), TYPE_VOLATILE (type),
> +                                real_type, NULL);
> +    }
> +
> +  return real_type;
>  }
>  
> +

Excessive newline.


>  /* Given a value pointed to by ARGP, check its real run-time type, and
>     if that is different from the enclosing type, create a new value
>     using the real run-time type as the enclosing type (and of the same
> diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
> index 3461b08..d81d07d 100644
> --- a/gdb/c-valprint.c
> +++ b/gdb/c-valprint.c
> @@ -698,22 +698,12 @@ c_value_print (struct value *val, struct ui_file *stream,
>  
>  	  if (value_entirely_available (val))
>   	    {
> -	      real_type = value_rtti_target_type (val, &full, &top, &using_enc);
> +	      real_type = value_rtti_indirect_type (val, &full, &top, &using_enc);

More than 80 characters.

>  	      if (real_type)
>  		{
>  		  /* RTTI entry found.  */
> -		  if (TYPE_CODE (type) == TYPE_CODE_PTR)
> -		    {
> -		      /* Create a pointer type pointing to the real
> -			 type.  */
> -		      type = lookup_pointer_type (real_type);
> -		    }
> -		  else
> -		    {
> -		      /* Create a reference type referencing the real
> -			 type.  */
> -		      type = lookup_reference_type (real_type);
> -		    }
> +		  type = real_type;
> +
>  		  /* Need to adjust pointer value.  */
>  		  val = value_from_pointer (type, value_as_address (val) - top);
>  
> diff --git a/gdb/eval.c b/gdb/eval.c
> index 5d758d1..3d23d0f 100644
> --- a/gdb/eval.c
> +++ b/gdb/eval.c
> @@ -1990,16 +1990,9 @@ evaluate_subexp_standard (struct type *expect_type,
>          if (opts.objectprint && TYPE_TARGET_TYPE(type)
>              && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
>            {
> -            real_type = value_rtti_target_type (arg1, &full, &top, &using_enc);
> +            real_type = value_rtti_indirect_type (arg1, &full, &top, &using_enc);

More than 80 characters.

>              if (real_type)
> -              {
> -                if (TYPE_CODE (type) == TYPE_CODE_PTR)
> -                  real_type = lookup_pointer_type (real_type);
> -                else
> -                  real_type = lookup_reference_type (real_type);
> -
>                  arg1 = value_cast (real_type, arg1);
> -              }
>            }
>        }
>  
> diff --git a/gdb/testsuite/gdb.mi/mi-var-rtti.cc b/gdb/testsuite/gdb.mi/mi-var-rtti.cc
> new file mode 100644
> index 0000000..3622f3b
> --- /dev/null
> +++ b/gdb/testsuite/gdb.mi/mi-var-rtti.cc
> @@ -0,0 +1,184 @@
> +/* Copyright 2011 Free Software Foundation, Inc.

Just a reminder to update the year for the final commit.


> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +struct Base {
> +    Base() : A(1) {}
> +    virtual ~Base() {}  // Enforce type to have vtable
> +    int A;
> +};
> +
> +struct Derived : public Base {

It would be nice to test also multiple inheritance where non-zero
EMBEDDED_OFFSET gets involved with value_enclosing_type, that is some

	struct Derived : public First, public Base {

But your code probably works with it during some quick tests.


> +    Derived() : B(2), C(3) {}
> +    int B;
> +    int C;
> +};
> +
> +
> +void use_rtti_for_ptr_test ()
> +{
> +  /*: BEGIN: use_rtti_for_ptr :*/
> +	Derived d;
> +	Base* ptr = &d;
> +	const Base* constPtr = &d;
> +	Base* const ptrConst = &d;
> +	Base const* const constPtrConst = &d;
> +  /*: 
> +	mi_var_rtti__set_print_object off
> +	mi_var_rtti__check_derived_class_without_rtti ptr {Base \*}
> +	mi_var_rtti__check_derived_class_without_rtti constPtr {const Base \*}
> +	mi_var_rtti__check_derived_class_without_rtti ptrConst {Base \* const}
> +	mi_var_rtti__check_derived_class_without_rtti constPtrConst {const Base \* const}
> +
> +	mi_var_rtti__set_print_object on
> +	mi_var_rtti__check_derived_class_with_rtti ptr {Derived \*}
> +	mi_var_rtti__check_derived_class_with_rtti constPtr {const Derived \*}
> +	mi_var_rtti__check_derived_class_with_rtti ptrConst {Derived \* const}
> +	mi_var_rtti__check_derived_class_with_rtti constPtrConst {const Derived \* const}
> +  :*/
> +	return;
> +  /*: END: use_rtti_for_ptr :*/
> +}
> +
> +
> +void use_rtti_for_ref_test ()
> +{
> +  /*: BEGIN: use_rtti_for_ref :*/
> +	Derived d;
> +	Base& ref = d;
> +	const Base& constRef = d;
> +  /*: 
> +	mi_var_rtti__set_print_object off
> +	mi_var_rtti__check_derived_class_without_rtti ref {Base \&}
> +	mi_var_rtti__check_derived_class_without_rtti constRef {const Base \&}
> +
> +	mi_var_rtti__set_print_object on
> +	mi_var_rtti__check_derived_class_with_rtti ref {Derived \&}
> +	mi_var_rtti__check_derived_class_with_rtti constRef {const Derived \&}
> +  :*/
> +	return;
> +  /*: END: use_rtti_for_ref :*/
> +}
> +
> +
> +void use_rtti_for_ptr_child_test ()
> +{
> +  /*: BEGIN: use_rtti_for_ptr_child :*/
> +	Derived d;
> +	struct S {	
> +		Base* ptr;
> +		const Base* constPtr;
> +		Base* const ptrConst;
> +		Base const* const constPtrConst;
> +		S ( Base* v ) :
> +			ptr ( v ),
> +			constPtr ( v ),
> +			ptrConst ( v ),
> +			constPtrConst ( v ) {}
> +	} s ( &d );
> +  /*: 
> +	mi_var_rtti__set_print_object off
> +	mi_var_rtti__check_derived_class_without_rtti s.ptr {Base \*}
> +	mi_var_rtti__check_derived_class_without_rtti s.constPtr {const Base \*}
> +	mi_var_rtti__check_derived_class_without_rtti s.ptrConst {Base \* const}
> +	mi_var_rtti__check_derived_class_without_rtti s.constPtrConst {const Base \* const}
> +
> +	mi_var_rtti__set_print_object on
> +	mi_var_rtti__check_derived_class_with_rtti s.ptr {Derived \*}
> +	mi_var_rtti__check_derived_class_with_rtti s.constPtr {const Derived \*}
> +	mi_var_rtti__check_derived_class_with_rtti s.ptrConst {Derived \* const}
> +	mi_var_rtti__check_derived_class_with_rtti s.constPtrConst {const Derived \* const}
> +  :*/
> +	return;
> +  /*: END: use_rtti_for_ptr_child :*/
> +}
> +
> +
> +void use_rtti_for_ref_child_test ()
> +{
> +  /*: BEGIN: use_rtti_for_ref_child :*/
> +	Derived d;
> +	struct S {	
> +		Base& ref;
> +		const Base& constRef;
> +		S ( Base& v ) :
> +			ref ( v ),
> +			constRef ( v ) {}
> +	} s ( d );
> +  /*: 
> +	mi_var_rtti__set_print_object off
> +	mi_var_rtti__check_derived_class_without_rtti s.ref {Base \&}
> +	mi_var_rtti__check_derived_class_without_rtti s.constRef {const Base \&}
> +
> +	mi_var_rtti__set_print_object on
> +	mi_var_rtti__check_derived_class_with_rtti s.ref {Derived \&}
> +	mi_var_rtti__check_derived_class_with_rtti s.constRef {const Derived \&}
> +  :*/
> +	return;
> +  /*: END: use_rtti_for_ref_child :*/
> +}
> +
> +void type_update_when_use_rtti_test ()
> +{
> +  /*: BEGIN: type_update_when_use_rtti :*/
> +	Derived d;
> +  /*: 
> +	mi_var_rtti__set_print_object on
> +	mi_create_varobj_checked VAR ptr {Base \*} "create varobj for ptr"
> +	mi_var_rtti__check_derived_children_without_rtti ptr
> +  :*/
> +
> +	Base* ptr = &d;
> +  /*: 
> +	mi_varobj_update_with_type_change VAR {Derived \*} 2 "update ptr"
> +	mi_var_rtti__check_derived_children_with_rtti ptr
> +	mi_var_rtti__check_derived_content_with_rtti ptr
> +	mi_delete_varobj VAR "delete varobj for ptr"
> +  :*/
> +	return;
> +  /*: END: type_update_when_use_rtti :*/
> +}
> +
> +void skip_type_update_when_not_use_rtti_test ()
> +{
> +  /*: BEGIN: skip_type_update_when_not_use_rtti :*/
> +	Derived d;
> +  /*: 
> +	mi_var_rtti__set_print_object off
> +	mi_create_varobj_checked VAR ptr {Base \*} "create varobj for ptr"
> +	mi_var_rtti__check_derived_children_without_rtti ptr
> +  :*/
> +
> +	Base* ptr = &d;
> +  /*: 
> +	mi_varobj_update VAR {} "update ptr"
> +	mi_var_rtti__check_derived_children_without_rtti ptr
> +	mi_var_rtti__check_derived_content_without_rtti ptr
> +	mi_delete_varobj VAR "delete varobj for ptr"
> +  :*/
> +	return;
> +  /*: END: skip_type_update_when_not_use_rtti :*/
> +}
> +
> +int main ()
> +{
> +	use_rtti_for_ptr_test();
> +	use_rtti_for_ref_test();
> +	use_rtti_for_ptr_child_test();
> +	use_rtti_for_ref_child_test();
> +	type_update_when_use_rtti_test();
> +	skip_type_update_when_not_use_rtti_test();
> +	return 0;
> +}
> diff --git a/gdb/testsuite/gdb.mi/mi-var-rtti.exp b/gdb/testsuite/gdb.mi/mi-var-rtti.exp
> new file mode 100644
> index 0000000..177b63c
> --- /dev/null
> +++ b/gdb/testsuite/gdb.mi/mi-var-rtti.exp
> @@ -0,0 +1,108 @@
> +# Copyright 2011 Free Software Foundation, Inc.

Just a reminder to update the year for the final commit.

> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +if { [skip_cplus_tests] } { continue }
> +
> +load_lib mi-support.exp
> +set MIFLAGS "-i=mi"
> +
> +gdb_exit
> +if [mi_gdb_start] {
> +    continue
> +}
> +
> +set testfile mi-var-rtti
> +set srcfile "$testfile.cc"
> +set binfile $objdir/$subdir/$testfile
> +
> +if [get_compiler_info ${binfile} "c++"] {
> +    return -1;
> +}
> +
> +if {[gdb_compile $srcdir/$subdir/$srcfile $binfile executable {debug c++}] != ""} {
> +  untested $testfile.exp
> +  return -1
> +}

build_executable is preferred nowadays.


> +
> +mi_gdb_load ${binfile}
> +
> +mi_prepare_inline_tests $srcfile
> +
> +# Enable using RTTI to determine real types of the objects
> +proc mi_var_rtti__set_print_object {state} {
> +  mi_gdb_test "-interpreter-exec console \"set print object ${state}\"" \
> +    {\^done} \
> +    "-interpreter-exec console \"set print object ${state}\""
> +}
> +
> +proc mi_var_rtti__check_derived_children_without_rtti {var_name} {
> +  mi_list_varobj_children VAR {
> +     { VAR.public			public	1		 }
> +  } "list children of ${var_name} (without RTTI)"
> +  mi_list_varobj_children "VAR.public" {
> +     { VAR.public.A			A		0	int }
> +  } "list children of ${var_name}.public (without RTTI)"
> +}
> +
> +proc mi_var_rtti__check_derived_content_without_rtti {var_name} {
> +  mi_check_varobj_value VAR.public.A		1 "check ${var_name}->A (without RTTI)"
> +}
> +
> +proc mi_var_rtti__check_derived_class_without_rtti {var_name var_type} {
> +  mi_create_varobj_checked VAR ${var_name} ${var_type} "create varobj for ${var_name} (without RTTI)"
> +  mi_var_rtti__check_derived_children_without_rtti ${var_name}
> +  mi_var_rtti__check_derived_content_without_rtti ${var_name}
> +  mi_delete_varobj VAR "delete varobj for ${var_name} (without RTTI)"
> +}
> +
> +proc mi_var_rtti__check_derived_children_with_rtti {var_name} {
> +    mi_list_varobj_children VAR {
> +       { VAR.Base			Base	1	Base }
> +       { VAR.public			public	2		 }
> +    } "list children of ${var_name} (with RTTI)"
> +    mi_list_varobj_children "VAR.Base" {
> +       { VAR.Base.public	public 1 }
> +    } "list children of ${var_name}.Base (with RTTI)"
> +    mi_list_varobj_children "VAR.Base.public" {
> +       { VAR.Base.public.A	A		0	int	}
> +    } "list children of ${var_name}.Base.public (with RTTI)"
> +    mi_list_varobj_children "VAR.public" {
> +       { VAR.public.B		B		0	int }
> +       { VAR.public.C		C		0	int }
> +    } "list children of ${var_name}.public (with RTTI)"
> +}
> +
> +proc mi_var_rtti__check_derived_content_with_rtti {var_name} {
> +    mi_check_varobj_value VAR.Base.public.A	1 "check ${var_name}->A (with RTTI)"
> +    mi_check_varobj_value VAR.public.B		2 "check ${var_name}->B (with RTTI)"
> +    mi_check_varobj_value VAR.public.C		3 "check ${var_name}->C (with RTTI)"
> +}
> +
> +proc mi_var_rtti__check_derived_class_with_rtti {var_name var_type} {
> +    mi_create_varobj_checked VAR ${var_name} ${var_type} "create varobj for ${var_name} (with RTTI)"
> +	mi_var_rtti__check_derived_children_with_rtti ${var_name}
> +	mi_var_rtti__check_derived_content_with_rtti ${var_name}
> +    mi_delete_varobj VAR "delete varobj for ${var_name} (with RTTI)"
> +}
> +
> +mi_run_inline_test use_rtti_for_ptr
> +mi_run_inline_test use_rtti_for_ref
> +mi_run_inline_test use_rtti_for_ptr_child
> +mi_run_inline_test use_rtti_for_ref_child
> +mi_run_inline_test type_update_when_use_rtti
> +mi_run_inline_test skip_type_update_when_not_use_rtti
> +
> +mi_gdb_exit
> +return 0
> diff --git a/gdb/typeprint.c b/gdb/typeprint.c
> index cf4158d..6546c98 100644
> --- a/gdb/typeprint.c
> +++ b/gdb/typeprint.c
> @@ -140,16 +140,7 @@ whatis_exp (char *exp, int show)
>        if (((TYPE_CODE (type) == TYPE_CODE_PTR)
>  	   || (TYPE_CODE (type) == TYPE_CODE_REF))
>  	  && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
> -        {
> -          real_type = value_rtti_target_type (val, &full, &top, &using_enc);
> -          if (real_type)
> -            {
> -              if (TYPE_CODE (type) == TYPE_CODE_PTR)
> -                real_type = lookup_pointer_type (real_type);
> -              else
> -                real_type = lookup_reference_type (real_type);
> -            }
> -        }
> +        real_type = value_rtti_indirect_type (val, &full, &top, &using_enc);
>        else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
>  	real_type = value_rtti_type (val, &full, &top, &using_enc);
>      }
> diff --git a/gdb/value.c b/gdb/value.c
> index d263d0c..15726c0 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -821,6 +821,35 @@ value_enclosing_type (struct value *value)
>    return value->enclosing_type;
>  }
>  
> +/* Look at value.h for description.  */

Empty line after function comment.

> +struct type *
> +value_actual_type (struct value *value, int resolve_simple_types)
> +{
> +  struct value_print_options opts;
> +  struct value *target;
> +  struct type *result;
> +
> +  get_user_print_options (&opts);
> +
> +  result = value_type (value);
> +  if (opts.objectprint)
> +  {

This block should be indented by 2 more characters right.


> +    if (TYPE_CODE (result) == TYPE_CODE_PTR
> +        || TYPE_CODE (result) == TYPE_CODE_REF)

Use tabs, not spaces.


> +    {

This block should be indented by 2 more characters right.


> +      struct type *real_type;
> +
> +      real_type = value_rtti_indirect_type (value, 0, 0, 0);

         real_type = value_rtti_indirect_type (value, NULL, NULL, NULL);
(I am aware, it is compatible.)


> +      if (real_type)
> +        result = real_type;

Use tabs, not spaces.


> +    }
> +    else if (resolve_simple_types)
> +      result = value_enclosing_type (value);
> +  }
> +
> +  return result;
> +}
> +
>  static void
>  require_not_optimized_out (const struct value *value)
>  {
> @@ -3110,10 +3139,26 @@ coerce_ref_if_computed (const struct value *arg)
>  }
>  

Missing the comment:
	/* Look at value.h for description.  */

>  struct value *
> +readjust_value_type (struct value *value, struct type *enc_type,
> +                     struct type *original_type, struct value *original_value)
> +{
> +  /* Re-adjust type.  */
> +  deprecated_set_value_type (value, TYPE_TARGET_TYPE (original_type));
> +
> +  /* Add embedding info.  */
> +  set_value_enclosing_type (value, enc_type);
> +  set_value_embedded_offset (value, value_pointed_to_offset (original_value));
> +
> +  /* We may be pointing to an object of some derived type.  */
> +  return value_full_object (value, NULL, 0, 0, 0);
> +}
> +
> +struct value *
>  coerce_ref (struct value *arg)
>  {
>    struct type *value_type_arg_tmp = check_typedef (value_type (arg));
>    struct value *retval;
> +  struct type *enc_type;
>  
>    retval = coerce_ref_if_computed (arg);
>    if (retval)
> @@ -3122,9 +3167,13 @@ coerce_ref (struct value *arg)
>    if (TYPE_CODE (value_type_arg_tmp) != TYPE_CODE_REF)
>      return arg;
>  
> -  return value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp),
> -			unpack_pointer (value_type (arg),
> -					value_contents (arg)));
> +  enc_type = check_typedef (value_enclosing_type (arg));
> +  enc_type = TYPE_TARGET_TYPE (enc_type);
> +
> +  retval = value_at_lazy (enc_type,
> +                          unpack_pointer (value_type (arg),
> +                                          value_contents (arg)));
> +  return readjust_value_type (retval, enc_type, value_type_arg_tmp, arg);
>  }
>  
>  struct value *
> diff --git a/gdb/value.h b/gdb/value.h
> index d2c58ec..7345c71 100644
> --- a/gdb/value.h
> +++ b/gdb/value.h
> @@ -139,6 +139,16 @@ extern struct type *value_enclosing_type (struct value *);
>  extern void set_value_enclosing_type (struct value *val,
>  				      struct type *new_type);
>  
> +/* Returns value_type or value_enclosing_type depending on
> +   value_print_options.objectprint.
> +
> +   If RESOLVE_SIMPLE_TYPES is 0 the enclosing type will be resolved
> +   only for pointers and references, else it will be returned
> +   for all the types (e.g. structures).  This option is useful
> +   to prevent retrieving enclosing type for the base classes fields.  */
> +
> +extern struct type *value_actual_type (struct value *value, int resolve_simple_types);

More than 80 characters.

> +
>  extern int value_pointed_to_offset (struct value *value);
>  extern void set_value_pointed_to_offset (struct value *value, int val);
>  extern int value_embedded_offset (struct value *value);
> @@ -353,6 +363,13 @@ extern short *deprecated_value_regnum_hack (struct value *);
>  
>  extern struct value *coerce_ref_if_computed (const struct value *arg);
>  
> +/* Setup a new value type and enclosing value type for dereferenced value.
> +   It is a common implementation for coerce_ref and value_ind.  */
> +
> +extern struct value *
> +readjust_value_type (struct value *value, struct type *enc_type,
> +                     struct type *original_type, struct value *original_value);

Use tabs, not spaces.  The function name should be more specific, such as
readjust_indirect_value_type.  Missing comment on the parameters.  Comment
that VALUE will will be modified by this function.


> +
>  /* Convert a REF to the object referenced.  */
>  
>  extern struct value *coerce_ref (struct value *value);
> @@ -617,8 +634,8 @@ extern struct value *value_primitive_field (struct value *arg1, int offset,
>  					    struct type *arg_type);
>  
>  
> -extern struct type *value_rtti_target_type (struct value *, int *, int *,
> -					    int *);
> +extern struct type *value_rtti_indirect_type (struct value *, int *, int *,
> +					      int *);
>  
>  extern struct value *value_full_object (struct value *, struct type *, int,
>  					int, int);
> diff --git a/gdb/varobj.c b/gdb/varobj.c
> index 7c68a93..dfeb71b 100644
> --- a/gdb/varobj.c
> +++ b/gdb/varobj.c
> @@ -659,8 +659,18 @@ varobj_create (char *objname,
>  
>  	  var->type = value_type (type_only_value);
>  	}
> -      else 
> -	var->type = value_type (value);
> +	else
> +	{

This block should be indented by 2 more characters right.

> +	  struct type *enclosing_type;
> +
> +	  var->type = value_type (value);
> +	  enclosing_type = value_actual_type (value, 0);
> +	  if (check_typedef (enclosing_type) != check_typedef (var->type))

As noted by Tom, I would extend it that maybe value_actual_type should return
whether it did any action as that check_typedef != check_typedef check is
fragile in general, the same type has multiple instances.


> +	    {
> +	      var->type = enclosing_type;
> +	      value = value_cast (enclosing_type, value);
> +	    }
> +	}
>  
>        install_new_value (var, value, 1 /* Initial assignment */);
>  
> @@ -2194,7 +2204,7 @@ create_child_with_value (struct varobj *parent, int index, const char *name,
>    if (value != NULL)
>      /* If the child had no evaluation errors, var->value
>         will be non-NULL and contain a valid type.  */
> -    child->type = value_type (value);
> +    child->type = value_actual_type (value, 0);
>    else
>      /* Otherwise, we must compute the type.  */
>      child->type = (*child->root->lang->type_of_child) (child->parent, 
> @@ -2480,6 +2490,7 @@ static struct value *
>  value_of_root (struct varobj **var_handle, int *type_changed)
>  {
>    struct varobj *var;
> +  struct value_print_options opts;
>  
>    if (var_handle == NULL)
>      return NULL;
> @@ -2492,7 +2503,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
>    if (!is_root_p (var))
>      return NULL;
>  
> -  if (var->root->floating)
> +  get_user_print_options (&opts);
> +  if (var->root->floating || opts.objectprint)
>      {
>        struct varobj *tmp_var;
>        char *old_type, *new_type;
> @@ -2781,6 +2793,10 @@ varobj_floating_p (struct varobj *var)
>     to all types and dereferencing pointers to
>     structures.
>  
> +   If LOOKUP_ACTUAL_TYPE is set the enclosing type of the
> +   value will be fetched and if it differs from static type
> +   the value will be casted to it.
> +
>     Both TYPE and *TYPE should be non-null.  VALUE
>     can be null if we want to only translate type.
>     *VALUE can be null as well -- if the parent
> @@ -2792,7 +2808,8 @@ varobj_floating_p (struct varobj *var)
>  static void
>  adjust_value_for_child_access (struct value **value,
>  				  struct type **type,
> -				  int *was_ptr)
> +				  int *was_ptr,
> +				  int lookup_actual_type)
>  {
>    gdb_assert (type && *type);
>  
> @@ -2832,6 +2849,19 @@ adjust_value_for_child_access (struct value **value,
>    /* The 'get_target_type' function calls check_typedef on
>       result, so we can immediately check type code.  No
>       need to call check_typedef here.  */
> +
> +  /* Access a real type of the value (if necessary and possible).  */
> +  if (value && *value && lookup_actual_type)
> +    {
> +      struct type *enclosing_type;
> +
> +      enclosing_type = value_actual_type (*value, 1);
> +      if (check_typedef (enclosing_type) != check_typedef (*type))

The same check_typedef != check_typedef and value_actual_type comment like
above.

> +        {
> +          *type = enclosing_type;
> +          *value = value_cast (enclosing_type, *value);
> +        }
> +    }
>  }
>  
>  /* C */
> @@ -2842,7 +2872,7 @@ c_number_of_children (struct varobj *var)
>    int children = 0;
>    struct type *target;
>  
> -  adjust_value_for_child_access (NULL, &type, NULL);
> +  adjust_value_for_child_access (NULL, &type, NULL, 0);
>    target = get_target_type (type);
>  
>    switch (TYPE_CODE (type))
> @@ -2957,7 +2987,7 @@ c_describe_child (struct varobj *parent, int index,
>        *cfull_expression = NULL;
>        parent_expression = varobj_get_path_expr (parent);
>      }
> -  adjust_value_for_child_access (&value, &type, &was_ptr);
> +  adjust_value_for_child_access (&value, &type, &was_ptr, 0);
>        
>    switch (TYPE_CODE (type))
>      {
> @@ -3223,16 +3253,28 @@ c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
>  static int
>  cplus_number_of_children (struct varobj *var)
>  {
> +  struct value *value = 0;

Please use:
     struct value *value = NULL;


>    struct type *type;
>    int children, dont_know;
> +  int lookup_actual_type = 0;
> +  struct value_print_options opts;
>  
>    dont_know = 1;
>    children = 0;
>  
> +  get_user_print_options (&opts);
> +
>    if (!CPLUS_FAKE_CHILD (var))
>      {
>        type = get_value_type (var);
> -      adjust_value_for_child_access (NULL, &type, NULL);

Empty line before comment.

> +      /* It is necessary to access a real type (via RTTI).  */
> +      if (opts.objectprint)
> +        {
> +          value = var->value;
> +          lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
> +                                || TYPE_CODE (var->type) == TYPE_CODE_PTR);

Use tabs, not spaces.


> +        }
> +      adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
>  
>        if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
>  	  ((TYPE_CODE (type)) == TYPE_CODE_UNION))
> @@ -3259,7 +3301,15 @@ cplus_number_of_children (struct varobj *var)
>        int kids[3];
>  
>        type = get_value_type (var->parent);
> -      adjust_value_for_child_access (NULL, &type, NULL);
> +
> +      /* It is necessary to access a real type (via RTTI).  */
> +      if (opts.objectprint)
> +        {
> +          value = var->parent->value;
> +          lookup_actual_type = (TYPE_CODE (var->parent->type) == TYPE_CODE_REF
> +                                || TYPE_CODE (var->parent->type) == TYPE_CODE_PTR);

More than 80 characters.

> +        }
> +      adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
>  
>        cplus_class_num_children (type, kids);
>        if (strcmp (var->name, "public") == 0)
> @@ -3341,7 +3391,10 @@ cplus_describe_child (struct varobj *parent, int index,
>    struct value *value;
>    struct type *type;
>    int was_ptr;
> +  int lookup_actual_type = 0;
>    char *parent_expression = NULL;
> +  struct varobj *var;
> +  struct value_print_options opts;
>  
>    if (cname)
>      *cname = NULL;
> @@ -3352,22 +3405,18 @@ cplus_describe_child (struct varobj *parent, int index,
>    if (cfull_expression)
>      *cfull_expression = NULL;
>  
> -  if (CPLUS_FAKE_CHILD (parent))
> -    {
> -      value = parent->parent->value;
> -      type = get_value_type (parent->parent);
> -      if (cfull_expression)
> -	parent_expression = varobj_get_path_expr (parent->parent);
> -    }
> -  else
> -    {
> -      value = parent->value;
> -      type = get_value_type (parent);
> -      if (cfull_expression)
> -	parent_expression = varobj_get_path_expr (parent);
> -    }
> +  get_user_print_options (&opts);
> +
> +  var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
> +  if (opts.objectprint)
> +    lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
> +                          || TYPE_CODE (var->type) == TYPE_CODE_PTR);
> +  value = var->value;
> +  type = get_value_type (var);
> +  if (cfull_expression)
> +    parent_expression = varobj_get_path_expr (var);
>  
> -  adjust_value_for_child_access (&value, &type, &was_ptr);
> +  adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type);
>  
>    if (TYPE_CODE (type) == TYPE_CODE_STRUCT
>        || TYPE_CODE (type) == TYPE_CODE_UNION)



Thanks,
Jan


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]