]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/c-valprint.c
Turn many optimized-out value functions into methods
[thirdparty/binutils-gdb.git] / gdb / c-valprint.c
index 94118905852831b725f63dbe89c32ec18847af18..34a9d0f607561710612ff05cd1aa29d6faf44675 100644 (file)
@@ -1,7 +1,6 @@
 /* Support for printing C values for GDB, the GNU debugger.
 
-   Copyright (C) 1986, 1988-1989, 1991-2001, 2003, 2005-2012 Free
-   Software Foundation, Inc.
+   Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -19,7 +18,6 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include "gdb_string.h"
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "expression.h"
@@ -29,6 +27,7 @@
 #include "c-lang.h"
 #include "cp-abi.h"
 #include "target.h"
+#include "objfiles.h"
 \f
 
 /* A helper for c_textual_element_type.  This checks the name of the
@@ -67,11 +66,11 @@ c_textual_element_type (struct type *type, char format)
   true_type = check_typedef (type);
 
   /* TYPE_CODE_CHAR is always textual.  */
-  if (TYPE_CODE (true_type) == TYPE_CODE_CHAR)
+  if (true_type->code () == TYPE_CODE_CHAR)
     return 1;
 
   /* Any other character-like types must be integral.  */
-  if (TYPE_CODE (true_type) != TYPE_CODE_INT)
+  if (true_type->code () != TYPE_CODE_INT)
     return 0;
 
   /* We peel typedefs one by one, looking for a match.  */
@@ -79,17 +78,17 @@ c_textual_element_type (struct type *type, char format)
   while (iter_type)
     {
       /* Check the name of the type.  */
-      if (TYPE_NAME (iter_type) && textual_name (TYPE_NAME (iter_type)))
+      if (iter_type->name () && textual_name (iter_type->name ()))
        return 1;
 
-      if (TYPE_CODE (iter_type) != TYPE_CODE_TYPEDEF)
+      if (iter_type->code () != TYPE_CODE_TYPEDEF)
        break;
 
       /* Peel a single typedef.  If the typedef doesn't have a target
         type, we use check_typedef and hope the result is ok -- it
         might be for C++, where wchar_t is a built-in type.  */
-      if (TYPE_TARGET_TYPE (iter_type))
-       iter_type = TYPE_TARGET_TYPE (iter_type);
+      if (iter_type->target_type ())
+       iter_type = iter_type->target_type ();
       else
        iter_type = check_typedef (iter_type);
     }
@@ -98,8 +97,8 @@ c_textual_element_type (struct type *type, char format)
     {
       /* Print this as a string if we can manage it.  For now, no wide
         character support.  */
-      if (TYPE_CODE (true_type) == TYPE_CODE_INT
-         && TYPE_LENGTH (true_type) == 1)
+      if (true_type->code () == TYPE_CODE_INT
+         && true_type->length () == 1)
        return 1;
     }
   else
@@ -107,8 +106,8 @@ c_textual_element_type (struct type *type, char format)
       /* If a one-byte TYPE_CODE_INT is missing the not-a-character
         flag, then we treat it as text; otherwise, we assume it's
         being used as data.  */
-      if (TYPE_CODE (true_type) == TYPE_CODE_INT
-         && TYPE_LENGTH (true_type) == 1
+      if (true_type->code () == TYPE_CODE_INT
+         && true_type->length () == 1
          && !TYPE_NOTTEXT (true_type))
        return 1;
     }
@@ -122,298 +121,334 @@ static const struct generic_val_print_decorations c_decorations =
 {
   "",
   " + ",
-  " * I",
+  "i",
   "true",
   "false",
-  "void"
+  "void",
+  "{",
+  "}"
 };
 
-/* See val_print for a description of the various parameters of this
-   function; they are identical.  */
+/* Print a pointer based on the type of its target.
 
-void
-c_val_print (struct type *type, const gdb_byte *valaddr,
-            int embedded_offset, CORE_ADDR address,
-            struct ui_file *stream, int recurse,
-            const struct value *original_value,
-            const struct value_print_options *options)
+   Arguments to this functions are roughly the same as those in c_val_print.
+   A difference is that ADDRESS is the address to print, with embedded_offset
+   already added.  UNRESOLVED_ELTTYPE and ELTTYPE represent the pointed type,
+   respectively before and after check_typedef.  */
+
+static void
+print_unpacked_pointer (struct type *type, struct type *elttype,
+                       struct type *unresolved_elttype,
+                       const gdb_byte *valaddr, int embedded_offset,
+                       CORE_ADDR address, struct ui_file *stream, int recurse,
+                       const struct value_print_options *options)
 {
-  struct gdbarch *gdbarch = get_type_arch (type);
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  unsigned int i = 0;  /* Number of characters printed.  */
-  unsigned len;
-  struct type *elttype, *unresolved_elttype;
-  struct type *unresolved_type = type;
-  unsigned eltlen;
-  LONGEST val;
-  CORE_ADDR addr;
-
-  CHECK_TYPEDEF (type);
-  switch (TYPE_CODE (type))
+  int want_space = 0;
+  struct gdbarch *gdbarch = type->arch ();
+
+  if (elttype->code () == TYPE_CODE_FUNC)
     {
-    case TYPE_CODE_ARRAY:
-      unresolved_elttype = TYPE_TARGET_TYPE (type);
-      elttype = check_typedef (unresolved_elttype);
-      if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0)
+      /* Try to print what function it points to.  */
+      print_function_pointer_address (options, gdbarch, address, stream);
+      return;
+    }
+
+  if (options->symbol_print)
+    want_space = print_address_demangle (options, gdbarch, address, stream,
+                                        demangle);
+  else if (options->addressprint)
+    {
+      gdb_puts (paddress (gdbarch, address), stream);
+      want_space = 1;
+    }
+
+  /* For a pointer to a textual type, also print the string
+     pointed to, unless pointer is null.  */
+
+  if (c_textual_element_type (unresolved_elttype, options->format)
+      && address != 0)
+    {
+      if (want_space)
+       gdb_puts (" ", stream);
+      val_print_string (unresolved_elttype, NULL, address, -1, stream, options);
+    }
+  else if (cp_is_vtbl_member (type))
+    {
+      /* Print vtbl's nicely.  */
+      CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset);
+      struct bound_minimal_symbol msymbol =
+       lookup_minimal_symbol_by_pc (vt_address);
+
+      /* If 'symbol_print' is set, we did the work above.  */
+      if (!options->symbol_print
+         && (msymbol.minsym != NULL)
+         && (vt_address == msymbol.value_address ()))
+       {
+         if (want_space)
+           gdb_puts (" ", stream);
+         gdb_puts (" <", stream);
+         gdb_puts (msymbol.minsym->print_name (), stream);
+         gdb_puts (">", stream);
+         want_space = 1;
+       }
+
+      if (vt_address && options->vtblprint)
        {
-          LONGEST low_bound, high_bound;
+         struct value *vt_val;
+         struct symbol *wsym = NULL;
+         struct type *wtype;
 
-          if (!get_array_bounds (type, &low_bound, &high_bound))
-            error (_("Could not determine the array high bound"));
+         if (want_space)
+           gdb_puts (" ", stream);
 
-         eltlen = TYPE_LENGTH (elttype);
-         len = high_bound - low_bound + 1;
-         if (options->prettyprint_arrays)
+         if (msymbol.minsym != NULL)
            {
-             print_spaces_filtered (2 + 2 * recurse, stream);
+             const char *search_name = msymbol.minsym->search_name ();
+             wsym = lookup_symbol_search_name (search_name, NULL,
+                                               VAR_DOMAIN).symbol;
            }
 
-         /* Print arrays of textual chars with a string syntax, as
-            long as the entire array is valid.  */
-          if (c_textual_element_type (unresolved_elttype,
-                                     options->format)
-             && value_bytes_available (original_value, embedded_offset,
-                                       TYPE_LENGTH (type))
-             && value_bits_valid (original_value,
-                                  TARGET_CHAR_BIT * embedded_offset,
-                                  TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+         if (wsym)
            {
-             /* If requested, look for the first null char and only
-                print elements up to it.  */
-             if (options->stop_print_at_null)
-               {
-                 unsigned int temp_len;
-
-                 for (temp_len = 0;
-                      (temp_len < len
-                       && temp_len < options->print_max
-                       && extract_unsigned_integer (valaddr + embedded_offset
-                                                    + temp_len * eltlen,
-                                                    eltlen, byte_order) != 0);
-                      ++temp_len)
-                   ;
-                 len = temp_len;
-               }
-
-             LA_PRINT_STRING (stream, unresolved_elttype,
-                              valaddr + embedded_offset, len,
-                              NULL, 0, options);
-             i = len;
+             wtype = wsym->type ();
            }
          else
            {
-             fprintf_filtered (stream, "{");
-             /* If this is a virtual function table, print the 0th
-                entry specially, and the rest of the members
-                normally.  */
-             if (cp_is_vtbl_ptr_type (elttype))
-               {
-                 i = 1;
-                 fprintf_filtered (stream, _("%d vtable entries"),
-                                   len - 1);
-               }
-             else
-               {
-                 i = 0;
-               }
-             val_print_array_elements (type, valaddr, embedded_offset,
-                                       address, stream,
-                                       recurse, original_value, options, i);
-             fprintf_filtered (stream, "}");
+             wtype = unresolved_elttype;
+           }
+         vt_val = value_at (wtype, vt_address);
+         common_val_print (vt_val, stream, recurse + 1, options,
+                           current_language);
+         if (options->prettyformat)
+           {
+             gdb_printf (stream, "\n");
+             print_spaces (2 + 2 * recurse, stream);
            }
-         break;
        }
-      /* Array of unspecified length: treat like pointer to first
-        elt.  */
-      addr = address + embedded_offset;
-      goto print_unpacked_pointer;
+    }
+}
 
-    case TYPE_CODE_METHODPTR:
-      cplus_print_method_ptr (valaddr + embedded_offset, type, stream);
-      break;
+/* c_value_print helper for TYPE_CODE_ARRAY.  */
 
-    case TYPE_CODE_PTR:
-      if (options->format && options->format != 's')
+static void
+c_value_print_array (struct value *val,
+                    struct ui_file *stream, int recurse,
+                    const struct value_print_options *options)
+{
+  struct type *type = check_typedef (val->type ());
+  CORE_ADDR address = val->address ();
+  const gdb_byte *valaddr = val->contents_for_printing ().data ();
+  struct type *unresolved_elttype = type->target_type ();
+  struct type *elttype = check_typedef (unresolved_elttype);
+
+  if (type->length () > 0 && unresolved_elttype->length () > 0)
+    {
+      LONGEST low_bound, high_bound;
+      int eltlen, len;
+      enum bfd_endian byte_order = type_byte_order (type);
+
+      if (!get_array_bounds (type, &low_bound, &high_bound))
+       error (_("Could not determine the array high bound"));
+
+      eltlen = elttype->length ();
+      len = high_bound - low_bound + 1;
+
+      /* Print arrays of textual chars with a string syntax, as
+        long as the entire array is valid.  */
+      if (c_textual_element_type (unresolved_elttype,
+                                 options->format)
+         && val->bytes_available (0, type->length ())
+         && !val->bits_any_optimized_out (0,
+                                          TARGET_CHAR_BIT * type->length ()))
        {
-         val_print_scalar_formatted (type, valaddr, embedded_offset,
-                                     original_value, options, 0, stream);
-         break;
+         int force_ellipses = 0;
+
+         /* If requested, look for the first null char and only
+            print elements up to it.  */
+         if (options->stop_print_at_null)
+           {
+             unsigned int print_max_chars = get_print_max_chars (options);
+             unsigned int temp_len;
+
+             for (temp_len = 0;
+                  (temp_len < len
+                   && temp_len < print_max_chars
+                   && extract_unsigned_integer (valaddr + temp_len * eltlen,
+                                                eltlen, byte_order) != 0);
+                  ++temp_len)
+               ;
+
+             /* Force printstr to print ellipses if
+                we've printed the maximum characters and
+                the next character is not \000.  */
+             if (temp_len == print_max_chars && temp_len < len)
+               {
+                 ULONGEST ival
+                   = extract_unsigned_integer (valaddr + temp_len * eltlen,
+                                               eltlen, byte_order);
+                 if (ival != 0)
+                   force_ellipses = 1;
+               }
+
+             len = temp_len;
+           }
+
+         current_language->printstr (stream, unresolved_elttype, valaddr, len,
+                                     NULL, force_ellipses, options);
        }
-      if (options->vtblprint && cp_is_vtbl_ptr_type (type))
+      else
        {
-         /* Print the unmangled name if desired.  */
-         /* Print vtable entry - we only get here if we ARE using
-            -fvtable_thunks.  (Otherwise, look under
-            TYPE_CODE_STRUCT.)  */
-         CORE_ADDR addr
-           = extract_typed_address (valaddr + embedded_offset, type);
-
-         print_function_pointer_address (options, gdbarch, addr, stream);
-         break;
+         unsigned int i = 0;
+         gdb_printf (stream, "{");
+         /* If this is a virtual function table, print the 0th
+            entry specially, and the rest of the members
+            normally.  */
+         if (cp_is_vtbl_ptr_type (elttype))
+           {
+             i = 1;
+             gdb_printf (stream, _("%d vtable entries"),
+                         len - 1);
+           }
+         value_print_array_elements (val, stream, recurse, options, i);
+         gdb_printf (stream, "}");
        }
-      unresolved_elttype = TYPE_TARGET_TYPE (type);
-      elttype = check_typedef (unresolved_elttype);
-       {
-         int want_space;
+    }
+  else
+    {
+      /* Array of unspecified length: treat like pointer to first elt.  */
+      print_unpacked_pointer (type, elttype, unresolved_elttype, valaddr,
+                             0, address, stream, recurse, options);
+    }
+}
 
-         addr = unpack_pointer (type, valaddr + embedded_offset);
-       print_unpacked_pointer:
+/* c_value_print_inner helper for TYPE_CODE_PTR.  */
 
-         want_space = 0;
+static void
+c_value_print_ptr (struct value *val, struct ui_file *stream, int recurse,
+                  const struct value_print_options *options)
+{
+  if (options->format && options->format != 's')
+    {
+      value_print_scalar_formatted (val, options, 0, stream);
+      return;
+    }
 
-         if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
-           {
-             /* Try to print what function it points to.  */
-             print_function_pointer_address (options, gdbarch, addr, stream);
-             return;
-           }
+  struct type *type = check_typedef (val->type ());
+  const gdb_byte *valaddr = val->contents_for_printing ().data ();
 
-         if (options->addressprint)
-           {
-             fputs_filtered (paddress (gdbarch, addr), stream);
-             want_space = 1;
-           }
+  if (options->vtblprint && cp_is_vtbl_ptr_type (type))
+    {
+      /* Print the unmangled name if desired.  */
+      /* Print vtable entry - we only get here if we ARE using
+        -fvtable_thunks.  (Otherwise, look under
+        TYPE_CODE_STRUCT.)  */
+      CORE_ADDR addr = extract_typed_address (valaddr, type);
 
-         /* For a pointer to a textual type, also print the string
-            pointed to, unless pointer is null.  */
+      print_function_pointer_address (options, type->arch (), addr, stream);
+    }
+  else
+    {
+      struct type *unresolved_elttype = type->target_type ();
+      struct type *elttype = check_typedef (unresolved_elttype);
+      CORE_ADDR addr = unpack_pointer (type, valaddr);
 
-         if (c_textual_element_type (unresolved_elttype,
-                                     options->format)
-             && addr != 0)
-           {
-             if (want_space)
-               fputs_filtered (" ", stream);
-             i = val_print_string (unresolved_elttype, NULL,
-                                   addr, -1,
-                                   stream, options);
-           }
-         else if (cp_is_vtbl_member (type))
-           {
-             /* Print vtbl's nicely.  */
-             CORE_ADDR vt_address = unpack_pointer (type,
-                                                    valaddr
-                                                    + embedded_offset);
-             struct minimal_symbol *msymbol =
-             lookup_minimal_symbol_by_pc (vt_address);
-
-             if ((msymbol != NULL)
-                 && (vt_address == SYMBOL_VALUE_ADDRESS (msymbol)))
-               {
-                 if (want_space)
-                   fputs_filtered (" ", stream);
-                 fputs_filtered (" <", stream);
-                 fputs_filtered (SYMBOL_PRINT_NAME (msymbol), stream);
-                 fputs_filtered (">", stream);
-                 want_space = 1;
-               }
+      print_unpacked_pointer (type, elttype, unresolved_elttype, valaddr,
+                             0, addr, stream, recurse, options);
+    }
+}
 
-             if (vt_address && options->vtblprint)
-               {
-                 struct value *vt_val;
-                 struct symbol *wsym = (struct symbol *) NULL;
-                 struct type *wtype;
-                 struct block *block = (struct block *) NULL;
-                 int is_this_fld;
-
-                 if (want_space)
-                   fputs_filtered (" ", stream);
-
-                 if (msymbol != NULL)
-                   wsym = lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol),
-                                         block, VAR_DOMAIN,
-                                         &is_this_fld);
-
-                 if (wsym)
-                   {
-                     wtype = SYMBOL_TYPE (wsym);
-                   }
-                 else
-                   {
-                     wtype = unresolved_elttype;
-                   }
-                 vt_val = value_at (wtype, vt_address);
-                 common_val_print (vt_val, stream, recurse + 1,
-                                   options, current_language);
-                 if (options->pretty)
-                   {
-                     fprintf_filtered (stream, "\n");
-                     print_spaces_filtered (2 + 2 * recurse, stream);
-                   }
-               }
-           }
-         return;
+/* c_value_print helper for TYPE_CODE_STRUCT and TYPE_CODE_UNION.  */
+
+static void
+c_value_print_struct (struct value *val, struct ui_file *stream, int recurse,
+                     const struct value_print_options *options)
+{
+  struct type *type = check_typedef (val->type ());
+
+  if (type->code () == TYPE_CODE_UNION && recurse && !options->unionprint)
+    gdb_printf (stream, "{...}");
+  else if (options->vtblprint && cp_is_vtbl_ptr_type (type))
+    {
+      /* Print the unmangled name if desired.  */
+      /* Print vtable entry - we only get here if NOT using
+        -fvtable_thunks.  (Otherwise, look under
+        TYPE_CODE_PTR.)  */
+      int offset = type->field (VTBL_FNADDR_OFFSET).loc_bitpos () / 8;
+      struct type *field_type = type->field (VTBL_FNADDR_OFFSET).type ();
+      const gdb_byte *valaddr = val->contents_for_printing ().data ();
+      CORE_ADDR addr = extract_typed_address (valaddr + offset, field_type);
+
+      print_function_pointer_address (options, type->arch (), addr, stream);
+    }
+  else
+    cp_print_value_fields (val, stream, recurse, options, NULL, 0);
+}
+
+/* c_value_print helper for TYPE_CODE_INT.  */
+
+static void
+c_value_print_int (struct value *val, struct ui_file *stream,
+                  const struct value_print_options *options)
+{
+  if (options->format || options->output_format)
+    {
+      struct value_print_options opts = *options;
+
+      opts.format = (options->format ? options->format
+                    : options->output_format);
+      value_print_scalar_formatted (val, &opts, 0, stream);
+    }
+  else
+    {
+      value_print_scalar_formatted (val, options, 0, stream);
+      /* C and C++ has no single byte int type, char is used
+        instead.  Since we don't know whether the value is really
+        intended to be used as an integer or a character, print
+        the character equivalent as well.  */
+      struct type *type = val->type ();
+      const gdb_byte *valaddr = val->contents_for_printing ().data ();
+      if (c_textual_element_type (type, options->format))
+       {
+         gdb_puts (" ", stream);
+         current_language->printchar (unpack_long (type, valaddr), type,
+                                      stream);
        }
+    }
+}
+
+/* See c-lang.h.  */
+
+void
+c_value_print_inner (struct value *val, struct ui_file *stream, int recurse,
+                    const struct value_print_options *options)
+{
+  struct type *type = val->type ();
+
+  type = check_typedef (type);
+  switch (type->code ())
+    {
+    case TYPE_CODE_ARRAY:
+      c_value_print_array (val, stream, recurse, options);
+      break;
+
+    case TYPE_CODE_PTR:
+      c_value_print_ptr (val, stream, recurse, options);
       break;
 
     case TYPE_CODE_UNION:
-      if (recurse && !options->unionprint)
-       {
-         fprintf_filtered (stream, "{...}");
-         break;
-       }
-      /* Fall through.  */
     case TYPE_CODE_STRUCT:
-      /*FIXME: Abstract this away.  */
-      if (options->vtblprint && cp_is_vtbl_ptr_type (type))
-       {
-         /* Print the unmangled name if desired.  */
-         /* Print vtable entry - we only get here if NOT using
-            -fvtable_thunks.  (Otherwise, look under
-            TYPE_CODE_PTR.)  */
-         int offset = (embedded_offset
-                       + TYPE_FIELD_BITPOS (type,
-                                            VTBL_FNADDR_OFFSET) / 8);
-         struct type *field_type = TYPE_FIELD_TYPE (type,
-                                                    VTBL_FNADDR_OFFSET);
-         CORE_ADDR addr
-           = extract_typed_address (valaddr + offset, field_type);
-
-         print_function_pointer_address (options, gdbarch, addr, stream);
-       }
-      else
-       cp_print_value_fields_rtti (type, valaddr,
-                                   embedded_offset, address,
-                                   stream, recurse,
-                                   original_value, options,
-                                   NULL, 0);
+      c_value_print_struct (val, stream, recurse, options);
       break;
 
+    case TYPE_CODE_CHAR:
     case TYPE_CODE_INT:
-      if (options->format || options->output_format)
-       {
-         struct value_print_options opts = *options;
-
-         opts.format = (options->format ? options->format
-                        : options->output_format);
-         val_print_scalar_formatted (type, valaddr, embedded_offset,
-                                     original_value, &opts, 0, stream);
-       }
-      else
-       {
-         val_print_type_code_int (type, valaddr + embedded_offset,
-                                  stream);
-         /* C and C++ has no single byte int type, char is used
-            instead.  Since we don't know whether the value is really
-            intended to be used as an integer or a character, print
-            the character equivalent as well.  */
-         if (c_textual_element_type (unresolved_type, options->format))
-           {
-             fputs_filtered (" ", stream);
-             LA_PRINT_CHAR (unpack_long (type, valaddr + embedded_offset),
-                            unresolved_type, stream);
-           }
-       }
+      c_value_print_int (val, stream, options);
       break;
 
+    case TYPE_CODE_METHODPTR:
     case TYPE_CODE_MEMBERPTR:
-      if (!options->format)
-       {
-         cp_print_class_member (valaddr + embedded_offset, type, stream, "&");
-         break;
-       }
-      /* FALLTHROUGH */
-
     case TYPE_CODE_REF:
+    case TYPE_CODE_RVALUE_REF:
     case TYPE_CODE_ENUM:
     case TYPE_CODE_FLAGS:
     case TYPE_CODE_FUNC:
@@ -426,25 +461,23 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
     case TYPE_CODE_ERROR:
     case TYPE_CODE_UNDEF:
     case TYPE_CODE_COMPLEX:
-    case TYPE_CODE_CHAR:
     default:
-      generic_val_print (type, valaddr, embedded_offset, address,
-                        stream, recurse, original_value, options,
-                        &c_decorations);
+      generic_value_print (val, stream, recurse, options, &c_decorations);
       break;
     }
-  gdb_flush (stream);
 }
+
 \f
 void
 c_value_print (struct value *val, struct ui_file *stream, 
               const struct value_print_options *options)
 {
-  struct type *type, *real_type, *val_type;
-  int full, top, using_enc;
+  struct type *type, *real_type;
+  int full, using_enc;
+  LONGEST top;
   struct value_print_options opts = *options;
 
-  opts.deref_ref = 1;
+  opts.deref_ref = true;
 
   /* If it is a pointer, indicate what it points to.
 
@@ -453,80 +486,78 @@ c_value_print (struct value *val, struct ui_file *stream,
      C++: if it is a member pointer, we will take care
      of that when we print it.  */
 
-  /* Preserve the original type before stripping typedefs.  We prefer
-     to pass down the original type when possible, but for local
-     checks it is better to look past the typedefs.  */
-  val_type = value_type (val);
-  type = check_typedef (val_type);
+  type = check_typedef (val->type ());
 
-  if (TYPE_CODE (type) == TYPE_CODE_PTR
-      || TYPE_CODE (type) == TYPE_CODE_REF)
+  if (type->is_pointer_or_reference ())
     {
+      struct type *original_type = val->type ();
+
       /* Hack:  remove (char *) for char strings.  Their
-         type is indicated by the quoted string anyway.
-         (Don't use c_textual_element_type here; quoted strings
-         are always exactly (char *), (wchar_t *), or the like.  */
-      if (TYPE_CODE (val_type) == TYPE_CODE_PTR
-         && TYPE_NAME (val_type) == NULL
-         && TYPE_NAME (TYPE_TARGET_TYPE (val_type)) != NULL
-         && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (val_type)),
+        type is indicated by the quoted string anyway.
+        (Don't use c_textual_element_type here; quoted strings
+        are always exactly (char *), (wchar_t *), or the like.  */
+      if (original_type->code () == TYPE_CODE_PTR
+         && original_type->name () == NULL
+         && original_type->target_type ()->name () != NULL
+         && (strcmp (original_type->target_type ()->name (),
                      "char") == 0
-             || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (val_type)))))
+             || textual_name (original_type->target_type ()->name ())))
        {
          /* Print nothing.  */
        }
       else if (options->objectprint
-              && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+              && (type->target_type ()->code () == TYPE_CODE_STRUCT))
        {
+         int is_ref = TYPE_IS_REFERENCE (type);
+         enum type_code refcode = TYPE_CODE_UNDEF;
 
-         if (TYPE_CODE(type) == TYPE_CODE_REF)
+         if (is_ref)
            {
-             /* Copy value, change to pointer, so we don't get an
-                error about a non-pointer type in
-                value_rtti_target_type.  */
-             struct value *temparg;
-             temparg=value_copy(val);
-             deprecated_set_value_type
-               (temparg, lookup_pointer_type (TYPE_TARGET_TYPE (type)));
-             val = temparg;
+             val = value_addr (val);
+             refcode = type->code ();
            }
+
          /* Pointer to class, check real type of object.  */
-         fprintf_filtered (stream, "(");
+         gdb_printf (stream, "(");
 
-         if (value_entirely_available (val))
-           {
+         if (val->entirely_available ())
+           {
              real_type = value_rtti_indirect_type (val, &full, &top,
                                                    &using_enc);
              if (real_type)
                {
                  /* RTTI entry found.  */
-                 type = real_type;
 
                  /* Need to adjust pointer value.  */
-                 val = value_from_pointer (type, value_as_address (val) - top);
+                 val = value_from_pointer (real_type,
+                                           value_as_address (val) - top);
 
                  /* Note: When we look up RTTI entries, we don't get
                     any information on const or volatile
                     attributes.  */
                }
            }
-          type_print (type, "", stream, -1);
-         fprintf_filtered (stream, ") ");
-         val_type = type;
+
+         if (is_ref)
+           val = value_ref (value_ind (val), refcode);
+
+         type = val->type ();
+         type_print (type, "", stream, -1);
+         gdb_printf (stream, ") ");
        }
       else
        {
          /* normal case */
-         fprintf_filtered (stream, "(");
-         type_print (value_type (val), "", stream, -1);
-         fprintf_filtered (stream, ") ");
+         gdb_printf (stream, "(");
+         type_print (val->type (), "", stream, -1);
+         gdb_printf (stream, ") ");
        }
     }
 
-  if (!value_initialized (val))
-    fprintf_filtered (stream, " [uninitialized] ");
+  if (!val->initialized ())
+    gdb_printf (stream, " [uninitialized] ");
 
-  if (options->objectprint && (TYPE_CODE (type) == TYPE_CODE_CLASS))
+  if (options->objectprint && (type->code () == TYPE_CODE_STRUCT))
     {
       /* Attempt to determine real type of object.  */
       real_type = value_rtti_type (val, &full, &top, &using_enc);
@@ -535,36 +566,25 @@ c_value_print (struct value *val, struct ui_file *stream,
          /* We have RTTI information, so use it.  */
          val = value_full_object (val, real_type, 
                                   full, top, using_enc);
-         fprintf_filtered (stream, "(%s%s) ",
-                           TYPE_NAME (real_type),
-                           full ? "" : _(" [incomplete object]"));
-         /* Print out object: enclosing type is same as real_type if
-            full.  */
-         val_print (value_enclosing_type (val),
-                    value_contents_for_printing (val), 0,
-                    value_address (val), stream, 0,
-                    val, &opts, current_language);
-         return;
-          /* Note: When we look up RTTI entries, we don't get any
-             information on const or volatile attributes.  */
+         /* In a destructor we might see a real type that is a
+            superclass of the object's type.  In this case it is
+            better to leave the object as-is.  */
+         if (!(full
+               && (real_type->length ()
+                   < val->enclosing_type ()->length ())))
+           val = value_cast (real_type, val);
+         gdb_printf (stream, "(%s%s) ",
+                     real_type->name (),
+                     full ? "" : _(" [incomplete object]"));
        }
-      else if (type != check_typedef (value_enclosing_type (val)))
+      else if (type != check_typedef (val->enclosing_type ()))
        {
          /* No RTTI information, so let's do our best.  */
-         fprintf_filtered (stream, "(%s ?) ",
-                           TYPE_NAME (value_enclosing_type (val)));
-         val_print (value_enclosing_type (val),
-                    value_contents_for_printing (val), 0,
-                    value_address (val), stream, 0,
-                    val, &opts, current_language);
-         return;
+         gdb_printf (stream, "(%s ?) ",
+                     val->enclosing_type ()->name ());
+         val = value_cast (val->enclosing_type (), val);
        }
-      /* Otherwise, we end up at the return outside this "if".  */
     }
 
-  val_print (val_type, value_contents_for_printing (val),
-            value_embedded_offset (val),
-            value_address (val),
-            stream, 0,
-            val, &opts, current_language);
+  common_val_print (val, stream, 0, &opts, current_language);
 }