diff options
author | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-08-07 22:50:15 +0000 |
---|---|---|
committer | redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-08-07 22:50:15 +0000 |
commit | cbbf2c54ced008db7b95c893ada427256bc2df03 (patch) | |
tree | af0cf411fb069b990af28f72d67eebe45563ac00 | |
parent | 03340ff1848dec5e0548777cde0a36c02fdd0030 (diff) |
Add workaround for aligned_alloc bug on AIX
On AIX 7.2.0.0 aligned_alloc incorrectly requires the alignment to be a
multiple of sizeof(void*).
This adds a workaround to the operator new overload taking an alignment
value, to increase the alignment (and size) if needed.
Backport from mainline
2018-07-30 Jonathan Wakely <jwakely@redhat.com>
* libsupc++/new_opa.cc (operator new(size_t, align_val_t)): Add
workaround for aligned_alloc bug on AIX.
* testsuite/18_support/new_aligned.cc: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@263375 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libstdc++-v3/ChangeLog | 7 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/new_opa.cc | 6 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/18_support/new_aligned.cc | 119 |
3 files changed, 132 insertions, 0 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a332654893f..563959f79f6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -3,6 +3,13 @@ Backport from mainline 2018-07-30 Jonathan Wakely <jwakely@redhat.com> + * libsupc++/new_opa.cc (operator new(size_t, align_val_t)): Add + workaround for aligned_alloc bug on AIX. + * testsuite/18_support/new_aligned.cc: New test. + + Backport from mainline + 2018-07-30 Jonathan Wakely <jwakely@redhat.com> + PR libstdc++/86734 * include/bits/stl_iterator.h (reverse_iterator::operator->): Use addressof (LWG 2188). diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc index e2a0d2f5371..1bb1d05e68f 100644 --- a/libstdc++-v3/libsupc++/new_opa.cc +++ b/libstdc++-v3/libsupc++/new_opa.cc @@ -95,6 +95,12 @@ operator new (std::size_t sz, std::align_val_t al) sz = 1; #if _GLIBCXX_HAVE_ALIGNED_ALLOC +# ifdef _AIX + /* AIX 7.2.0.0 aligned_alloc incorrectly has posix_memalign's requirement + * that alignment is a multiple of sizeof(void*). */ + if (align < sizeof(void*)) + align = sizeof(void*); +# endif /* C11: the value of size shall be an integral multiple of alignment. */ if (std::size_t rem = sz & (align - 1)) sz += align - rem; diff --git a/libstdc++-v3/testsuite/18_support/new_aligned.cc b/libstdc++-v3/testsuite/18_support/new_aligned.cc new file mode 100644 index 00000000000..8e77422a2b2 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/new_aligned.cc @@ -0,0 +1,119 @@ +// Copyright (C) 2018 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 "-std=gnu++17" } +// { dg-do run { target c++1z } } + +#include <new> +#include <memory> +#include <testsuite_hooks.h> + +struct Test +{ + Test(std::size_t size, std::size_t a) + : size(size), alignment(std::align_val_t{a}), + p(::operator new(size, alignment)) + { } + + ~Test() { ::operator delete(p, size, alignment); } + + std::size_t size; + std::align_val_t alignment; + void* p; + + bool valid() const { return p != nullptr; } + + bool aligned() const + { + auto ptr = p; + auto space = size; + return std::align((std::size_t)alignment, size, ptr, space) == p; + } +}; + +// operator new(size_t size, align_val_t alignment) has +// undefined behaviour if the alignment argument is not +// a valid alignment value (i.e. not a power of two). +// +// Unlike posix_memalign there is no requirement that +// alignment >= sizeof(void*). +// +// Unlike aligned_alloc there is no requirement that +// size is an integer multiple of alignment. + +void +test01() +{ + // Test small values that would not be valid for + // posix_memalign or aligned_alloc. + + Test t11{1, 1}; + VERIFY( t11.valid() ); + VERIFY( t11.aligned() ); + + Test t21{2, 1}; + VERIFY( t21.valid() ); + VERIFY( t21.aligned() ); + + Test t12{1, 2}; + VERIFY( t12.valid() ); + VERIFY( t12.aligned() ); + + Test t22{2, 2}; + VERIFY( t22.valid() ); + VERIFY( t22.aligned() ); + + Test t32{3, 2}; + VERIFY( t32.valid() ); + VERIFY( t32.aligned() ); + + Test t42{4, 2}; + VERIFY( t42.valid() ); + VERIFY( t42.aligned() ); + + Test t24{2, 4}; + VERIFY( t24.valid() ); + VERIFY( t24.aligned() ); + + Test t34{3, 4}; + VERIFY( t34.valid() ); + VERIFY( t34.aligned() ); + + Test t44{4, 4}; + VERIFY( t44.valid() ); + VERIFY( t44.aligned() ); + + // Test some larger values. + + Test t128_16{128, 16}; + VERIFY( t128_16.valid() ); + VERIFY( t128_16.aligned() ); + + Test t128_64{128, 64}; + VERIFY( t128_64.valid() ); + VERIFY( t128_64.aligned() ); + + Test t64_128{64, 128}; + VERIFY( t64_128.valid() ); + VERIFY( t64_128.aligned() ); +} + +int +main() +{ + test01(); +} |