commit 8f66f02efa907dbcd3b88a761a4106e4f0354ccd Author: Jonathan Wakely Date: Mon Jul 30 11:47:19 2018 +0100 Add workaround for aligned_alloc bug on AIX 20_util/memory_resource/2.cc FAILs on AIX 7.2.0.0, because 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. * 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. diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc index 097280d9b54..7c4bb79cdab 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..a9f539d36e8 --- /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 +// . + +// { dg-options "-std=gnu++17" } +// { dg-do run { target c++17 } } + +#include +#include +#include + +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(); +}