public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* RFC: optimized-out pieces
@ 2010-06-04 19:19 Tom Tromey
  2010-06-04 21:42 ` Tom Tromey
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Tom Tromey @ 2010-06-04 19:19 UTC (permalink / raw)
  To: gdb-patches

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 *);
 \f
 
@@ -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);
 }
 \f
 
@@ -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);
+
 \f
 
 #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);
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-04 19:19 RFC: optimized-out pieces Tom Tromey
@ 2010-06-04 21:42 ` Tom Tromey
  2010-06-07 22:35 ` Jan Kratochvil
  2010-06-14 12:13 ` [commit] Fix "return" command (Re: RFC: optimized-out pieces) Ulrich Weigand
  2 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2010-06-04 21:42 UTC (permalink / raw)
  To: gdb-patches

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

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

I looked into this a little and my first impression is that neither
varobj nor Python will need any code changes at all.

I will test this out next week.

Python's Value could use a bit more documentation in this area.  I will
write something.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-04 19:19 RFC: optimized-out pieces Tom Tromey
  2010-06-04 21:42 ` Tom Tromey
@ 2010-06-07 22:35 ` Jan Kratochvil
  2010-06-08 18:36   ` Tom Tromey
  2010-06-14 12:13 ` [commit] Fix "return" command (Re: RFC: optimized-out pieces) Ulrich Weigand
  2 siblings, 1 reply; 14+ messages in thread
From: Jan Kratochvil @ 2010-06-07 22:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi Tom,

On Fri, 04 Jun 2010 21:19:28 +0200, Tom Tromey wrote:
> I'd appreciate comments on this patch.  In the absence of comments I
> plan to check it in.

currently it has a lot of regressions, at least tested on Fedora 13 with
-lefence.  Most of them are for x86_64-m32 and i686.  64bit x86_64 is not
regressing much as it has few DW_OP_piece in use.

Good reproducer for x86_64-m32 was for me on current FSF GDB HEAD:
	file gdb.base/store
	b 213
	run
	print u
	print 42

set_value_address sets there value->location.address despite it is an
lval_computed value that time.  Later it crashes on next command:
==4402== Jump to the invalid address stated on the next line
==4402==    at 0x300000: ???
==4402==    by 0x5D6169: free_all_values (value.c:708)
==4402==    by 0x412EED: prepare_execute_command (top.c:339)
==4402==    by 0x412F78: execute_command (top.c:379)
==4402==    by 0x4133B4: command_loop (top.c:524)


x86_64-m32:
	gdb.base/siginfo-obj.exp
	gdb.base/store.exp
x86_64:
	gdb.base/siginfo-obj.exp
	gdb.opt/clobbered-registers-O2.exp - only expected output change
i686:
	gdb.base/siginfo-obj.exp
	gdb.base/store.exp
	gdb.dwarf2/pieces.exp


Regards,
Jan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-07 22:35 ` Jan Kratochvil
@ 2010-06-08 18:36   ` Tom Tromey
  2010-06-08 18:42     ` Jan Kratochvil
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2010-06-08 18:36 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

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

Jan> currently it has a lot of regressions, at least tested on Fedora 13 with
Jan> -lefence.  Most of them are for x86_64-m32 and i686.  64bit x86_64 is not
Jan> regressing much as it has few DW_OP_piece in use.

Thanks.

Jan> set_value_address sets there value->location.address despite it is an
Jan> lval_computed value that time.  Later it crashes on next command:

I fixed this.  I just added lval_computed to the exclusion list in
apply_val_pretty_printer.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-08 18:36   ` Tom Tromey
@ 2010-06-08 18:42     ` Jan Kratochvil
  2010-06-08 18:57       ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Jan Kratochvil @ 2010-06-08 18:42 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Tue, 08 Jun 2010 20:36:04 +0200, Tom Tromey wrote:
> I fixed this.  I just added lval_computed to the exclusion list in
> apply_val_pretty_printer.

And maybe a new patch to post?

(there were also some [obv] const changes)


Thanks,
Jan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-08 18:42     ` Jan Kratochvil
@ 2010-06-08 18:57       ` Tom Tromey
  2010-06-09  5:50         ` Jan Kratochvil
  2010-06-09 18:44         ` Jan Kratochvil
  0 siblings, 2 replies; 14+ messages in thread
From: Tom Tromey @ 2010-06-08 18:57 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

Jan> And maybe a new patch to post?

Here you go... I just rebased so I could update the AX translation patch
to account for your latest DW_OP_call* patch...

I could push to archer if you really want.  I'm enjoying rebasing to
keep the patches clean though.

Jan> (there were also some [obv] const changes)

I must have missed those, point them out and I will fix them.

Tom

b/gdb/ChangeLog:
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.

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 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 *);
 \f
 
@@ -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 e58797e..dd9c558 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -456,7 +456,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++)
     {
@@ -580,13 +586,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:
@@ -630,7 +630,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];
@@ -733,17 +740,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);
   
@@ -763,6 +804,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);
 }
 \f
 
@@ -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..52bfe61 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,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)
@@ -730,6 +741,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);
+
 \f
 
 #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);
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-08 18:57       ` Tom Tromey
@ 2010-06-09  5:50         ` Jan Kratochvil
  2010-06-10 17:14           ` Tom Tromey
  2010-06-09 18:44         ` Jan Kratochvil
  1 sibling, 1 reply; 14+ messages in thread
From: Jan Kratochvil @ 2010-06-09  5:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi Tom,

a fixup is needed there.

 print operand0
-$1 = <value optimized out>
-(gdb) PASS: gdb.opt/clobbered-registers-O2.exp: print operand0
+$1 = (unsigned int *) <value optimized out>
+(gdb) FAIL: gdb.opt/clobbered-registers-O2.exp: print operand0
 print operand1
-$2 = <value optimized out>
-(gdb) PASS: gdb.opt/clobbered-registers-O2.exp: print operand1
+$2 = (unsigned int *) <value optimized out>
+(gdb) FAIL: gdb.opt/clobbered-registers-O2.exp: print operand1


Thanks,
Jan


2010-06-09  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.opt/clobbered-registers-O2.exp (print operand0, print operand1):
	Expect also the type.

--- a/gdb/testsuite/gdb.opt/clobbered-registers-O2.exp
+++ b/gdb/testsuite/gdb.opt/clobbered-registers-O2.exp
@@ -53,12 +53,12 @@ if { ![runto start_sequence] } then {
 gdb_test "frame 1" "#1.*in gen_movsd.*" "Backtracing"
 
 gdb_test_multiple "print operand0" "print operand0" {
-    -re "\\\$$decimal = <value optimized out>\r\n$gdb_prompt $" { pass "print operand0"}
+    -re "\\\$$decimal = \\(unsigned int \\*\\) <value optimized out>\r\n$gdb_prompt $" { pass "print operand0"}
     -re "$hex\r\n$gdb_prompt $" { gdb_test "print *operand0" "13" "print operand0" }
 }
 
 gdb_test_multiple "print operand1" "print operand1" {
-    -re "\\\$$decimal = <value optimized out>\r\n$gdb_prompt $" { pass "print operand1"}
+    -re "\\\$$decimal = \\(unsigned int \\*\\) <value optimized out>\r\n$gdb_prompt $" { pass "print operand1"}
     -re "$hex\r\n$gdb_prompt $" { gdb_test "print *operand1" "14" "print operand1" }
 }
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-08 18:57       ` Tom Tromey
  2010-06-09  5:50         ` Jan Kratochvil
@ 2010-06-09 18:44         ` Jan Kratochvil
  1 sibling, 0 replies; 14+ messages in thread
From: Jan Kratochvil @ 2010-06-09 18:44 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> +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);

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


> +  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;

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

If we heve:
	this_size_bits = 8
	bit_offset = 7
	bit_length = 2
then your code does
	bit_length -= 7; bit_length = -5;
while for the next piece it should be:
	bit_length -= 1; bit_length = 1;


> +	  bit_offset = 0;
> +	}
> +      else
> +	bit_length -= this_size_bits;
> +
> +      if (p->location == DWARF_VALUE_OPTIMIZED_OUT)
> +	return 0;
> +    }
> +
> +  return 1;
> +}


Thanks,
Jan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-09  5:50         ` Jan Kratochvil
@ 2010-06-10 17:14           ` Tom Tromey
  2010-06-11 15:34             ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2010-06-10 17:14 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "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 *);
 \f
 
@@ -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);
 }
 \f
 
@@ -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);
+
 \f
 
 #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);
 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-10 17:14           ` Tom Tromey
@ 2010-06-11 15:34             ` Tom Tromey
  2010-06-14 12:07               ` Frederic Riss
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2010-06-11 15:34 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> New patch appended.

I am checking in the latest version of this patch.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-11 15:34             ` Tom Tromey
@ 2010-06-14 12:07               ` Frederic Riss
  2010-06-15 15:54                 ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Frederic Riss @ 2010-06-14 12:07 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Jan Kratochvil, gdb-patches

Hi Tom,

On 11 June 2010 17:34, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
>
> Tom> New patch appended.
>
> I am checking in the latest version of this patch.

I think this patch regresses on architectures that mark registers as
optimized in their CFI. Specifically when executing the 'return'
command. When iterating over the unwound registers to gather the
values to assign to the registers in pop_frame, frame_register_unwind
calls value_contents_all that will error out if it finds an unsaved
register. I think it's expected to have such registers when doing a
return.

I fixed that by preventing frame_register_unwind to call
value_contents_all in the optimized case (not providing the one-liner
as I don't have the copyright assignment in place anymore).

Cheers,
Fred

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [commit] Fix "return" command (Re: RFC: optimized-out pieces)
  2010-06-04 19:19 RFC: optimized-out pieces Tom Tromey
  2010-06-04 21:42 ` Tom Tromey
  2010-06-07 22:35 ` Jan Kratochvil
@ 2010-06-14 12:13 ` Ulrich Weigand
  2010-06-15 15:58   ` Tom Tromey
  2 siblings, 1 reply; 14+ messages in thread
From: Ulrich Weigand @ 2010-06-14 12:13 UTC (permalink / raw)
  To: tromey; +Cc: gdb-patches

Tom Tromey wrote:

> 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.

This causes several hundred FAILs on PowerPC because the "return"
command is now completely broken.  Instead of actually implementing
the "return" action, the command now simply immediately fails with
an error message: "value has been optimized out".

The problem is that return_command calls frame_pop, which calls
frame_save_as_regcache to retrieve the unwound register values
that are to be restored.  This in turn involves in the end calling
frame_register_unwind for each register, which does:

  value = frame_unwind_register_value (frame, regnum);

  gdb_assert (value != NULL);

  *optimizedp = value_optimized_out (value);
  *lvalp = VALUE_LVAL (value);
  *addrp = value_address (value);
  *realnump = VALUE_REGNUM (value);

  if (bufferp)
    memcpy (bufferp, value_contents_all (value),
            TYPE_LENGTH (value_type (value)));

Now the problem is that if any of those registers cannot be unwound,
such that frame_unwind_register_value returns an optimized-out value,
the value_contents_all call will now throw an exception, which kills
the whole return_command execution.

But this is pretty common occurrence, since usually some registers
indeed cannot be unwound (e.g. because they're call-clobbered).
[ Note that this unfortunately may not show up on Intel because of
somewhat weird behaviour of the DWARF CFI layer: GCC will not
generate *any* CFI records for registers that are call-clobbered
according to the platform ABI.  The default GDB handling of this
case will consider these as DWARF2_FRAME_REG_UNSPECIFIED, which
are treated as "same value as next frame".  This is really not
quite correct, and leads to stale register values shown with
"info register" on any non-innermost frame.  Some platforms,
*but not Intel* fix this by means of a dwarf2_frame_init_reg
routine that marks ABI call-clobbered registers instead as
DWARF2_FRAME_REG_UNDEFINED.  On such platforms, the error will
show up just about every time. ]

Now it seems to me that in any case, it is not expected behaviour
for frame_register_unwind to throw an exception if the register
could not be unwound.  After all, it explicitly *returns* that
fact via the optimizedp parameter to its caller!  The caller
is expected to take proper actions if the value is indeed not
available.  [ And frame_save_as_regcache actually does so.  ]

On the other hand, it does not make sense to memcpy an
uninitialized value either.  Thus, it seems the correct fix
is to simply skip the memcpy, and hence the value_contents_all
call, if the register value is "optimized out". 

The patch below implements this check, and indeed fixes all the
regressions I'm seeing on powerpc(64)-linux.

Tested on powerpc(pc)-linux, committed to mainline.

Bye,
Ulrich


ChangeLog:

	* frame.c (frame_register_unwind): Do not access contents
	of "optimized out" unwound register value.


Index: gdb/frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.283
diff -u -p -r1.283 frame.c
--- gdb/frame.c	14 May 2010 19:27:05 -0000	1.283
+++ gdb/frame.c	13 Jun 2010 17:00:15 -0000
@@ -771,7 +771,7 @@ frame_register_unwind (struct frame_info
   *addrp = value_address (value);
   *realnump = VALUE_REGNUM (value);
 
-  if (bufferp)
+  if (bufferp && !*optimizedp)
     memcpy (bufferp, value_contents_all (value),
 	    TYPE_LENGTH (value_type (value)));
 

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: RFC: optimized-out pieces
  2010-06-14 12:07               ` Frederic Riss
@ 2010-06-15 15:54                 ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2010-06-15 15:54 UTC (permalink / raw)
  To: Frederic Riss; +Cc: Jan Kratochvil, gdb-patches

>>>>> "Frederic" == Frederic Riss <frederic.riss@gmail.com> writes:

Tom> I am checking in the latest version of this patch.

Frederic> I think this patch regresses on architectures that mark registers as
Frederic> optimized in their CFI.

Thanks for the detailed report.  It looks like Ulrich already fixed
this.  I'm sorry about the breakage; I'm looking at setting up a
buildbot so we can more easily regression test on multiple
architectures.

Frederic> I fixed that by preventing frame_register_unwind to call
Frederic> value_contents_all in the optimized case (not providing the one-liner
Frederic> as I don't have the copyright assignment in place anymore).

A short patch like that would not require an assignment.

However... why not get a new assignment?  It will be fun and rewarding!

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [commit] Fix "return" command (Re: RFC: optimized-out pieces)
  2010-06-14 12:13 ` [commit] Fix "return" command (Re: RFC: optimized-out pieces) Ulrich Weigand
@ 2010-06-15 15:58   ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2010-06-15 15:58 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

>>>>> "Ulrich" == Ulrich Weigand <uweigand@de.ibm.com> writes:

Ulrich> On the other hand, it does not make sense to memcpy an
Ulrich> uninitialized value either.  Thus, it seems the correct fix
Ulrich> is to simply skip the memcpy, and hence the value_contents_all
Ulrich> call, if the register value is "optimized out". 

Thank you for fixing this.  I'm sorry for the breakage.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2010-06-15 15:58 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-04 19:19 RFC: optimized-out pieces Tom Tromey
2010-06-04 21:42 ` Tom Tromey
2010-06-07 22:35 ` Jan Kratochvil
2010-06-08 18:36   ` Tom Tromey
2010-06-08 18:42     ` Jan Kratochvil
2010-06-08 18:57       ` Tom Tromey
2010-06-09  5:50         ` Jan Kratochvil
2010-06-10 17:14           ` Tom Tromey
2010-06-11 15:34             ` Tom Tromey
2010-06-14 12:07               ` Frederic Riss
2010-06-15 15:54                 ` Tom Tromey
2010-06-09 18:44         ` Jan Kratochvil
2010-06-14 12:13 ` [commit] Fix "return" command (Re: RFC: optimized-out pieces) Ulrich Weigand
2010-06-15 15:58   ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).