ODR warnings for "struct insn_info"
[binutils-gdb.git] / gdb / value.c
index bb2adae0a51b1e68c7ea903df7228ffe09f2d079..022fca91a42a8b4d5bccc745b62e642aea8a02ed 100644 (file)
@@ -1,6 +1,6 @@
 /* Low level packing and unpacking of values for GDB, the GNU Debugger.
 
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -343,8 +343,10 @@ struct value
   LONGEST embedded_offset = 0;
   LONGEST pointed_to_offset = 0;
 
-  /* Actual contents of the value.  Target byte-order.  NULL or not
-     valid if lazy is nonzero.  */
+  /* Actual contents of the value.  Target byte-order.
+
+     May be nullptr if the value is lazy or is entirely optimized out.
+     Guaranteed to be non-nullptr otherwise.  */
   gdb::unique_xmalloc_ptr<gdb_byte> contents;
 
   /* Unavailable ranges in CONTENTS.  We mark unavailable ranges,
@@ -989,10 +991,10 @@ show_max_value_size (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
   if (max_value_size == -1)
-    fprintf_filtered (file, _("Maximum value size is unlimited.\n"));
+    gdb_printf (file, _("Maximum value size is unlimited.\n"));
   else
-    fprintf_filtered (file, _("Maximum value size is %d bytes.\n"),
-                     max_value_size);
+    gdb_printf (file, _("Maximum value size is %d bytes.\n"),
+               max_value_size);
 }
 
 /* Called before we attempt to allocate or reallocate a buffer for the
@@ -1146,21 +1148,26 @@ set_value_parent (struct value *value, struct value *parent)
   value->parent = value_ref_ptr::new_reference (parent);
 }
 
-gdb_byte *
+gdb::array_view<gdb_byte>
 value_contents_raw (struct value *value)
 {
   struct gdbarch *arch = get_value_arch (value);
   int unit_size = gdbarch_addressable_memory_unit_size (arch);
 
   allocate_value_contents (value);
-  return value->contents.get () + value->embedded_offset * unit_size;
+
+  ULONGEST length = TYPE_LENGTH (value_type (value));
+  return gdb::make_array_view
+    (value->contents.get () + value->embedded_offset * unit_size, length);
 }
 
-gdb_byte *
+gdb::array_view<gdb_byte>
 value_contents_all_raw (struct value *value)
 {
   allocate_value_contents (value);
-  return value->contents.get ();
+
+  ULONGEST length = TYPE_LENGTH (value_enclosing_type (value));
+  return gdb::make_array_view (value->contents.get (), length);
 }
 
 struct type *
@@ -1216,7 +1223,7 @@ value_actual_type (struct value *value, int resolve_simple_types,
 void
 error_value_optimized_out (void)
 {
-  error (_("value has been optimized out"));
+  throw_error (OPTIMIZED_OUT_ERROR, _("value has been optimized out"));
 }
 
 static void
@@ -1225,7 +1232,8 @@ require_not_optimized_out (const struct value *value)
   if (!value->optimized_out.empty ())
     {
       if (value->lval == lval_register)
-       error (_("register has not been saved in frame"));
+       throw_error (OPTIMIZED_OUT_ERROR,
+                    _("register has not been saved in frame"));
       else
        error_value_optimized_out ();
     }
@@ -1238,25 +1246,29 @@ require_available (const struct value *value)
     throw_error (NOT_AVAILABLE_ERROR, _("value is not available"));
 }
 
-const gdb_byte *
+gdb::array_view<const gdb_byte>
 value_contents_for_printing (struct value *value)
 {
   if (value->lazy)
     value_fetch_lazy (value);
-  return value->contents.get ();
+
+  ULONGEST length = TYPE_LENGTH (value_enclosing_type (value));
+  return gdb::make_array_view (value->contents.get (), length);
 }
 
-const gdb_byte *
+gdb::array_view<const gdb_byte>
 value_contents_for_printing_const (const struct value *value)
 {
   gdb_assert (!value->lazy);
-  return value->contents.get ();
+
+  ULONGEST length = TYPE_LENGTH (value_enclosing_type (value));
+  return gdb::make_array_view (value->contents.get (), length);
 }
 
-const gdb_byte *
+gdb::array_view<const gdb_byte>
 value_contents_all (struct value *value)
 {
-  const gdb_byte *result = value_contents_for_printing (value);
+  gdb::array_view<const gdb_byte> result = value_contents_for_printing (value);
   require_not_optimized_out (value);
   require_available (value);
   return result;
@@ -1334,9 +1346,13 @@ value_contents_copy_raw (struct value *dst, LONGEST dst_offset,
                                             TARGET_CHAR_BIT * length));
 
   /* Copy the data.  */
-  memcpy (value_contents_all_raw (dst) + dst_offset * unit_size,
-         value_contents_all_raw (src) + src_offset * unit_size,
-         length * unit_size);
+  gdb::array_view<gdb_byte> dst_contents
+    = value_contents_all_raw (dst).slice (dst_offset * unit_size,
+                                         length * unit_size);
+  gdb::array_view<const gdb_byte> src_contents
+    = value_contents_all_raw (src).slice (src_offset * unit_size,
+                                         length * unit_size);
+  copy (src_contents, dst_contents);
 
   /* Copy the meta-data, adjusted.  */
   src_bit_offset = src_offset * unit_size * HOST_CHAR_BIT;
@@ -1392,16 +1408,16 @@ set_value_stack (struct value *value, int val)
   value->stack = val;
 }
 
-const gdb_byte *
+gdb::array_view<const gdb_byte>
 value_contents (struct value *value)
 {
-  const gdb_byte *result = value_contents_writeable (value);
+  gdb::array_view<const gdb_byte> result = value_contents_writeable (value);
   require_not_optimized_out (value);
   require_available (value);
   return result;
 }
 
-gdb_byte *
+gdb::array_view<gdb_byte>
 value_contents_writeable (struct value *value)
 {
   if (value->lazy)
@@ -1689,7 +1705,7 @@ value_release_to_mark (const struct value *mark)
    but it's a different block of storage.  */
 
 struct value *
-value_copy (struct value *arg)
+value_copy (const value *arg)
 {
   struct type *encl_type = value_enclosing_type (arg);
   struct value *val;
@@ -1699,7 +1715,7 @@ value_copy (struct value *arg)
   else
     val = allocate_value (encl_type);
   val->type = arg->type;
-  VALUE_LVAL (val) = VALUE_LVAL (arg);
+  VALUE_LVAL (val) = arg->lval;
   val->location = arg->location;
   val->offset = arg->offset;
   val->bitpos = arg->bitpos;
@@ -1711,14 +1727,18 @@ value_copy (struct value *arg)
   val->stack = arg->stack;
   val->is_zero = arg->is_zero;
   val->initialized = arg->initialized;
-  if (!value_lazy (val))
-    {
-      memcpy (value_contents_all_raw (val), value_contents_all_raw (arg),
-             TYPE_LENGTH (value_enclosing_type (arg)));
-
-    }
   val->unavailable = arg->unavailable;
   val->optimized_out = arg->optimized_out;
+
+  if (!value_lazy (val) && !value_entirely_optimized_out (val))
+    {
+      gdb_assert (arg->contents != nullptr);
+      ULONGEST length = TYPE_LENGTH (value_enclosing_type (arg));
+      const auto &arg_view
+       = gdb::make_array_view (arg->contents.get (), length);
+      copy (arg_view, value_contents_all_raw (val));
+    }
+
   val->parent = arg->parent;
   if (VALUE_LVAL (val) == lval_computed)
     {
@@ -1761,8 +1781,7 @@ value_non_lval (struct value *arg)
       struct type *enc_type = value_enclosing_type (arg);
       struct value *val = allocate_value (enc_type);
 
-      memcpy (value_contents_all_raw (val), value_contents_all (arg),
-             TYPE_LENGTH (enc_type));
+      copy (value_contents_all (arg), value_contents_all_raw (val));
       val->type = arg->type;
       set_value_embedded_offset (val, value_embedded_offset (arg));
       set_value_pointed_to_offset (val, value_pointed_to_offset (arg));
@@ -1778,7 +1797,7 @@ value_force_lval (struct value *v, CORE_ADDR addr)
 {
   gdb_assert (VALUE_LVAL (v) == not_lval);
 
-  write_memory (addr, value_contents_raw (v), TYPE_LENGTH (value_type (v)));
+  write_memory (addr, value_contents_raw (v).data (), TYPE_LENGTH (value_type (v)));
   v->lval = lval_memory;
   v->location.address = addr;
 }
@@ -1897,6 +1916,14 @@ access_value_history (int num)
   return value_copy (value_history[absnum].get ());
 }
 
+/* See value.h.  */
+
+ULONGEST
+value_history_count ()
+{
+  return value_history.size ();
+}
+
 static void
 show_values (const char *num_exp, int from_tty)
 {
@@ -1925,10 +1952,10 @@ show_values (const char *num_exp, int from_tty)
       struct value_print_options opts;
 
       val = access_value_history (i);
-      printf_filtered (("$%d = "), i);
+      gdb_printf (("$%d = "), i);
       get_user_print_options (&opts);
       value_print (val, gdb_stdout, &opts);
-      printf_filtered (("\n"));
+      gdb_printf (("\n"));
     }
 
   /* The next "show values +" should start after what we just printed.  */
@@ -2303,7 +2330,7 @@ set_internalvar_component (struct internalvar *var,
   switch (var->kind)
     {
     case INTERNALVAR_VALUE:
-      addr = value_contents_writeable (var->u.value);
+      addr = value_contents_writeable (var->u.value).data ();
       arch = get_value_arch (var->u.value);
       unit_size = gdbarch_addressable_memory_unit_size (arch);
 
@@ -2311,7 +2338,7 @@ set_internalvar_component (struct internalvar *var,
        modify_field (value_type (var->u.value), addr + offset,
                      value_as_long (newval), bitpos, bitsize);
       else
-       memcpy (addr + offset * unit_size, value_contents (newval),
+       memcpy (addr + offset * unit_size, value_contents (newval).data (),
                TYPE_LENGTH (value_type (newval)));
       break;
 
@@ -2429,11 +2456,6 @@ clear_internalvar (struct internalvar *var)
       xfree (var->u.string);
       break;
 
-    case INTERNALVAR_MAKE_VALUE:
-      if (var->u.make_value.functions->destroy != NULL)
-       var->u.make_value.functions->destroy (var->u.make_value.data);
-      break;
-
     default:
       break;
     }
@@ -2614,7 +2636,7 @@ show_convenience (const char *ignore, int from_tty)
        {
          varseen = 1;
        }
-      printf_filtered (("$%s = "), var->name);
+      gdb_printf (("$%s = "), var->name);
 
       try
        {
@@ -2629,7 +2651,7 @@ show_convenience (const char *ignore, int from_tty)
                          _("<error: %s>"), ex.what ());
        }
 
-      printf_filtered (("\n"));
+      gdb_printf (("\n"));
     }
   if (!varseen)
     {
@@ -2637,11 +2659,11 @@ show_convenience (const char *ignore, int from_tty)
         The user can't create them except via Python, and if Python support
         is installed this message will never be printed ($_streq will
         exist).  */
-      printf_unfiltered (_("No debugger convenience variables now defined.\n"
-                          "Convenience variables have "
-                          "names starting with \"$\";\n"
-                          "use \"set\" as in \"set "
-                          "$foo = 5\" to define them.\n"));
+      gdb_printf (_("No debugger convenience variables now defined.\n"
+                   "Convenience variables have "
+                   "names starting with \"$\";\n"
+                   "use \"set\" as in \"set "
+                   "$foo = 5\" to define them.\n"));
     }
 }
 \f
@@ -2695,7 +2717,7 @@ value_as_long (struct value *val)
      in disassemble_command).  It also dereferences references, which
      I suspect is the most logical thing to do.  */
   val = coerce_array (val);
-  return unpack_long (value_type (val), value_contents (val));
+  return unpack_long (value_type (val), value_contents (val).data ());
 }
 
 /* Extract a value as a C pointer.  Does not deallocate the value.
@@ -2798,9 +2820,9 @@ value_as_address (struct value *val)
   if (!value_type (val)->is_pointer_or_reference ()
       && gdbarch_integer_to_address_p (gdbarch))
     return gdbarch_integer_to_address (gdbarch, value_type (val),
-                                      value_contents (val));
+                                      value_contents (val).data ());
 
-  return unpack_long (value_type (val), value_contents (val));
+  return unpack_long (value_type (val), value_contents (val).data ());
 #endif
 }
 \f
@@ -2924,7 +2946,7 @@ is_floating_value (struct value *val)
 
   if (is_floating_type (type))
     {
-      if (!target_float_is_valid (value_contents (val), type))
+      if (!target_float_is_valid (value_contents (val).data (), type))
        error (_("Invalid floating value found in program."));
       return true;
     }
@@ -2941,15 +2963,15 @@ value_static_field (struct type *type, int fieldno)
 {
   struct value *retval;
 
-  switch (TYPE_FIELD_LOC_KIND (type, fieldno))
+  switch (type->field (fieldno).loc_kind ())
     {
     case FIELD_LOC_KIND_PHYSADDR:
       retval = value_at_lazy (type->field (fieldno).type (),
-                             TYPE_FIELD_STATIC_PHYSADDR (type, fieldno));
+                             type->field (fieldno).loc_physaddr ());
       break;
     case FIELD_LOC_KIND_PHYSNAME:
     {
-      const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
+      const char *phys_name = type->field (fieldno).loc_physname ();
       /* type->field (fieldno).name (); */
       struct block_symbol sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0);
 
@@ -2964,7 +2986,7 @@ value_static_field (struct type *type, int fieldno)
          if (!msym.minsym)
            retval = allocate_optimized_out_value (field_type);
          else
-           retval = value_at_lazy (field_type, BMSYMBOL_VALUE_ADDRESS (msym));
+           retval = value_at_lazy (field_type, msym.value_address ());
        }
       else
        retval = value_of_variable (sym.symbol, sym.block);
@@ -3033,7 +3055,7 @@ value_primitive_field (struct value *arg1, LONGEST offset,
         bit.  Assume that the address, offset, and embedded offset
         are sufficiently aligned.  */
 
-      LONGEST bitpos = TYPE_FIELD_BITPOS (arg_type, fieldno);
+      LONGEST bitpos = arg_type->field (fieldno).loc_bitpos ();
       LONGEST container_bitsize = TYPE_LENGTH (type) * 8;
 
       v = allocate_value_lazy (type);
@@ -3066,12 +3088,12 @@ value_primitive_field (struct value *arg1, LONGEST offset,
         for references to ordinary fields of unavailable values.  */
       if (BASETYPE_VIA_VIRTUAL (arg_type, fieldno))
        boffset = baseclass_offset (arg_type, fieldno,
-                                   value_contents (arg1),
+                                   value_contents (arg1).data (),
                                    value_embedded_offset (arg1),
                                    value_address (arg1),
                                    arg1);
       else
-       boffset = TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+       boffset = arg_type->field (fieldno).loc_bitpos () / 8;
 
       if (value_lazy (arg1))
        v = allocate_value_lazy (value_enclosing_type (arg1));
@@ -3099,7 +3121,7 @@ value_primitive_field (struct value *arg1, LONGEST offset,
   else
     {
       /* Plain old data member */
-      offset += (TYPE_FIELD_BITPOS (arg_type, fieldno)
+      offset += (arg_type->field (fieldno).loc_bitpos ()
                 / (HOST_CHAR_BIT * unit_size));
 
       /* Lazy register values with offsets are not supported.  */
@@ -3151,13 +3173,8 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
   struct bound_minimal_symbol msym;
 
   sym = lookup_symbol (physname, 0, VAR_DOMAIN, 0).symbol;
-  if (sym != NULL)
+  if (sym == nullptr)
     {
-      memset (&msym, 0, sizeof (msym));
-    }
-  else
-    {
-      gdb_assert (sym == NULL);
       msym = lookup_bound_minimal_symbol (physname);
       if (msym.minsym == NULL)
        return NULL;
@@ -3167,7 +3184,7 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
   VALUE_LVAL (v) = lval_memory;
   if (sym)
     {
-      set_value_address (v, BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)));
+      set_value_address (v, sym->value_block ()->entry_pc ());
     }
   else
     {
@@ -3178,7 +3195,7 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
 
       set_value_address (v,
        gdbarch_convert_from_func_ptr_addr
-          (gdbarch, BMSYMBOL_VALUE_ADDRESS (msym),
+          (gdbarch, msym.value_address (),
            current_inferior ()->top_target ()));
     }
 
@@ -3263,7 +3280,7 @@ unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
                            LONGEST embedded_offset, int fieldno,
                            const struct value *val, LONGEST *result)
 {
-  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitpos = type->field (fieldno).loc_bitpos ();
   int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
   struct type *field_type = type->field (fieldno).type ();
   int bit_offset;
@@ -3286,7 +3303,7 @@ unpack_value_field_as_long (struct type *type, const gdb_byte *valaddr,
 LONGEST
 unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
 {
-  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitpos = type->field (fieldno).loc_bitpos ();
   int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
   struct type *field_type = type->field (fieldno).type ();
 
@@ -3325,7 +3342,7 @@ unpack_value_bitfield (struct value *dest_val,
 
       num = unpack_bits_as_long (field_type, valaddr + embedded_offset,
                                 bitpos, bitsize);
-      store_signed_integer (value_contents_raw (dest_val),
+      store_signed_integer (value_contents_raw (dest_val).data (),
                            TYPE_LENGTH (field_type), byte_order, num);
     }
 
@@ -3351,7 +3368,7 @@ value_field_bitfield (struct type *type, int fieldno,
                      const gdb_byte *valaddr,
                      LONGEST embedded_offset, const struct value *val)
 {
-  int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+  int bitpos = type->field (fieldno).loc_bitpos ();
   int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
   struct value *res_val = allocate_value (type->field (fieldno).type ());
 
@@ -3532,7 +3549,7 @@ value_from_longest (struct type *type, LONGEST num)
 {
   struct value *val = allocate_value (type);
 
-  pack_long (value_contents_raw (val), type, num);
+  pack_long (value_contents_raw (val).data (), type, num);
   return val;
 }
 
@@ -3544,7 +3561,7 @@ value_from_ulongest (struct type *type, ULONGEST num)
 {
   struct value *val = allocate_value (type);
 
-  pack_unsigned_long (value_contents_raw (val), type, num);
+  pack_unsigned_long (value_contents_raw (val).data (), type, num);
 
   return val;
 }
@@ -3558,7 +3575,7 @@ value_from_pointer (struct type *type, CORE_ADDR addr)
 {
   struct value *val = allocate_value (type);
 
-  store_typed_address (value_contents_raw (val),
+  store_typed_address (value_contents_raw (val).data (),
                       check_typedef (type), addr);
   return val;
 }
@@ -3572,7 +3589,7 @@ value_from_host_double (struct type *type, double d)
 {
   struct value *value = allocate_value (type);
   gdb_assert (type->code () == TYPE_CODE_FLT);
-  target_float_from_host_double (value_contents_raw (value),
+  target_float_from_host_double (value_contents_raw (value).data (),
                                 value_type (value), d);
   return value;
 }
@@ -3638,7 +3655,7 @@ value_from_contents (struct type *type, const gdb_byte *contents)
   struct value *result;
 
   result = allocate_value (type);
-  memcpy (value_contents_raw (result), contents, TYPE_LENGTH (type));
+  memcpy (value_contents_raw (result).data (), contents, TYPE_LENGTH (type));
   return result;
 }
 
@@ -3790,7 +3807,7 @@ coerce_ref (struct value *arg)
   enc_type = check_typedef (value_enclosing_type (arg));
   enc_type = TYPE_TARGET_TYPE (enc_type);
 
-  CORE_ADDR addr = unpack_pointer (value_type (arg), value_contents (arg));
+  CORE_ADDR addr = unpack_pointer (value_type (arg), value_contents (arg).data ());
   retval = value_at_lazy (enc_type, addr);
   enc_type = value_type (retval);
   return readjust_indirect_value_type (retval, enc_type, value_type_arg_tmp,
@@ -3887,7 +3904,7 @@ value_fetch_lazy_bitfield (struct value *val)
     value_fetch_lazy (parent);
 
   unpack_value_bitfield (val, value_bitpos (val), value_bitsize (val),
-                        value_contents_for_printing (parent),
+                        value_contents_for_printing (parent).data (),
                         value_offset (val), parent);
 }
 
@@ -3903,7 +3920,7 @@ value_fetch_lazy_memory (struct value *val)
 
   if (TYPE_LENGTH (type))
       read_value_memory (val, 0, value_stack (val),
-                        addr, value_contents_all_raw (val),
+                        addr, value_contents_all_raw (val).data (),
                         type_length_units (type));
 }
 
@@ -3985,37 +4002,37 @@ value_fetch_lazy_register (struct value *val)
       gdbarch = get_frame_arch (frame);
 
       string_file debug_file;
-      fprintf_unfiltered (&debug_file,
-                         "(frame=%d, regnum=%d(%s), ...) ",
-                         frame_relative_level (frame), regnum,
-                         user_reg_map_regnum_to_name (gdbarch, regnum));
+      gdb_printf (&debug_file,
+                 "(frame=%d, regnum=%d(%s), ...) ",
+                 frame_relative_level (frame), regnum,
+                 user_reg_map_regnum_to_name (gdbarch, regnum));
 
-      fprintf_unfiltered (&debug_file, "->");
+      gdb_printf (&debug_file, "->");
       if (value_optimized_out (new_val))
        {
-         fprintf_unfiltered (&debug_file, " ");
+         gdb_printf (&debug_file, " ");
          val_print_optimized_out (new_val, &debug_file);
        }
       else
        {
          int i;
-         const gdb_byte *buf = value_contents (new_val);
+         gdb::array_view<const gdb_byte> buf = value_contents (new_val);
 
          if (VALUE_LVAL (new_val) == lval_register)
-           fprintf_unfiltered (&debug_file, " register=%d",
-                               VALUE_REGNUM (new_val));
+           gdb_printf (&debug_file, " register=%d",
+                       VALUE_REGNUM (new_val));
          else if (VALUE_LVAL (new_val) == lval_memory)
-           fprintf_unfiltered (&debug_file, " address=%s",
-                               paddress (gdbarch,
-                                         value_address (new_val)));
+           gdb_printf (&debug_file, " address=%s",
+                       paddress (gdbarch,
+                                 value_address (new_val)));
          else
-           fprintf_unfiltered (&debug_file, " computed");
+           gdb_printf (&debug_file, " computed");
 
-         fprintf_unfiltered (&debug_file, " bytes=");
-         fprintf_unfiltered (&debug_file, "[");
+         gdb_printf (&debug_file, " bytes=");
+         gdb_printf (&debug_file, "[");
          for (i = 0; i < register_size (gdbarch, regnum); i++)
-           fprintf_unfiltered (&debug_file, "%02x", buf[i]);
-         fprintf_unfiltered (&debug_file, "]");
+           gdb_printf (&debug_file, "%02x", buf[i]);
+         gdb_printf (&debug_file, "]");
        }
 
       frame_debug_printf ("%s", debug_file.c_str ());
@@ -4256,6 +4273,20 @@ test_insert_into_bit_range_vector ()
   }
 }
 
+static void
+test_value_copy ()
+{
+  type *type = builtin_type (current_inferior ()->gdbarch)->builtin_int;
+
+  /* Verify that we can copy an entirely optimized out value, that may not have
+     its contents allocated.  */
+  value_ref_ptr val = release_value (allocate_optimized_out_value (type));
+  value_ref_ptr copy = release_value (value_copy (val.get ()));
+
+  SELF_CHECK (value_entirely_optimized_out (val.get ()));
+  SELF_CHECK (value_entirely_optimized_out (copy.get ()));
+}
+
 } /* namespace selftests */
 #endif /* GDB_SELF_TEST */
 
@@ -4340,6 +4371,7 @@ and exceeds this limit will cause an error."),
   selftests::register_test ("ranges_contain", selftests::test_ranges_contain);
   selftests::register_test ("insert_into_bit_range_vector",
                            selftests::test_insert_into_bit_range_vector);
+  selftests::register_test ("value_copy", selftests::test_value_copy);
 #endif
 }