From: Jonathan Wakely Date: Tue, 7 Aug 2018 22:50:15 +0000 (+0100) Subject: Add workaround for aligned_alloc bug on AIX X-Git-Tag: releases/gcc-7.4.0~228 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2d762245d712fda04c73b7f528f4aad3e18a5fd;p=thirdparty%2Fgcc.git 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 * 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. From-SVN: r263375 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a332654893f8..563959f79f64 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -3,6 +3,13 @@ Backport from mainline 2018-07-30 Jonathan Wakely + * 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 + 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 e2a0d2f53719..1bb1d05e68f2 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 000000000000..8e77422a2b2d --- /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++1z } } + +#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(); +}