[PATCH] Replace gnu::unique_ptr with std::unique_ptr

Jonathan Wakely jwakely@redhat.com
Tue Nov 9 17:51:27 GMT 2021


Now that GCC is compiled as C++11 there is no need to keep the C++03
implementation of gnu::unique_ptr.

This removes the unique-ptr.h header and replaces it with <memory> in
system.h, and changes the INCLUDE_UNIQUE_PTR macro to INCLUDE_MEMORY.
Uses of gnu::unique_ptr and gnu::move can be replaced with
std::unique_ptr and std::move. There are no uses of unique_xmalloc_ptr
or xmalloc_deleter in GCC.


Bootstrapped and tested on powerpc64le-linux. OK for trunk?



gcc/analyzer/ChangeLog:

	* engine.cc: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR.

gcc/c-family/ChangeLog:

	* known-headers.cc: Define INCLUDE_MEMORY instead of
	INCLUDE_UNIQUE_PTR.
	* name-hint.h: Likewise.
	(class name_hint): Use std::unique_ptr instead of gnu::unique_ptr.

gcc/c/ChangeLog:

	* c-decl.c: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR.
	* c-parser.c: Likewise.

gcc/cp/ChangeLog:

	* error.c: Define INCLUDE_MEMORY instead of
	INCLUDE_UNIQUE_PTR.
	* lex.c: Likewise.
	* name-lookup.c: Likewise.
	(class namespace_limit_reached): Use std::unique_ptr instead of
	gnu::unique_ptr.
	(suggest_alternatives_for): Use std::move instead of gnu::move.
	(suggest_alternatives_in_other_namespaces): Likewise.
	* parser.c: Define INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR.

gcc/ChangeLog:

	* Makefile.in: Remove unique-ptr-tests.o.
	* selftest-run-tests.c (selftest::run_tests): Remove
	unique_ptr_tests_cc_tests.
	* selftest.h (unique_ptr_tests_cc_tests): Remove.
	* system.h: Check INCLUDE_MEMORY instead of INCLUDE_UNIQUE_PTR
	and include <memory> instead of "unique-ptr.h".
	* unique-ptr-tests.cc: Removed.

include/ChangeLog:

	* unique-ptr.h: Removed.
---
 gcc/Makefile.in               |   1 -
 gcc/analyzer/engine.cc        |   2 +-
 gcc/c-family/known-headers.cc |   2 +-
 gcc/c-family/name-hint.h      |  12 +-
 gcc/c/c-decl.c                |   2 +-
 gcc/c/c-parser.c              |   2 +-
 gcc/cp/error.c                |   2 +-
 gcc/cp/lex.c                  |   2 +-
 gcc/cp/name-lookup.c          |  10 +-
 gcc/cp/parser.c               |   2 +-
 gcc/selftest-run-tests.c      |   1 -
 gcc/selftest.h                |   1 -
 gcc/system.h                  |   8 +-
 gcc/unique-ptr-tests.cc       | 236 --------------------
 include/unique-ptr.h          | 405 ----------------------------------
 15 files changed, 21 insertions(+), 667 deletions(-)
 delete mode 100644 gcc/unique-ptr-tests.cc
 delete mode 100644 include/unique-ptr.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 571e9c28e29..1e8e4449ffb 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1693,7 +1693,6 @@ OBJS = \
 	tree.o \
 	tristate.o \
 	typed-splay-tree.o \
-	unique-ptr-tests.o \
 	valtrack.o \
 	value-pointer-equiv.o \
 	value-query.o \
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index f21f8e5b78a..1312741bb47 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -19,7 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc
index a3912468a8d..572cca177fa 100644
--- a/gcc/c-family/known-headers.cc
+++ b/gcc/c-family/known-headers.cc
@@ -18,7 +18,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "c-family/c-common.h"
diff --git a/gcc/c-family/name-hint.h b/gcc/c-family/name-hint.h
index ea433243ba4..3141552ea59 100644
--- a/gcc/c-family/name-hint.h
+++ b/gcc/c-family/name-hint.h
@@ -20,12 +20,12 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_NAME_HINT_H
 #define GCC_NAME_HINT_H
 
-/* This header uses gnu::unique_ptr, but unique-ptr.h can't be directly
+/* This header uses std::unique_ptr, but <memory> can't be directly
    included due to issues with macros.  Hence it must be included from
-   system.h by defining INCLUDE_UNIQUE_PTR in any source file using it.  */
+   system.h by defining INCLUDE_MEMORY in any source file using it.  */
 
-#ifndef GNU_UNIQUE_PTR_H
-# error "You must define INCLUDE_UNIQUE_PTR before including system.h to use name-hint.h"
+#ifndef INCLUDE_MEMORY
+# error "You must define INCLUDE_MEMORY before including system.h to use name-hint.h"
 #endif
 
 enum lookup_name_fuzzy_kind {
@@ -106,7 +106,7 @@ public:
 
   /* Take ownership of this name_hint's deferred_diagnostic, for use
      in chaining up deferred diagnostics.  */
-  gnu::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); }
+  std::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); }
 
   /* Call this on a name_hint if the corresponding warning was not emitted,
      in which case we should also not emit the deferred_diagnostic.  */
@@ -119,7 +119,7 @@ public:
 
 private:
   const char *m_suggestion;
-  gnu::unique_ptr<deferred_diagnostic> m_deferred;
+  std::unique_ptr<deferred_diagnostic> m_deferred;
 };
 
 extern name_hint lookup_name_fuzzy (tree, enum lookup_name_fuzzy_kind,
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 186fa1692c1..603c1e05dd3 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "config.h"
 #define INCLUDE_STRING
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 80dd61d599e..ff5b89abfde 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3.  If not see
    location rather than implicitly using input_location.  */
 
 #include "config.h"
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "target.h"
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 012a4ecddf4..3e420aba3ba 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -19,7 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "config.h"
 /* For use with name_hint.  */
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 43abd019e6e..06de6cfe3b3 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "config.h"
 /* For use with name_hint.  */
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 035bcf51278..5be332569eb 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -19,7 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
@@ -6383,7 +6383,7 @@ class namespace_limit_reached : public deferred_diagnostic
 {
  public:
   namespace_limit_reached (location_t loc, unsigned limit, tree name,
-			   gnu::unique_ptr<deferred_diagnostic> wrapped)
+			   std::unique_ptr<deferred_diagnostic> wrapped)
   : deferred_diagnostic (loc),
     m_limit (limit), m_name (name),
     m_wrapped (move (wrapped))
@@ -6403,7 +6403,7 @@ class namespace_limit_reached : public deferred_diagnostic
  private:
   unsigned m_limit;
   tree m_name;
-  gnu::unique_ptr<deferred_diagnostic> m_wrapped;
+  std::unique_ptr<deferred_diagnostic> m_wrapped;
 };
 
 /* Subclass of deferred_diagnostic, for use when issuing a single suggestion.
@@ -6647,7 +6647,7 @@ suggest_alternatives_for (location_t location, tree name,
   if (!result)
     result = suggest_alternatives_for_1 (location, name, suggest_misspellings);
 
-  return ns_hints.maybe_decorate_with_limit (gnu::move (result));
+  return ns_hints.maybe_decorate_with_limit (std::move (result));
 }
 
 /* The second half of suggest_alternatives_for, for when no exact matches
@@ -6692,7 +6692,7 @@ suggest_alternatives_in_other_namespaces (location_t location, tree name)
 
   name_hint result = ns_hints.convert_candidates_to_name_hint ();
 
-  return ns_hints.maybe_decorate_with_limit (gnu::move (result));
+  return ns_hints.maybe_decorate_with_limit (std::move (result));
 }
 
 /* A well-known name within the C++ standard library, returned by
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 32de97b08bd..a678340d67d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19,7 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
-#define INCLUDE_UNIQUE_PTR
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 6a8f291f5dd..8eb1239b59c 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -71,7 +71,6 @@ selftest::run_tests ()
   sreal_c_tests ();
   fibonacci_heap_c_tests ();
   typed_splay_tree_c_tests ();
-  unique_ptr_tests_cc_tests ();
   opt_proposer_c_tests ();
   opts_c_tests ();
   json_cc_tests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 24ef57cb6cc..e6c7fc35afa 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -262,7 +262,6 @@ extern void tree_cfg_c_tests ();
 extern void tree_diagnostic_path_cc_tests ();
 extern void tristate_cc_tests ();
 extern void typed_splay_tree_c_tests ();
-extern void unique_ptr_tests_cc_tests ();
 extern void vec_c_tests ();
 extern void vec_perm_indices_c_tests ();
 extern void wide_int_cc_tests ();
diff --git a/gcc/system.h b/gcc/system.h
index 4ac656c9c3c..2cd201743c3 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -737,12 +737,10 @@ extern int vsnprintf (char *, size_t, const char *, va_list);
 
 /* Some of the headers included by <memory> can use "abort" within a
    namespace, e.g. "_VSTD::abort();", which fails after we use the
-   preprocessor to redefine "abort" as "fancy_abort" below.
-   Given that unique-ptr.h can use "free", we need to do this after "free"
-   is declared but before "abort" is overridden.  */
+   preprocessor to redefine "abort" as "fancy_abort" below.  */
 
-#ifdef INCLUDE_UNIQUE_PTR
-# include "unique-ptr.h"
+#ifdef INCLUDE_MEMORY
+# include <memory>
 #endif
 
 #ifdef INCLUDE_MALLOC_H
diff --git a/gcc/unique-ptr-tests.cc b/gcc/unique-ptr-tests.cc
deleted file mode 100644
index 975dd57398e..00000000000
--- a/gcc/unique-ptr-tests.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-/* 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 */
diff --git a/include/unique-ptr.h b/include/unique-ptr.h
deleted file mode 100644
index d1b2ba5b62d..00000000000
--- a/include/unique-ptr.h
+++ /dev/null
@@ -1,405 +0,0 @@
-/* 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 */
-- 
2.31.1



More information about the Gcc-patches mailing list