diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-08-07 17:10:29 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-08-07 17:10:29 +0100 |
commit | 1d1b732865a2dd3a97b8a8e605d7c5906ab0df0e (patch) | |
tree | 2eca860ce69658e282f224ed7764199fd83d39ba | |
parent | e81c3c1e9cc642160749ad7a0577e1d18698438e (diff) | |
download | gcc-1d1b732865a2dd3a97b8a8e605d7c5906ab0df0e.zip gcc-1d1b732865a2dd3a97b8a8e605d7c5906ab0df0e.tar.gz gcc-1d1b732865a2dd3a97b8a8e605d7c5906ab0df0e.tar.bz2 |
PR libstdc++/86861 Meet precondition for Solaris memalign
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 10 | ||||
-rw-r--r-- | libstdc++-v3/libsupc++/new_opa.cc | 28 |
2 files changed, 29 insertions, 9 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5f098c8..ce410ed 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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. diff --git a/libstdc++-v3/libsupc++/new_opa.cc b/libstdc++-v3/libsupc++/new_opa.cc index 7c4bb79..5be0cc2 100644 --- a/libstdc++-v3/libsupc++/new_opa.cc +++ b/libstdc++-v3/libsupc++/new_opa.cc @@ -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 |