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]

Re: RFC: optimized-out pieces


>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> a fixup is needed there.
Jan>  print operand0
Jan> -$1 = <value optimized out>
Jan> -(gdb) PASS: gdb.opt/clobbered-registers-O2.exp: print operand0
Jan> +$1 = (unsigned int *) <value optimized out>
Jan> +(gdb) FAIL: gdb.opt/clobbered-registers-O2.exp: print operand0

I think if the entire value is optimized out, we should not print the
type.  So, I fixed it that way.

With my gcc, this isn't actually optimized out, though.

>> +static int
>> +check_pieced_value_validity (const struct value *value, int bit_offset,
>> +			     int bit_length)

Jan> I miss some `value_bitpos (value)' possibility here.

Yeah, oops.  Fixed.

Jan> Here should be `bit_length -= this_size_bits - bit_offset'.

Fixed.

New patch appended.

Tom

b/gdb/ChangeLog:
2010-06-10  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_entirely_optimized_out): Declare.
	* 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.
	(value_entirely_optimized_out): New function.
	(value_bitsize): Argument now 'const'.
	(value_bitpos): Likewise.
	(value_type): Likewise.
	* 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): Use value_entirely_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,
	check_pieced_value_invalid.
	(copy_pieced_value_closure): Update.
	(check_pieced_value_bits): New function.
	(check_pieced_value_invalid): New function.
	* 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.

b/gdb/testsuite/ChangeLog:
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 7e93e3a..2ab2ba2 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 ce5d485..f987b0f 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -490,7 +490,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++)
     {
@@ -614,13 +620,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:
@@ -664,7 +664,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];
@@ -767,17 +774,76 @@ 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_bits (const struct value *value, int bit_offset,
+			 int bit_length, int validity)
+{
+  struct piece_closure *c
+    = (struct piece_closure *) value_computed_closure (value);
+  int i;
+
+  bit_offset += 8 * value_offset (value);
+  if (value_bitsize (value))
+    bit_offset += value_bitpos (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 -= this_size_bits - bit_offset;
+	  bit_offset = 0;
+	}
+      else
+	bit_length -= this_size_bits;
+
+      if (p->location == DWARF_VALUE_OPTIMIZED_OUT)
+	{
+	  if (validity)
+	    return 0;
+	}
+      else
+	{
+	  if (!validity)
+	    return 1;
+	}
+    }
+
+  return validity;
+}
+
+static int
+check_pieced_value_validity (const struct value *value, int bit_offset,
+			     int bit_length)
+{
+  return check_pieced_value_bits (value, bit_offset, bit_length, 1);
+}
+
+static int
+check_pieced_value_invalid (const struct value *value)
+{
+  return check_pieced_value_bits (value, 0,
+				  8 * TYPE_LENGTH (value_type (value)), 0);
+}
+
 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);
   
@@ -802,6 +868,8 @@ free_pieced_value_closure (struct value *v)
 static struct lval_funcs pieced_value_funcs = {
   read_pieced_value,
   write_pieced_value,
+  check_pieced_value_validity,
+  check_pieced_value_invalid,
   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 ec6753d..85a3f99 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -1131,7 +1131,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);
     }
@@ -1222,9 +1222,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 e58f9d2..3d00a69 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 4d60c96..9a205b4 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -603,6 +603,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)
 {
@@ -621,6 +622,16 @@ 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 set it again.  */
+      if (VALUE_LVAL (value) != lval_internalvar
+	  && VALUE_LVAL (value) != lval_internalvar_component
+	  && VALUE_LVAL (value) != lval_computed)
+	set_value_address (value, address + embedded_offset);
+    }
 
   val_obj = value_to_value_object (value);
   if (! val_obj)
@@ -735,6 +746,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 4264d69..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 "exp/11636" *-*-*
     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 08a64ce..506d40e 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 2b06579..ad6268e 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,7 +367,7 @@ value_check_printable (struct value *val, struct ui_file *stream)
       return 0;
     }
 
-  if (value_optimized_out (val))
+  if (value_entirely_optimized_out (val))
     {
       fprintf_filtered (stream, _("<value optimized out>"));
       return 0;
@@ -369,9 +407,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 +429,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;
@@ -1097,6 +1136,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)
 {
@@ -1175,7 +1215,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 ();
@@ -1186,7 +1226,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 070d796..6e339d1 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..5e0e8d8 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -349,7 +349,7 @@ value_next (struct value *value)
 }
 
 struct type *
-value_type (struct value *value)
+value_type (const struct value *value)
 {
   return value->type;
 }
@@ -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;
 }
@@ -371,7 +371,7 @@ set_value_offset (struct value *value, int offset)
 }
 
 int
-value_bitpos (struct value *value)
+value_bitpos (const struct value *value)
 {
   return value->bitpos;
 }
@@ -382,7 +382,7 @@ set_value_bitpos (struct value *value, int bit)
 }
 
 int
-value_bitsize (struct value *value)
+value_bitsize (const struct value *value)
 {
   return value->bitsize;
 }
@@ -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,29 @@ set_value_optimized_out (struct value *value, int val)
 }
 
 int
+value_entirely_optimized_out (const struct value *value)
+{
+  if (!value->optimized_out)
+    return 0;
+  if (value->lval != lval_computed
+      || !value->location.computed.funcs->check_validity)
+    return 1;
+  return value->location.computed.funcs->check_all_valid (value);
+}
+
+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 +569,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 +811,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 7f71dc4..c3dfb17 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -50,7 +50,7 @@ struct value *value_next (struct value *);
 
 /* Type of the value.  */
 
-extern struct type *value_type (struct value *);
+extern struct type *value_type (const struct value *);
 
 /* This is being used to change the type of an existing value, that
    code should instead be creating a new value with the changed type
@@ -61,14 +61,14 @@ extern void deprecated_set_value_type (struct value *value,
 
 /* Only used for bitfields; number of bits contained in them.  */
 
-extern int value_bitsize (struct value *);
+extern int value_bitsize (const struct value *);
 extern void set_value_bitsize (struct value *, int bit);
 
 /* Only used for bitfields; position of start of field.  For
    gdbarch_bits_big_endian=0 targets, it is the position of the LSB.  For
    gdbarch_bits_big_endian=1 targets, it is the position of the MSB.  */
 
-extern int value_bitpos (struct value *);
+extern int value_bitpos (const struct value *);
 extern void set_value_bitpos (struct value *, int bit);
 
 /* Only used for bitfields; the containing value.  This allows a
@@ -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,21 @@ 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 1 if any bit in VALUE is valid, 0 if they are all invalid.  */
+  int (*check_all_valid) (const struct value *value);
+
   /* 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 +203,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 +257,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);
 
@@ -257,6 +270,10 @@ extern int value_contents_equal (struct value *val1, struct value *val2);
 extern int value_optimized_out (struct value *value);
 extern void set_value_optimized_out (struct value *value, int val);
 
+/* Like value_optimized_out, but return false if any bit in the object
+   is valid.  */
+extern int value_entirely_optimized_out (const struct value *value);
+
 /* Set or return field indicating whether a variable is initialized or
    not, based on debugging information supplied by the compiler. 
    1 = initialized; 0 = uninitialized.  */
@@ -266,7 +283,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 +330,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"
@@ -647,6 +671,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]