This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: optimized-out pieces


I'd appreciate comments on this patch.  In the absence of comments I
plan to check it in.

This patch adds better support for optimized-out pieces to gdb.

Now, value_contents and friends will error if the value has been
optimized out.  This is true even if a piece of the value has been
optimized out.  This means that "naive" uses of the contents of a value
do not need to be changed.

Then, I updated a couple specific parts of gdb to explicitly examine bit
validity of a value's contents.

First, I changed value_fetch_lazy to respect bitwise validity.
This was all that was needed to properly handle field accesses.

Second, the bulk of the patch is concerned with updating val_print.
This adds a new "val" argument to the entire hierarchy, which is
preserved and then consulted, when needed, to check bit validity.  This
part is pretty ugly, and big.  It is hard to be certain I got
everything.

I still have not implemented support in varobj or in Python.
I plan to do that.

Built and regtested on x86-64 (compile farm).

Tom

2010-06-04  Tom Tromey  <tromey@redhat.com>

	PR gdb/9977, PR exp/11636:
	* value.h (value_offset): Update.
	(struct lval_funcs) <check_validity>: New field.
	<copy_closure>: Make argument const.
	(value_computed_closure): Update.
	(value_contents_for_printing): Declare.
	(value_bits_valid): Likewise.
	(val_print): Likewise.
	(set_value_component_location): Update.
	* value.c (value_offset): Argument now const.
	(require_not_optimized_out): New function.
	(value_contents_for_printing): New function.
	(value_contents_all): Call require_not_optimized_out.
	(value_contents): Likewise.
	(value_bits_valid): New function.
	(value_computed_closure): Argument now const.
	(set_value_component_location): Make 'whole' argument const.
	* valprint.h (val_print_array_elements): Update.
	* valprint.c (val_print): Add 'val' argument.  Use
	valprint_check_validity.
	(valprint_check_validity): New function.
	(value_check_printable): Don't check value_optimized_out.
	(common_val_print): Update.
	(value_print): Likewise.
	(val_print_array_elements): Add 'val' argument.
	* valops.c (value_fetch_lazy): Use value_contents_for_printing,
	value_bits_valid.  Reinit frame cache for lval_computed.
	* sh64-tdep.c (sh64_do_register): Update.
	* scm-valprint.c (scm_val_print): Add 'val' argument.
	* scm-lang.h (scm_val_print): Update.
	* python/python.h (apply_val_pretty_printer): Update.
	* python/py-prettyprint.c (apply_val_pretty_printer): Add 'val'
	argument.  Call set_value_component_location.
	* printcmd.c (print_scalar_formatted): Update.
	* p-valprint.c (pascal_val_print): Add 'val' argument.
	(pascal_object_print_value_fields): Likewise.
	(pascal_object_print_value): Likewise.
	(pascal_object_print_static_field): Update.
	* p-lang.h (pascal_val_print): Update.
	(pascal_object_print_value_fields): Update.
	* mt-tdep.c (mt_registers_info): Update.
	* mi/mi-main.c (get_register): Update.
	(mi_cmd_data_evaluate_expression): Use common_val_print.
	* m2-valprint.c (m2_print_array_contents): Add 'val' argument.
	(m2_print_unbounded_array): Likewise.
	(m2_val_print): Likewise.
	* m2-lang.h (m2_val_print): Update.
	* language.h (struct language_defn) <la_val_print>: Add 'val'
	argument.
	(LA_VAL_PRINT): Likewise.
	* language.c (unk_lang_val_print): Add 'val' argument.
	* jv-valprint.c (java_print_value_fields): Add 'val' argument.
	(java_val_print): Likewise.
	* jv-lang.h (java_val_print): Add 'val' argument.
	* infcmd.c (default_print_registers_info): Update.
	* f-valprint.c (f77_print_array_1): Add 'val' argument.
	(f77_print_array): Likewise.
	(f_val_print): Likewise.
	* f-lang.h (f_val_print): Add 'val' argument.
	* dwarf2loc.c (read_pieced_value): Use value_bitsize and
	value_bitpos.
	<DWARF_VALUE_OPTIMIZED_OUT>: Don't print warning.  Call
	set_value_optimized_out.
	(write_pieced_value): Use value_bitsize and value_bitpos.
	<default>: Don't exit loop.
	(check_pieced_value_validity): New function.
	(pieced_value_funcs): Reference check_pieced_value_validity.
	(copy_pieced_value_closure): Update.
	* d-valprint.c (dynamic_array_type): Add 'val' argument.
	(d_val_print): Likewise.
	* d-lang.h (d_val_print): Update.
	* cp-valprint.c (cp_print_value_fields): Add 'val' argument.
	(cp_print_value_fields_rtti): Likewise.
	(cp_print_value): Likewise.
	(cp_print_static_field): Update.
	* c-valprint.c (c_val_print): Add 'val' argument.
	(c_value_print): Update.
	* c-lang.h (c_val_print): Update.
	(cp_print_value_fields): Likewise.
	(cp_print_value_fields_rtti): Likewise.
	* ada-valprint.c (struct ada_val_print_args): Remove.
	(val_print_packed_array_elements): Add 'val' argument.
	(ada_val_print): Likewise.  Rewrite.
	(ada_val_print_stub): Remove.
	(ada_val_print_array): Add 'val' argument.
	(ada_val_print_1): Likewise.
	(print_variant_part): Likewise.
	(ada_value_print): Update.
	(print_record): Add 'val' argument.
	(print_field_values): Likewise.
	* ada-lang.h (ada_val_print): Update.

2010-06-03  Tom Tromey  <tromey@redhat.com>

	PR gdb/9977, PR exp/11636::
	* gdb.dwarf2/pieces.exp (pieces_test_f3): Remove kfail.
	(pieces_test_f6): Update expected output.

diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index f6b613f..c51964a 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -164,6 +164,7 @@ extern void ada_print_typedef (struct type *type, struct symbol *new_symbol,
 
 extern int ada_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
                           struct ui_file *, int,
+			  const struct value *,
 			  const struct value_print_options *);
 
 extern int ada_value_print (struct value *, struct ui_file *,
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index c56d221..329edef 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -36,33 +36,23 @@
 #include "exceptions.h"
 #include "objfiles.h"
 
-/* Encapsulates arguments to ada_val_print.  */
-struct ada_val_print_args
-{
-  struct type *type;
-  const gdb_byte *valaddr0;
-  int embedded_offset;
-  CORE_ADDR address;
-  struct ui_file *stream;
-  int recurse;
-  const struct value_print_options *options;
-};
-
 static void print_record (struct type *, const gdb_byte *, struct ui_file *,
-			  int, const struct value_print_options *);
+			  int,
+			  const struct value *,
+			  const struct value_print_options *);
 
 static int print_field_values (struct type *, const gdb_byte *,
 			       struct ui_file *, int,
+			       const struct value *,
 			       const struct value_print_options *,
 			       int, struct type *,
 			       const gdb_byte *);
 
 static void adjust_type_signedness (struct type *);
 
-static int ada_val_print_stub (void *args0);
-
 static int ada_val_print_1 (struct type *, const gdb_byte *, int, CORE_ADDR,
 			    struct ui_file *, int,
+			    const struct value *,
 			    const struct value_print_options *);
 
 
@@ -146,6 +136,7 @@ static void
 val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
 				 int bitoffset, struct ui_file *stream,
 				 int recurse,
+				 const struct value *val,
 				 const struct value_print_options *options)
 {
   unsigned int i;
@@ -217,7 +208,7 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
 
 	  opts.deref_ref = 0;
 	  val_print (elttype, value_contents (v0), 0, 0, stream,
-		     recurse + 1, &opts, current_language);
+		     recurse + 1, val, &opts, current_language);
 	  annotate_elt_rep (i - i0);
 	  fprintf_filtered (stream, _(" <repeats %u times>"), i - i0);
 	  annotate_elt_rep_end ();
@@ -247,7 +238,7 @@ val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
 					   stream, options);
 		}
 	      val_print (elttype, value_contents (v0), 0, 0, stream,
-			 recurse + 1, &opts, current_language);
+			 recurse + 1, val, &opts, current_language);
 	      annotate_elt ();
 	    }
 	}
@@ -581,30 +572,22 @@ int
 ada_val_print (struct type *type, const gdb_byte *valaddr0,
 	       int embedded_offset, CORE_ADDR address,
 	       struct ui_file *stream, int recurse,
+	       const struct value *val,
 	       const struct value_print_options *options)
 {
-  struct ada_val_print_args args;
-  args.type = type;
-  args.valaddr0 = valaddr0;
-  args.embedded_offset = embedded_offset;
-  args.address = address;
-  args.stream = stream;
-  args.recurse = recurse;
-  args.options = options;
-
-  return catch_errors (ada_val_print_stub, &args, NULL, RETURN_MASK_ALL);
-}
+  volatile struct gdb_exception except;
+  int result = 0;
 
-/* Helper for ada_val_print; used as argument to catch_errors to
-   unmarshal the arguments to ada_val_print_1, which does the work.  */
-static int
-ada_val_print_stub (void *args0)
-{
-  struct ada_val_print_args *argsp = (struct ada_val_print_args *) args0;
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      result = ada_val_print_1 (type, valaddr0, embedded_offset, address,
+				stream, recurse, val, options);
+    }
 
-  return ada_val_print_1 (argsp->type, argsp->valaddr0,
-			  argsp->embedded_offset, argsp->address,
-			  argsp->stream, argsp->recurse, argsp->options);
+  if (except.reason < 0)
+    result = 0;
+
+  return result;
 }
 
 /* Assuming TYPE is a simple array, print the value of this array located
@@ -615,6 +598,7 @@ ada_val_print_stub (void *args0)
 static int
 ada_val_print_array (struct type *type, const gdb_byte *valaddr,
 		     CORE_ADDR address, struct ui_file *stream, int recurse,
+		     const struct value *val,
 		     const struct value_print_options *options)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -663,10 +647,10 @@ ada_val_print_array (struct type *type, const gdb_byte *valaddr,
       print_optional_low_bound (stream, type, options);
       if (TYPE_FIELD_BITSIZE (type, 0) > 0)
         val_print_packed_array_elements (type, valaddr, 0, stream,
-                                         recurse, options);
+                                         recurse, val, options);
       else
         val_print_array_elements (type, valaddr, address, stream,
-                                  recurse, options, 0);
+                                  recurse, val, options, 0);
       fprintf_filtered (stream, ")");
     }
 
@@ -680,6 +664,7 @@ static int
 ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
 		 int embedded_offset, CORE_ADDR address,
 		 struct ui_file *stream, int recurse,
+		 const struct value *original_value,
 		 const struct value_print_options *options)
 {
   unsigned int len;
@@ -706,7 +691,8 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
 	}
       else
 	retn = ada_val_print_1 (value_type (val), value_contents (val), 0,
-				value_address (val), stream, recurse, options);
+				value_address (val), stream, recurse,
+				NULL, options);
       value_free_to_mark (mark);
       return retn;
     }
@@ -719,12 +705,12 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
     {
     default:
       return c_val_print (type, valaddr0, embedded_offset, address, stream,
-			  recurse, options);
+			  recurse, original_value, options);
 
     case TYPE_CODE_PTR:
       {
 	int ret = c_val_print (type, valaddr0, embedded_offset, address, 
-			       stream, recurse, options);
+			       stream, recurse, original_value, options);
 
 	if (ada_is_tag_type (type))
 	  {
@@ -765,12 +751,12 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
 					    (type, valaddr, 0));
 
 	      return ada_val_print_1 (target_type, value_contents (v), 0, 0,
-				      stream, recurse + 1, options);
+				      stream, recurse + 1, NULL, options);
 	    }
 	  else
 	    return ada_val_print_1 (TYPE_TARGET_TYPE (type),
 				    valaddr0, embedded_offset,
-				    address, stream, recurse, options);
+				    address, stream, recurse, original_value, options);
 	}
       else
 	{
@@ -855,7 +841,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
     case TYPE_CODE_FLT:
       if (options->format)
 	return c_val_print (type, valaddr0, embedded_offset, address, stream,
-			    recurse, options);
+			    recurse, original_value, options);
       else
 	ada_print_floating (valaddr0 + embedded_offset, type, stream);
       break;
@@ -869,13 +855,14 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
 	}
       else
 	{
-	  print_record (type, valaddr, stream, recurse, options);
+	  print_record (type, valaddr, stream, recurse, original_value,
+			options);
 	  return 0;
 	}
 
     case TYPE_CODE_ARRAY:
       return ada_val_print_array (type, valaddr, address, stream,
-				  recurse, options);
+				  recurse, original_value, options);
 
     case TYPE_CODE_REF:
       /* For references, the debugger is expected to print the value as
@@ -899,7 +886,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
               val_print (value_type (deref_val),
                          value_contents (deref_val), 0,
                          value_address (deref_val), stream, recurse + 1,
-			 options, current_language);
+			 original_value, options, current_language);
             }
           else
             fputs_filtered ("(null)", stream);
@@ -916,6 +903,7 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0,
 static int
 print_variant_part (struct type *type, int field_num, const gdb_byte *valaddr,
 		    struct ui_file *stream, int recurse,
+		    const struct value *val,
 		    const struct value_print_options *options, int comma_needed,
 		    struct type *outer_type, const gdb_byte *outer_valaddr)
 {
@@ -929,7 +917,7 @@ print_variant_part (struct type *type, int field_num, const gdb_byte *valaddr,
       (TYPE_FIELD_TYPE (var_type, which),
        valaddr + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT
        + TYPE_FIELD_BITPOS (var_type, which) / HOST_CHAR_BIT,
-       stream, recurse, options,
+       stream, recurse, val, options,
        comma_needed, outer_type, outer_valaddr);
 }
 
@@ -973,19 +961,20 @@ ada_value_print (struct value *val0, struct ui_file *stream,
   opts = *options;
   opts.deref_ref = 1;
   return (val_print (type, value_contents (val), 0, address,
-		     stream, 0, &opts, current_language));
+		     stream, 0, val, &opts, current_language));
 }
 
 static void
 print_record (struct type *type, const gdb_byte *valaddr,
 	      struct ui_file *stream, int recurse,
+	      const struct value *val,
 	      const struct value_print_options *options)
 {
   type = ada_check_typedef (type);
 
   fprintf_filtered (stream, "(");
 
-  if (print_field_values (type, valaddr, stream, recurse, options,
+  if (print_field_values (type, valaddr, stream, recurse, val, options,
 			  0, type, valaddr) != 0 && options->pretty)
     {
       fprintf_filtered (stream, "\n");
@@ -1012,6 +1001,7 @@ print_record (struct type *type, const gdb_byte *valaddr,
 static int
 print_field_values (struct type *type, const gdb_byte *valaddr,
 		    struct ui_file *stream, int recurse,
+		    const struct value *val,
 		    const struct value_print_options *options,
 		    int comma_needed,
 		    struct type *outer_type, const gdb_byte *outer_valaddr)
@@ -1031,7 +1021,7 @@ print_field_values (struct type *type, const gdb_byte *valaddr,
 	    print_field_values (TYPE_FIELD_TYPE (type, i),
 				valaddr
 				+ TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
-				stream, recurse, options,
+				stream, recurse, val, options,
 				comma_needed, type, valaddr);
 	  continue;
 	}
@@ -1039,7 +1029,7 @@ print_field_values (struct type *type, const gdb_byte *valaddr,
 	{
 	  comma_needed =
 	    print_variant_part (type, i, valaddr,
-				stream, recurse, options, comma_needed,
+				stream, recurse, val, options, comma_needed,
 				outer_type, outer_valaddr);
 	  continue;
 	}
@@ -1106,7 +1096,8 @@ print_field_values (struct type *type, const gdb_byte *valaddr,
 	      opts = *options;
 	      opts.deref_ref = 0;
 	      val_print (TYPE_FIELD_TYPE (type, i), value_contents (v), 0, 0,
-			 stream, recurse + 1, &opts, current_language);
+			 stream, recurse + 1, v,
+			 &opts, current_language);
 	    }
 	}
       else
@@ -1116,7 +1107,7 @@ print_field_values (struct type *type, const gdb_byte *valaddr,
 	  opts.deref_ref = 0;
 	  ada_val_print (TYPE_FIELD_TYPE (type, i),
 			 valaddr + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
-			 0, 0, stream, recurse + 1, &opts);
+			 0, 0, stream, recurse + 1, val, &opts);
 	}
       annotate_field_end ();
     }
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index c2cdd56..8da1ff6 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -70,6 +70,7 @@ extern void c_print_typedef (struct type *, struct symbol *, struct ui_file *);
 
 extern int c_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
 			struct ui_file *, int,
+			const struct value *,
 			const struct value_print_options *);
 
 extern int c_value_print (struct value *, struct ui_file *,
@@ -104,12 +105,14 @@ extern void cp_print_class_member (const gdb_byte *, struct type *,
 extern void cp_print_value_fields (struct type *, struct type *,
 				   const gdb_byte *, int, CORE_ADDR,
 				   struct ui_file *, int,
+				   const struct value *,
 				   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 *,
 					const struct value_print_options *,
 					struct type **, int);
 
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index 9d2da35..e2a5b95 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -150,6 +150,7 @@ c_textual_element_type (struct type *type, char format)
 int
 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)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -177,8 +178,12 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	      print_spaces_filtered (2 + 2 * recurse, stream);
 	    }
 
-	  /* Print arrays of textual chars with a string syntax.  */
-          if (c_textual_element_type (unresolved_elttype, options->format))
+	  /* 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_bits_valid (original_value,
+				   TARGET_CHAR_BIT * embedded_offset,
+				   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
 	    {
 	      /* If requested, look for the first null char and only print
 	         elements up to it.  */
@@ -217,7 +222,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 		  i = 0;
 		}
 	      val_print_array_elements (type, valaddr + embedded_offset, address, stream,
-					recurse, options, i);
+					recurse, original_value, options, i);
 	      fprintf_filtered (stream, "}");
 	    }
 	  break;
@@ -394,7 +399,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
       else
 	cp_print_value_fields_rtti (type, valaddr,
 				    embedded_offset, address, stream,
-				    recurse, options, NULL, 0);
+				    recurse, original_value, options, NULL, 0);
       break;
 
     case TYPE_CODE_ENUM:
@@ -695,9 +700,9 @@ c_value_print (struct value *val, struct ui_file *stream,
 			    full ? "" : _(" [incomplete object]"));
 	  /* Print out object: enclosing type is same as real_type if full */
 	  return val_print (value_enclosing_type (val),
-			    value_contents_all (val), 0,
+			    value_contents_for_printing (val), 0,
 			    value_address (val), stream, 0,
-			    &opts, current_language);
+			    val, &opts, current_language);
           /* Note: When we look up RTTI entries, we don't get any information on
              const or volatile attributes */
 	}
@@ -707,15 +712,16 @@ c_value_print (struct value *val, struct ui_file *stream,
 	  fprintf_filtered (stream, "(%s ?) ",
 			    TYPE_NAME (value_enclosing_type (val)));
 	  return val_print (value_enclosing_type (val),
-			    value_contents_all (val), 0,
+			    value_contents_for_printing (val), 0,
 			    value_address (val), stream, 0,
-			    &opts, current_language);
+			    val, &opts, current_language);
 	}
       /* Otherwise, we end up at the return outside this "if" */
     }
 
-  return val_print (val_type, value_contents_all (val),
+  return val_print (val_type, value_contents_for_printing (val),
 		    value_embedded_offset (val),
 		    value_address (val),
-		    stream, 0, &opts, current_language);
+		    stream, 0,
+		    val, &opts, current_language);
 }
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index 3fbb1f1..209a752 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -81,6 +81,7 @@ static void cp_print_static_field (struct type *, struct value *,
 
 static void cp_print_value (struct type *, struct type *, const gdb_byte *,
 			    int, CORE_ADDR, struct ui_file *, int,
+			    const struct value *,
 			    const struct value_print_options *, struct type **);
 
 
@@ -151,6 +152,7 @@ void
 cp_print_value_fields (struct type *type, struct type *real_type,
 		       const gdb_byte *valaddr, int offset, CORE_ADDR address,
 		       struct ui_file *stream, int recurse,
+		       const struct value *val,
 		       const struct value_print_options *options,
 		       struct type **dont_print_vb, int dont_print_statmem)
 {
@@ -177,7 +179,7 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 
   if (n_baseclasses > 0)
     cp_print_value (type, real_type, valaddr, offset, address, stream,
-		    recurse + 1, options, dont_print_vb);
+		    recurse + 1, val, options, dont_print_vb);
 
   /* Second, print out data fields */
 
@@ -278,6 +280,11 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 		{
 		  fputs_filtered ("<optimized out or zero length>", stream);
 		}
+	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
+					  TYPE_FIELD_BITSIZE (type, i)))
+		{
+		  fputs_filtered (_("<value optimized out>"), stream);
+		}
 	      else
 		{
 		  struct value_print_options opts = *options;
@@ -315,7 +322,7 @@ cp_print_value_fields (struct type *type, struct type *real_type,
 		  val_print (TYPE_FIELD_TYPE (type, i),
 			     valaddr, offset + TYPE_FIELD_BITPOS (type, i) / 8,
 			     address,
-			     stream, recurse + 1, &opts,
+			     stream, recurse + 1, val, &opts,
 			     current_language);
 		}
 	    }
@@ -377,26 +384,35 @@ 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 *val,
 			    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);
+  struct type *real_type = NULL;
+
+  /* We require all bits to be valid in order to attempt a
+     conversion.  */
+  if (value_bits_valid (val, TARGET_CHAR_BIT * offset,
+			TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+    {
+      struct value *value;
+      int full, top, using_enc;
+
+      /* 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,
+			 address, stream, recurse, val, options,
 			 dont_print_vb, dont_print_statmem);
 }
 
@@ -407,6 +423,7 @@ static void
 cp_print_value (struct type *type, struct type *real_type,
 		const gdb_byte *valaddr, int offset, CORE_ADDR address,
 		struct ui_file *stream, int recurse,
+		const struct value *val,
 		const struct value_print_options *options,
 		struct type **dont_print_vb)
 {
@@ -508,14 +525,14 @@ cp_print_value (struct type *type, struct type *real_type,
 	    result = apply_val_pretty_printer (baseclass, base_valaddr,
 					       thisoffset + boffset,
 					       address,
-					       stream, recurse,
+					       stream, recurse, val, 
 					       options,
 					       current_language);
 	  	  
 	  if (!result)
 	    cp_print_value_fields (baseclass, thistype, base_valaddr,
 				   thisoffset + boffset, address,
-				   stream, recurse, options,
+				   stream, recurse, val, options,
 				   ((struct type **)
 				    obstack_base (&dont_print_vb_obstack)),
 				   0);
@@ -582,9 +599,10 @@ cp_print_static_field (struct type *type,
 		    sizeof (CORE_ADDR));
       CHECK_TYPEDEF (type);
       cp_print_value_fields (type, value_enclosing_type (val),
-			     value_contents_all (val),
+			     value_contents_for_printing (val),
 			     value_embedded_offset (val), addr,
-			     stream, recurse, options, NULL, 1);
+			     stream, recurse,
+			     val, options, NULL, 1);
       return;
     }
 
@@ -616,9 +634,10 @@ cp_print_static_field (struct type *type,
 
   opts = *options;
   opts.deref_ref = 0;
-  val_print (type, value_contents_all (val), 
+  val_print (type, value_contents_for_printing (val), 
 	     value_embedded_offset (val), value_address (val),
-	     stream, recurse, &opts, current_language);
+	     stream, recurse,
+	     val, &opts, current_language);
 }
 
 
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
index be27827..c2ec728 100644
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -27,6 +27,7 @@ extern char *d_demangle (const char *mangled, int options);
 extern int d_val_print (struct type *type, const gdb_byte *valaddr,
 			int embedded_offset, CORE_ADDR address,
 			struct ui_file *stream, int recurse,
+			const struct value *val,
 			const struct value_print_options *options);
 
 #endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
index ba3f1f0..87edddb 100644
--- a/gdb/d-valprint.c
+++ b/gdb/d-valprint.c
@@ -31,12 +31,15 @@ static int
 dynamic_array_type (struct type *type, const gdb_byte *valaddr,
 		    int embedded_offset, CORE_ADDR address,
 		    struct ui_file *stream, int recurse,
+		    const struct value *val,
 		    const struct value_print_options *options)
 {
   if (TYPE_NFIELDS (type) == 2
       && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
       && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
-      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+      && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0
+      && value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
+			   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     {
       CORE_ADDR addr;
       struct type *elttype;
@@ -60,7 +63,7 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr,
       ptraddr = value_contents (val);
 
       return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
-			  options);
+			  NULL, options);
     }
   return -1;
 }
@@ -69,6 +72,7 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr,
 int
 d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
              CORE_ADDR address, struct ui_file *stream, int recurse,
+	     const struct value *val,
              const struct value_print_options *options)
 {
   int ret;
@@ -78,12 +82,12 @@ d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
     {
       case TYPE_CODE_STRUCT:
         ret = dynamic_array_type (type, valaddr, embedded_offset, address,
-				  stream, recurse, options);
+				  stream, recurse, val, options);
 	if (ret != -1)
 	   break;
       default:
 	ret = c_val_print (type, valaddr, embedded_offset, address, stream,
-			   recurse, options);
+			   recurse, val, options);
     }
 
   return ret;
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 9e4c85c..3dc1ea7 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -462,7 +462,13 @@ read_pieced_value (struct value *v)
 
   contents = value_contents_raw (v);
   bits_to_skip = 8 * value_offset (v);
-  type_len = 8 * TYPE_LENGTH (value_type (v));
+  if (value_bitsize (v))
+    {
+      bits_to_skip += value_bitpos (v);
+      type_len = value_bitsize (v);
+    }
+  else
+    type_len = 8 * TYPE_LENGTH (value_type (v));
 
   for (i = 0; i < c->n_pieces && offset < type_len; i++)
     {
@@ -586,13 +592,7 @@ read_pieced_value (struct value *v)
 	  break;
 
 	case DWARF_VALUE_OPTIMIZED_OUT:
-	  /* We just leave the bits empty for now.  This is not ideal
-	     but gdb currently does not have a nice way to represent
-	     optimized-out pieces.  */
-	  warning (_("bits %ld-%ld in computed object were optimized out; "
-		     "replacing with zeroes"),
-		   offset,
-		   offset + (long) this_size_bits);
+	  set_value_optimized_out (v, 1);
 	  break;
 
 	default:
@@ -636,7 +636,14 @@ write_pieced_value (struct value *to, struct value *from)
 
   contents = value_contents (from);
   bits_to_skip = 8 * value_offset (to);
-  type_len = 8 * TYPE_LENGTH (value_type (to));
+  if (value_bitsize (to))
+    {
+      bits_to_skip += value_bitpos (to);
+      type_len = value_bitsize (to);
+    }
+  else
+    type_len = 8 * TYPE_LENGTH (value_type (to));
+
   for (i = 0; i < c->n_pieces && offset < type_len; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
@@ -739,17 +746,51 @@ write_pieced_value (struct value *to, struct value *from)
 	  break;
 	default:
 	  set_value_optimized_out (to, 1);
-	  goto done;
+	  break;
 	}
       offset += this_size_bits;
     }
 
- done:
   do_cleanups (cleanup);
 }
 
+static int
+check_pieced_value_validity (const struct value *value, int bit_offset,
+			     int bit_length)
+{
+  struct piece_closure *c
+    = (struct piece_closure *) value_computed_closure (value);
+  int i;
+
+  bit_offset += 8 * value_offset (value);
+  for (i = 0; i < c->n_pieces && bit_length > 0; i++)
+    {
+      struct dwarf_expr_piece *p = &c->pieces[i];
+      size_t this_size_bits = p->size;
+
+      if (bit_offset > 0)
+	{
+	  if (bit_offset >= this_size_bits)
+	    {
+	      bit_offset -= this_size_bits;
+	      continue;
+	    }
+
+	  bit_length -= bit_offset;
+	  bit_offset = 0;
+	}
+      else
+	bit_length -= this_size_bits;
+
+      if (p->location == DWARF_VALUE_OPTIMIZED_OUT)
+	return 0;
+    }
+
+  return 1;
+}
+
 static void *
-copy_pieced_value_closure (struct value *v)
+copy_pieced_value_closure (const struct value *v)
 {
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
   
@@ -774,6 +815,7 @@ free_pieced_value_closure (struct value *v)
 static struct lval_funcs pieced_value_funcs = {
   read_pieced_value,
   write_pieced_value,
+  check_pieced_value_validity,
   copy_pieced_value_closure,
   free_pieced_value_closure
 };
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
index 094d6fa..ee3d91f 100644
--- a/gdb/f-lang.h
+++ b/gdb/f-lang.h
@@ -30,6 +30,7 @@ extern void f_print_type (struct type *, char *, struct ui_file *, int,
 
 extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
 			struct ui_file *, int,
+			const struct value *,
 			const struct value_print_options *);
 
 /* Language-specific data structures */
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
index acd6487..4db0b27 100644
--- a/gdb/f-valprint.c
+++ b/gdb/f-valprint.c
@@ -164,6 +164,7 @@ static void
 f77_print_array_1 (int nss, int ndimensions, struct type *type,
 		   const gdb_byte *valaddr, CORE_ADDR address,
 		   struct ui_file *stream, int recurse,
+		   const struct value *val,
 		   const struct value_print_options *options,
 		   int *elts)
 {
@@ -177,7 +178,7 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type,
 	  f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type),
 			     valaddr + i * F77_DIM_OFFSET (nss),
 			     address + i * F77_DIM_OFFSET (nss),
-			     stream, recurse, options, elts);
+			     stream, recurse, val, options, elts);
 	  fprintf_filtered (stream, ") ");
 	}
       if (*elts >= options->print_max && i < F77_DIM_SIZE (nss)) 
@@ -192,7 +193,7 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type,
 		     valaddr + i * F77_DIM_OFFSET (ndimensions),
 		     0,
 		     address + i * F77_DIM_OFFSET (ndimensions),
-		     stream, recurse, options, current_language);
+		     stream, recurse, val, options, current_language);
 
 	  if (i != (F77_DIM_SIZE (nss) - 1))
 	    fprintf_filtered (stream, ", ");
@@ -210,7 +211,9 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type,
 static void
 f77_print_array (struct type *type, const gdb_byte *valaddr,
 		 CORE_ADDR address, struct ui_file *stream,
-		 int recurse, const struct value_print_options *options)
+		 int recurse,
+		 const struct value *val,
+		 const struct value_print_options *options)
 {
   int ndimensions;
   int elts = 0;
@@ -228,7 +231,7 @@ f77_print_array (struct type *type, const gdb_byte *valaddr,
   f77_create_arrayprint_offset_tbl (type, stream);
 
   f77_print_array_1 (1, ndimensions, type, valaddr, address, stream,
-		     recurse, options, &elts);
+		     recurse, val, options, &elts);
 }
 
 
@@ -242,6 +245,7 @@ f77_print_array (struct type *type, const gdb_byte *valaddr,
 int
 f_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)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -263,7 +267,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
     case TYPE_CODE_ARRAY:
       fprintf_filtered (stream, "(");
-      f77_print_array (type, valaddr, address, stream, recurse, options);
+      f77_print_array (type, valaddr, address, stream, recurse, original_value, options);
       fprintf_filtered (stream, ")");
       break;
 
@@ -424,7 +428,8 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	    {
 	      /* Bash the type code temporarily.  */
 	      TYPE_CODE (type) = TYPE_CODE_INT;
-	      f_val_print (type, valaddr, 0, address, stream, recurse, options);
+	      val_print (type, valaddr, 0, address, stream, recurse,
+			 original_value, options, current_language);
 	      /* Restore the type code so later uses work as intended. */
 	      TYPE_CODE (type) = TYPE_CODE_BOOL;
 	    }
@@ -456,8 +461,9 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
         {
           int offset = TYPE_FIELD_BITPOS (type, index) / 8;
 
-          f_val_print (TYPE_FIELD_TYPE (type, index), valaddr + offset,
-                       embedded_offset, address, stream, recurse, options);
+          val_print (TYPE_FIELD_TYPE (type, index), valaddr + offset,
+		     embedded_offset, address, stream, recurse + 1,
+		     original_value, options, current_language);
           if (index != TYPE_NFIELDS (type) - 1)
             fputs_filtered (", ", stream);
         }
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 5ada1e8..4a91a40 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1957,7 +1957,7 @@ default_print_registers_info (struct gdbarch *gdbarch,
 	  get_user_print_options (&opts);
 	  opts.deref_ref = 1;
 	  val_print (register_type (gdbarch, i), buffer, 0, 0,
-		     file, 0, &opts, current_language);
+		     file, 0, NULL, &opts, current_language);
 
 	  fprintf_filtered (file, "\t(raw 0x");
 	  for (j = 0; j < register_size (gdbarch, i); j++)
@@ -1980,8 +1980,7 @@ default_print_registers_info (struct gdbarch *gdbarch,
 	  get_formatted_print_options (&opts, 'x');
 	  opts.deref_ref = 1;
 	  val_print (register_type (gdbarch, i), buffer, 0, 0,
-		     file, 0, &opts,
-		     current_language);
+		     file, 0, NULL, &opts, current_language);
           /* If not a vector register, print it also according to its
              natural format.  */
 	  if (TYPE_VECTOR (register_type (gdbarch, i)) == 0)
@@ -1990,7 +1989,7 @@ default_print_registers_info (struct gdbarch *gdbarch,
 	      opts.deref_ref = 1;
 	      fprintf_filtered (file, "\t");
 	      val_print (register_type (gdbarch, i), buffer, 0, 0,
-			 file, 0, &opts, current_language);
+			 file, 0, NULL, &opts, current_language);
 	    }
 	}
 
diff --git a/gdb/jv-lang.h b/gdb/jv-lang.h
index 95d6384..24ca61e 100644
--- a/gdb/jv-lang.h
+++ b/gdb/jv-lang.h
@@ -44,6 +44,7 @@ extern const struct builtin_java_type *builtin_java_type (struct gdbarch *);
 
 extern int java_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
 			   struct ui_file *, int,
+			   const struct value *,
 			   const struct value_print_options *);
 
 extern int java_value_print (struct value *, struct ui_file *,
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index 165f14e..1819b50 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -259,6 +259,7 @@ static void
 java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 			 CORE_ADDR address, struct ui_file *stream,
 			 int recurse,
+			 const struct value *val,
 			 const struct value_print_options *options)
 {
   int i, len, n_baseclasses;
@@ -302,7 +303,7 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 	  base_valaddr = valaddr;
 
 	  java_print_value_fields (baseclass, base_valaddr, address + boffset,
-				   stream, recurse + 1, options);
+				   stream, recurse + 1, val, options);
 	  fputs_filtered (", ", stream);
 	}
 
@@ -392,6 +393,11 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		{
 		  fputs_filtered ("<optimized out or zero length>", stream);
 		}
+	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
+					  TYPE_FIELD_BITSIZE (type, i)))
+		{
+		  fputs_filtered (_("<value optimized out>"), stream);
+		}
 	      else
 		{
 		  struct value_print_options opts;
@@ -440,7 +446,7 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		  val_print (TYPE_FIELD_TYPE (type, i),
 			     valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0,
 			     address + TYPE_FIELD_BITPOS (type, i) / 8,
-			     stream, recurse + 1, &opts,
+			     stream, recurse + 1, val, &opts,
 			     current_language);
 		}
 	    }
@@ -467,6 +473,7 @@ int
 java_val_print (struct type *type, const gdb_byte *valaddr,
 		int embedded_offset, CORE_ADDR address,
 		struct ui_file *stream, int recurse,
+		const struct value *val,
 		const struct value_print_options *options)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -543,12 +550,12 @@ java_val_print (struct type *type, const gdb_byte *valaddr,
 
     case TYPE_CODE_STRUCT:
       java_print_value_fields (type, valaddr, address, stream, recurse,
-			       options);
+			       val, options);
       break;
 
     default:
       return c_val_print (type, valaddr, embedded_offset, address, stream,
-			  recurse, options);
+			  recurse, val, options);
     }
 
   return 0;
diff --git a/gdb/language.c b/gdb/language.c
index c20d7c0..90bb228 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -1107,6 +1107,7 @@ static int
 unk_lang_val_print (struct type *type, const gdb_byte *valaddr,
 		    int embedded_offset, CORE_ADDR address,
 		    struct ui_file *stream, int recurse,
+		    const struct value *val,
 		    const struct value_print_options *options)
 {
   error (_("internal error - unimplemented function unk_lang_val_print called."));
diff --git a/gdb/language.h b/gdb/language.h
index 9306a82..0c04208 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -233,6 +233,7 @@ struct language_defn
 			 const gdb_byte *contents,
 			 int embedded_offset, CORE_ADDR address,
 			 struct ui_file *stream, int recurse,
+			 const struct value *val,
 			 const struct value_print_options *options);
 
     /* Print a top-level value using syntax appropriate for this language. */
@@ -401,9 +402,9 @@ extern enum language set_language (enum language);
 #define LA_PRINT_TYPEDEF(type,new_symbol,stream) \
   (current_language->la_print_typedef(type,new_symbol,stream))
 
-#define LA_VAL_PRINT(type,valaddr,offset,addr,stream,recurse,options) \
+#define LA_VAL_PRINT(type,valaddr,offset,addr,stream,val,recurse,options) \
   (current_language->la_val_print(type,valaddr,offset,addr,stream, \
-				  recurse,options))
+				  val,recurse,options))
 #define LA_VALUE_PRINT(val,stream,options) \
   (current_language->la_value_print(val,stream,options))
 
diff --git a/gdb/m2-lang.h b/gdb/m2-lang.h
index 75623e2..161b4b6 100644
--- a/gdb/m2-lang.h
+++ b/gdb/m2-lang.h
@@ -34,6 +34,7 @@ extern int m2_is_unbounded_array (struct type *type);
 
 extern int m2_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
 			 struct ui_file *, int,
+			 const struct value *,
 			 const struct value_print_options *);
 
 extern int get_long_set_bounds (struct type *type, LONGEST *low,
diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c
index edfd324..95a7a93 100644
--- a/gdb/m2-valprint.c
+++ b/gdb/m2-valprint.c
@@ -38,6 +38,7 @@ static void
 m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 			 int embedded_offset, CORE_ADDR address,
 			 struct ui_file *stream, int recurse,
+			 const struct value *val,
 			 const struct value_print_options *options,
 			 int len);
 
@@ -202,7 +203,7 @@ m2_print_unbounded_array (struct type *type, const gdb_byte *valaddr,
   fprintf_filtered (stream, "{");  
   m2_print_array_contents (value_type (val), value_contents(val),
 			   value_embedded_offset (val), addr, stream,
-			   recurse, options, len);
+			   recurse, NULL, options, len);
   fprintf_filtered (stream, ", HIGH = %d}", (int) len);
 }
 
@@ -277,6 +278,7 @@ static void
 m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 			 int embedded_offset, CORE_ADDR address,
 			 struct ui_file *stream, int recurse,
+			 const struct value *val,
 			 const struct value_print_options *options,
 			 int len)
 {
@@ -299,7 +301,8 @@ m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 	{
 	  fprintf_filtered (stream, "{");
 	  val_print_array_elements (type, valaddr + embedded_offset,
-				    address, stream, recurse, options, 0);
+				    address, stream, recurse, val,
+				    options, 0);
 	  fprintf_filtered (stream, "}");
 	}
     }
@@ -316,6 +319,7 @@ m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 int
 m2_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)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -367,7 +371,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	    {
 	      fprintf_filtered (stream, "{");
 	      val_print_array_elements (type, valaddr + embedded_offset,
-					address, stream, recurse, options, 0);
+					address, stream, recurse, original_value,
+					options, 0);
 	      fprintf_filtered (stream, "}");
 	    }
 	  break;
@@ -436,7 +441,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 				  address, stream, recurse, options);
       else
 	cp_print_value_fields (type, type, valaddr, embedded_offset,
-			       address, stream, recurse, options, NULL, 0);
+			       address, stream, recurse, original_value,
+			       options, NULL, 0);
       break;
 
     case TYPE_CODE_ENUM:
@@ -508,7 +514,7 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
       if (TYPE_LENGTH (type) == TYPE_LENGTH (TYPE_TARGET_TYPE (type)))
 	{
 	  m2_val_print (TYPE_TARGET_TYPE (type), valaddr, embedded_offset,
-			address, stream, recurse, options);
+			address, stream, recurse, original_value, options);
 	  break;
 	}
       /* FIXME: create_range_type does not set the unsigned bit in a
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index c9472ed..8048756 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -1124,7 +1124,7 @@ get_register (struct frame_info *frame, int regnum, int format)
       get_formatted_print_options (&opts, format);
       opts.deref_ref = 1;
       val_print (register_type (gdbarch, regnum), buffer, 0, 0,
-		 stb->stream, 0, &opts, current_language);
+		 stb->stream, 0, NULL, &opts, current_language);
       ui_out_field_stream (uiout, "value", stb);
       ui_out_stream_delete (stb);
     }
@@ -1215,9 +1215,7 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc)
   /* Print the result of the expression evaluation.  */
   get_user_print_options (&opts);
   opts.deref_ref = 0;
-  val_print (value_type (val), value_contents (val),
-	     value_embedded_offset (val), value_address (val),
-	     stb->stream, 0, &opts, current_language);
+  common_val_print (val, stb->stream, 0, &opts, current_language);
 
   ui_out_field_stream (uiout, "value", stb);
   ui_out_stream_delete (stb);
diff --git a/gdb/mt-tdep.c b/gdb/mt-tdep.c
index 1548151..e8ea5bc 100644
--- a/gdb/mt-tdep.c
+++ b/gdb/mt-tdep.c
@@ -710,8 +710,8 @@ mt_registers_info (struct gdbarch *gdbarch,
 	  get_raw_print_options (&opts);
 	  opts.deref_ref = 1;
 	  val_print (register_type (gdbarch, regnum), buf,
-		     0, 0, file, 0, &opts,
-		     current_language);
+		     0, 0, file, 0, NULL,
+		     &opts, current_language);
 	  fputs_filtered ("\n", file);
 	}
       else if (regnum == MT_MAC_REGNUM || regnum == MT_MAC_PSEUDOREG_REGNUM)
diff --git a/gdb/p-lang.h b/gdb/p-lang.h
index 4090caa..0ea2fc9 100644
--- a/gdb/p-lang.h
+++ b/gdb/p-lang.h
@@ -37,6 +37,7 @@ extern void pascal_print_typedef (struct type *, struct symbol *,
 
 extern int pascal_val_print (struct type *, const gdb_byte *, int,
 			     CORE_ADDR, struct ui_file *, int,
+			     const struct value *,
 			     const struct value_print_options *);
 
 extern int pascal_value_print (struct value *, struct ui_file *,
@@ -70,6 +71,7 @@ extern void
 extern void pascal_object_print_value_fields (struct type *, const gdb_byte *,
 					      CORE_ADDR, struct ui_file *,
 					      int,
+					      const struct value *,
 					      const struct value_print_options *,
 					      struct type **, int);
 
diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c
index 1c2f36d..539df76 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -54,6 +54,7 @@ int
 pascal_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)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -125,7 +126,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
 		  i = 0;
 		}
 	      val_print_array_elements (type, valaddr + embedded_offset, address, stream,
-					recurse, options, i);
+					recurse, original_value, options, i);
 	      fprintf_filtered (stream, "}");
 	    }
 	  break;
@@ -317,7 +318,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
 	    }
 	  else
 	    pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream,
-					      recurse, options, NULL, 0);
+					      recurse, original_value, options, NULL, 0);
 	}
       break;
 
@@ -611,6 +612,7 @@ static void pascal_object_print_static_field (struct value *,
 
 static void pascal_object_print_value (struct type *, const gdb_byte *,
 				       CORE_ADDR, struct ui_file *, int,
+				       const struct value *,
 				       const struct value_print_options *,
 				       struct type **);
 
@@ -668,6 +670,7 @@ void
 pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
 				  CORE_ADDR address, struct ui_file *stream,
 				  int recurse,
+				  const struct value *val,
 				  const struct value_print_options *options,
 				  struct type **dont_print_vb,
 				  int dont_print_statmem)
@@ -685,7 +688,7 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
      duplicates of virtual baseclasses.  */
   if (n_baseclasses > 0)
     pascal_object_print_value (type, valaddr, address, stream,
-			       recurse + 1, options, dont_print_vb);
+			       recurse + 1, val, options, dont_print_vb);
 
   if (!len && n_baseclasses == 1)
     fprintf_filtered (stream, "<No data fields>");
@@ -774,6 +777,11 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		{
 		  fputs_filtered ("<optimized out or zero length>", stream);
 		}
+	      else if (!value_bits_valid (val, TYPE_FIELD_BITPOS (type, i),
+					  TYPE_FIELD_BITSIZE (type, i)))
+		{
+		  fputs_filtered (_("<value optimized out>"), stream);
+		}
 	      else
 		{
 		  struct value_print_options opts = *options;
@@ -818,7 +826,7 @@ pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
 		  val_print (TYPE_FIELD_TYPE (type, i),
 			     valaddr, TYPE_FIELD_BITPOS (type, i) / 8,
 			     address + TYPE_FIELD_BITPOS (type, i) / 8,
-			     stream, recurse + 1, &opts,
+			     stream, recurse + 1, val, &opts,
 			     current_language);
 		}
 	    }
@@ -849,6 +857,7 @@ static void
 pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
 			   CORE_ADDR address, struct ui_file *stream,
 			   int recurse,
+			   const struct value *val,
 			   const struct value_print_options *options,
 			   struct type **dont_print_vb)
 {
@@ -923,7 +932,7 @@ pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
 	fprintf_filtered (stream, "<invalid address>");
       else
 	pascal_object_print_value_fields (baseclass, base_valaddr, address + boffset,
-					  stream, recurse, options,
+					  stream, recurse, val, options,
 		     (struct type **) obstack_base (&dont_print_vb_obstack),
 					  0);
       fputs_filtered (", ", stream);
@@ -987,7 +996,8 @@ pascal_object_print_static_field (struct value *val,
 
       CHECK_TYPEDEF (type);
       pascal_object_print_value_fields (type, value_contents (val), addr,
-					stream, recurse, options, NULL, 1);
+					stream, recurse, NULL, options,
+					NULL, 1);
       return;
     }
 
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 58cb1f6..42aff63 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -374,7 +374,7 @@ print_scalar_formatted (const void *valaddr, struct type *type,
       struct value_print_options opts = *options;
       opts.format = 0;
       opts.deref_ref = 0;
-      val_print (type, valaddr, 0, 0, stream, 0, &opts,
+      val_print (type, valaddr, 0, 0, stream, 0, NULL, &opts,
 		 current_language);
       return;
     }
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index e678898..9601d40 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -598,6 +598,7 @@ int
 apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
 			  int embedded_offset, CORE_ADDR address,
 			  struct ui_file *stream, int recurse,
+			  const struct value *val,
 			  const struct value_print_options *options,
 			  const struct language_defn *language)
 {
@@ -616,6 +617,15 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
     valaddr += embedded_offset;
   value = value_from_contents_and_address (type, valaddr,
 					   address + embedded_offset);
+  if (val != NULL)
+    {
+      set_value_component_location (value, val);
+      /* set_value_component_location resets the address, so we may
+	 need to reset it.  */
+      if (VALUE_LVAL (value) != lval_internalvar
+	  && VALUE_LVAL (value) != lval_internalvar_component)
+	set_value_address (value, address + embedded_offset);
+    }
 
   val_obj = value_to_value_object (value);
   if (! val_obj)
@@ -730,6 +740,7 @@ int
 apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
 			  int embedded_offset, CORE_ADDR address,
 			  struct ui_file *stream, int recurse,
+			  const struct value *val,
 			  const struct value_print_options *options,
 			  const struct language_defn *language)
 {
diff --git a/gdb/python/python.h b/gdb/python/python.h
index ae808c0..affd4a4 100644
--- a/gdb/python/python.h
+++ b/gdb/python/python.h
@@ -31,6 +31,7 @@ void source_python_script (FILE *stream, const char *file);
 int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
 			      int embedded_offset, CORE_ADDR address,
 			      struct ui_file *stream, int recurse,
+			      const struct value *val,
 			      const struct value_print_options *options,
 			      const struct language_defn *language);
 
diff --git a/gdb/scm-lang.h b/gdb/scm-lang.h
index bcb29d8..1adeee5 100644
--- a/gdb/scm-lang.h
+++ b/gdb/scm-lang.h
@@ -50,6 +50,7 @@ extern int scm_value_print (struct value *, struct ui_file *,
 
 extern int scm_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
 			  struct ui_file *, int,
+			  const struct value *,
 			  const struct value_print_options *);
 
 extern LONGEST scm_get_field (LONGEST, int, int, enum bfd_endian);
diff --git a/gdb/scm-valprint.c b/gdb/scm-valprint.c
index 8000c78..c5e1ce1 100644
--- a/gdb/scm-valprint.c
+++ b/gdb/scm-valprint.c
@@ -422,9 +422,12 @@ int
 scm_val_print (struct type *type, const gdb_byte *valaddr,
 	       int embedded_offset, CORE_ADDR address,
 	       struct ui_file *stream, int recurse,
+	       const struct value *val,
 	       const struct value_print_options *options)
 {
-  if (is_scmvalue_type (type))
+  if (is_scmvalue_type (type)
+      && value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset,
+			   TARGET_CHAR_BIT * TYPE_LENGTH (type)))
     {
       enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
       LONGEST svalue
@@ -443,7 +446,8 @@ scm_val_print (struct type *type, const gdb_byte *valaddr,
     }
   else
     {
-      return c_val_print (type, valaddr, 0, address, stream, recurse, options);
+      return c_val_print (type, valaddr, 0, address, stream, recurse,
+			  val, options);
     }
 }
 
diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c
index 8d7782a..6267541 100644
--- a/gdb/sh64-tdep.c
+++ b/gdb/sh64-tdep.c
@@ -2121,12 +2121,12 @@ sh64_do_register (struct gdbarch *gdbarch, struct ui_file *file,
   get_formatted_print_options (&opts, 'x');
   opts.deref_ref = 1;
   val_print (register_type (gdbarch, regnum), raw_buffer, 0, 0,
-	     file, 0, &opts, current_language);
+	     file, 0, NULL, &opts, current_language);
   fprintf_filtered (file, "\t");
   get_formatted_print_options (&opts, 0);
   opts.deref_ref = 1;
   val_print (register_type (gdbarch, regnum), raw_buffer, 0, 0,
-	     file, 0, &opts, current_language);
+	     file, 0, NULL, &opts, current_language);
   fprintf_filtered (file, "\n");
 }
 
diff --git a/gdb/testsuite/gdb.dwarf2/pieces.exp b/gdb/testsuite/gdb.dwarf2/pieces.exp
index 2e812b5..1e3ef7f 100644
--- a/gdb/testsuite/gdb.dwarf2/pieces.exp
+++ b/gdb/testsuite/gdb.dwarf2/pieces.exp
@@ -76,8 +76,6 @@ proc pieces_test_f3 {} {
     gdb_continue_to_breakpoint "continue to f3 breakpoint for pieces"
     gdb_test "print a.i" " = 4" "print a.i in pieces:f3"
     gdb_test "print a.j" " = 14" "print a.j in pieces:f3"
-    # Right now gdb says "value optimized out" here, but that is wrong.
-    setup_kfail "no bug yet" *-*-*
     gdb_test "print a.i = 7" " = 7" "set a.i in pieces:f3"
     gdb_test "print a.i" " = 7" "print new a.i in pieces:f3"
 }
@@ -90,7 +88,7 @@ proc pieces_test_f6 {} {
        "set f6 breakpoint for pieces"
     gdb_continue_to_breakpoint "continue to f6 breakpoint for pieces"
     gdb_test "print a" \
-	"warning: bits .* in computed object were.* = {i = 7, j = 8, q = 0}" \
+	" = {i = 7, j = 8, q = .value optimized out.}" \
 	"print a with optimized out piece"
     # Note: no warning for this case.
     gdb_test_multiple "print a.i" \
diff --git a/gdb/valops.c b/gdb/valops.c
index 6cd66dd..5103041 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -941,11 +941,17 @@ value_fetch_lazy (struct value *val)
       struct value *parent = value_parent (val);
       LONGEST offset = value_offset (val);
       LONGEST num = unpack_bits_as_long (value_type (val),
-					 value_contents (parent) + offset,
+					 (value_contents_for_printing (parent)
+					  + offset),
 					 value_bitpos (val),
 					 value_bitsize (val));
       int length = TYPE_LENGTH (type);
 
+      if (!value_bits_valid (val,
+			     TARGET_CHAR_BIT * offset + value_bitpos (val),
+			     value_bitsize (val)))
+	error (_("value has been optimized out"));
+
       store_signed_integer (value_contents_raw (val), length, byte_order, num);
     }
   else if (VALUE_LVAL (val) == lval_memory)
@@ -1246,6 +1252,7 @@ value_assign (struct value *toval, struct value *fromval)
     {
     case lval_memory:
     case lval_register:
+    case lval_computed:
 
       reinit_frame_cache ();
 
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 517e607..b1909c3 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -245,6 +245,39 @@ scalar_type_p (struct type *type)
     }
 }
 
+/* Helper function to check the validity of some bits of a value.
+
+   If TYPE represents some aggregate type (e.g., a structure), return 1.
+   
+   Otherwise, any of the bytes starting at OFFSET and extending for
+   TYPE_LENGTH(TYPE) bytes are invalid, print a message to STREAM and
+   return 0.  The checking is done using FUNCS.
+   
+   Otherwise, return 1.  */
+
+static int
+valprint_check_validity (struct ui_file *stream,
+			 struct type *type,
+			 int offset,
+			 const struct value *val)
+{
+  CHECK_TYPEDEF (type);
+
+  if (TYPE_CODE (type) != TYPE_CODE_UNION
+      && TYPE_CODE (type) != TYPE_CODE_STRUCT
+      && TYPE_CODE (type) != TYPE_CODE_ARRAY)
+    {
+      if (! value_bits_valid (val, TARGET_CHAR_BIT * offset,
+			      TARGET_CHAR_BIT * TYPE_LENGTH (type)))
+	{
+	  fprintf_filtered (stream, _("<value optimized out>"));
+	  return 0;
+	}
+    }
+
+  return 1;
+}
+
 /* Print using the given LANGUAGE the data of type TYPE located at VALADDR
    (within GDB), which came from the inferior at address ADDRESS, onto
    stdio stream STREAM according to OPTIONS.
@@ -263,6 +296,7 @@ scalar_type_p (struct type *type)
 int
 val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	   CORE_ADDR address, struct ui_file *stream, int recurse,
+	   const struct value *val,
 	   const struct value_print_options *options,
 	   const struct language_defn *language)
 {
@@ -283,16 +317,19 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 
   if (TYPE_STUB (real_type))
     {
-      fprintf_filtered (stream, "<incomplete type>");
+      fprintf_filtered (stream, _("<incomplete type>"));
       gdb_flush (stream);
       return (0);
     }
 
+  if (!valprint_check_validity (stream, real_type, embedded_offset, val))
+    return 0;
+
   if (!options->raw)
     {
       ret = apply_val_pretty_printer (type, valaddr, embedded_offset,
-				      address, stream, recurse, options,
-				      language);
+				      address, stream, recurse,
+				      val, options, language);
       if (ret)
 	return ret;
     }
@@ -308,7 +345,8 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
   TRY_CATCH (except, RETURN_MASK_ERROR)
     {
       ret = language->la_val_print (type, valaddr, embedded_offset, address,
-				    stream, recurse, &local_opts);
+				    stream, recurse, val,
+				    &local_opts);
     }
   if (except.reason < 0)
     fprintf_filtered (stream, _("<error reading variable>"));
@@ -329,12 +367,6 @@ value_check_printable (struct value *val, struct ui_file *stream)
       return 0;
     }
 
-  if (value_optimized_out (val))
-    {
-      fprintf_filtered (stream, _("<value optimized out>"));
-      return 0;
-    }
-
   if (TYPE_CODE (value_type (val)) == TYPE_CODE_INTERNAL_FUNCTION)
     {
       fprintf_filtered (stream, _("<internal function %s>"),
@@ -369,9 +401,10 @@ common_val_print (struct value *val, struct ui_file *stream, int recurse,
        get a fixed representation of our value.  */
     val = ada_to_fixed_value (val);
 
-  return val_print (value_type (val), value_contents_all (val),
+  return val_print (value_type (val), value_contents_for_printing (val),
 		    value_embedded_offset (val), value_address (val),
-		    stream, recurse, options, language);
+		    stream, recurse,
+		    val, options, language);
 }
 
 /* Print on stream STREAM the value VAL according to OPTIONS.  The value
@@ -390,11 +423,11 @@ value_print (struct value *val, struct ui_file *stream,
   if (!options->raw)
     {
       int r = apply_val_pretty_printer (value_type (val),
-					value_contents_all (val),
+					value_contents_for_printing (val),
 					value_embedded_offset (val),
 					value_address (val),
-					stream, 0, options,
-					current_language);
+					stream, 0,
+					val, options, current_language);
 
       if (r)
 	return r;
@@ -1114,6 +1147,7 @@ void
 val_print_array_elements (struct type *type, const gdb_byte *valaddr,
 			  CORE_ADDR address, struct ui_file *stream,
 			  int recurse,
+			  const struct value *val,
 			  const struct value_print_options *options,
 			  unsigned int i)
 {
@@ -1192,7 +1226,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
       if (reps > options->repeat_count_threshold)
 	{
 	  val_print (elttype, valaddr + i * eltlen, 0, address + i * eltlen,
-		     stream, recurse + 1, options, current_language);
+		     stream, recurse + 1, val, options, current_language);
 	  annotate_elt_rep (reps);
 	  fprintf_filtered (stream, " <repeats %u times>", reps);
 	  annotate_elt_rep_end ();
@@ -1203,7 +1237,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
       else
 	{
 	  val_print (elttype, valaddr + i * eltlen, 0, address + i * eltlen,
-		     stream, recurse + 1, options, current_language);
+		     stream, recurse + 1, val, options, current_language);
 	  annotate_elt ();
 	  things_printed++;
 	}
diff --git a/gdb/valprint.h b/gdb/valprint.h
index 9b8004e..d171d61 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -118,6 +118,7 @@ extern void maybe_print_array_index (struct type *index_type, LONGEST index,
 
 extern void val_print_array_elements (struct type *, const gdb_byte *,
 				      CORE_ADDR, struct ui_file *, int,
+				      const struct value *,
 				      const struct value_print_options *,
 				      unsigned int);
 
diff --git a/gdb/value.c b/gdb/value.c
index ec33403..0e47daf 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -360,7 +360,7 @@ deprecated_set_value_type (struct value *value, struct type *type)
 }
 
 int
-value_offset (struct value *value)
+value_offset (const struct value *value)
 {
   return value->offset;
 }
@@ -418,14 +418,29 @@ value_enclosing_type (struct value *value)
   return value->enclosing_type;
 }
 
+static void
+require_not_optimized_out (struct value *value)
+{
+  if (value->optimized_out)
+    error (_("value has been optimized out"));
+}
+
 const gdb_byte *
-value_contents_all (struct value *value)
+value_contents_for_printing (struct value *value)
 {
   if (value->lazy)
     value_fetch_lazy (value);
   return value->contents;
 }
 
+const gdb_byte *
+value_contents_all (struct value *value)
+{
+  const gdb_byte *result = value_contents_for_printing (value);
+  require_not_optimized_out (value);
+  return result;
+}
+
 int
 value_lazy (struct value *value)
 {
@@ -453,7 +468,9 @@ set_value_stack (struct value *value, int val)
 const gdb_byte *
 value_contents (struct value *value)
 {
-  return value_contents_writeable (value);
+  const gdb_byte *result = value_contents_writeable (value);
+  require_not_optimized_out (value);
+  return result;
 }
 
 gdb_byte *
@@ -497,6 +514,18 @@ set_value_optimized_out (struct value *value, int val)
 }
 
 int
+value_bits_valid (const struct value *value, int offset, int length)
+{
+  if (value == NULL || !value->optimized_out)
+    return 1;
+  if (value->lval != lval_computed
+      || !value->location.computed.funcs->check_validity)
+    return 0;
+  return value->location.computed.funcs->check_validity (value, offset,
+							 length);
+}
+
+int
 value_embedded_offset (struct value *value)
 {
   return value->embedded_offset;
@@ -529,9 +558,9 @@ value_computed_funcs (struct value *v)
 }
 
 void *
-value_computed_closure (struct value *v)
+value_computed_closure (const struct value *v)
 {
-  gdb_assert (VALUE_LVAL (v) == lval_computed);
+  gdb_assert (v->lval == lval_computed);
 
   return v->location.computed.closure;
 }
@@ -771,15 +800,16 @@ value_copy (struct value *arg)
 }
 
 void
-set_value_component_location (struct value *component, struct value *whole)
+set_value_component_location (struct value *component,
+			      const struct value *whole)
 {
-  if (VALUE_LVAL (whole) == lval_internalvar)
+  if (whole->lval == lval_internalvar)
     VALUE_LVAL (component) = lval_internalvar_component;
   else
-    VALUE_LVAL (component) = VALUE_LVAL (whole);
+    VALUE_LVAL (component) = whole->lval;
 
   component->location = whole->location;
-  if (VALUE_LVAL (whole) == lval_computed)
+  if (whole->lval == lval_computed)
     {
       struct lval_funcs *funcs = whole->location.computed.funcs;
 
diff --git a/gdb/value.h b/gdb/value.h
index 57b4dd7..ee7499f 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -83,7 +83,7 @@ struct value *value_parent (struct value *);
    within the registers structure.  Note also the member
    embedded_offset below.  */
 
-extern int value_offset (struct value *);
+extern int value_offset (const struct value *);
 extern void set_value_offset (struct value *, int offset);
 
 /* The comment from "struct value" reads: ``Is it modifiable?  Only
@@ -164,13 +164,18 @@ struct lval_funcs
      should call 'error'.  */
   void (*write) (struct value *toval, struct value *fromval);
 
+  /* Check the validity of some bits in VALUE.  This should return 1
+     if all the bits starting at OFFSET and extending for LENGTH bits
+     are valid, or 0 if any bit is invalid.  */
+  int (*check_validity) (const struct value *value, int offset, int length);
+
   /* Return a duplicate of VALUE's closure, for use in a new value.
      This may simply return the same closure, if VALUE's is
      reference-counted or statically allocated.
 
      This may be NULL, in which case VALUE's closure is re-used in the
      new value.  */
-  void *(*copy_closure) (struct value *v);
+  void *(*copy_closure) (const struct value *v);
 
   /* Drop VALUE's reference to its closure.  Maybe this frees the
      closure; maybe this decrements a reference count; maybe the
@@ -195,7 +200,7 @@ extern struct lval_funcs *value_computed_funcs (struct value *value);
 /* If VALUE is lval_computed, return its closure.  The meaning of the
    returned value depends on the functions VALUE uses.  */
 
-extern void *value_computed_closure (struct value *value);
+extern void *value_computed_closure (const struct value *value);
 
 /* If zero, contents of this value are in the contents field.  If
    nonzero, contents are in inferior.  If the lval field is lval_memory,
@@ -249,6 +254,11 @@ extern gdb_byte *value_contents_writeable (struct value *);
 extern gdb_byte *value_contents_all_raw (struct value *);
 extern const gdb_byte *value_contents_all (struct value *);
 
+/* Like value_contents_all, but does not require that the returned
+   bits be valid.  This should only be used in situations where you
+   plan to check the validity manually.  */
+extern const gdb_byte *value_contents_for_printing (struct value *value);
+
 extern int value_fetch_lazy (struct value *val);
 extern int value_contents_equal (struct value *val1, struct value *val2);
 
@@ -266,7 +276,7 @@ extern void set_value_initialized (struct value *, int);
 /* Set COMPONENT's location as appropriate for a component of WHOLE
    --- regardless of what kind of lvalue WHOLE is.  */
 extern void set_value_component_location (struct value *component,
-                                          struct value *whole);
+                                          const struct value *whole);
 
 /* While the following fields are per- VALUE .CONTENT .PIECE (i.e., a
    single value might have multiple LVALs), this hacked interface is
@@ -313,6 +323,13 @@ extern struct value *coerce_ref (struct value *value);
 
 extern struct value *coerce_array (struct value *value);
 
+/* Given a value, determine whether the bits starting at OFFSET and
+   extending for LENGTH bits are valid.  This returns nonzero if all
+   bits in the given range are valid, zero if any bit is invalid.  */
+
+extern int value_bits_valid (const struct value *value,
+			     int offset, int length);
+
 
 
 #include "symtab.h"
@@ -644,6 +661,7 @@ extern struct value *value_release_to_mark (struct value *mark);
 extern int val_print (struct type *type, const gdb_byte *valaddr,
 		      int embedded_offset, CORE_ADDR address,
 		      struct ui_file *stream, int recurse,
+		      const struct value *val,
 		      const struct value_print_options *options,
 		      const struct language_defn *language);
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]