Remove free_value_chain
authorTom Tromey <tom@tromey.com>
Wed, 4 Apr 2018 02:20:01 +0000 (20:20 -0600)
committerTom Tromey <tom@tromey.com>
Fri, 6 Apr 2018 21:44:49 +0000 (15:44 -0600)
This patch changes value_release_to_mark and fetch_subexp_value to
return a std::vector of value references, rather than relying on the
"next" field that is contained in a struct value.  This makes it
simpler to reason about the returned values, and also allows for the
removal of free_value_chain.

gdb/ChangeLog
2018-04-06  Tom Tromey  <tom@tromey.com>

* value.h (fetch_subexp_value, value_release_to_mark): Update.
(free_value_chain): Remove.
* value.c (free_value_chain): Remove.
(value_release_to_mark): Return a std::vector.
* ppc-linux-nat.c (num_memory_accesses): Change "chain" to a
std::vector.
(check_condition): Update.
* eval.c (fetch_subexp_value): Change "val_chain" to a
std::vector.
* breakpoint.c (update_watchpoint): Update.
(can_use_hardware_watchpoint): Change "vals" to a std::vector.

gdb/ChangeLog
gdb/breakpoint.c
gdb/eval.c
gdb/ppc-linux-nat.c
gdb/value.c
gdb/value.h

index 1b553d6153a8b3198e6981d351a9bb590c65014d..192f8e203e8889742ca342cda2b0f72da441ff78 100644 (file)
@@ -1,3 +1,17 @@
+2018-04-06  Tom Tromey  <tom@tromey.com>
+
+       * value.h (fetch_subexp_value, value_release_to_mark): Update.
+       (free_value_chain): Remove.
+       * value.c (free_value_chain): Remove.
+       (value_release_to_mark): Return a std::vector.
+       * ppc-linux-nat.c (num_memory_accesses): Change "chain" to a
+       std::vector.
+       (check_condition): Update.
+       * eval.c (fetch_subexp_value): Change "val_chain" to a
+       std::vector.
+       * breakpoint.c (update_watchpoint): Update.
+       (can_use_hardware_watchpoint): Change "vals" to a std::vector.
+
 2018-04-06  Tom Tromey  <tom@tromey.com>
 
        * value.h (free_all_values): Remove.
index a1c6e7723a2198592c1c7ea2ca4b5d59b51302ff..11b89bcf88202d7b7ac63e762ec230b9f395574b 100644 (file)
@@ -117,7 +117,8 @@ static std::vector<symtab_and_line> decode_location_default
   (struct breakpoint *b, const struct event_location *location,
    struct program_space *search_pspace);
 
-static int can_use_hardware_watchpoint (struct value *);
+static int can_use_hardware_watchpoint
+    (const std::vector<value_ref_ptr> &vals);
 
 static void mention (struct breakpoint *);
 
@@ -1777,7 +1778,8 @@ update_watchpoint (struct watchpoint *b, int reparse)
   else if (within_current_scope && b->exp)
     {
       int pc = 0;
-      struct value *val_chain, *v, *result, *next;
+      std::vector<value_ref_ptr> val_chain;
+      struct value *v, *result, *next;
       struct program_space *frame_pspace;
 
       fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, 0);
@@ -1799,15 +1801,18 @@ update_watchpoint (struct watchpoint *b, int reparse)
       frame_pspace = get_frame_program_space (get_selected_frame (NULL));
 
       /* Look at each value on the value chain.  */
-      for (v = val_chain; v; v = value_next (v))
+      gdb_assert (!val_chain.empty ());
+      for (const value_ref_ptr &iter : val_chain)
        {
+         v = iter.get ();
+
          /* If it's a memory location, and GDB actually needed
             its contents to evaluate the expression, then we
             must watch it.  If the first value returned is
             still lazy, that means an error occurred reading it;
             watch it anyway in case it becomes readable.  */
          if (VALUE_LVAL (v) == lval_memory
-             && (v == val_chain || ! value_lazy (v)))
+             && (v == val_chain[0] || ! value_lazy (v)))
            {
              struct type *vtype = check_typedef (value_type (v));
 
@@ -1962,13 +1967,6 @@ update_watchpoint (struct watchpoint *b, int reparse)
            bl->loc_type = loc_type;
        }
 
-      for (v = val_chain; v; v = next)
-       {
-         next = value_next (v);
-         if (v != b->val)
-           value_decref (v);
-       }
-
       /* If a software watchpoint is not watching any memory, then the
         above left it without any location set up.  But,
         bpstat_stop_status requires a location to be able to report
@@ -10875,15 +10873,17 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
    If the watchpoint cannot be handled in hardware return zero.  */
 
 static int
-can_use_hardware_watchpoint (struct value *v)
+can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
 {
   int found_memory_cnt = 0;
-  struct value *head = v;
 
   /* Did the user specifically forbid us to use hardware watchpoints? */
   if (!can_use_hw_watchpoints)
     return 0;
 
+  gdb_assert (!vals.empty ());
+  struct value *head = vals[0].get ();
+
   /* Make sure that the value of the expression depends only upon
      memory contents, and values computed from them within GDB.  If we
      find any register references or function calls, we can't use a
@@ -10903,8 +10903,10 @@ can_use_hardware_watchpoint (struct value *v)
      function calls are special in any way.  So this function may not
      notice that an expression involving an inferior function call
      can't be watched with hardware watchpoints.  FIXME.  */
-  for (; v; v = value_next (v))
+  for (const value_ref_ptr &iter : vals)
     {
+      struct value *v = iter.get ();
+
       if (VALUE_LVAL (v) == lval_memory)
        {
          if (v != head && value_lazy (v))
index 021503e9dd94f7b481e3e96952a5699a0efa961b..b6fbfcf6c9595e43b27d9877f9a3d1eb66fea2d0 100644 (file)
@@ -179,14 +179,14 @@ evaluate_subexpression_type (struct expression *exp, int subexp)
    set to any referenced values.  *VALP will never be a lazy value.
    This is the value which we store in struct breakpoint.
 
-   If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the
-   value chain.  The caller must free the values individually.  If
-   VAL_CHAIN is NULL, all generated values will be left on the value
-   chain.  */
+   If VAL_CHAIN is non-NULL, the values put into *VAL_CHAIN will be
+   released from the value chain.  If VAL_CHAIN is NULL, all generated
+   values will be left on the value chain.  */
 
 void
 fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
-                   struct value **resultp, struct value **val_chain,
+                   struct value **resultp,
+                   std::vector<value_ref_ptr> *val_chain,
                    int preserve_errors)
 {
   struct value *mark, *new_mark, *result;
@@ -195,7 +195,7 @@ fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
   if (resultp)
     *resultp = NULL;
   if (val_chain)
-    *val_chain = NULL;
+    val_chain->clear ();
 
   /* Evaluate the expression.  */
   mark = value_mark ();
@@ -253,8 +253,7 @@ fetch_subexp_value (struct expression *exp, int *pc, struct value **valp,
     {
       /* Return the chain of intermediate values.  We use this to
         decide which addresses to watch.  */
-      *val_chain = new_mark;
-      value_release_to_mark (mark);
+      *val_chain = value_release_to_mark (mark);
     }
 }
 
index 1d2769a983447765b82f213863c26679c2fd36ac..2cd8792d30c0d01ddfd177d05659f5fa94e1540c 100644 (file)
@@ -1840,10 +1840,9 @@ calculate_dvc (CORE_ADDR addr, int len, CORE_ADDR data_value,
    other kinds of values which are not acceptable in a condition
    expression (e.g., lval_computed or lval_internalvar).  */
 static int
-num_memory_accesses (struct value *v)
+num_memory_accesses (const std::vector<value_ref_ptr> &chain)
 {
   int found_memory_cnt = 0;
-  struct value *head = v;
 
   /* The idea here is that evaluating an expression generates a series
      of values, one holding the value of every subexpression.  (The
@@ -1860,8 +1859,10 @@ num_memory_accesses (struct value *v)
      notice that an expression contains an inferior function call.
      FIXME.  */
 
-  for (; v; v = value_next (v))
+  for (const value_ref_ptr &iter : chain)
     {
+      struct value *v = iter.get ();
+
       /* Constants and values from the history are fine.  */
       if (VALUE_LVAL (v) == not_lval || deprecated_value_modifiable (v) == 0)
        continue;
@@ -1892,7 +1893,8 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
                 CORE_ADDR *data_value, int *len)
 {
   int pc = 1, num_accesses_left, num_accesses_right;
-  struct value *left_val, *right_val, *left_chain, *right_chain;
+  struct value *left_val, *right_val;
+  std::vector<value_ref_ptr> left_chain, right_chain;
 
   if (cond->elts[0].opcode != BINOP_EQUAL)
     return 0;
@@ -1901,22 +1903,13 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
   num_accesses_left = num_memory_accesses (left_chain);
 
   if (left_val == NULL || num_accesses_left < 0)
-    {
-      free_value_chain (left_chain);
-
-      return 0;
-    }
+    return 0;
 
   fetch_subexp_value (cond, &pc, &right_val, NULL, &right_chain, 0);
   num_accesses_right = num_memory_accesses (right_chain);
 
   if (right_val == NULL || num_accesses_right < 0)
-    {
-      free_value_chain (left_chain);
-      free_value_chain (right_chain);
-
-      return 0;
-    }
+    return 0;
 
   if (num_accesses_left == 1 && num_accesses_right == 0
       && VALUE_LVAL (left_val) == lval_memory
@@ -1939,15 +1932,7 @@ check_condition (CORE_ADDR watch_addr, struct expression *cond,
       *len = TYPE_LENGTH (check_typedef (value_type (right_val)));
     }
   else
-    {
-      free_value_chain (left_chain);
-      free_value_chain (right_chain);
-
-      return 0;
-    }
-
-  free_value_chain (left_chain);
-  free_value_chain (right_chain);
+    return 0;
 
   return 1;
 }
index a84c196aaaae4e9b6bb7545355490c5e7f19fd08..004ff3b9a9d1a202cc78249b23c170101150f29e 100644 (file)
@@ -1638,20 +1638,6 @@ value_free_to_mark (const struct value *mark)
   all_values = val;
 }
 
-/* Frees all the elements in a chain of values.  */
-
-void
-free_value_chain (struct value *v)
-{
-  struct value *next;
-
-  for (; v; v = next)
-    {
-      next = value_next (v);
-      value_decref (v);
-    }
-}
-
 /* Remove VAL from the chain all_values
    so it will not be freed automatically.  */
 
@@ -1695,25 +1681,30 @@ release_value (struct value *val)
   return value_ref_ptr (val);
 }
 
-/* Release all values up to mark  */
-struct value *
+/* See value.h.  */
+
+std::vector<value_ref_ptr>
 value_release_to_mark (const struct value *mark)
 {
-  struct value *val;
+  std::vector<value_ref_ptr> result;
   struct value *next;
 
-  for (val = next = all_values; next; next = next->next)
+  for (next = all_values; next; next = next->next)
     {
+      next->released = 1;
+      result.emplace_back (next);
+
       if (next->next == mark)
        {
-         all_values = next->next;
+         struct value *save = next->next;
          next->next = NULL;
-         return val;
+         next = save;
+         break;
        }
-      next->released = 1;
     }
-  all_values = 0;
-  return val;
+
+  all_values = next;
+  return result;
 }
 
 /* Return a copy of the value ARG.
index 20169374062b872a5b87dfc5d5853e32c1e07f76..b58f78998a1f675f18f2e7781940e68b14cec785 100644 (file)
@@ -915,7 +915,7 @@ extern value *eval_skip_value (expression *exp);
 
 extern void fetch_subexp_value (struct expression *exp, int *pc,
                                struct value **valp, struct value **resultp,
-                               struct value **val_chain,
+                               std::vector<value_ref_ptr> *val_chain,
                                int preserve_errors);
 
 extern const char *extract_field_op (struct expression *exp, int *subexp);
@@ -1053,8 +1053,6 @@ extern int unop_user_defined_p (enum exp_opcode op, struct value *arg1);
 
 extern int destructor_name_p (const char *name, struct type *type);
 
-extern void free_value_chain (struct value *v);
-
 extern value_ref_ptr release_value (struct value *val);
 
 extern int record_latest_value (struct value *val);
@@ -1084,7 +1082,14 @@ extern void value_print_array_elements (struct value *val,
                                        struct ui_file *stream, int format,
                                        enum val_prettyformat pretty);
 
-extern struct value *value_release_to_mark (const struct value *mark);
+/* Release values from the value chain and return them.  Values
+   created after MARK are released.  If MARK is nullptr, or if MARK is
+   not found on the value chain, then all values are released.  Values
+   are returned in reverse order of creation; that is, newest
+   first.  */
+
+extern std::vector<value_ref_ptr> value_release_to_mark
+    (const struct value *mark);
 
 extern void val_print (struct type *type,
                       LONGEST embedded_offset, CORE_ADDR address,