aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2017-01-26 14:30:45 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2017-01-26 14:30:45 +0000
commitbc9efeab61120db9c282def38dd1a052de69f610 (patch)
treeaef51adb0dc768bece17a84b975f87f079e9ca93
parentb5f75f0b64a5692ebe823fffcf6d3a8c82c52d10 (diff)
downloadgcc-bc9efeab61120db9c282def38dd1a052de69f610.zip
gcc-bc9efeab61120db9c282def38dd1a052de69f610.tar.gz
gcc-bc9efeab61120db9c282def38dd1a052de69f610.tar.bz2
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
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/aligned-new3.C5
-rw-r--r--libstdc++-v3/ChangeLog13
-rw-r--r--libstdc++-v3/libsupc++/del_opa.cc8
-rw-r--r--libstdc++-v3/libsupc++/new_opa.cc29
5 files changed, 56 insertions, 5 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4054dd0..79c7295 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-01-26 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/79190
+ * g++.dg/cpp1z/aligned-new3.C: Replace operator new so behaviour
+ matches replaced operator delete.
+
2017-01-26 Jakub Jelinek <jakub@redhat.com>
* 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 73e3343..e50e62c 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 c70aade..2fc38c9 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,16 @@
+2017-01-26 Jonathan Wakely <jwakely@redhat.com>
+
+ 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 <jakub@redhat.com>
* libsupc++/eh_atomics.h: Update copyright years.
diff --git a/libstdc++-v3/libsupc++/del_opa.cc b/libstdc++-v3/libsupc++/del_opa.cc
index c9afb46..f7bf7a4 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 0bc2b5f..e2a0d2f 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 <stdint.h>
+// 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