gdb
authorTom Tromey <tromey@redhat.com>
Tue, 2 Feb 2010 16:45:17 +0000 (16:45 +0000)
committerTom Tromey <tromey@redhat.com>
Tue, 2 Feb 2010 16:45:17 +0000 (16:45 +0000)
PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890:
* valops.c (search_struct_field): Compute nbases after calling
CHECK_TYPEDEF.
(check_field): Call CHECK_TYPEDEF.
* cp-valprint.c (cp_print_value): Pass correct address to
baseclass_offset.  Fix check for virtual base past the end of the
object.  Don't offset address passed to cp_print_value_fields or
apply_val_pretty_printer.
(cp_print_value_fields): Fix call to val_print.
(cp_print_value_fields_rtti): New function.
* c-valprint.c (c_val_print): Use cp_print_value_fields_rtti.
* p-valprint.c (pascal_object_print_value_fields): Fix call to
val_print.
* python/py-prettyprint.c (apply_val_pretty_printer): Add embedded
offset to address.
* language.h (struct language_defn) <la_val_print>: Document.
* c-lang.h (cp_print_value_fields_rtti): Declare.
gdb/testsuite
PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890:
* gdb.cp/virtbase.cc: New file.
* gdb.cp/virtbase.exp: New file.
* gdb.cp/userdef.exp: Allow 'struct' or 'class'.

gdb/ChangeLog
gdb/c-lang.h
gdb/c-valprint.c
gdb/cp-valprint.c
gdb/language.h
gdb/python/py-prettyprint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/userdef.exp
gdb/testsuite/gdb.cp/virtbase.cc [new file with mode: 0644]
gdb/testsuite/gdb.cp/virtbase.exp [new file with mode: 0644]
gdb/valops.c

index b2b1ce09d81d83698a14e8b29ce14701e7ff8f18..01ce1210d9b803e348ce52ac08c5cb8a052b2326 100644 (file)
@@ -1,3 +1,23 @@
+2010-02-02  Tom Tromey  <tromey@redhat.com>
+
+       PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890:
+       * valops.c (search_struct_field): Compute nbases after calling
+       CHECK_TYPEDEF.
+       (check_field): Call CHECK_TYPEDEF.
+       * cp-valprint.c (cp_print_value): Pass correct address to
+       baseclass_offset.  Fix check for virtual base past the end of the
+       object.  Don't offset address passed to cp_print_value_fields or
+       apply_val_pretty_printer.
+       (cp_print_value_fields): Fix call to val_print.
+       (cp_print_value_fields_rtti): New function.
+       * c-valprint.c (c_val_print): Use cp_print_value_fields_rtti.
+       * p-valprint.c (pascal_object_print_value_fields): Fix call to
+       val_print.
+       * python/py-prettyprint.c (apply_val_pretty_printer): Add embedded
+       offset to address.
+       * language.h (struct language_defn) <la_val_print>: Document.
+       * c-lang.h (cp_print_value_fields_rtti): Declare.
+
 2010-02-01  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        PR libc/11214:
index d567e81d76cfffb212538c2744c0d1c8d7c5347e..423cee05899c2b8680aa0aa6b66f4ac309d90812 100644 (file)
@@ -102,6 +102,12 @@ extern void cp_print_value_fields (struct type *, struct type *,
                                   const struct value_print_options *,
                                   struct type **, int);
 
+extern void cp_print_value_fields_rtti (struct type *,
+                                       const gdb_byte *, int, CORE_ADDR,
+                                       struct ui_file *, int,
+                                       const struct value_print_options *,
+                                       struct type **, int);
+
 extern int cp_is_vtbl_ptr_type (struct type *);
 
 extern int cp_is_vtbl_member (struct type *);
index d681a03f96ff3251671fd13fb523f9a621819515..31ae4e795e88717a8aef907fda5fb5a8e6fe132e 100644 (file)
@@ -389,8 +389,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
                                          options->addressprint);
        }
       else
-       cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream,
-                              recurse, options, NULL, 0);
+       cp_print_value_fields_rtti (type, valaddr,
+                                   embedded_offset, address, stream,
+                                   recurse, options, NULL, 0);
       break;
 
     case TYPE_CODE_ENUM:
index 3e9beb690ea94c1dec2bbda80d3463b080aecb3d..167c6d4e6cd47be4e2a4a35caffb34e1ba72ec50 100644 (file)
@@ -295,7 +295,7 @@ cp_print_value_fields (struct type *type, struct type *real_type,
                  opts.deref_ref = 0;
                  val_print (TYPE_FIELD_TYPE (type, i),
                             valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8,
-                            address + TYPE_FIELD_BITPOS (type, i) / 8,
+                            address,
                             stream, recurse + 1, &opts,
                             current_language);
                }
@@ -321,6 +321,39 @@ cp_print_value_fields (struct type *type, struct type *real_type,
   fprintf_filtered (stream, "}");
 }
 
+/* Like cp_print_value_fields, but find the runtime type of the object
+   and pass it as the `real_type' argument to cp_print_value_fields.
+   This function is a hack to work around the fact that
+   common_val_print passes the embedded offset to val_print, but not
+   the enclosing type.  */
+
+void
+cp_print_value_fields_rtti (struct type *type,
+                           const gdb_byte *valaddr, int offset,
+                           CORE_ADDR address,
+                           struct ui_file *stream, int recurse,
+                           const struct value_print_options *options,
+                           struct type **dont_print_vb, int dont_print_statmem)
+{
+  struct value *value;
+  int full, top, using_enc;
+  struct type *real_type;
+
+  /* Ugh, we have to convert back to a value here.  */
+  value = value_from_contents_and_address (type, valaddr + offset,
+                                          address + offset);
+  /* We don't actually care about most of the result here -- just the
+     type.  We already have the correct offset, due to how val_print
+     was initially called.  */
+  real_type = value_rtti_type (value, &full, &top, &using_enc);
+  if (!real_type)
+    real_type = type;
+
+  cp_print_value_fields (type, real_type, valaddr, offset,
+                        address, stream, recurse, options,
+                        dont_print_vb, dont_print_statmem);
+}
+
 /* Special val_print routine to avoid printing multiple copies of virtual
    baseclasses.  */
 
@@ -373,7 +406,7 @@ cp_print_value (struct type *type, struct type *real_type,
       thisoffset = offset;
       thistype = real_type;
 
-      boffset = baseclass_offset (type, i, valaddr + offset, address);
+      boffset = baseclass_offset (type, i, valaddr + offset, address + offset);
       skip = ((boffset == -1) || (boffset + offset) < 0) ? 1 : -1;
 
       if (BASETYPE_VIA_VIRTUAL (type, i))
@@ -384,7 +417,7 @@ cp_print_value (struct type *type, struct type *real_type,
 
          if (boffset != -1
              && ((boffset + offset) < 0
-                 || (boffset + offset) >= TYPE_LENGTH (type)))
+                 || (boffset + offset) >= TYPE_LENGTH (real_type)))
            {
              /* FIXME (alloca): unsafe if baseclass is really really large. */
              gdb_byte *buf = alloca (TYPE_LENGTH (baseclass));
@@ -427,14 +460,14 @@ cp_print_value (struct type *type, struct type *real_type,
          if (!options->raw)
            result = apply_val_pretty_printer (baseclass, base_valaddr,
                                               thisoffset + boffset,
-                                              address + boffset,
+                                              address,
                                               stream, recurse,
                                               options,
                                               current_language);
                  
          if (!result)
            cp_print_value_fields (baseclass, thistype, base_valaddr,
-                                  thisoffset + boffset, address + boffset,
+                                  thisoffset + boffset, address,
                                   stream, recurse, options,
                                   ((struct type **)
                                    obstack_base (&dont_print_vb_obstack)),
@@ -501,7 +534,8 @@ cp_print_static_field (struct type *type,
                    sizeof (CORE_ADDR));
 
       CHECK_TYPEDEF (type);
-      cp_print_value_fields (type, type, value_contents_all (val),
+      cp_print_value_fields (type, value_enclosing_type (val),
+                            value_contents_all (val),
                             value_embedded_offset (val), addr,
                             stream, recurse, options, NULL, 1);
       return;
index aaefb036383a059b294eed6bca4712ddd2e50946..4f78a28a470f48912e4a3e6fb1b0a4c248315b43 100644 (file)
@@ -208,11 +208,32 @@ struct language_defn
     void (*la_print_typedef) (struct type *type, struct symbol *new_symbol,
                              struct ui_file *stream);
 
-    /* Print a value using syntax appropriate for this language. */
+    /* Print a value using syntax appropriate for this language.
+       
+       TYPE is the type of the sub-object to be printed.
 
-    int (*la_val_print) (struct type *, const gdb_byte *, int, CORE_ADDR,
-                        struct ui_file *, int,
-                        const struct value_print_options *);
+       CONTENTS holds the bits of the value.  This holds the entire
+       enclosing object.
+
+       EMBEDDED_OFFSET is the offset into the outermost object of the
+       sub-object represented by TYPE.  This is the object which this
+       call should print.  Note that the enclosing type is not
+       available.
+
+       ADDRESS is the address in the inferior of the enclosing object.
+
+       STREAM is the stream on which the value is to be printed.
+
+       RECURSE is the recursion depth.  It is zero-based.
+
+       OPTIONS are the formatting options to be used when
+       printing.  */
+
+    int (*la_val_print) (struct type *type,
+                        const gdb_byte *contents,
+                        int embedded_offset, CORE_ADDR address,
+                        struct ui_file *stream, int recurse,
+                        const struct value_print_options *options);
 
     /* Print a top-level value using syntax appropriate for this language. */
 
index 193f97cc114493e730c8e66dd02915d6bf5ede81..454aa5a3e3e4d1df528255166340b686303ea40e 100644 (file)
@@ -538,7 +538,8 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
   /* Instantiate the printer.  */
   if (valaddr)
     valaddr += embedded_offset;
-  value = value_from_contents_and_address (type, valaddr, address);
+  value = value_from_contents_and_address (type, valaddr,
+                                          address + embedded_offset);
 
   val_obj = value_to_value_object (value);
   if (! val_obj)
index 0be26e6d49a2e9b00549064da13332e2fa428b1d..d55d31a763e90a92f5fe54f0f14d52c44886b1ca 100644 (file)
@@ -1,3 +1,10 @@
+2010-02-02  Tom Tromey  <tromey@redhat.com>
+
+       PR c++/11226, PR c++/9629, PR c++/9688, PR c++/8890:
+       * gdb.cp/virtbase.cc: New file.
+       * gdb.cp/virtbase.exp: New file.
+       * gdb.cp/userdef.exp: Allow 'struct' or 'class'.
+
 2010-02-01  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        PR libc/11214:
index bd54c78ba3073076e77cecb1325c54f352ac4083..2bbf95e91e016cbb89a1431189b58c63376eb77d 100644 (file)
@@ -153,7 +153,7 @@ gdb_test "break A2::'operator +'" ".*Breakpoint $decimal at.*"
 gdb_test "print c" "\\\$\[0-9\]* = {m = {z = .*}}"
 gdb_test "print *c" "\\\$\[0-9\]* = \\(Member &\\) @$hex: {z = .*}"
 gdb_test "print &*c" "\\\$\[0-9\]* = \\(Member \\*\\) $hex"
-gdb_test "ptype &*c" "type = struct Member {\[\r\n \]+int z;\[\r\n\]+} &\\*"
+gdb_test "ptype &*c" "type = (struct|class) Member {(\[\r\n \]+public:)?\[\r\n \]+int z;\[\r\n\]+} &\\*"
 
 gdb_exit
 return 0
diff --git a/gdb/testsuite/gdb.cp/virtbase.cc b/gdb/testsuite/gdb.cp/virtbase.cc
new file mode 100644 (file)
index 0000000..ae0a2c7
--- /dev/null
@@ -0,0 +1,57 @@
+// This first batch of classes are for PR 11226.
+namespace mc {
+  class Base {
+  protected:
+    int x;
+    
+  public:
+    Base(void) { x = 2; };
+  };
+}
+
+namespace ph {
+  class Middle: public virtual mc::Base {
+  protected:
+    int y;
+    
+  public:
+    Middle(void): mc::Base() { y = 3; };
+
+    int get_y(void)
+    {
+      return y;                        // breakpoint 1
+    };
+  };
+
+  class Derived: public virtual Middle {
+  protected:
+    int z;
+    
+  public:
+    Derived(void): Middle() { z = 4; };
+
+    int get_z(void)
+    {
+      return z;                        // breakpoint 2
+    };
+  };
+}
+
+// These classes are for PR 9629.
+struct A {};
+struct B : virtual A {};
+
+struct C {int v; C() {v=11;};};
+struct D:virtual C{};
+
+class E:B,D{};
+
+int main() {
+  ph::Derived tst;
+  tst.get_y();
+  tst.get_z();
+
+  E *e = new E;
+
+  return 0;                    // breakpoint 3
+}
diff --git a/gdb/testsuite/gdb.cp/virtbase.exp b/gdb/testsuite/gdb.cp/virtbase.exp
new file mode 100644 (file)
index 0000000..6a37626
--- /dev/null
@@ -0,0 +1,57 @@
+# Copyright 2010 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/>.
+
+# This file is part of the gdb testsuite.
+
+if { [skip_cplus_tests] } { continue }
+
+set testfile "virtbase"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+     untested virtbase.exp
+     return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if {![runto_main]} then {
+    perror "couldn't run to breakpoint"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "breakpoint 1"]
+gdb_continue_to_breakpoint "first breakpoint"
+
+# In PR 11226, we failed to print x correctly in the "print *this"
+# case.
+gdb_test "print *this" " = {<mc::Base> = {x = 2}, _vptr.Middle = $hex, y = 3}"
+gdb_test "print x" " = 2"
+
+gdb_breakpoint [gdb_get_line_number "breakpoint 2"]
+gdb_continue_to_breakpoint "second breakpoint"
+
+# In PR 11226, we could not find x here.
+gdb_test "print x" " = 2"
+
+gdb_breakpoint [gdb_get_line_number "breakpoint 3"]
+gdb_continue_to_breakpoint "third breakpoint"
+
+# In PR 9629, we failed to print v correctly here.
+gdb_test "print *(D *) e" " = {<C> = {v = 11}, _vptr.D = $hex}"
index 2cdbcbe873cd18203167289bb3b33256aa3a87c2..4c5927d7c571a7dd636fa2f5eeeb2541cbd91a06 100644 (file)
@@ -1787,9 +1787,10 @@ search_struct_field (char *name, struct value *arg1, int offset,
                     struct type *type, int looking_for_baseclass)
 {
   int i;
-  int nbases = TYPE_N_BASECLASSES (type);
+  int nbases;
 
   CHECK_TYPEDEF (type);
+  nbases = TYPE_N_BASECLASSES (type);
 
   if (!looking_for_baseclass)
     for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--)
@@ -2763,6 +2764,9 @@ check_field (struct type *type, const char *name)
 {
   int i;
 
+  /* The type may be a stub.  */
+  CHECK_TYPEDEF (type);
+
   for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
     {
       char *t_field_name = TYPE_FIELD_NAME (type, i);