PR libstdc++/79190 add fallback aligned_alloc implementation
authorJonathan Wakely <jwakely@redhat.com>
Thu, 26 Jan 2017 14:30:45 +0000 (14:30 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 26 Jan 2017 14:30:45 +0000 (14:30 +0000)
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
gcc/testsuite/g++.dg/cpp1z/aligned-new3.C
libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/del_opa.cc
libstdc++-v3/libsupc++/new_opa.cc

index 4054dd0a11ab37fbacf37131f48e46749d67b955..79c7295963e39c6aee8e58ff0b74b70ef989f7d4 100644 (file)
@@ -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 ...
index 73e33432542b9dfb6ebfe0751b9c96dc1a8b63c0..e50e62c92e13e006652eafe0c4f8f2c37552282e 100644 (file)
@@ -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)
 {
index c70aadec0738a923629aef5d7e8ecb2f82c02070..2fc38c97a639a38e87f00813a149d57d737645ef 100644 (file)
@@ -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.
index c9afb466a7949cae9dc12303ae4eb1abbf414337..f7bf7a4a1dca0f399b66b5beec34e5a8dd352111 100644 (file)
@@ -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
 }
index 0bc2b5f232814d056dbdaeb534d075d8fe9da442..e2a0d2f53719ec94f05305f1e5f038bd43cf1190 100644 (file)
@@ -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