aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/infcall.c22
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.cp/Makefile.in3
-rw-r--r--gdb/testsuite/gdb.cp/ref-params.cc80
-rw-r--r--gdb/testsuite/gdb.cp/ref-params.exp79
-rw-r--r--gdb/valops.c130
-rw-r--r--gdb/value.h4
8 files changed, 284 insertions, 53 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4cd5bde..5ce4c80 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/infcall.c b/gdb/infcall.c
index c8a6334..3a1ad6a 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -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:
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 7e239a7..d811e0e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
diff --git a/gdb/testsuite/gdb.cp/Makefile.in b/gdb/testsuite/gdb.cp/Makefile.in
index 8f4a90e..0684650 100644
--- a/gdb/testsuite/gdb.cp/Makefile.in
+++ b/gdb/testsuite/gdb.cp/Makefile.in
@@ -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 $@..."
diff --git a/gdb/testsuite/gdb.cp/ref-params.cc b/gdb/testsuite/gdb.cp/ref-params.cc
new file mode 100644
index 0000000..9ccfe09
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/ref-params.cc
@@ -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. */
+}
diff --git a/gdb/testsuite/gdb.cp/ref-params.exp b/gdb/testsuite/gdb.cp/ref-params.exp
new file mode 100644
index 0000000..8ad0198
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/ref-params.exp
@@ -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"
diff --git a/gdb/valops.c b/gdb/valops.c
index e86b532..7d1b7d8 100644
--- a/gdb/valops.c
+++ b/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;
-
- /* 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;
- }
- }
+ return value_cast_pointers (type, arg2);
- /* 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;
}
diff --git a/gdb/value.h b/gdb/value.h
index a878ec4..87129d6 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -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);