From 46d2b77d71c3c9a2ea326ae9c3a89a19de3254ca Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 16 Oct 2017 20:50:40 +0000 Subject: 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 (taken from gdb, but changing "xfree" to "free", and adding support for pre-C++-11) gcc/ChangeLog: David Malcolm * 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 David Malcolm * unique-ptr.h: New file. From-SVN: r253797 --- gcc/ChangeLog | 8 ++ gcc/Makefile.in | 1 + gcc/selftest-run-tests.c | 1 + gcc/selftest.h | 1 + gcc/unique-ptr-tests.cc | 234 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 245 insertions(+) create mode 100644 gcc/unique-ptr-tests.cc (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1814910..933e4e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-10-16 David Malcolm + + * 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 PR sanitizer/82353 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 878ce7b..2809619 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1568,6 +1568,7 @@ OBJS = \ tree-vrp.o \ tree.o \ typed-splay-tree.o \ + unique-ptr-tests.o \ valtrack.o \ value-prof.o \ var-tracking.o \ diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c index 5c84f3a..11bf0cc 100644 --- a/gcc/selftest-run-tests.c +++ b/gcc/selftest-run-tests.c @@ -67,6 +67,7 @@ selftest::run_tests () sreal_c_tests (); fibonacci_heap_c_tests (); typed_splay_tree_c_tests (); + unique_ptr_tests_cc_tests (); /* Mid-level data structures. */ input_c_tests (); diff --git a/gcc/selftest.h b/gcc/selftest.h index 2e649a7..6478922 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -195,6 +195,7 @@ extern void store_merging_c_tests (); extern void typed_splay_tree_c_tests (); extern void tree_c_tests (); extern void tree_cfg_c_tests (); +extern void unique_ptr_tests_cc_tests (); extern void vec_c_tests (); extern void wide_int_cc_tests (); extern void predict_c_tests (); diff --git a/gcc/unique-ptr-tests.cc b/gcc/unique-ptr-tests.cc new file mode 100644 index 0000000..f5b72a8 --- /dev/null +++ b/gcc/unique-ptr-tests.cc @@ -0,0 +1,234 @@ +/* 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 +. */ + +#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. */ + +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 p; + ASSERT_EQ (NULL, p); + + gnu::unique_xmalloc_ptr 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 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 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 (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 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 (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 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 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 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 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 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 */ -- cgit v1.1