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();
+}
