From patchwork Fri Oct 14 12:03:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 682234 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3swR9B0VnNz9rxw for ; Fri, 14 Oct 2016 23:04:29 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=n8IXZ/mR; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=nj+pCtjmZBsaCmXGrGS5hoP5QSzQvOMczbSt4aWCD16Nv+WkZlckZ WPapuTjQf8RSVfQ7tuG78YBdEP7mV4spEQP99ygTSCgLqGYxWrZdIj1h1niyqwvr 7gjtwqoJm9yNhdn4s+4z56QUDBsUsmNdiTVqNSSYIxYixIIA23FA9Q= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=+Bv7oxcDw2jFIwAK1IUmO6XI0Gk=; b=n8IXZ/mR1RyN4AZ99uLR QPBfbPr1Az4ebgB07ziVp6zN7zCRRDKmrQ+1qrOA3eWa7WztDwuMqdledjajf/wg KM8fkcwuAKfN3Rp72hfkHpJcOwAK21Ily7GrY/Alw6lt9Ur47dU5Yo52eEk8ST+d 1zKQRECc5dDdgliw3/Qoi3E= Received: (qmail 116117 invoked by alias); 14 Oct 2016 12:03:59 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 113739 invoked by uid 89); 14 Oct 2016 12:03:57 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=30, 6, __p, bad_alloc, 1009 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 14 Oct 2016 12:03:47 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D596B81138; Fri, 14 Oct 2016 12:03:45 +0000 (UTC) Received: from localhost (ovpn-116-70.ams2.redhat.com [10.36.116.70]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u9EC3i1r008177; Fri, 14 Oct 2016 08:03:45 -0400 Date: Fri, 14 Oct 2016 13:03:44 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] PR65122 extended alignment support in allocators Message-ID: <20161014120344.GE2922@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Clacks-Overhead: GNU Terry Pratchett User-Agent: Mutt/1.7.0 (2016-08-17) 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 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(::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 +#include #include #include #include @@ -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(__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(_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 +// . + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include +#include +#include +#include + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + std::allocator a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(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 +// . + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include +#include +#include +#include + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::bitmap_allocator a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(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 +// . + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include +#include +#include +#include + +constexpr std::size_t align = alignof(std::max_align_t) * 2; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::malloc_allocator a; +#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(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(p1) % align) == 0 ); + a.deallocate(p1, 1); + } + catch (const std::bad_alloc&) + { } + try + { + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(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 +// . + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include +#include +#include +#include + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::__mt_alloc a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(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 +// . + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include +#include +#include +#include + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::new_allocator a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(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 +// . + +// { dg-options "-faligned-new" } +// { dg-do run { target c++11 } } + +#include +#include +#include +#include + +constexpr std::size_t align = alignof(std::max_align_t) * 4; + +struct X { + alignas(align) char c; +}; + +void +test01() +{ + __gnu_cxx::__pool_alloc a; + X* p1 = a.allocate(1); + VERIFY( (reinterpret_cast(p1) % align) == 0 ); + a.deallocate(p1, 1); + X* p2 = a.allocate(20); + VERIFY( (reinterpret_cast(p2) % align) == 0 ); + a.deallocate(p2, 20); +} + +int +main() +{ + test01(); +}