+2016-10-14 Jonathan Wakely <jwakely@redhat.com>
+
+ 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.
+
2016-10-14 Tim Shen <timshen@google.com>
PR libstdc++/77944
- * include/std/variant: include <bits/funcexcept.h> for __try and __catch.
+ * include/std/variant: Include <bits/funcexcept.h> for __try and
+ __catch.
2016-10-14 Jonathan Wakely <jwakely@redhat.com>
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
{
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
#define _MALLOC_ALLOCATOR_H 1
#include <cstdlib>
+#include <cstddef>
#include <new>
#include <bits/functexcept.h>
#include <bits/move.h>
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;
}
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
{
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();
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
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.
__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
{
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);
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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();
+}