Add gnu::unique_ptr

Message ID 1507855253-47093-1-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series
  • Add gnu::unique_ptr
Related show

Commit Message

David Malcolm Oct. 13, 2017, 12:40 a.m.
From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>

I had a go at updating Trevor's unique_ptr patch from July
( https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02084.html )

One of the sticking points was what to call the namespace; there was
wariness about using "gtl" as the name.

Richi proposed (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00155.html):
> If it should be short use g::.  We can also use gnu:: I guess and I
> agree gnutools:: is a little long (similar to libiberty::).  Maybe
> gt:: as a short-hand for gnutools.  

Pedro noted (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00157.html):
> Exactly 3 letters has the nice property of making s/gtl::foo/std::foo/
> super trivial down the road; you don't have to care about reindenting
> stuff

Hence this version of the patch uses "gnu::" - 3 letters, one of the
ones Richi proposed, and *not* a match for ".tl" (e.g. "gtl");
(FWIW personally "gnu::" is my favorite, followed by "gcc::").

The include/unique-ptr.h in this patch is identical to that posted
by Trevor in July, with the following changes (by me):
- renaming of "gtl" to "gnu" 
- 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)

I also went and added a gcc/unique-ptr-tests.cc file containing
selftests (my thinking here is that although std::unique_ptr ought
to already be well-tested, we need to ensure that the fallback
implementation is sane when building with C++ prior to C++11).

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu,
using gcc 4.8 for the initial bootstrap (hence testing both gnu+03
and then gnu++14 in the selftests, for stage 1 and stages 2 and 3
respectively).

I also manually tested selftests with both gcc 4.8 and trunk on
the same hardware (again, to exercise both the with/without C++11
behavior).

Tested with "make selftest-valgrind" (no new issues).

OK for trunk?

Motivation/use-cases:
(a) I have an updated version of the
name_hint/deferred_diagnostic patch kit, which uses this (rather
than the refcounting used by
https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00439.html ); and
(b) having this available ought to allow various other cleanups
e.g. the example ones identified by Trevor here:
  https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02085.html

Thanks
Dave


Blurb from Trevor:

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

include/ChangeLog:

2017-07-29  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>

	* unique-ptr.h: New file.

Combined ChangeLog follows:

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.
---
 gcc/Makefile.in          |   1 +
 gcc/selftest-run-tests.c |   1 +
 gcc/selftest.h           |   1 +
 gcc/unique-ptr-tests.cc  | 177 ++++++++++++++++++++++
 include/unique-ptr.h     | 386 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 566 insertions(+)
 create mode 100644 gcc/unique-ptr-tests.cc
 create mode 100644 include/unique-ptr.h

Comments

Richard Biener Oct. 13, 2017, 9:26 a.m. | #1
On Fri, Oct 13, 2017 at 2:40 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
>
> I had a go at updating Trevor's unique_ptr patch from July
> ( https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02084.html )
>
> One of the sticking points was what to call the namespace; there was
> wariness about using "gtl" as the name.
>
> Richi proposed (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00155.html):
>> If it should be short use g::.  We can also use gnu:: I guess and I
>> agree gnutools:: is a little long (similar to libiberty::).  Maybe
>> gt:: as a short-hand for gnutools.
>
> Pedro noted (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00157.html):
>> Exactly 3 letters has the nice property of making s/gtl::foo/std::foo/
>> super trivial down the road; you don't have to care about reindenting
>> stuff
>
> Hence this version of the patch uses "gnu::" - 3 letters, one of the
> ones Richi proposed, and *not* a match for ".tl" (e.g. "gtl");
> (FWIW personally "gnu::" is my favorite, followed by "gcc::").
>
> The include/unique-ptr.h in this patch is identical to that posted
> by Trevor in July, with the following changes (by me):
> - renaming of "gtl" to "gnu"
> - 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)
>
> I also went and added a gcc/unique-ptr-tests.cc file containing
> selftests (my thinking here is that although std::unique_ptr ought
> to already be well-tested, we need to ensure that the fallback
> implementation is sane when building with C++ prior to C++11).
>
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu,
> using gcc 4.8 for the initial bootstrap (hence testing both gnu+03
> and then gnu++14 in the selftests, for stage 1 and stages 2 and 3
> respectively).
>
> I also manually tested selftests with both gcc 4.8 and trunk on
> the same hardware (again, to exercise both the with/without C++11
> behavior).
>
> Tested with "make selftest-valgrind" (no new issues).
>
> OK for trunk?

Ok if the gdb folks approve (and will change to this version).

Thanks,
Richard.

> Motivation/use-cases:
> (a) I have an updated version of the
> name_hint/deferred_diagnostic patch kit, which uses this (rather
> than the refcounting used by
> https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00439.html ); and
> (b) having this available ought to allow various other cleanups
> e.g. the example ones identified by Trevor here:
>   https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02085.html
>
> Thanks
> Dave
>
>
> Blurb from Trevor:
>
> 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
>
> include/ChangeLog:
>
> 2017-07-29  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
>
>         * unique-ptr.h: New file.
>
> Combined ChangeLog follows:
>
> 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.
> ---
>  gcc/Makefile.in          |   1 +
>  gcc/selftest-run-tests.c |   1 +
>  gcc/selftest.h           |   1 +
>  gcc/unique-ptr-tests.cc  | 177 ++++++++++++++++++++++
>  include/unique-ptr.h     | 386 +++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 566 insertions(+)
>  create mode 100644 gcc/unique-ptr-tests.cc
>  create mode 100644 include/unique-ptr.h
>
> 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 30e476d..b05e0fc 100644
> --- a/gcc/selftest-run-tests.c
> +++ b/gcc/selftest-run-tests.c
> @@ -66,6 +66,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 96eccac..adc0b68 100644
> --- a/gcc/selftest.h
> +++ b/gcc/selftest.h
> @@ -194,6 +194,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..df18467
> --- /dev/null
> +++ b/gcc/unique-ptr-tests.cc
> @@ -0,0 +1,177 @@
> +/* 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;
> +};
> +
> +} // 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);
> +}
> +
> +/* 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 ();
> +}
> +
> +} // namespace selftest
> +
> +#endif /* #if CHECKING_P */
> diff --git a/include/unique-ptr.h b/include/unique-ptr.h
> new file mode 100644
> index 0000000..eddb001
> --- /dev/null
> +++ b/include/unique-ptr.h
> @@ -0,0 +1,386 @@
> +/* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
> +
> +   Copyright (C) 2007-2016 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
> +
> +#include <memory>
> +
> +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.  Instead relies on
> +   the fact that gnu::unique_ptr has move semantics like
> +   std::auto_ptr.  I.e., copy/assignment actually moves.  */
> +
> +template<typename T, typename D>
> +unique_ptr<T, D>
> +move (unique_ptr<T, D> 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); }
> +};
> +
> +#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)
> +};
> +
> +#endif /* C++11 */
> +
> +} /* namespace gnu */
> +
> +#endif /* GNU_UNIQUE_PTR_H */
> --
> 1.8.5.3
>
Pedro Alves Oct. 13, 2017, 12:01 p.m. | #2
On 10/13/2017 10:26 AM, Richard Biener wrote:
> On Fri, Oct 13, 2017 at 2:40 AM, David Malcolm <dmalcolm@redhat.com> wrote:
>> From: Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
>>
>> I had a go at updating Trevor's unique_ptr patch from July
>> ( https://gcc.gnu.org/ml/gcc-patches/2017-07/msg02084.html )
>>
>> One of the sticking points was what to call the namespace; there was
>> wariness about using "gtl" as the name.
>>
>> Richi proposed (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00155.html):
>>> If it should be short use g::.  We can also use gnu:: I guess and I
>>> agree gnutools:: is a little long (similar to libiberty::).  Maybe
>>> gt:: as a short-hand for gnutools.
>>
>> Pedro noted (https://gcc.gnu.org/ml/gcc-patches/2017-09/msg00157.html):
>>> Exactly 3 letters has the nice property of making s/gtl::foo/std::foo/
>>> super trivial down the road; you don't have to care about reindenting
>>> stuff
>>
>> Hence this version of the patch uses "gnu::" - 3 letters, one of the
>> ones Richi proposed, and *not* a match for ".tl" (e.g. "gtl");
>> (FWIW personally "gnu::" is my favorite, followed by "gcc::").
>>
>> The include/unique-ptr.h in this patch is identical to that posted
>> by Trevor in July, with the following changes (by me):
>> - renaming of "gtl" to "gnu"
>> - 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)
>>
>> I also went and added a gcc/unique-ptr-tests.cc file containing
>> selftests (my thinking here is that although std::unique_ptr ought
>> to already be well-tested, we need to ensure that the fallback
>> implementation is sane when building with C++ prior to C++11).
>>
>> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu,
>> using gcc 4.8 for the initial bootstrap (hence testing both gnu+03
>> and then gnu++14 in the selftests, for stage 1 and stages 2 and 3
>> respectively).
>>
>> I also manually tested selftests with both gcc 4.8 and trunk on
>> the same hardware (again, to exercise both the with/without C++11
>> behavior).
>>
>> Tested with "make selftest-valgrind" (no new issues).
>>
>> OK for trunk?
> 
> Ok if the gdb folks approve 

The new tests looks good to me.  [ The class too, obviously. :-) ]

(and will change to this version).

GDB used this emulation/shim in master for a period, but it
no longer does, because GDB switched to requiring
C++11 (gcc >= 4.8) instead meanwhile...  I.e., GDB uses
standard std::unique_ptr nowadays.

GDB still uses gdb::unique_xmalloc_ptr though.  Might make
sense to switch to using gnu::unique_xmalloc_ptr instead.

GDB does have an xfree function that we call instead
of free throughout (that's where the reference David fixed
comes from).  We can most probably just switch to free too nowadays.

Also, gdb nowadays also has a gdb::unique_xmalloc_ptr<T[]> specialization
that this patch is missing (because the specialization was added
after switching to C++11):

  [pushed] Allow gdb::unique_xmalloc_ptr<T[]>
  https://sourceware.org/ml/gdb-patches/2017-08/msg00212.html

So we'd need that before switching.  I don't recall off hand whether
it's easy to make that work with the C++03 version.

Thanks,
Pedro Alves

Patch

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 30e476d..b05e0fc 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -66,6 +66,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 96eccac..adc0b68 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -194,6 +194,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..df18467
--- /dev/null
+++ b/gcc/unique-ptr-tests.cc
@@ -0,0 +1,177 @@ 
+/* 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;
+};
+
+} // 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);
+}
+
+/* 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 ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/include/unique-ptr.h b/include/unique-ptr.h
new file mode 100644
index 0000000..eddb001
--- /dev/null
+++ b/include/unique-ptr.h
@@ -0,0 +1,386 @@ 
+/* gnu::unique_ptr, a simple std::unique_ptr replacement for C++03.
+
+   Copyright (C) 2007-2016 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
+
+#include <memory>
+
+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.  Instead relies on
+   the fact that gnu::unique_ptr has move semantics like
+   std::auto_ptr.  I.e., copy/assignment actually moves.  */
+
+template<typename T, typename D>
+unique_ptr<T, D>
+move (unique_ptr<T, D> 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); }
+};
+
+#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)
+};
+
+#endif /* C++11 */
+
+} /* namespace gnu */
+
+#endif /* GNU_UNIQUE_PTR_H */