[v4] Introduce gdb::unique_ptr

Message ID 70152188-5427-1eb1-a2bf-d77251d36a78@redhat.com
State New, archived
Headers

Commit Message

Pedro Alves Oct. 17, 2016, 1:51 p.m. UTC
  On 10/16/2016 08:13 AM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> For managing malloc pointers, this adds a gdb::unique_malloc_ptr<T>
> Pedro> "specialization" with a custom xfree deleter.
> 
> I found something surprising while using this patch: it can't be used in
> a .y file, due to the malloc->xmalloc renaming done in the .y.c rule.
> I puzzled over the error about "unique_xmalloc_ptr" for a while until I
> remembered this.

Oh, I saw that too, when I tried to use it to manage the result of
ui_file_xstrdup in c-exp.y, I think, but then added added ui_file_as_string
instead, and then I completely forgot about that!  FWIW, I also puzzled
over the error for a while...

> One option would be to fix up that renaming, maybe something like:
> 
> -	     -e 's/\([^x]\)malloc/\1xmalloc/g' \
> -	     -e 's/\([^x_]\)malloc/\1xmalloc/g' \
> 
> Another would be to rename the class unique_xmalloc_ptr after all.

Guess renaming makes sense anyway.  I renamed it, and forced-pushed this
along with the rest of the series (meanwhile split into smaller pieces
and a few more patches added; it's now at 32 patches...) to the
users/palves/cxx-eliminate-cleanups branch.

While splitting up the series, I noticed that it'd be nice to 
support implicit construction from NULL, since that works in C++11,
so I tweaked the patch accordingly.  The problem was that the
not-a-type-based nullptr emulation wouldn't trigger because it
would require two conversions, because I had used a separate class...
Inlining that in auto_ptr_base makes things work, and, ends up
looking simpler even...

So here's v4.  WDTY?

From f35cf129b55e331c1edd3dfd4bf633a9bd649418 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 17 Oct 2016 14:11:23 +0100
Subject: [PATCH] Introduce gdb::unique_ptr

New in v4:

  - implict construction from NULL allowed too now, for:

     gdb::unique_ptr<foo> func (....)
     {
        return NULL;
     }

  - Rename unique_malloc_ptr to unique_xmalloc_ptr.

New in v3:

  - Comment typos fixed.  Detail things moved to detail namespace.

New in v2:

  - considering a move to C++11, it no longer makes much sense to add
    a base class just for the one instance of the safe bool idiom.
    That's now inlined into unique_ptr directly.

  - added missing </<=/>/>= comparison operators.

  - simplified the implementation even further, by removing the "ref"
    class, and adding converting contructors instead.  This actually
    fixes this use case:

      unique_ptr<Derived> func_returning_unique_ptr (.....);
      ...
      unique_ptr<Base> ptr = func_returning_unique_ptr (.....);

    Looks like GCC's std::auto_ptr is buggy in that respect, because
    that doesn't actually work with std::auto_ptr, despite the
    comments indicating otherwise, and I was copying the comment/bug.

  - comments updated/rewritten throughout, including the git commit
    log, to hopefully clarify things.

  I think that the code looks clearer and less "magic" now.

I'd like to get this in soon to unblock Tromey's C++ series, and more.
We can move along with the C++11 discussion / plan in parallel.

Any objections?

I'll be more than happy to remove this when we finally make C++11 a
requirement.  But I don't want to rush that.  We should make sure that
the buildbot's buildslaves are ready, for example.

~~~

Many make_cleanup uses in the code base are best eliminated by using a
"owning" smart pointer to manage ownership of the resource
automatically.

The question is _which_ smart pointer.

GDB currently supports building with a C++03 compiler.  We have
std::auto_ptr in C++03, but, as is collective wisdom by now, that's
too easy to misuse, and has therefore been deprecated in C++11 and
finally removed in C++17.

It'd be nice to be able to use std::unique_ptr instead, which is the
modern, safe std::auto_ptr replacement in C++11.

In addition to extra safety -- moving (i.e., transfer of ownership of
the managed pointer between smart pointers) must be explicit --
std::unique_ptr has (among others) one nice feature that std::auto_ptr
doesn't --- ability to specify a custom deleter as template parameter.
In gdb's context, that allows easily creating a smart pointer for
memory allocated with xmalloc -- the smart pointer then knows to
release with xfree instead of delete.  This is particularly
interesting when managing objects allocated in C libraries, and also,
for C++-fying parts of GDB that interact with other parts that still
return objects allocated with xmalloc.

Since std::unique_ptr's API is quite nice, and eventually we'd like to
move to C++11, this patch adds a C++03-compatible smart pointer that
exposes the subset of the std::unique_ptr API that we're interested
in.  An advantage is that whenever we start requiring C++11, we won't
have to learn a new API.  Meanwhile, this allows continuing to support
building with a C++03 compiler.

Since C++03 doesn't support rvalue references (boost gets close to
emulating them, but it's not fully transparent to user code), the
C++03 std::unique_ptr emulation here doesn't try hard to prevent
accidentally moving, which is where most of complication of a more
thorough emulation would be.  Instead, we rely on the fact that GDB
will be usually compiled with a C++11 compiler, and use the real
std::unique_ptr in that case to catch such accidental moves.  IOW, 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.

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:

   - Support for custom (stateless) deleters.  (Support for stateful
     deleters could be added, if necessary.)

   - unique_ptr<T[]> partial specialization (auto_ptr<T> does not know
     to use delete[]).

   - Support for all of 'ptr != NULL', 'ptr == NULL' and 'if (ptr)'
     using the safe bool idiom.

   - Assignment from NULL.

   - Allow using all of 'ptr != NULL', 'ptr == NULL' and 'if (ptr)'
     using the safe bool idiom to emulate C++11's explicit bool
     conversion.

   - Variable names un-uglified (ie., no leading __ prefix everywhere).

   - Formatting made to follow GDB's coding conventions, including
     comment style.

   - Initialization and assignment from NULL (std::unique_ptr allows
    "ptr = nullptr" instead, while std::auto_ptr allows neither.)

   - Converting "move" constructors done differently in order to truly
     support:

      unique_ptr<Derived> func_returning_unique_ptr (.....);
      ...
      unique_ptr<Base> ptr = func_returning_unique_ptr (.....);

At this point, it no longer shares much at all with the original file,
but, that's the history.

See comments in the code to find out more.

I thought of putting the "emulation" / shim in the "std" namespace, so
that when we start requiring C++11 at some point, no actual changes to
users of the smart pointer throughout would be necessary.  Putting
things in the std namespace is technically undefined, however in
practice it doesn't cause any issue with any compiler.  However,
thinking that people might be confused with seeing std::unique_ptr and
thinking that we're actually requiring C++11 already, I put the new
types in the "gdb" namespace instead.

For managing xmalloc pointers, this adds a gdb::unique_xmalloc_ptr<T>
"specialization" with a custom xfree deleter.

No actual use of any smart pointer is introduced in this patch.
That'll be done in following patches.

Tested (along with the rest of the series) on:

 - NetBSD 5.1 (gcc70 on the compile farm), w/ gcc 4.1.3
 - x86-64 Fedora 23, gcc 5.3.1 (gnu++03)
 - x86-64 Fedora 23, and gcc 7.0 (gnu++14)

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* common/common-defs.h: Include "gdb_unique_ptr.h".
	* common/gdb_unique_ptr.h: New.
---
 gdb/common/common-defs.h    |   3 +
 gdb/common/gdb_unique_ptr.h | 360 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 363 insertions(+)
 create mode 100644 gdb/common/gdb_unique_ptr.h
  

Comments

Pedro Alves Oct. 17, 2016, 6 p.m. UTC | #1
On 10/17/2016 02:51 PM, Pedro Alves wrote:

> I'd like to get this in soon to unblock Tromey's C++ series, and more.
> We can move along with the C++11 discussion / plan in parallel.
> 
> Any objections?
> 
> I'll be more than happy to remove this when we finally make C++11 a
> requirement.  But I don't want to rush that.  We should make sure that
> the buildbot's buildslaves are ready, for example.

A small update here.

I plan to use the new trybot support to test a patch
that forces the C++11 requirement, to determine which
buildbots don't have a recent enough compiler yet.  Also
chatting with Sergio about getting this info written
down and visible on the buildbot web frontend or extracted
systematically out of the builds, to avoid this "in the dark"
situation.

The Debian buildslave was one I knew was old enough to not have
recent enough gcc for full C++11 support.  It was running Debian
Wheezy, which comes with gcc 4.4 OOTB.  After a little digging,
I found at [1] that it's easy to install Jessie's gcc 4.9
packages on Wheezy:

~~~~
 This leaves the original GCC,G++ in place. If you wish to compile with
 the 4.9 version, then either set the CC and CXX env vars accordingly or
 invoke the compilers as gcc-4.9 or g++-4.9 explicitly.
~~~~

I pointed Mark Wielaard, the buildslave owner, at this, and he
instead upgraded the machine to Debian Jessie instead over the
weekend.  :-)  Many thanks Mark.  One down, $N to go.

[1] - http://stackoverflow.com/questions/25147363/how-to-install-g-4-9-on-debian-wheezy-armel

Thanks,
Pedro Alves
  
Pedro Alves Oct. 17, 2016, 11:20 p.m. UTC | #2
On 10/17/2016 07:00 PM, Pedro Alves wrote:

> A small update here.
> 
> I plan to use the new trybot support to test a patch
> that forces the C++11 requirement, to determine which
> buildbots don't have a recent enough compiler yet.  Also
> chatting with Sergio about getting this info written
> down and visible on the buildbot web frontend or extracted
> systematically out of the builds, to avoid this "in the dark"
> situation.

I was looking at this, and noticed that 

 https://sourceware.org/gdb/wiki/BuildBot#Available_Builders

doesn't actually cover all the build slaves.  The ones it does cover I
think we already know run sufficient enough gcc from the OS version.

So I looked at the full list of configured build slaves, at:

  http://gdb-build.sergiodj.net/buildslaves

and built the following table based on info I could find either in the
build slaves' info page, or if compiler info missing there, by doing a
web search for which gcc version a given distro ships with.

Slave                            | Compiler / Info
---------------------------------+-----------------------------------------------------------
aix-power8-1                     | AIX 7.2 - it's on the gcc compile farm; I logged in, and it has GCC 6.1
debian-jessie-mips-be-1          | Debian Jessie (comes with GCC 4.9, AFAIK); not connected anyway.
debian-jessie-s390x-1            | Debian Jessie (comes with GCC 4.9, AFAIK); connected
fedora-ppc64be-1                 | Fedora 23 (comes with GCC 5.3.1)
fedora-ppc64le-1                 | Fedora 23 (comes with GCC 5.3.1)
fedora-x86-64-1                  | Fedora 24 (GCC 6.1)
fedora-x86-64-2                  | Fedora 24 (GCC 6.1)
fedora-x86-64-3                  | Fedora 24 (GCC 6.1)
fedora-x86-64-4                  | Fedora 24 (GCC 6.1)
gdb-amd64-netbsd7                | NetBSD 7 (gcc version 4.8.4 (nb2 20150115))
koobs-freebsd8                   | *not connected*
koobs-freebsd9                   | gcc 4.2 (fails building gdb now already)
koobs-freebsd10                  | clang 3.4.1 (C++11 ready)
koobs-freebsd11                  | clang 3.8.0 (C++11 ready)
marist-fedora-s390x              | Fedora 23 (GCC 5.3.1)
rhel-7.1-s390x-1                 | RHEL 7.1 - should be GCC 4.8 
ubuntu-aarch64-1                 | Ubuntu 14.04 (GCC 4.8.2)
wildebeest-debian-jessie-i686    | Debian Jessie (GCC 4.9.2)
wildebeest-debian-jessie-x86_64  | Debian Jessie (GCC 4.9.2)

I believe that if any is not actually building with the
system compiler, it'll probably be using a newer gcc version...

So looks like the only one not C++11 ready is the FreeBSD 9 one.
But, that one hasn't managed to build gdb for a long while
[1] (did it ever?) and isn't even hooked to send test reports to the
testers list, AFAIK.  We wouldn't really miss it, IMO.

[1] - http://gdb-build.sergiodj.net/builders/FreeBSD-x86_64-m64

So looks like Mark's Debian Wheezer buildslave was really the only one
that needed updating and we're actually ready for C++11 from
the buildbot's perspective?

Thanks,
Pedro Alves
  
Tom Tromey Oct. 18, 2016, 2:33 a.m. UTC | #3
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> So here's v4.  WDTY?

It looks good to me and I've had good experiences with it in some
patches I have locally.

Tom
  
John Baldwin Oct. 19, 2016, 3:19 a.m. UTC | #4
On Tuesday, October 18, 2016 12:20:00 AM Pedro Alves wrote:
> On 10/17/2016 07:00 PM, Pedro Alves wrote:
> 
> > A small update here.
> > 
> > I plan to use the new trybot support to test a patch
> > that forces the C++11 requirement, to determine which
> > buildbots don't have a recent enough compiler yet.  Also
> > chatting with Sergio about getting this info written
> > down and visible on the buildbot web frontend or extracted
> > systematically out of the builds, to avoid this "in the dark"
> > situation.
> 
> I was looking at this, and noticed that 
> 
>  https://sourceware.org/gdb/wiki/BuildBot#Available_Builders
> 
> doesn't actually cover all the build slaves.  The ones it does cover I
> think we already know run sufficient enough gcc from the OS version.
> 
> So I looked at the full list of configured build slaves, at:
> 
>   http://gdb-build.sergiodj.net/buildslaves
> 
> and built the following table based on info I could find either in the
> build slaves' info page, or if compiler info missing there, by doing a
> web search for which gcc version a given distro ships with.
> 
> Slave                            | Compiler / Info
> ---------------------------------+-----------------------------------------------------------
> aix-power8-1                     | AIX 7.2 - it's on the gcc compile farm; I logged in, and it has GCC 6.1
> debian-jessie-mips-be-1          | Debian Jessie (comes with GCC 4.9, AFAIK); not connected anyway.
> debian-jessie-s390x-1            | Debian Jessie (comes with GCC 4.9, AFAIK); connected
> fedora-ppc64be-1                 | Fedora 23 (comes with GCC 5.3.1)
> fedora-ppc64le-1                 | Fedora 23 (comes with GCC 5.3.1)
> fedora-x86-64-1                  | Fedora 24 (GCC 6.1)
> fedora-x86-64-2                  | Fedora 24 (GCC 6.1)
> fedora-x86-64-3                  | Fedora 24 (GCC 6.1)
> fedora-x86-64-4                  | Fedora 24 (GCC 6.1)
> gdb-amd64-netbsd7                | NetBSD 7 (gcc version 4.8.4 (nb2 20150115))
> koobs-freebsd8                   | *not connected*
> koobs-freebsd9                   | gcc 4.2 (fails building gdb now already)
> koobs-freebsd10                  | clang 3.4.1 (C++11 ready)
> koobs-freebsd11                  | clang 3.8.0 (C++11 ready)
> marist-fedora-s390x              | Fedora 23 (GCC 5.3.1)
> rhel-7.1-s390x-1                 | RHEL 7.1 - should be GCC 4.8 
> ubuntu-aarch64-1                 | Ubuntu 14.04 (GCC 4.8.2)
> wildebeest-debian-jessie-i686    | Debian Jessie (GCC 4.9.2)
> wildebeest-debian-jessie-x86_64  | Debian Jessie (GCC 4.9.2)
> 
> I believe that if any is not actually building with the
> system compiler, it'll probably be using a newer gcc version...
> 
> So looks like the only one not C++11 ready is the FreeBSD 9 one.
> But, that one hasn't managed to build gdb for a long while
> [1] (did it ever?) and isn't even hooked to send test reports to the
> testers list, AFAIK.  We wouldn't really miss it, IMO.
> 
> [1] - http://gdb-build.sergiodj.net/builders/FreeBSD-x86_64-m64
> 
> So looks like Mark's Debian Wheezer buildslave was really the only one
> that needed updating and we're actually ready for C++11 from
> the buildbot's perspective?

For FreeBSD 9, I can fix the port that is used to build the package folks
install to use a C++11 compiler for GDB 7.13, so that should be fine.  It
should also be fairly simple to fix the buildbot to install a newer compiler
from a package to use instead of the system compiler as well.  I can follow
up with the maintainer.

Personally, I am only testing GDB on FreeBSD 10.x and later generally using
clang (though the clang build has a few warnings still, when I've used gcc
it built cleanly).
  
Pedro Alves Oct. 19, 2016, 12:49 p.m. UTC | #5
On 10/19/2016 04:19 AM, John Baldwin wrote:
> For FreeBSD 9, I can fix the port that is used to build the package folks
> install to use a C++11 compiler for GDB 7.13, so that should be fine.  It
> should also be fairly simple to fix the buildbot to install a newer compiler
> from a package to use instead of the system compiler as well.  I can follow
> up with the maintainer.

Excellent.  Thanks much John.

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h
index b82906f..5426dd5 100644
--- a/gdb/common/common-defs.h
+++ b/gdb/common/common-defs.h
@@ -82,4 +82,7 @@ 
 #define EXTERN_C_PUSH extern "C" {
 #define EXTERN_C_POP }
 
+/* Pull in gdb::unique_ptr and gdb::unique_xmalloc_ptr.  */
+#include "common/gdb_unique_ptr.h"
+
 #endif /* COMMON_DEFS_H */
diff --git a/gdb/common/gdb_unique_ptr.h b/gdb/common/gdb_unique_ptr.h
new file mode 100644
index 0000000..52b5c4b
--- /dev/null
+++ b/gdb/common/gdb_unique_ptr.h
@@ -0,0 +1,360 @@ 
+/* gdb::unique_ptr, a simple std::unique_ptr replacement for C++03.
+
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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/>.  */
+
+/* gdb::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, gdb::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 gdb::unique_ptr partial
+   specialization that uses a custom (stateless) deleter:
+   gdb::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.
+
+   Putting gdb::unique_ptr in standard containers is not supported.
+*/
+
+#ifndef GDB_UNIQUE_PTR_H
+#define GDB_UNIQUE_PTR_H 1
+
+#include <memory>
+
+namespace gdb
+{
+
+#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 gdb::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:
+
+     gdb::unique_ptr<foo> func (....)
+     {
+        return NULL;
+     }
+
+   and assignment from NULL:
+
+     gdb::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.  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.  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 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;
+  }
+
+  /* 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_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 non-array gdb::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_UNIQUE_PTR (unique_ptr)
+
+public:
+  /* Dereferencing.  */
+  T &operator* () const throw () { return *this->get (); }
+  T *operator-> () const throw () { return this->get (); }
+};
+
+/* gdb::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_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 gdb::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 gdb::unique_xmalloc_ptr, a gdb::unique_ptr that manages
+   xmalloc'ed memory.  */
+
+/* The deleter for gdb::unique_xmalloc_ptr.  Uses xfree.  */
+template <typename T>
+struct xfree_deleter
+{
+  void operator() (T *ptr) const { xfree (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, xfree_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, xfree_deleter<T> >
+{
+  typedef unique_ptr<T, xfree_deleter<T> > base_type;
+
+  DEFINE_UNIQUE_PTR (unique_xmalloc_ptr)
+};
+
+#endif /* C++11 */
+
+} /* namespace gdb */
+
+#endif /* GDB_UNIQUE_PTR_H */