Commit 46d2b77d by David Malcolm

Add gnu::unique_ptr

This is a version of the patch posted by Trevor Saunders on 2017-07-31,
for which he wrote:
> For most of the history of this see
>   https://sourceware.org/ml/gdb-patches/2016-10/msg00223.html
> The changes are mostly s/gdb/gtl/g

This version was updated by me (dmalcolm) adding these changes:
- renaming of "gtl" to "gnu" (3 letters, and one of the ones Richi
  proposed, and not a match for "*tl")
- renaming of DEFINE_GDB_UNIQUE_PTR to DEFINE_GNU_UNIQUE_PTR
- renaming of xfree_deleter to xmalloc_deleter, and making it
  use "free" rather than "xfree" (which doesn't exist)
- added a gcc/unique-ptr-tests.cc
- implement unique_xmalloc_ptr<T[]> (taken from gdb, but changing
  "xfree" to "free", and adding support for pre-C++-11)

gcc/ChangeLog:

	David Malcolm <dmalcolm@redhat.com>

	* Makefile.in (OBJS): Add unique-ptr-tests.o.
	* selftest-run-tests.c (selftest::run_tests): Call
	selftest::unique_ptr_tests_cc_tests.
	* selftest.h (selftest::unique_ptr_tests_cc_tests): New decl.
	* unique-ptr-tests.cc: New file.

include/ChangeLog:

	Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
	David Malcolm <dmalcolm@redhat.com>

	* unique-ptr.h: New file.

From-SVN: r253797
parent 2de3d3c6
2017-10-16 David Malcolm <dmalcolm@redhat.com>
* Makefile.in (OBJS): Add unique-ptr-tests.o.
* selftest-run-tests.c (selftest::run_tests): Call
selftest::unique_ptr_tests_cc_tests.
* selftest.h (selftest::unique_ptr_tests_cc_tests): New decl.
* unique-ptr-tests.cc: New file.
2017-10-16 Vladimir Makarov <vmakarov@redhat.com> 2017-10-16 Vladimir Makarov <vmakarov@redhat.com>
PR sanitizer/82353 PR sanitizer/82353
...@@ -1568,6 +1568,7 @@ OBJS = \ ...@@ -1568,6 +1568,7 @@ OBJS = \
tree-vrp.o \ tree-vrp.o \
tree.o \ tree.o \
typed-splay-tree.o \ typed-splay-tree.o \
unique-ptr-tests.o \
valtrack.o \ valtrack.o \
value-prof.o \ value-prof.o \
var-tracking.o \ var-tracking.o \
......
...@@ -67,6 +67,7 @@ selftest::run_tests () ...@@ -67,6 +67,7 @@ selftest::run_tests ()
sreal_c_tests (); sreal_c_tests ();
fibonacci_heap_c_tests (); fibonacci_heap_c_tests ();
typed_splay_tree_c_tests (); typed_splay_tree_c_tests ();
unique_ptr_tests_cc_tests ();
/* Mid-level data structures. */ /* Mid-level data structures. */
input_c_tests (); input_c_tests ();
......
...@@ -195,6 +195,7 @@ extern void store_merging_c_tests (); ...@@ -195,6 +195,7 @@ extern void store_merging_c_tests ();
extern void typed_splay_tree_c_tests (); extern void typed_splay_tree_c_tests ();
extern void tree_c_tests (); extern void tree_c_tests ();
extern void tree_cfg_c_tests (); extern void tree_cfg_c_tests ();
extern void unique_ptr_tests_cc_tests ();
extern void vec_c_tests (); extern void vec_c_tests ();
extern void wide_int_cc_tests (); extern void wide_int_cc_tests ();
extern void predict_c_tests (); extern void predict_c_tests ();
......
/* Unit tests for unique-ptr.h.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "unique-ptr.h"
#include "selftest.h"
#if CHECKING_P
namespace selftest {
namespace {
/* A class for counting ctor and dtor invocations. */
struct stats
{
stats () : ctor_count (0), dtor_count (0) {}
int ctor_count;
int dtor_count;
};
/* A class that uses "stats" to track its ctor and dtor invocations. */
class foo
{
public:
foo (stats &s) : m_s (s) { ++m_s.ctor_count; }
~foo () { ++m_s.dtor_count; }
int example_method () const { return 42; }
private:
foo (const foo&);
foo & operator= (const foo &);
private:
stats &m_s;
};
/* A struct for testing unique_ptr<T[]>. */
struct has_default_ctor
{
has_default_ctor () : m_field (42) {}
int m_field;
};
/* A dummy struct for testing unique_xmalloc_ptr. */
struct dummy
{
int field;
};
} // anonymous namespace
/* Verify that the default ctor inits ptrs to NULL. */
static void
test_null_ptr ()
{
gnu::unique_ptr<void *> p;
ASSERT_EQ (NULL, p);
gnu::unique_xmalloc_ptr<void *> q;
ASSERT_EQ (NULL, q);
}
/* Verify that deletion happens when a unique_ptr goes out of scope. */
static void
test_implicit_deletion ()
{
stats s;
ASSERT_EQ (0, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
{
gnu::unique_ptr<foo> f (new foo (s));
ASSERT_NE (NULL, f);
ASSERT_EQ (1, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
}
/* Verify that the foo was implicitly deleted. */
ASSERT_EQ (1, s.ctor_count);
ASSERT_EQ (1, s.dtor_count);
}
/* Verify that we can assign to a NULL unique_ptr. */
static void
test_overwrite_of_null ()
{
stats s;
ASSERT_EQ (0, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
{
gnu::unique_ptr<foo> f;
ASSERT_EQ (NULL, f);
ASSERT_EQ (0, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
/* Overwrite with a non-NULL value. */
f = gnu::unique_ptr<foo> (new foo (s));
ASSERT_EQ (1, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
}
/* Verify that the foo is implicitly deleted. */
ASSERT_EQ (1, s.ctor_count);
ASSERT_EQ (1, s.dtor_count);
}
/* Verify that we can assign to a non-NULL unique_ptr. */
static void
test_overwrite_of_non_null ()
{
stats s;
ASSERT_EQ (0, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
{
gnu::unique_ptr<foo> f (new foo (s));
ASSERT_NE (NULL, f);
ASSERT_EQ (1, s.ctor_count);
ASSERT_EQ (0, s.dtor_count);
/* Overwrite with a different value. */
f = gnu::unique_ptr<foo> (new foo (s));
ASSERT_EQ (2, s.ctor_count);
ASSERT_EQ (1, s.dtor_count);
}
/* Verify that the 2nd foo was implicitly deleted. */
ASSERT_EQ (2, s.ctor_count);
ASSERT_EQ (2, s.dtor_count);
}
/* Verify that unique_ptr's overloaded ops work. */
static void
test_overloaded_ops ()
{
stats s;
gnu::unique_ptr<foo> f (new foo (s));
ASSERT_EQ (42, f->example_method ());
ASSERT_EQ (42, (*f).example_method ());
ASSERT_EQ (f, f);
ASSERT_NE (NULL, f.get ());
gnu::unique_ptr<foo> g (new foo (s));
ASSERT_NE (f, g);
}
/* Verify that the gnu::unique_ptr specialization for T[] works. */
static void
test_array_new ()
{
const int num = 10;
gnu::unique_ptr<has_default_ctor[]> p (new has_default_ctor[num]);
ASSERT_NE (NULL, p.get ());
/* Verify that operator[] works, and that the default ctor was called
on each element. */
for (int i = 0; i < num; i++)
ASSERT_EQ (42, p[i].m_field);
}
/* Verify that gnu::unique_xmalloc_ptr works. */
static void
test_xmalloc ()
{
gnu::unique_xmalloc_ptr<dummy> p (XNEW (dummy));
ASSERT_NE (NULL, p.get ());
}
/* Verify the gnu::unique_xmalloc_ptr specialization for T[]. */
static void
test_xmalloc_array ()
{
const int num = 10;
gnu::unique_xmalloc_ptr<dummy[]> p (XNEWVEC (dummy, num));
ASSERT_NE (NULL, p.get ());
/* Verify that operator[] works. */
for (int i = 0; i < num; i++)
p[i].field = 42;
for (int i = 0; i < num; i++)
ASSERT_EQ (42, p[i].field);
}
/* Run all of the selftests within this file. */
void
unique_ptr_tests_cc_tests ()
{
test_null_ptr ();
test_implicit_deletion ();
test_overwrite_of_null ();
test_overwrite_of_non_null ();
test_overloaded_ops ();
test_array_new ();
test_xmalloc ();
test_xmalloc_array ();
}
} // namespace selftest
#endif /* #if CHECKING_P */
2017-10-16 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
David Malcolm <dmalcolm@redhat.com>
* unique-ptr.h: New file.
2017-09-15 Yao Qi <yao.qi@linaro.org> 2017-09-15 Yao Qi <yao.qi@linaro.org>
Pedro Alves <palves@redhat.com> Pedro Alves <palves@redhat.com>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment