https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92143

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Thanks for the checking the preprocessor output.

(In reply to Daryl Haresign from comment #4)

> C11 said:
> 
> The aligned_alloc function allocates space for an object whose alignment is
> specified by alignment, whose size is specified by size, and whose value is
> indeterminate. The value of alignment shall be a valid alignment supported
> by the implementation and the value of size shall be an integral multiple of
> alignment.
> 
> So it seems macOS and AIX's implementations are technically conformant.

I disagree.

The code in comment 2 makes two adjustments when we're using C11 aligned_alloc.
The first one is specific to AIX, and increases the alignment to at least
sizeof(void*):

#if _GLIBCXX_HAVE_ALIGNED_ALLOC
# ifdef _AIX
  /* AIX 7.2.0.0 aligned_alloc incorrectly has posix_memalign's requirement
   * that alignment is a multiple of sizeof(void*).  */
  if (align < sizeof(void*))
    align = sizeof(void*);
# endif

This is *not* allowed by POSIX or C11. C11 6.2.8 says "Valid alignments include
only those values returned by an _Alignof expression for fundamental types,
plus an additional implementation-defined set of values, which may be empty.
Every valid alignment shall be a nonnegative integral power of two."

_Alignof(char) and _Alignof(short) and _Alignof(int) are valid alignments
supported by the implementation, and so aligned_alloc is wrong to reject them.

The second part of the code applies to all targets and makes the size
adjustment required by C11:

  /* C11: the value of size shall be an integral multiple of alignment.  */
  sz = (sz + align - 1) & ~(align - 1);
#endif


> Perhaps GCC should determine whether the platform supports alignments less
> than sizeof(void*) when GCC is built, and put a new macro in c++config.h
> (assuming that's how that file is constructed)?

That isn't necessarily possible because GCC could be built on a completely
different system, so we can't run tests reliably. For this specific case I
think the difference between using posix_memalign and aligned_alloc would not
be ABI-breaking, so it would not be a problem if a native compiler used one and
a cross-compiler used the other, but such a solution would mean the
cross-compiler is still broken. So we need to add workarounds on a
target-by-target basis anyway.

The OS X man page does say:

"In addition, aligned_alloc() returns a NULL pointer and sets errno to EINVAL
if size is not an integral multiple of alignment, or if alignment is not a
power of 2 at least as large as sizeof(void*)."

So I'll extend the workaround to apply to OS X too.

Reply via email to