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
This commit is contained in:
Jonathan Wakely 2018-08-07 17:10:29 +01:00 committed by Jonathan Wakely
parent e81c3c1e9c
commit 1d1b732865
2 changed files with 29 additions and 9 deletions

View 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.

View 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