+++ /dev/null
-/* Unit tests for unique-ptr.h.
- Copyright (C) 2017-2021 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"
-#define INCLUDE_UNIQUE_PTR
-#include "system.h"
-#include "coretypes.h"
-#include "selftest.h"
-
-#if CHECKING_P
-
-namespace selftest {
-
-namespace {
-
-/* A class for counting ctor and dtor invocations. */
-
-class stats
-{
-public:
- 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[]>. */
-
-class has_default_ctor
-{
-public:
- 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 */
+++ /dev/null
-/* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
-
- Copyright (C) 2007-2021 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- This program 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 of the License, or
- (at your option) any later version.
-
- This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
-
-/* gnu::unique_ptr defines a C++ owning smart pointer that exposes a
- subset of the std::unique_ptr API.
-
- In fact, when compiled with a C++11 compiler, gnu::unique_ptr
- actually _is_ std::unique_ptr. When compiled with a C++03 compiler
- OTOH, it's an hand coded std::unique_ptr emulation that assumes
- code is correct and doesn't try to be too smart.
-
- This supports custom deleters, but not _stateful_ deleters, so you
- can't use those in C++11 mode either. Only the managed pointer is
- stored in the smart pointer. That could be changed; it simply
- wasn't found necessary.
-
- At the end of the file you'll find a gnu::unique_ptr partial
- specialization that uses a custom (stateless) deleter:
- gnu::unique_xmalloc_ptr. That is used to manage pointers to
- objects allocated with xmalloc.
-
- The C++03 version was originally based on GCC 7.0's std::auto_ptr
- and then heavily customized to behave more like C++11's
- std::unique_ptr, but at this point, it no longer shares much at all
- with the original file. But, that's the history and the reason for
- the copyright's starting year.
-
- The C++03 version lets you shoot yourself in the foot, since
- similarly to std::auto_ptr, the copy constructor and assignment
- operators actually move. Also, in the name of simplicity, no
- effort is spent on using SFINAE to prevent invalid conversions,
- etc. This is not really a problem, because the goal here is to
- allow code that would be correct using std::unique_ptr to be
- equally correct in C++03 mode, and, just as efficient. If client
- code compiles correctly with a C++11 (or newer) compiler, we know
- we're not doing anything invalid by mistake.
-
- Usage notes:
-
- - Putting gnu::unique_ptr in standard containers is not supported,
- since C++03 containers are not move-aware (and our emulation
- relies on copy actually moving).
-
- - Since there's no nullptr in C++03, gnu::unique_ptr allows
- implicit initialization and assignment from NULL instead.
-
- - To check whether there's an associated managed object, all these
- work as expected:
-
- if (ptr)
- if (!ptr)
- if (ptr != NULL)
- if (ptr == NULL)
- if (NULL != ptr)
- if (NULL == ptr)
-*/
-
-#ifndef GNU_UNIQUE_PTR_H
-#define GNU_UNIQUE_PTR_H 1
-
-#if __cplusplus >= 201103
-# include <memory>
-#endif
-
-namespace gnu
-{
-
-#if __cplusplus >= 201103
-
-/* In C++11 mode, all we need is import the standard
- std::unique_ptr. */
-template<typename T> using unique_ptr = std::unique_ptr<T>;
-
-/* Pull in move as well. */
-using std::move;
-
-#else /* C++11 */
-
-/* Default destruction policy used by gnu::unique_ptr when no deleter
- is specified. Uses delete. */
-
-template<typename T>
-struct default_delete
-{
- void operator () (T *ptr) const { delete ptr; }
-};
-
-/* Specialization for arrays. Uses delete[]. */
-
-template<typename T>
-struct default_delete<T[]>
-{
- void operator () (T *ptr) const { delete [] ptr; }
-};
-
-namespace detail
-{
-/* Type used to support implicit construction from NULL:
-
- gnu::unique_ptr<foo> func (....)
- {
- return NULL;
- }
-
- and assignment from NULL:
-
- gnu::unique_ptr<foo> ptr (....);
- ...
- ptr = NULL;
-
- It is intentionally not defined anywhere. */
-struct nullptr_t;
-
-/* Base class of our unique_ptr emulation. Contains code common to
- both unique_ptr<T, D> and unique_ptr<T[], D>. */
-
-template<typename T, typename D>
-class unique_ptr_base
-{
-public:
- typedef T *pointer;
- typedef T element_type;
- typedef D deleter_type;
-
- /* Takes ownership of a pointer. P is a pointer to an object of
- element_type type. Defaults to NULL. */
- explicit unique_ptr_base (element_type *p = NULL) throw () : m_ptr (p) {}
-
- /* The "move" constructor. Really a copy constructor that actually
- moves. Even though std::unique_ptr is not copyable, our little
- simpler emulation allows it, because:
-
- - There are no rvalue references in C++03. Our move emulation
- instead relies on copy/assignment moving, like std::auto_ptr.
- - RVO/NRVO requires an accessible copy constructor
- */
- unique_ptr_base (const unique_ptr_base &other) throw ()
- : m_ptr (const_cast<unique_ptr_base &> (other).release ()) {}
-
- /* Converting "move" constructor. Really an lvalue ref converting
- constructor that actually moves. This allows constructs such as:
-
- unique_ptr<Derived> func_returning_unique_ptr (.....);
- ...
- unique_ptr<Base> ptr = func_returning_unique_ptr (.....);
- */
- template<typename T1, typename D1>
- unique_ptr_base (const unique_ptr_base<T1, D1> &other) throw ()
- : m_ptr (const_cast<unique_ptr_base<T1, D1> &> (other).release ()) {}
-
- /* The "move" assignment operator. Really an lvalue ref copy
- assignment operator that actually moves. See comments above. */
- unique_ptr_base &operator= (const unique_ptr_base &other) throw ()
- {
- reset (const_cast<unique_ptr_base &> (other).release ());
- return *this;
- }
-
- /* Converting "move" assignment. Really an lvalue ref converting
- copy assignment operator that moves. See comments above. */
- template<typename T1, typename D1>
- unique_ptr_base &operator= (const unique_ptr_base<T1, D1> &other) throw ()
- {
- reset (const_cast<unique_ptr_base<T1, D1> &> (other).release ());
- return *this;
- }
-
- /* std::unique_ptr does not allow assignment, except from nullptr.
- nullptr doesn't exist in C++03, so we allow assignment from NULL
- instead [ptr = NULL;].
- */
- unique_ptr_base &operator= (detail::nullptr_t *) throw ()
- {
- reset ();
- return *this;
- }
-
- ~unique_ptr_base () { call_deleter (); }
-
- /* "explicit operator bool ()" emulation using the safe bool
- idiom. */
-private:
- typedef void (unique_ptr_base::*explicit_operator_bool) () const;
- void this_type_does_not_support_comparisons () const {}
-
-public:
- operator explicit_operator_bool () const
- {
- return (m_ptr != NULL
- ? &unique_ptr_base::this_type_does_not_support_comparisons
- : 0);
- }
-
- element_type *get () const throw () { return m_ptr; }
-
- element_type *release () throw ()
- {
- pointer tmp = m_ptr;
- m_ptr = NULL;
- return tmp;
- }
-
- void reset (element_type *p = NULL) throw ()
- {
- if (p != m_ptr)
- {
- call_deleter ();
- m_ptr = p;
- }
- }
-
-private:
-
- /* Call the deleter. Note we assume the deleter is "stateless". */
- void call_deleter ()
- {
- D d;
-
- d (m_ptr);
- }
-
- element_type *m_ptr;
-};
-
-} /* namespace detail */
-
-/* Macro used to create a unique_ptr_base "partial specialization" --
- a subclass that uses a specific deleter. Basically this re-defines
- the necessary constructors. This is necessary because C++03
- doesn't support inheriting constructors with "using". While at it,
- we inherit the assignment operator. TYPE is the name of the type
- being defined. Assumes that 'base_type' is a typedef of the
- baseclass TYPE is inheriting from. */
-#define DEFINE_GNU_UNIQUE_PTR(TYPE) \
-public: \
- explicit TYPE (T *p = NULL) throw () \
- : base_type (p) {} \
- \
- TYPE (const TYPE &other) throw () : base_type (other) {} \
- \
- TYPE (detail::nullptr_t *) throw () : base_type (NULL) {} \
- \
- template<typename T1, typename D1> \
- TYPE (const detail::unique_ptr_base<T1, D1> &other) throw () \
- : base_type (other) {} \
- \
- using base_type::operator=;
-
-/* Define single-object gnu::unique_ptr. */
-
-template <typename T, typename D = default_delete<T> >
-class unique_ptr : public detail::unique_ptr_base<T, D>
-{
- typedef detail::unique_ptr_base<T, D> base_type;
-
- DEFINE_GNU_UNIQUE_PTR (unique_ptr)
-
-public:
- /* Dereferencing. */
- T &operator* () const throw () { return *this->get (); }
- T *operator-> () const throw () { return this->get (); }
-};
-
-/* Define gnu::unique_ptr specialization for T[]. */
-
-template <typename T, typename D>
-class unique_ptr<T[], D> : public detail::unique_ptr_base<T, D>
-{
- typedef detail::unique_ptr_base<T, D> base_type;
-
- DEFINE_GNU_UNIQUE_PTR (unique_ptr)
-
-public:
- /* Indexing operator. */
- T &operator[] (size_t i) const { return this->get ()[i]; }
-};
-
-/* Comparison operators. */
-
-template <typename T, typename D,
- typename U, typename E>
-inline bool
-operator== (const detail::unique_ptr_base<T, D> &x,
- const detail::unique_ptr_base<U, E> &y)
-{ return x.get() == y.get(); }
-
-template <typename T, typename D,
- typename U, typename E>
-inline bool
-operator!= (const detail::unique_ptr_base<T, D> &x,
- const detail::unique_ptr_base<U, E> &y)
-{ return x.get() != y.get(); }
-
-template<typename T, typename D,
- typename U, typename E>
-inline bool
-operator< (const detail::unique_ptr_base<T, D> &x,
- const detail::unique_ptr_base<U, E> &y)
-{ return x.get() < y.get (); }
-
-template<typename T, typename D,
- typename U, typename E>
-inline bool
-operator<= (const detail::unique_ptr_base<T, D> &x,
- const detail::unique_ptr_base<U, E> &y)
-{ return !(y < x); }
-
-template<typename T, typename D,
- typename U, typename E>
-inline bool
-operator> (const detail::unique_ptr_base<T, D> &x,
- const detail::unique_ptr_base<U, E> &y)
-{ return y < x; }
-
-template<typename T, typename D,
- typename U, typename E>
-inline bool
-operator>= (const detail::unique_ptr_base<T, D> &x,
- const detail::unique_ptr_base<U, E> &y)
-{ return !(x < y); }
-
-/* std::move "emulation". This is as simple as it can be -- no
- attempt is made to emulate rvalue references. This relies on T
- having move semantics like std::auto_ptr.
- I.e., copy/assignment actually moves. */
-
-template<typename T>
-const T&
-move (T& v)
-{
- return v;
-}
-
-#endif /* C++11 */
-
-/* Define gnu::unique_xmalloc_ptr, a gnu::unique_ptr that manages
- xmalloc'ed memory. */
-
-/* The deleter for gnu::unique_xmalloc_ptr. Uses free. */
-template <typename T>
-struct xmalloc_deleter
-{
- void operator() (T *ptr) const { free (ptr); }
-};
-
-/* Same, for arrays. */
-template <typename T>
-struct xmalloc_deleter<T[]>
-{
- void operator() (T *ptr) const { free (ptr); }
-};
-
-#if __cplusplus >= 201103
-
-/* In C++11, we just import the standard unique_ptr to our namespace
- with a custom deleter. */
-
-template<typename T> using unique_xmalloc_ptr
- = std::unique_ptr<T, xmalloc_deleter<T>>;
-
-#else /* C++11 */
-
-/* In C++03, we don't have template aliases, so we need to define a
- subclass instead, and re-define the constructors, because C++03
- doesn't support inheriting constructors either. */
-
-template <typename T>
-class unique_xmalloc_ptr : public unique_ptr<T, xmalloc_deleter<T> >
-{
- typedef unique_ptr<T, xmalloc_deleter<T> > base_type;
-
- DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
-};
-
-/* Define gnu::unique_xmalloc_ptr specialization for T[]. */
-
-template <typename T>
-class unique_xmalloc_ptr<T[]> : public unique_ptr<T[], xmalloc_deleter<T[]> >
-{
- typedef unique_ptr<T[], xmalloc_deleter<T[]> > base_type;
-
- DEFINE_GNU_UNIQUE_PTR (unique_xmalloc_ptr)
-};
-
-#endif /* C++11 */
-
-} /* namespace gnu */
-
-#endif /* GNU_UNIQUE_PTR_H */