[04/41] vec.h: add auto_delete_vec

Message ID 20200108090302.2425-5-dmalcolm@redhat.com
State New
Headers show
Series
  • v5 of analyzer patch kit
Related show

Commit Message

David Malcolm Jan. 8, 2020, 9:02 a.m.
Needs review.  Used by diagnostic_path patch and in various places
in the analyzer.

msebor raised some concerns about the v1 version of this patch here:
  https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00221.html
which I believe I addressed in v4:
  https://gcc.gnu.org/ml/gcc-patches/2019-12/msg01319.html

Changed in v4: added DISABLE_COPY_AND_ASSIGN

This patch adds a class auto_delete_vec<T>, a subclass of auto_vec <T *>
that deletes all of its elements on destruction; it's used in many
places later in the kit.

This is a crude way for a vec to "own" the objects it points to
and clean up automatically (essentially a workaround for not being able
to use unique_ptr, due to C++98).

gcc/ChangeLog:
	* vec.c (class selftest::count_dtor): New class.
	(selftest::test_auto_delete_vec): New test.
	(selftest::vec_c_tests): Call it.
	* vec.h (class auto_delete_vec): New class template.
	(auto_delete_vec<T>::~auto_delete_vec): New dtor.
---
 gcc/vec.c | 27 +++++++++++++++++++++++++++
 gcc/vec.h | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

-- 
2.21.0

Comments

Jeff Law Jan. 9, 2020, 4:15 a.m. | #1
On Wed, 2020-01-08 at 04:02 -0500, David Malcolm wrote:
> Needs review.  Used by diagnostic_path patch and in various places

> in the analyzer.

> 

> msebor raised some concerns about the v1 version of this patch here:

>   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00221.html

> which I believe I addressed in v4:

>   https://gcc.gnu.org/ml/gcc-patches/2019-12/msg01319.html

> 

> Changed in v4: added DISABLE_COPY_AND_ASSIGN

> 

> This patch adds a class auto_delete_vec<T>, a subclass of auto_vec <T *>

> that deletes all of its elements on destruction; it's used in many

> places later in the kit.

> 

> This is a crude way for a vec to "own" the objects it points to

> and clean up automatically (essentially a workaround for not being able

> to use unique_ptr, due to C++98).

> 

> gcc/ChangeLog:

> 	* vec.c (class selftest::count_dtor): New class.

> 	(selftest::test_auto_delete_vec): New test.

> 	(selftest::vec_c_tests): Call it.

> 	* vec.h (class auto_delete_vec): New class template.

> 	(auto_delete_vec<T>::~auto_delete_vec): New dtor.

Just to be clear because my earlier message referenced this patch from
an earlier thread, this is OK.

jeff
>

Patch

diff --git a/gcc/vec.c b/gcc/vec.c
index 0056dd0af942..1c4b958871b4 100644
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -516,6 +516,32 @@  test_reverse ()
   }
 }
 
+/* A test class that increments a counter every time its dtor is called.  */
+
+class count_dtor
+{
+ public:
+  count_dtor (int *counter) : m_counter (counter) {}
+  ~count_dtor () { (*m_counter)++; }
+
+ private:
+  int *m_counter;
+};
+
+/* Verify that auto_delete_vec deletes the elements within it.  */
+
+static void
+test_auto_delete_vec ()
+{
+  int dtor_count = 0;
+  {
+    auto_delete_vec <count_dtor> v;
+    v.safe_push (new count_dtor (&dtor_count));
+    v.safe_push (new count_dtor (&dtor_count));
+  }
+  ASSERT_EQ (dtor_count, 2);
+}
+
 /* Run all of the selftests within this file.  */
 
 void
@@ -533,6 +559,7 @@  vec_c_tests ()
   test_block_remove ();
   test_qsort ();
   test_reverse ();
+  test_auto_delete_vec ();
 }
 
 } // namespace selftest
diff --git a/gcc/vec.h b/gcc/vec.h
index c230189f4048..bd7c7351dcd9 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -1547,6 +1547,31 @@  class auto_string_vec : public auto_vec <char *>
   ~auto_string_vec ();
 };
 
+/* A subclass of auto_vec <T *> that deletes all of its elements on
+   destruction.
+
+   This is a crude way for a vec to "own" the objects it points to
+   and clean up automatically.
+
+   For example, no attempt is made to delete elements when an item
+   within the vec is overwritten.
+
+   We can't rely on gnu::unique_ptr within a container,
+   since we can't rely on move semantics in C++98.  */
+
+template <typename T>
+class auto_delete_vec : public auto_vec <T *>
+{
+ public:
+  auto_delete_vec () {}
+  auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
+
+  ~auto_delete_vec ();
+
+private:
+  DISABLE_COPY_AND_ASSIGN(auto_delete_vec<T>);
+};
+
 /* Conditionally allocate heap memory for VEC and its internal vector.  */
 
 template<typename T>
@@ -1651,6 +1676,19 @@  auto_string_vec::~auto_string_vec ()
     free (str);
 }
 
+/* auto_delete_vec's dtor, deleting all contained items, automatically
+   chaining up to ~auto_vec <T*>, which frees the internal buffer.  */
+
+template <typename T>
+inline
+auto_delete_vec<T>::~auto_delete_vec ()
+{
+  int i;
+  T *item;
+  FOR_EACH_VEC_ELT (*this, i, item)
+    delete item;
+}
+
 
 /* Return a copy of this vector.  */