Add scoped_value_mark
authorTom Tromey <tom@tromey.com>
Tue, 22 Nov 2016 01:02:11 +0000 (18:02 -0700)
committerTom Tromey <tom@tromey.com>
Wed, 11 Jan 2017 02:14:12 +0000 (19:14 -0700)
This adds a scoped_value_mark class, that records the value mark in
the constructor and then calls value_free_to_mark in the destructor.
It then updates various spots in gdb to use this class, rather than a
cleanup.

It would be better overall to replace "struct value *" with a
shared_ptr, maybe eliminating the need for this class (watchpoints
would perhaps need some new mechanism as well).  However, that's
difficult to do.

2017-01-10  Tom Tromey  <tom@tromey.com>

* python/py-value.c (valpy_dereference, valpy_referenced_value)
(valpy_reference_value, valpy_const_value, valpy_get_address)
(valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
(valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
(valpy_absolute, valpy_richcompare_throw): Use scoped_value_mark.
* dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
scoped_value_mark.
* dwarf2-frame.c (execute_stack_op): Use scoped_value_mark.
* value.h (scoped_value_mark): New class.

gdb/ChangeLog
gdb/dwarf2-frame.c
gdb/dwarf2loc.c
gdb/python/py-value.c
gdb/value.h

index ba3af7a0990729f367409d540cdfd5204907976e..692240686c93733d124601d8cd9d7f7caa878dfa 100644 (file)
@@ -1,3 +1,15 @@
+2017-01-10  Tom Tromey  <tom@tromey.com>
+
+       * python/py-value.c (valpy_dereference, valpy_referenced_value)
+       (valpy_reference_value, valpy_const_value, valpy_get_address)
+       (valpy_get_dynamic_type, valpy_lazy_string, valpy_do_cast)
+       (valpy_getitem, valpy_call, valpy_binop_throw, valpy_negative)
+       (valpy_absolute, valpy_richcompare_throw): Use scoped_value_mark.
+       * dwarf2loc.c (dwarf2_loc_desc_get_symbol_read_needs): Use
+       scoped_value_mark.
+       * dwarf2-frame.c (execute_stack_op): Use scoped_value_mark.
+       * value.h (scoped_value_mark): New class.
+
 2017-01-10  Tom Tromey  <tom@tromey.com>
 
        * dwarf2read.c (dwarf2_build_psymtabs): Use psymtab_discarder.
index c6a3d40a204aa18a8c8c99f114d5467c0396efa8..c5ad0dd71e602e9d927e71bbbc3870b2a5f93f77 100644 (file)
@@ -403,10 +403,9 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
                  CORE_ADDR initial, int initial_in_stack_memory)
 {
   CORE_ADDR result;
-  struct cleanup *old_chain;
 
   dwarf_expr_executor ctx;
-  old_chain = make_cleanup_value_free_to_mark (value_mark ());
+  scoped_value_mark free_values;
 
   ctx.this_frame = this_frame;
   ctx.gdbarch = get_frame_arch (this_frame);
@@ -430,8 +429,6 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
 Not implemented: computing unwound register using explicit value operator"));
     }
 
-  do_cleanups (old_chain);
-
   return result;
 }
 \f
index e9b41a1d68847bf8610d17db53ad563a35674c57..633a459113dbffedfd07b4a1cab7235953a3e214 100644 (file)
@@ -2790,16 +2790,14 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
                                       struct dwarf2_per_cu_data *per_cu)
 {
   int in_reg;
-  struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
+  scoped_value_mark free_values;
+
   symbol_needs_eval_context ctx;
 
   ctx.needs = SYMBOL_NEEDS_NONE;
   ctx.per_cu = per_cu;
-
-  old_chain = make_cleanup_value_free_to_mark (value_mark ());
-
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
@@ -2820,8 +2818,6 @@ dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
           in_reg = 1;
     }
 
-  do_cleanups (old_chain);
-
   if (in_reg)
     ctx.needs = SYMBOL_NEEDS_FRAME;
   return ctx.needs;
index 97136e314160d567818c78fd6b7869905aaa4d84..8f3164b53c43658689298e95020db6604ddb9f6c 100644 (file)
@@ -178,11 +178,10 @@ valpy_dereference (PyObject *self, PyObject *args)
   TRY
     {
       struct value *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       res_val = value_ind (((value_object *) self)->value);
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -209,7 +208,7 @@ valpy_referenced_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val, *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       self_val = ((value_object *) self)->value;
       switch (TYPE_CODE (check_typedef (value_type (self_val))))
@@ -226,7 +225,6 @@ valpy_referenced_value (PyObject *self, PyObject *args)
         }
 
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -247,12 +245,10 @@ valpy_reference_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       self_val = ((value_object *) self)->value;
       result = value_to_value_object (value_ref (self_val));
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -273,13 +269,11 @@ valpy_const_value (PyObject *self, PyObject *args)
   TRY
     {
       struct value *self_val, *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       self_val = ((value_object *) self)->value;
       res_val = make_cv_value (1, 0, self_val);
       result = value_to_value_object (res_val);
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -301,12 +295,10 @@ valpy_get_address (PyObject *self, void *closure)
       TRY
        {
          struct value *res_val;
-         struct cleanup *cleanup
-           = make_cleanup_value_free_to_mark (value_mark ());
+         scoped_value_mark free_values;
 
          res_val = value_addr (val_obj->value);
          val_obj->address = value_to_value_object (res_val);
-         do_cleanups (cleanup);
        }
       CATCH (except, RETURN_MASK_ALL)
        {
@@ -354,7 +346,7 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
   TRY
     {
       struct value *val = obj->value;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       type = value_type (val);
       type = check_typedef (type);
@@ -387,8 +379,6 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
          /* Re-use object's static type.  */
          type = NULL;
        }
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -428,7 +418,7 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
        value = value_ind (value);
@@ -436,8 +426,6 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
       str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
                                                 user_encoding,
                                                 value_type (value));
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -514,7 +502,7 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
     {
       struct value *val = ((value_object *) self)->value;
       struct value *res_val;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       if (op == UNOP_DYNAMIC_CAST)
        res_val = value_dynamic_cast (type, val);
@@ -527,7 +515,6 @@ valpy_do_cast (PyObject *self, PyObject *args, enum exp_opcode op)
        }
 
       result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -737,8 +724,8 @@ valpy_getitem (PyObject *self, PyObject *key)
   TRY
     {
       struct value *tmp = self_value->value;
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
       struct value *res_val = NULL;
+      scoped_value_mark free_values;
 
       if (field)
        res_val = value_struct_elt (&tmp, NULL, field.get (), NULL,
@@ -783,7 +770,6 @@ valpy_getitem (PyObject *self, PyObject *key)
 
       if (res_val)
        result = value_to_value_object (res_val);
-      do_cleanups (cleanup);
     }
   CATCH (ex, RETURN_MASK_ALL)
     {
@@ -861,12 +847,11 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (mark);
+      scoped_value_mark free_values;
       struct value *return_value;
 
       return_value = call_function_by_hand (function, args_count, vargs);
       result = value_to_value_object (return_value);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1014,11 +999,12 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
   PyObject *result = NULL;
 
   struct value *arg1, *arg2;
-  struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
   struct value *res_val = NULL;
   enum exp_opcode op = OP_NULL;
   int handled = 0;
 
+  scoped_value_mark free_values;
+
   /* If the gdb.Value object is the second operand, then it will be
      passed to us as the OTHER argument, and SELF will be an entirely
      different kind of object, altogether.  Because of this, we can't
@@ -1026,17 +1012,11 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
      python as well.  */
   arg1 = convert_value_from_python (self);
   if (arg1 == NULL)
-    {
-      do_cleanups (cleanup);
-      return NULL;
-    }
+    return NULL;
 
   arg2 = convert_value_from_python (other);
   if (arg2 == NULL)
-    {
-      do_cleanups (cleanup);
-      return NULL;
-    }
+    return NULL;
 
   switch (opcode)
     {
@@ -1130,7 +1110,6 @@ valpy_binop_throw (enum valpy_opcode opcode, PyObject *self, PyObject *other)
   if (res_val)
     result = value_to_value_object (res_val);
 
-  do_cleanups (cleanup);
   return result;
 }
 
@@ -1209,12 +1188,11 @@ valpy_negative (PyObject *self)
   TRY
     {
       /* Perhaps overkill, but consistency has some virtue.  */
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
       struct value *val;
 
       val = value_neg (((value_object *) self)->value);
       result = value_to_value_object (val);
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1239,12 +1217,10 @@ valpy_absolute (PyObject *self)
 
   TRY
     {
-      struct cleanup *cleanup = make_cleanup_value_free_to_mark (value_mark ());
+      scoped_value_mark free_values;
 
       if (value_less (value, value_zero (value_type (value), not_lval)))
        isabs = 0;
-
-      do_cleanups (cleanup);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
@@ -1362,15 +1338,14 @@ valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
   int result;
   struct value *value_other;
   struct value *value_self;
-  struct value *mark = value_mark ();
   struct cleanup *cleanup;
 
+  scoped_value_mark free_values;
+
   value_other = convert_value_from_python (other);
   if (value_other == NULL)
     return -1;
 
-  cleanup = make_cleanup_value_free_to_mark (mark);
-
   value_self = ((value_object *) self)->value;
 
   switch (op)
@@ -1403,7 +1378,6 @@ valpy_richcompare_throw (PyObject *self, PyObject *other, int op)
       break;
     }
 
-  do_cleanups (cleanup);
   return result;
 }
 
index 4aba8c0a41c9637592b24401ec854b6d469e5865..0c5ab284b3b6c7addca29cc5b1b45aa60debc7fa 100644 (file)
@@ -714,6 +714,28 @@ extern struct value *value_mark (void);
 
 extern void value_free_to_mark (const struct value *mark);
 
+/* A helper class that uses value_mark at construction time and calls
+   value_free_to_mark in the destructor.  This is used to clear out
+   temporary values created during the lifetime of this object.  */
+class scoped_value_mark
+{
+ public:
+
+  scoped_value_mark ()
+    : m_value (value_mark ())
+  {
+  }
+
+  ~scoped_value_mark ()
+  {
+    value_free_to_mark (m_value);
+  }
+
+ private:
+
+  const struct value *m_value;
+};
+
 extern struct value *value_cstring (const char *ptr, ssize_t len,
                                    struct type *char_type);
 extern struct value *value_string (const char *ptr, ssize_t len,