Implement P0035R4 -- Add C++17 aligned allocation functions

Summary:
This patch implements the library side of P0035R4. The implementation is thanks to @rsmith.

In addition to the C++17 implementation, the library implementation can be explicitly turned on using `-faligned-allocation` in all dialects.


Reviewers: mclow.lists, rsmith

Subscribers: rsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D25591

llvm-svn: 284206
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 0ae4f23fdcd8a278c58ea3ae2f062220763bcb66
diff --git a/src/new.cpp b/src/new.cpp
index d5db461..8e002d4 100644
--- a/src/new.cpp
+++ b/src/new.cpp
@@ -39,10 +39,7 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void *
-operator new(std::size_t size)
-#if !__has_feature(cxx_noexcept)
-    throw(std::bad_alloc)
-#endif
+operator new(std::size_t size) _THROW_BAD_ALLOC
 {
     if (size == 0)
         size = 1;
@@ -65,6 +62,34 @@
 }
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void *
+operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
+{
+    if (size == 0)
+        size = 1;
+    if (static_cast<size_t>(alignment) < sizeof(void*))
+      alignment = std::align_val_t(sizeof(void*));
+    void* p;
+    while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
+    {
+        // If posix_memalign fails and there is a new_handler,
+        // call it to try free up memory.
+        std::new_handler nh = std::get_new_handler();
+        if (nh)
+            nh();
+        else {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+            throw std::bad_alloc();
+#else
+            p = nullptr; // posix_memalign doesn't initialize 'p' on failure
+            break;
+#endif
+        }
+    }
+    return p;
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void*
 operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
 {
@@ -85,16 +110,39 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void*
-operator new[](size_t size)
-#if !__has_feature(cxx_noexcept)
-    throw(std::bad_alloc)
-#endif
+operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+    void* p = 0;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        p = ::operator new(size, alignment);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+    return p;
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void*
+operator new[](size_t size) _THROW_BAD_ALLOC
 {
     return ::operator new(size);
 }
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void*
+operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
+{
+    return ::operator new(size, alignment);
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void*
 operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
 {
     void* p = 0;
@@ -113,6 +161,25 @@
 }
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void*
+operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+    void* p = 0;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try
+    {
+#endif  // _LIBCPP_NO_EXCEPTIONS
+        p = ::operator new[](size, alignment);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+    }
+#endif  // _LIBCPP_NO_EXCEPTIONS
+    return p;
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void
 operator delete(void* ptr) _NOEXCEPT
 {
@@ -122,6 +189,14 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void
+operator delete(void* ptr, std::align_val_t) _NOEXCEPT
+{
+    if (ptr)
+        ::free(ptr);
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void
 operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
 {
     ::operator delete(ptr);
@@ -129,6 +204,13 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void
+operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+    ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void
 operator delete(void* ptr, size_t) _NOEXCEPT
 {
     ::operator delete(ptr);
@@ -136,6 +218,13 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void
+operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
+{
+    ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void
 operator delete[] (void* ptr) _NOEXCEPT
 {
     ::operator delete(ptr);
@@ -143,6 +232,13 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void
+operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
+{
+    ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void
 operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
 {
     ::operator delete[](ptr);
@@ -150,11 +246,25 @@
 
 _LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
 void
+operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+{
+    ::operator delete[](ptr, alignment);
+}
+
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void
 operator delete[] (void* ptr, size_t) _NOEXCEPT
 {
     ::operator delete[](ptr);
 }
 
+_LIBCPP_WEAK _LIBCPP_NEW_DELETE_VIS
+void
+operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
+{
+    ::operator delete[](ptr, alignment);
+}
+
 #endif // !__GLIBCXX__
 
 namespace std