mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
gdb/
* infcall.c (value_arg_coerce): Use value_cast_pointers for references. Avoid value_cast to a reference type. Don't silently convert pointers to references. * valops.c (value_cast_pointers): New, based on value_cast. (value_cast): Use it. Reject reference types. (value_ref): New. (typecmp): Use it. * value.h (value_cast_pointers, value_ref): New prototypes. gdb/testsuite/ * gdb.cp/ref-params.exp: New test. * gdb.cp/ref-params.cc: New source file. * gdb.cp/Makefile.in (EXECUTABLES): Add ref-params.
This commit is contained in:
parent
d49c44d5f1
commit
fb93362492
@ -1,3 +1,15 @@
|
||||
2006-07-13 Paul N. Hilfinger <Hilfinger@adacore.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* infcall.c (value_arg_coerce): Use value_cast_pointers for
|
||||
references. Avoid value_cast to a reference type. Don't silently
|
||||
convert pointers to references.
|
||||
* valops.c (value_cast_pointers): New, based on value_cast.
|
||||
(value_cast): Use it. Reject reference types.
|
||||
(value_ref): New.
|
||||
(typecmp): Use it.
|
||||
* value.h (value_cast_pointers, value_ref): New prototypes.
|
||||
|
||||
2006-07-12 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* remote.c (unpack_varlen_hex): Correct type of retval.
|
||||
|
@ -109,14 +109,20 @@ value_arg_coerce (struct value *arg, struct type *param_type,
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_REF:
|
||||
if (TYPE_CODE (arg_type) != TYPE_CODE_REF
|
||||
&& TYPE_CODE (arg_type) != TYPE_CODE_PTR)
|
||||
{
|
||||
arg = value_addr (arg);
|
||||
deprecated_set_value_type (arg, param_type);
|
||||
return arg;
|
||||
}
|
||||
break;
|
||||
{
|
||||
struct value *new_value;
|
||||
|
||||
if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
|
||||
return value_cast_pointers (type, arg);
|
||||
|
||||
/* Cast the value to the reference's target type, and then
|
||||
convert it back to a reference. This will issue an error
|
||||
if the value was not previously in memory - in some cases
|
||||
we should clearly be allowing this, but how? */
|
||||
new_value = value_cast (TYPE_TARGET_TYPE (type), arg);
|
||||
new_value = value_ref (new_value);
|
||||
return new_value;
|
||||
}
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_CHAR:
|
||||
case TYPE_CODE_BOOL:
|
||||
|
@ -1,3 +1,10 @@
|
||||
2006-07-13 Paul N. Hilfinger <Hilfinger@adacore.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.cp/ref-params.exp: New test.
|
||||
* gdb.cp/ref-params.cc: New source file.
|
||||
* gdb.cp/Makefile.in (EXECUTABLES): Add ref-params.
|
||||
|
||||
2006-07-08 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* gdb.arch/alpha-step.exp (test_stepi): Do not include trailing
|
||||
|
@ -3,7 +3,8 @@ srcdir = @srcdir@
|
||||
|
||||
EXECUTABLES = ambiguous annota2 anon-union cplusfuncs cttiadd \
|
||||
derivation inherit local member-ptr method misc \
|
||||
overload ovldbreak ref-typ ref-typ2 templates userdef virtfunc namespace ref-types
|
||||
overload ovldbreak ref-typ ref-typ2 templates userdef virtfunc namespace \
|
||||
ref-types ref-params
|
||||
|
||||
all info install-info dvi install uninstall installcheck check:
|
||||
@echo "Nothing to be done for $@..."
|
||||
|
80
gdb/testsuite/gdb.cp/ref-params.cc
Normal file
80
gdb/testsuite/gdb.cp/ref-params.cc
Normal file
@ -0,0 +1,80 @@
|
||||
/* This test script is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2006
|
||||
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 2 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, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Author: Paul N. Hilfinger, AdaCore Inc. */
|
||||
|
||||
struct Parent {
|
||||
Parent (int id0) : id(id0) { }
|
||||
int id;
|
||||
};
|
||||
|
||||
struct Child : public Parent {
|
||||
Child (int id0) : Parent(id0) { }
|
||||
};
|
||||
|
||||
int f1(Parent& R)
|
||||
{
|
||||
return R.id; /* Set breakpoint marker3 here. */
|
||||
}
|
||||
|
||||
int f2(Child& C)
|
||||
{
|
||||
return f1(C); /* Set breakpoint marker2 here. */
|
||||
}
|
||||
|
||||
struct OtherParent {
|
||||
OtherParent (int other_id0) : other_id(other_id0) { }
|
||||
int other_id;
|
||||
};
|
||||
|
||||
struct MultiChild : public Parent, OtherParent {
|
||||
MultiChild (int id0) : Parent(id0), OtherParent(id0 * 2) { }
|
||||
};
|
||||
|
||||
int mf1(OtherParent& R)
|
||||
{
|
||||
return R.other_id;
|
||||
}
|
||||
|
||||
int mf2(MultiChild& C)
|
||||
{
|
||||
return mf1(C);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Child Q(42);
|
||||
Child& QR = Q;
|
||||
|
||||
#ifdef usestubs
|
||||
set_debug_traps();
|
||||
breakpoint();
|
||||
#endif
|
||||
|
||||
/* Set breakpoint marker1 here. */
|
||||
|
||||
f2(Q);
|
||||
f2(QR);
|
||||
|
||||
MultiChild MQ(53);
|
||||
MultiChild& MQR = MQ;
|
||||
|
||||
mf2(MQ); /* Set breakpoint MQ here. */
|
||||
}
|
79
gdb/testsuite/gdb.cp/ref-params.exp
Normal file
79
gdb/testsuite/gdb.cp/ref-params.exp
Normal file
@ -0,0 +1,79 @@
|
||||
# Tests for reference parameters of types and their subtypes in GDB.
|
||||
# Copyright 2006 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 2 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
# written by Paul N. Hilfinger (Hilfinger@adacore.com)
|
||||
|
||||
if $tracelevel then {
|
||||
strace $tracelevel
|
||||
}
|
||||
|
||||
#
|
||||
# test running programs
|
||||
#
|
||||
set prms_id 0
|
||||
set bug_id 0
|
||||
|
||||
if { [skip_cplus_tests] } { continue }
|
||||
|
||||
set testfile "ref-params"
|
||||
set srcfile ${testfile}.cc
|
||||
set binfile ${objdir}/${subdir}/${testfile}
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
|
||||
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
|
||||
}
|
||||
|
||||
gdb_exit
|
||||
|
||||
proc gdb_start_again { text } {
|
||||
global srcdir
|
||||
global subdir
|
||||
global binfile
|
||||
global srcfile
|
||||
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
gdb_load ${binfile}
|
||||
|
||||
runto ${srcfile}:[gdb_get_line_number $text]
|
||||
}
|
||||
|
||||
gdb_start_again "marker1 here"
|
||||
gdb_test "print Q" ".*id = 42.*" "print value of a Child in main"
|
||||
gdb_test "print f1(Q)" ".* = 42.*" "print value of f1 on Child in main"
|
||||
gdb_test "print f2(Q)" ".* = 42.*" "print value of f2 on Child in main"
|
||||
|
||||
gdb_start_again "marker1 here"
|
||||
gdb_test "print f1(QR)" ".* = 42.*" "print value of f1 on (Child&) in main"
|
||||
|
||||
gdb_start_again "marker1 here"
|
||||
gdb_test "print f2(QR)" ".* = 42.*" "print value of f2 on (Child&) in main"
|
||||
|
||||
gdb_start_again "marker2 here"
|
||||
gdb_test "print C" ".*id = 42.*" "print value of Child& in f2"
|
||||
gdb_test "print f1(C)" ".* = 42.*" "print value of f1 on Child& in f2"
|
||||
|
||||
gdb_start_again "marker3 here"
|
||||
gdb_test "print R" ".*id = 42.*" "print value of Parent& in f1"
|
||||
|
||||
gdb_start_again "breakpoint MQ here"
|
||||
gdb_test "print f1(MQ)" ".* = 53"
|
||||
gdb_test "print mf1(MQ)" ".* = 106"
|
||||
gdb_test "print mf2(MQ)" ".* = 106"
|
||||
gdb_test "print f1(MQR)" ".* = 53"
|
||||
gdb_test "print mf1(MQR)" ".* = 106"
|
||||
gdb_test "print mf2(MQR)" ".* = 106"
|
130
gdb/valops.c
130
gdb/valops.c
@ -201,6 +201,70 @@ allocate_space_in_inferior (int len)
|
||||
return value_as_long (value_allocate_space_in_inferior (len));
|
||||
}
|
||||
|
||||
/* Cast one pointer or reference type to another. Both TYPE and
|
||||
the type of ARG2 should be pointer types, or else both should be
|
||||
reference types. Returns the new pointer or reference. */
|
||||
|
||||
struct value *
|
||||
value_cast_pointers (struct type *type, struct value *arg2)
|
||||
{
|
||||
struct type *type2 = check_typedef (value_type (arg2));
|
||||
struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2));
|
||||
|
||||
if (TYPE_CODE (t1) == TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT
|
||||
&& !value_logical_not (arg2))
|
||||
{
|
||||
struct value *v;
|
||||
|
||||
/* Look in the type of the source to see if it contains the
|
||||
type of the target as a superclass. If so, we'll need to
|
||||
offset the pointer rather than just change its type. */
|
||||
if (TYPE_NAME (t1) != NULL)
|
||||
{
|
||||
struct value *v2;
|
||||
|
||||
if (TYPE_CODE (type2) == TYPE_CODE_REF)
|
||||
v2 = coerce_ref (arg2);
|
||||
else
|
||||
v2 = value_ind (arg2);
|
||||
v = search_struct_field (type_name_no_tag (t1),
|
||||
v2, 0, t2, 1);
|
||||
if (v)
|
||||
{
|
||||
v = value_addr (v);
|
||||
deprecated_set_value_type (v, type);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look in the type of the target to see if it contains the
|
||||
type of the source as a superclass. If so, we'll need to
|
||||
offset the pointer rather than just change its type.
|
||||
FIXME: This fails silently with virtual inheritance. */
|
||||
if (TYPE_NAME (t2) != NULL)
|
||||
{
|
||||
v = search_struct_field (type_name_no_tag (t2),
|
||||
value_zero (t1, not_lval), 0, t1, 1);
|
||||
if (v)
|
||||
{
|
||||
CORE_ADDR addr2 = value_as_address (arg2);
|
||||
addr2 -= (VALUE_ADDRESS (v)
|
||||
+ value_offset (v)
|
||||
+ value_embedded_offset (v));
|
||||
return value_from_pointer (type, addr2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No superclass found, just change the pointer type. */
|
||||
deprecated_set_value_type (arg2, type);
|
||||
arg2 = value_change_enclosing_type (arg2, type);
|
||||
set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */
|
||||
return arg2;
|
||||
}
|
||||
|
||||
/* Cast value ARG2 to type TYPE and return as a value.
|
||||
More general than a C cast: accepts any two types of the same length,
|
||||
and if ARG2 is an lvalue it can be cast into anything at all. */
|
||||
@ -224,6 +288,10 @@ value_cast (struct type *type, struct value *arg2)
|
||||
arg2 = coerce_ref (arg2);
|
||||
type2 = check_typedef (value_type (arg2));
|
||||
|
||||
/* You can't cast to a reference type. See value_cast_pointers
|
||||
instead. */
|
||||
gdb_assert (code1 != TYPE_CODE_REF);
|
||||
|
||||
/* A cast to an undetermined-length array_type, such as (TYPE [])OBJECT,
|
||||
is treated like a cast to (TYPE [N])OBJECT,
|
||||
where N is sizeof(OBJECT)/sizeof(TYPE). */
|
||||
@ -369,50 +437,8 @@ value_cast (struct type *type, struct value *arg2)
|
||||
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
|
||||
{
|
||||
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
|
||||
{
|
||||
struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2));
|
||||
if (TYPE_CODE (t1) == TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT
|
||||
&& !value_logical_not (arg2))
|
||||
{
|
||||
struct value *v;
|
||||
return value_cast_pointers (type, arg2);
|
||||
|
||||
/* Look in the type of the source to see if it contains the
|
||||
type of the target as a superclass. If so, we'll need to
|
||||
offset the pointer rather than just change its type. */
|
||||
if (TYPE_NAME (t1) != NULL)
|
||||
{
|
||||
v = search_struct_field (type_name_no_tag (t1),
|
||||
value_ind (arg2), 0, t2, 1);
|
||||
if (v)
|
||||
{
|
||||
v = value_addr (v);
|
||||
deprecated_set_value_type (v, type);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look in the type of the target to see if it contains the
|
||||
type of the source as a superclass. If so, we'll need to
|
||||
offset the pointer rather than just change its type.
|
||||
FIXME: This fails silently with virtual inheritance. */
|
||||
if (TYPE_NAME (t2) != NULL)
|
||||
{
|
||||
v = search_struct_field (type_name_no_tag (t2),
|
||||
value_zero (t1, not_lval), 0, t1, 1);
|
||||
if (v)
|
||||
{
|
||||
CORE_ADDR addr2 = value_as_address (arg2);
|
||||
addr2 -= (VALUE_ADDRESS (v)
|
||||
+ value_offset (v)
|
||||
+ value_embedded_offset (v));
|
||||
return value_from_pointer (type, addr2);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* No superclass found, just fall through to change ptr type. */
|
||||
}
|
||||
deprecated_set_value_type (arg2, type);
|
||||
arg2 = value_change_enclosing_type (arg2, type);
|
||||
set_value_pointed_to_offset (arg2, 0); /* pai: chk_val */
|
||||
@ -886,6 +912,22 @@ value_addr (struct value *arg1)
|
||||
return arg2;
|
||||
}
|
||||
|
||||
/* Return a reference value for the object for which ARG1 is the contents. */
|
||||
|
||||
struct value *
|
||||
value_ref (struct value *arg1)
|
||||
{
|
||||
struct value *arg2;
|
||||
|
||||
struct type *type = check_typedef (value_type (arg1));
|
||||
if (TYPE_CODE (type) == TYPE_CODE_REF)
|
||||
return arg1;
|
||||
|
||||
arg2 = value_addr (arg1);
|
||||
deprecated_set_value_type (arg2, lookup_reference_type (type));
|
||||
return arg2;
|
||||
}
|
||||
|
||||
/* Given a value of a pointer type, apply the C unary * operator to it. */
|
||||
|
||||
struct value *
|
||||
@ -1106,7 +1148,7 @@ typecmp (int staticp, int varargs, int nargs,
|
||||
if (TYPE_CODE (tt2) == TYPE_CODE_ARRAY)
|
||||
t2[i] = value_coerce_array (t2[i]);
|
||||
else
|
||||
t2[i] = value_addr (t2[i]);
|
||||
t2[i] = value_ref (t2[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -325,6 +325,8 @@ extern struct value *value_ind (struct value *arg1);
|
||||
|
||||
extern struct value *value_addr (struct value *arg1);
|
||||
|
||||
extern struct value *value_ref (struct value *arg1);
|
||||
|
||||
extern struct value *value_assign (struct value *toval,
|
||||
struct value *fromval);
|
||||
|
||||
@ -367,6 +369,8 @@ extern struct type *value_rtti_target_type (struct value *, int *, int *,
|
||||
extern struct value *value_full_object (struct value *, struct type *, int,
|
||||
int, int);
|
||||
|
||||
extern struct value *value_cast_pointers (struct type *, struct value *);
|
||||
|
||||
extern struct value *value_cast (struct type *type, struct value *arg2);
|
||||
|
||||
extern struct value *value_zero (struct type *type, enum lval_type lv);
|
||||
|
Loading…
Reference in New Issue
Block a user