PR libstdc++/86861 Meet precondition for Solaris memalign
authorJonathan Wakely <jwakely@redhat.com>
Tue, 7 Aug 2018 16:10:29 +0000 (17:10 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 7 Aug 2018 16:10:29 +0000 (17:10 +0100)
Solaris memalign requires alignment to be at least sizeof(int), so
increase it as needed.

Also move the check for valid alignments from the fallback
implementation of aligned_alloc into operator new, as it's required for
all of aligned_alloc, memalign, posix_memalign and __aligned_malloc.
This adds a branch to check for undefined behaviour which we could just
ignore, so the check could just be removed. It should certainly be
removed if PR 86878 is implemented to issue a warning about calls with
invalid alignments.

PR libstdc++/86861
* libsupc++/new_opa.cc [_GLIBCXX_HAVE_MEMALIGN] (aligned_alloc):
Replace macro with inline function.
[__sun]: Increase alignment to meet memalign precondition.
[!HAVE__ALIGNED_MALLOC && !HAVE_POSIX_MEMALIGN && !HAVE_MEMALIGN]
(aligned_alloc): Move check for valid alignment to operator new.
Remove redundant check for non-zero size, it's enforced by the caller.
(operator new): Move check for valid alignment here. Use
__builtin_expect on check for zero size.

From-SVN: r263360

libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/new_opa.cc

index 5f098c87e4051f5b1a136426683c84b007ce6898..ce410ed2e0df95adc083d03703d0fad5beec0a38 100644 (file)
@@ -1,5 +1,15 @@
 2018-08-07  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/86861
+       * libsupc++/new_opa.cc [_GLIBCXX_HAVE_MEMALIGN] (aligned_alloc):
+       Replace macro with inline function.
+       [__sun]: Increase alignment to meet memalign precondition.
+       [!HAVE__ALIGNED_MALLOC && !HAVE_POSIX_MEMALIGN && !HAVE_MEMALIGN]
+       (aligned_alloc): Move check for valid alignment to operator new.
+       Remove redundant check for non-zero size, it's enforced by the caller.
+       (operator new): Move check for valid alignment here. Use
+       __builtin_expect on check for zero size.
+
        * config/abi/pre/gnu.ver: Export monotonic_buffer_resource members.
        * include/std/memory_resource (monotonic_buffer_resource::release):
        Call _M_release_buffers to free buffers.
index 7c4bb79cdab798cd2936fe229aba050c5769865d..5be0cc2ca6516d86f19e25f40575f2a9245adebc 100644 (file)
@@ -39,6 +39,7 @@ static inline void*
 aligned_alloc (std::size_t al, std::size_t sz)
 {
   void *ptr;
+  // posix_memalign has additional requirement, not present on aligned_alloc:
   // The value of alignment shall be a power of two multiple of sizeof(void *).
   if (al < sizeof(void*))
     al = sizeof(void*);
@@ -53,20 +54,24 @@ aligned_alloc (std::size_t al, std::size_t sz)
 #else
 extern "C" void *memalign(std::size_t boundary, std::size_t size);
 #endif
-#define aligned_alloc memalign
-#else
+static inline void*
+aligned_alloc (std::size_t al, std::size_t sz)
+{
+#ifdef __sun
+  // Solaris 10 memalign requires that alignment is greater than or equal to
+  // the size of a word.
+  if (al < sizeof(int))
+    al = sizeof(int);
+#endif
+  return memalign (al, sz);
+}
+#else // !HAVE__ALIGNED_MALLOC && !HAVE_POSIX_MEMALIGN && !HAVE_MEMALIGN
 #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*);
@@ -90,8 +95,13 @@ operator new (std::size_t sz, std::align_val_t al)
   void *p;
   std::size_t align = (std::size_t)al;
 
+  /* Alignment must be a power of two.  */
+  /* XXX This should be checked by the compiler (PR 86878).  */
+  if (__builtin_expect (align & (align - 1), false))
+    _GLIBCXX_THROW_OR_ABORT(bad_alloc());
+
   /* malloc (0) is unpredictable; avoid it.  */
-  if (sz == 0)
+  if (__builtin_expect (sz == 0, false))
     sz = 1;
 
 #if _GLIBCXX_HAVE_ALIGNED_ALLOC