This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR65122 extended alignment support in allocators


Now that the warning in PR77742 is fixed we can make std::allocator
use aligned new for types with extended alignment.

This only changes the allocators that actually allocate memory
themselves.  The others (array, extptr, the testsuite ones) don't need
any changes because they simply forward (de)allocate calls to an
underlying allocator such as std::allocator, so if the underlying one
works then they will too.

The default, new_allocator, is straightforward because it always uses
new/delete so can just use aligned new/delete as needed. For bitmap,
mt and pool I made them always use aligned new/delete for types with
extended alignment (they already fallback on new/delete for types that
exceed some maximum size, so this isn't so different).

For malloc_allocator I've used aligned_alloc if available. If not then
it tries malloc, but throws bad_alloc if malloc returns memory that
isn't suitably aligned for the type. That means it will work
_sometimes_ but not reliably. We could reproduce the logic from
libsupc++/new_opa.cc and try alternatives to aligned_alloc, but I'm
not sure how many people care about malloc_allocator enough to bother.

	PR libstdc++/65122
	* include/ext/malloc_allocator.h (malloc_allocator::allocate): Use
	aligned_alloc for types with extended alignment if available,
	otherwise throw bad_alloc if malloc doesn't return a suitable value.
	* include/ext/bitmap_allocator.h (bitmap_allocator::allocate)
	(bitmap_allocator::deallocate): Use aligned new/delete for types with
	extended alignment.
	* include/ext/mt_allocator.h (__mt_alloc::allocate)
	(__mt_alloc::deallocate): Likewise.
	* include/ext/new_allocator.h (new_allocator::allocate)
	(new_allocator::deallocate): Likewise.
	* include/ext/pool_allocator.h (__pool_alloc::allocate)
	(__pool_alloc::deallocate): Likewise.
	* testsuite/20_util/allocator/overaligned.cc: New test.
	* testsuite/ext/bitmap_allocator/overaligned.cc: New test.
	* testsuite/ext/malloc_allocator/overaligned.cc: New test.
	* testsuite/ext/mt_allocator/overaligned.cc: New test.
	* testsuite/ext/new_allocator/overaligned.cc: New test.
	* testsuite/ext/pool_allocator/overaligned.cc: New test.

Tested powerpc64le-linux, committed to trunk.

commit 2d18ef0170407ce280235e8a37d95b8b0001d73c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Sep 27 16:42:25 2016 +0100

    PR65122 extended alignment support in allocators
    
    	PR libstdc++/65122
    	* include/ext/malloc_allocator.h (malloc_allocator::allocate): Use
    	aligned_alloc for types with extended alignment if available,
    	otherwise throw bad_alloc if malloc doesn't return a suitable value.
    	* include/ext/bitmap_allocator.h (bitmap_allocator::allocate)
    	(bitmap_allocator::deallocate): Use aligned new/delete for types with
    	extended alignment.
    	* include/ext/mt_allocator.h (__mt_alloc::allocate)
    	(__mt_alloc::deallocate): Likewise.
    	* include/ext/new_allocator.h (new_allocator::allocate)
    	(new_allocator::deallocate): Likewise.
    	* include/ext/pool_allocator.h (__pool_alloc::allocate)
    	(__pool_alloc::deallocate): Likewise.
    	* testsuite/20_util/allocator/overaligned.cc: New test.
    	* testsuite/ext/bitmap_allocator/overaligned.cc: New test.
    	* testsuite/ext/malloc_allocator/overaligned.cc: New test.
    	* testsuite/ext/mt_allocator/overaligned.cc: New test.
    	* testsuite/ext/new_allocator/overaligned.cc: New test.
    	* testsuite/ext/pool_allocator/overaligned.cc: New test.

diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h
index c7fbd3e..836abc8 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -1018,6 +1018,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__n > this->max_size())
 	  std::__throw_bad_alloc();
 
+#if __cpp_aligned_new
+	if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	  {
+	    const size_type __b = __n * sizeof(value_type);
+	    std::align_val_t __al = std::align_val_t(alignof(value_type));
+	    return static_cast<pointer>(::operator new(__b, __al));
+	  }
+#endif
+
 	if (__builtin_expect(__n == 1, true))
 	  return this->_M_allocate_single_object();
 	else
@@ -1036,6 +1045,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       {
 	if (__builtin_expect(__p != 0, true))
 	  {
+#if __cpp_aligned_new
+	    // Types with extended alignment are handled by operator delete.
+	    if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	      {
+		::operator delete(__p, std::align_val_t(alignof(value_type)));
+		return;
+	      }
+#endif
+
 	    if (__builtin_expect(__n == 1, true))
 	      this->_M_deallocate_single_object(__p);
 	    else
diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h
index 5c32eab..acb60a2 100644
--- a/libstdc++-v3/include/ext/malloc_allocator.h
+++ b/libstdc++-v3/include/ext/malloc_allocator.h
@@ -30,6 +30,7 @@
 #define _MALLOC_ALLOCATOR_H 1
 
 #include <cstdlib>
+#include <cstddef>
 #include <new>
 #include <bits/functexcept.h>
 #include <bits/move.h>
@@ -100,9 +101,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__n > this->max_size())
 	  std::__throw_bad_alloc();
 
-	pointer __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp)));
+	pointer __ret;
+#if __cpp_aligned_new
+#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC
+	if (alignof(_Tp) > alignof(std::max_align_t))
+	  {
+	    __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp),
+						      __n * sizeof(_Tp)));
+	  }
+#else
+# define _GLIBCXX_CHECK_MALLOC_RESULT
+#endif
+#endif
+	if (!__ret)
+	  __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp)));
 	if (!__ret)
 	  std::__throw_bad_alloc();
+#ifdef _GLIBCXX_CHECK_MALLOC_RESULT
+#undef _GLIBCXX_CHECK_MALLOC_RESULT
+	  if (reinterpret_cast<std::size_t>(__ret) % alignof(_Tp))
+	    {
+	      // Memory returned by malloc is not suitably aligned for _Tp.
+	      deallocate(__ret, __n);
+	      std::__throw_bad_alloc();
+	    }
+#endif
 	return __ret;
       }
 
diff --git a/libstdc++-v3/include/ext/mt_allocator.h b/libstdc++-v3/include/ext/mt_allocator.h
index 7016e48..d7ea7c1 100644
--- a/libstdc++-v3/include/ext/mt_allocator.h
+++ b/libstdc++-v3/include/ext/mt_allocator.h
@@ -691,6 +691,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (__n > this->max_size())
 	std::__throw_bad_alloc();
 
+#if __cpp_aligned_new
+      // Types with extended alignment are handled by operator new/delete.
+      if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	{
+	  std::align_val_t __al = std::align_val_t(alignof(_Tp));
+	  return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
+	}
+#endif
+
       __policy_type::_S_initialize_once();
 
       // Requests larger than _M_max_bytes are handled by operator
@@ -737,6 +746,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       if (__builtin_expect(__p != 0, true))
 	{
+#if __cpp_aligned_new
+	  // Types with extended alignment are handled by operator new/delete.
+	  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	    {
+	      ::operator delete(__p, std::align_val_t(alignof(_Tp)));
+	      return;
+	    }
+#endif
+
 	  // Requests larger than _M_max_bytes are handled by
 	  // operators new/delete directly.
 	  __pool_type& __pool = __policy_type::_S_get_pool();
diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h
index dd00b73..2ff4780 100644
--- a/libstdc++-v3/include/ext/new_allocator.h
+++ b/libstdc++-v3/include/ext/new_allocator.h
@@ -101,13 +101,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__n > this->max_size())
 	  std::__throw_bad_alloc();
 
+#if __cpp_aligned_new
+	if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	  {
+	    std::align_val_t __al = std::align_val_t(alignof(_Tp));
+	    return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al));
+	  }
+#endif
 	return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
       }
 
       // __p is not permitted to be a null pointer.
       void
       deallocate(pointer __p, size_type)
-      { ::operator delete(__p); }
+      {
+#if __cpp_aligned_new
+	if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	  {
+	    ::operator delete(__p, std::align_val_t(alignof(_Tp)));
+	    return;
+	  }
+#endif
+	::operator delete(__p);
+      }
 
       size_type
       max_size() const _GLIBCXX_USE_NOEXCEPT
diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h
index ee60e90..9e0511d 100644
--- a/libstdc++-v3/include/ext/pool_allocator.h
+++ b/libstdc++-v3/include/ext/pool_allocator.h
@@ -219,6 +219,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  if (__n > this->max_size())
 	    std::__throw_bad_alloc();
 
+	  const size_t __bytes = __n * sizeof(_Tp);
+
+#if __cpp_aligned_new
+	  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	    {
+	      std::align_val_t __al = std::align_val_t(alignof(_Tp));
+	      return static_cast<_Tp*>(::operator new(__bytes, __al));
+	    }
+#endif
+
 	  // If there is a race through here, assume answer from getenv
 	  // will resolve in same direction.  Inspired by techniques
 	  // to efficiently support threading found in basic_string.h.
@@ -230,7 +240,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		__atomic_add_dispatch(&_S_force_new, -1);
 	    }
 
-	  const size_t __bytes = __n * sizeof(_Tp);	      
 	  if (__bytes > size_t(_S_max_bytes) || _S_force_new > 0)
 	    __ret = static_cast<_Tp*>(::operator new(__bytes));
 	  else
@@ -259,6 +268,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       if (__builtin_expect(__n != 0 && __p != 0, true))
 	{
+#if __cpp_aligned_new
+	  if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+	    {
+	      ::operator delete(__p, std::align_val_t(alignof(_Tp)));
+	      return;
+	    }
+#endif
 	  const size_t __bytes = __n * sizeof(_Tp);
 	  if (__bytes > static_cast<size_t>(_S_max_bytes) || _S_force_new > 0)
 	    ::operator delete(__p);
diff --git a/libstdc++-v3/testsuite/20_util/allocator/overaligned.cc b/libstdc++-v3/testsuite/20_util/allocator/overaligned.cc
new file mode 100644
index 0000000..384d1d2
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/allocator/overaligned.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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.
+
+// This library 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 library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-faligned-new" }
+// { dg-do run { target c++11 } }
+
+#include <memory>
+#include <cstddef>
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t align = alignof(std::max_align_t) * 4;
+
+struct X {
+  alignas(align) char c;
+};
+
+void
+test01()
+{
+  std::allocator<X> a;
+  X* p1 = a.allocate(1);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+  a.deallocate(p1, 1);
+  X* p2 = a.allocate(20);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+  a.deallocate(p2, 20);
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc
new file mode 100644
index 0000000..7d365de
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/bitmap_allocator/overaligned.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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.
+
+// This library 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 library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-faligned-new" }
+// { dg-do run { target c++11 } }
+
+#include <ext/bitmap_allocator.h>
+#include <cstddef>
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t align = alignof(std::max_align_t) * 4;
+
+struct X {
+  alignas(align) char c;
+};
+
+void
+test01()
+{
+  __gnu_cxx::bitmap_allocator<X> a;
+  X* p1 = a.allocate(1);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+  a.deallocate(p1, 1);
+  X* p2 = a.allocate(20);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+  a.deallocate(p2, 20);
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc
new file mode 100644
index 0000000..87182f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/malloc_allocator/overaligned.cc
@@ -0,0 +1,68 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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.
+
+// This library 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 library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-faligned-new" }
+// { dg-do run { target c++11 } }
+
+#include <ext/malloc_allocator.h>
+#include <cstddef>
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t align = alignof(std::max_align_t) * 2;
+
+struct X {
+  alignas(align) char c;
+};
+
+void
+test01()
+{
+  __gnu_cxx::malloc_allocator<X> a;
+#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC
+  X* p1 = a.allocate(1);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+  a.deallocate(p1, 1);
+  X* p2 = a.allocate(20);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+  a.deallocate(p2, 20);
+#else
+  // Allocating for extended alignment is unreliable without aligned_alloc()
+  try
+  {
+    X* p1 = a.allocate(1);
+    VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+    a.deallocate(p1, 1);
+  }
+  catch (const std::bad_alloc&)
+  { }
+  try
+  {
+    X* p2 = a.allocate(20);
+    VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+    a.deallocate(p2, 20);
+  }
+  catch (const std::bad_alloc&)
+  { }
+#endif
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc
new file mode 100644
index 0000000..41b8b46
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/overaligned.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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.
+
+// This library 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 library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-faligned-new" }
+// { dg-do run { target c++11 } }
+
+#include <ext/mt_allocator.h>
+#include <cstddef>
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t align = alignof(std::max_align_t) * 4;
+
+struct X {
+  alignas(align) char c;
+};
+
+void
+test01()
+{
+  __gnu_cxx::__mt_alloc<X> a;
+  X* p1 = a.allocate(1);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+  a.deallocate(p1, 1);
+  X* p2 = a.allocate(20);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+  a.deallocate(p2, 20);
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc
new file mode 100644
index 0000000..27413cf
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/new_allocator/overaligned.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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.
+
+// This library 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 library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-faligned-new" }
+// { dg-do run { target c++11 } }
+
+#include <ext/new_allocator.h>
+#include <cstddef>
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t align = alignof(std::max_align_t) * 4;
+
+struct X {
+  alignas(align) char c;
+};
+
+void
+test01()
+{
+  __gnu_cxx::new_allocator<X> a;
+  X* p1 = a.allocate(1);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+  a.deallocate(p1, 1);
+  X* p2 = a.allocate(20);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+  a.deallocate(p2, 20);
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc b/libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc
new file mode 100644
index 0000000..b509b79
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/pool_allocator/overaligned.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2016 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library 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.
+
+// This library 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 library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-faligned-new" }
+// { dg-do run { target c++11 } }
+
+#include <ext/pool_allocator.h>
+#include <cstddef>
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr std::size_t align = alignof(std::max_align_t) * 4;
+
+struct X {
+  alignas(align) char c;
+};
+
+void
+test01()
+{
+  __gnu_cxx::__pool_alloc<X> a;
+  X* p1 = a.allocate(1);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p1) % align) == 0 );
+  a.deallocate(p1, 1);
+  X* p2 = a.allocate(20);
+  VERIFY( (reinterpret_cast<std::uintptr_t>(p2) % align) == 0 );
+  a.deallocate(p2, 20);
+}
+
+int
+main()
+{
+  test01();
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]