gdb/
authorDaniel Jacobowitz <drow@false.org>
Thu, 13 Jul 2006 04:31:42 +0000 (04:31 +0000)
committerDaniel Jacobowitz <drow@false.org>
Thu, 13 Jul 2006 04:31:42 +0000 (04:31 +0000)
* 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.

gdb/ChangeLog
gdb/infcall.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/Makefile.in
gdb/testsuite/gdb.cp/ref-params.cc [new file with mode: 0644]
gdb/testsuite/gdb.cp/ref-params.exp [new file with mode: 0644]
gdb/valops.c
gdb/value.h

index 4cd5bde6aaa852fa35b3bd895a7ba58d057868fd..5ce4c8019c03fa229e2c7d09bde8d554014c4639 100644 (file)
@@ -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.
index c8a63348ee3743d90011b68bffcdbc00a9a52902..3a1ad6aba7e9d1538547673f84e2b4f98a9cb316 100644 (file)
@@ -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:
index 7e239a72b62d019f12fdad88248c2777b3c9317d..d811e0ebfd2b1a09dad9e331971f7ba89cb3b9b1 100644 (file)
@@ -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
index 8f4a90e2bb25efe2ae447291a01846e71d8f51e9..06846505ab60cfb7012382f7723aed348d216e82 100644 (file)
@@ -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 (file)
index 0000000..9ccfe09
--- /dev/null
@@ -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 (file)
index 0000000..8ad0198
--- /dev/null
@@ -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"
index e86b532e40be696a6630a2fc8d81c38fa29e8d1a..7d1b7d83e7046c8aa5a1209a877aeabd763f668e 100644 (file)
@@ -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;
        }
 
index a878ec4008d48a28405338050670f7303f9805c1..87129d612162d2dde86cefe5f9f2bfa058d65e21 100644 (file)
@@ -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);