From bc9efeab61120db9c282def38dd1a052de69f610 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 26 Jan 2017 14:30:45 +0000 Subject: [PATCH] PR libstdc++/79190 add fallback aligned_alloc implementation libstdc++-v3: PR libstdc++/79190 * libsupc++/del_opa.cc (operator delete(void*, std::align_val_t)) [!_GLIBCXX_HAVE_ALIGNED_ALLOC && !_GLIBCXX_HAVE_POSIX_MEMALIGN && !_GLIBCXX_HAVE_MEMALIGN && !_GLIBCXX_HAVE__ALIGNED_MALLOC]: Retrieve original pointer value allocated by malloc. * libsupc++/new_opa.cc [!_GLIBCXX_HAVE_ALIGNED_ALLOC && !_GLIBCXX_HAVE_POSIX_MEMALIGN && !_GLIBCXX_HAVE_MEMALIGN && !_GLIBCXX_HAVE__ALIGNED_MALLOC] (aligned_alloc(size_t, size_t)): Define, adjusting pointer value allocated by malloc and storing for retrieval by operator delete. gcc/testsuite: PR libstdc++/79190 * g++.dg/cpp1z/aligned-new3.C: Replace operator new so behaviour matches replaced operator delete. From-SVN: r244933 --- gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/g++.dg/cpp1z/aligned-new3.C | 5 ++++ libstdc++-v3/ChangeLog | 13 ++++++++++ libstdc++-v3/libsupc++/del_opa.cc | 8 +++++-- libstdc++-v3/libsupc++/new_opa.cc | 29 ++++++++++++++++++++--- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4054dd0a11a..79c7295963e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-01-26 Jonathan Wakely + + PR libstdc++/79190 + * g++.dg/cpp1z/aligned-new3.C: Replace operator new so behaviour + matches replaced operator delete. + 2017-01-26 Jakub Jelinek * gcc.target/i386/avx512f-kaddw-1.c: Renamed to ... diff --git a/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C index 73e33432542..e50e62c92e1 100644 --- a/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C +++ b/gcc/testsuite/g++.dg/cpp1z/aligned-new3.C @@ -7,6 +7,11 @@ struct alignas(64) A { int i; }; +void* operator new (std::size_t n, std::align_val_t) +{ + return operator new (n); +} + bool deleted = false; void operator delete (void *p, std::size_t, std::align_val_t) { diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c70aadec073..2fc38c97a63 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2017-01-26 Jonathan Wakely + + PR libstdc++/79190 + * libsupc++/del_opa.cc (operator delete(void*, std::align_val_t)) + [!_GLIBCXX_HAVE_ALIGNED_ALLOC && !_GLIBCXX_HAVE_POSIX_MEMALIGN + && !_GLIBCXX_HAVE_MEMALIGN && !_GLIBCXX_HAVE__ALIGNED_MALLOC]: + Retrieve original pointer value allocated by malloc. + * libsupc++/new_opa.cc [!_GLIBCXX_HAVE_ALIGNED_ALLOC + && !_GLIBCXX_HAVE_POSIX_MEMALIGN && !_GLIBCXX_HAVE_MEMALIGN + && !_GLIBCXX_HAVE__ALIGNED_MALLOC] (aligned_alloc(size_t, size_t)): + Define, adjusting pointer value allocated by malloc and storing for + retrieval by operator delete. + 2017-01-26 Jakub Jelinek * libsupc++/eh_atomics.h: Update copyright years. diff --git a/libstdc++-v3/libsupc++/del_opa.cc b/libstdc++-v3/libsupc++/del_opa.cc index c9afb466a79..f7bf7a4a1dc 100644 --- a/libstdc++-v3/libsupc++/del_opa.cc +++ b/libstdc++-v3/libsupc++/del_opa.cc @@ -46,9 +46,13 @@ _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_WEAK_DEFINITION void operator delete(void* ptr, std::align_val_t) _GLIBCXX_USE_NOEXCEPT { -#if !_GLIBCXX_HAVE_ALIGNED_ALLOC && _GLIBCXX_HAVE__ALIGNED_MALLOC +#if _GLIBCXX_HAVE_ALIGNED_ALLOC || _GLIBCXX_HAVE_POSIX_MEMALIGN \ + || _GLIBCXX_HAVE_MEMALIGN + std::free (ptr); +#elif _GLIBCXX_HAVE__ALIGNED_MALLOC _aligned_free (ptr); #else - std::free(ptr); + if (ptr) + std::free (((void **) ptr)[-1]); // See aligned_alloc in new_opa.cc #endif } diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc index 0bc2b5f2328..e2a0d2f5371 100644 --- a/libstdc++-v3/libsupc++/new_opa.cc +++ b/libstdc++-v3/libsupc++/new_opa.cc @@ -55,9 +55,32 @@ extern "C" void *memalign(std::size_t boundary, std::size_t size); #endif #define aligned_alloc memalign #else -// The C library doesn't provide any aligned allocation functions, declare -// aligned_alloc and get a link failure if aligned new is used. -extern "C" void *aligned_alloc(std::size_t, std::size_t); +#include +// The C library doesn't provide any aligned allocation functions, define one. +// This is a modified version of code from gcc/config/i386/gmm_malloc.h +static inline void* +aligned_alloc (std::size_t al, std::size_t sz) +{ + // Alignment must be a power of two. + if (al & (al - 1)) + return nullptr; + else if (!sz) + return nullptr; + + // We need extra bytes to store the original value returned by malloc. + if (al < sizeof(void*)) + al = sizeof(void*); + void* const malloc_ptr = malloc(sz + al); + if (!malloc_ptr) + return nullptr; + // Align to the requested value, leaving room for the original malloc value. + void* const aligned_ptr = (void *) (((uintptr_t) malloc_ptr + al) & -al); + + // Store the original malloc value where it can be found by operator delete. + ((void **) aligned_ptr)[-1] = malloc_ptr; + + return aligned_ptr; +} #endif #endif -- 2.30.2