Mark entirely optimized out value as non-lazy.
[deliverable/binutils-gdb.git] / gdb / value.c
index 09ab1bb4e2dcbaf80e1a7ec22ae6cf9b54d0aa13..8052f52f874689aa07a6a54fb94a51bfc9f856c0 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "defs.h"
 #include "arch-utils.h"
-#include "gdb_string.h"
+#include <string.h>
 #include "symtab.h"
 #include "gdbtypes.h"
 #include "value.h"
@@ -197,8 +197,13 @@ struct value
      reset, be sure to consider this use as well!  */
   unsigned int lazy : 1;
 
-  /* If nonzero, this is the value of a variable which does not
-     actually exist in the program.  */
+  /* If nonzero, this is the value of a variable that does not
+     actually exist in the program.  If nonzero, and LVAL is
+     lval_register, this is a register ($pc, $sp, etc., never a
+     program variable) that has not been saved in the frame.  All
+     optimized-out values are treated pretty much the same, except
+     registers have a different string representation and related
+     error strings.  */
   unsigned int optimized_out : 1;
 
   /* If value is a variable, is it initialized or not.  */
@@ -353,6 +358,26 @@ value_entirely_available (struct value *value)
   return 0;
 }
 
+int
+value_entirely_unavailable (struct value *value)
+{
+  /* We can only tell whether the whole value is available when we try
+     to read it.  */
+  if (value->lazy)
+    value_fetch_lazy (value);
+
+  if (VEC_length (range_s, value->unavailable) == 1)
+    {
+      struct range *t = VEC_index (range_s, value->unavailable, 0);
+
+      if (t->offset == 0
+         && t->length == TYPE_LENGTH (value_enclosing_type (value)))
+       return 1;
+    }
+
+  return 0;
+}
+
 void
 mark_value_bytes_unavailable (struct value *value, int offset, int length)
 {
@@ -687,7 +712,7 @@ allocate_value_lazy (struct type *type)
 
 /* Allocate the contents of VAL if it has not been allocated yet.  */
 
-void
+static void
 allocate_value_contents (struct value *val)
 {
   if (!val->contents)
@@ -743,7 +768,7 @@ allocate_optimized_out_value (struct type *type)
   struct value *retval = allocate_value_lazy (type);
 
   set_value_optimized_out (retval, 1);
-
+  set_value_lazy (retval, 0);
   return retval;
 }
 
@@ -882,11 +907,22 @@ value_actual_type (struct value *value, int resolve_simple_types,
   return result;
 }
 
+void
+error_value_optimized_out (void)
+{
+  error (_("value has been optimized out"));
+}
+
 static void
 require_not_optimized_out (const struct value *value)
 {
   if (value->optimized_out)
-    error (_("value has been optimized out"));
+    {
+      if (value->lval == lval_register)
+       error (_("register has not been saved in frame"));
+      else
+       error_value_optimized_out ();
+    }
 }
 
 static void
@@ -2554,8 +2590,7 @@ unpack_pointer (struct type *type, const gdb_byte *valaddr)
 
 \f
 /* Get the value of the FIELDNO'th field (which must be static) of
-   TYPE.  Return NULL if the field doesn't exist or has been
-   optimized out.  */
+   TYPE.  */
 
 struct value *
 value_static_field (struct type *type, int fieldno)
@@ -2582,7 +2617,7 @@ value_static_field (struct type *type, int fieldno)
                                                               NULL, NULL);
 
          if (!msym)
-           return NULL;
+           return allocate_optimized_out_value (type);
          else
            {
              retval = value_at_lazy (TYPE_FIELD_TYPE (type, fieldno),
@@ -3168,10 +3203,7 @@ value_from_contents_and_address (struct type *type,
   if (valaddr == NULL)
     v = allocate_value_lazy (type);
   else
-    {
-      v = allocate_value (type);
-      memcpy (value_contents_raw (v), valaddr, TYPE_LENGTH (type));
-    }
+    v = value_from_contents (type, valaddr);
   set_value_address (v, address);
   VALUE_LVAL (v) = lval_memory;
   return v;
@@ -3475,7 +3507,9 @@ value_fetch_lazy (struct value *val)
 
       while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
        {
-         frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
+         struct frame_id frame_id = VALUE_FRAME_ID (new_val);
+
+         frame = frame_find_by_id (frame_id);
          regnum = VALUE_REGNUM (new_val);
 
          gdb_assert (frame != NULL);
@@ -3489,6 +3523,22 @@ value_fetch_lazy (struct value *val)
                                                   regnum, type));
 
          new_val = get_frame_register_value (frame, regnum);
+
+         /* If we get another lazy lval_register value, it means the
+            register is found by reading it from the next frame.
+            get_frame_register_value should never return a value with
+            the frame id pointing to FRAME.  If it does, it means we
+            either have two consecutive frames with the same frame id
+            in the frame chain, or some code is trying to unwind
+            behind get_prev_frame's back (e.g., a frame unwind
+            sniffer trying to unwind), bypassing its validations.  In
+            any case, it should always be an internal error to end up
+            in this situation.  */
+         if (VALUE_LVAL (new_val) == lval_register
+             && value_lazy (new_val)
+             && frame_id_eq (VALUE_FRAME_ID (new_val), frame_id))
+           internal_error (__FILE__, __LINE__,
+                           _("infinite loop while fetching a register"));
        }
 
       /* If it's still lazy (for instance, a saved register on the
@@ -3567,6 +3617,23 @@ value_fetch_lazy (struct value *val)
   return 0;
 }
 
+/* Implementation of the convenience function $_isvoid.  */
+
+static struct value *
+isvoid_internal_fn (struct gdbarch *gdbarch,
+                   const struct language_defn *language,
+                   void *cookie, int argc, struct value **argv)
+{
+  int ret;
+
+  if (argc != 1)
+    error (_("You must provide one argument for $_isvoid."));
+
+  ret = TYPE_CODE (value_type (argv[0])) == TYPE_CODE_VOID;
+
+  return value_from_longest (builtin_type (gdbarch)->builtin_int, ret);
+}
+
 void
 _initialize_values (void)
 {
@@ -3599,4 +3666,10 @@ VARIABLE is already initialized."));
   add_prefix_cmd ("function", no_class, function_command, _("\
 Placeholder command for showing help on convenience functions."),
                  &functionlist, "function ", 0, &cmdlist);
+
+  add_internal_function ("_isvoid", _("\
+Check whether an expression is void.\n\
+Usage: $_isvoid (expression)\n\
+Return 1 if the expression is void, zero otherwise."),
+                        isvoid_internal_fn, NULL);
 }
This page took 0.026609 seconds and 4 git commands to generate.