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

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@284206 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/new b/include/new
index e77d3e6..c42ea08 100644
--- a/include/new
+++ b/include/new
@@ -27,18 +27,19 @@
     virtual const char* what() const noexcept;
 };
 
-class bad_array_length : public bad_alloc // C++14
+class bad_array_length : public bad_alloc // FIXME: Not part of C++
 {
 public:
     bad_array_length() noexcept;
 };
 
-class bad_array_new_length : public bad_alloc
+class bad_array_new_length : public bad_alloc // C++14
 {
 public:
     bad_array_new_length() noexcept;
 };
 
+enum class align_val_t : size_t {}; // C++17
 struct nothrow_t {};
 extern const nothrow_t nothrow;
 typedef void (*new_handler)();
@@ -48,16 +49,34 @@
 }  // std
 
 void* operator new(std::size_t size);                                   // replaceable
+void* operator new(std::size_t size, std::align_val_t alignment);       // replaceable, C++17
 void* operator new(std::size_t size, const std::nothrow_t&) noexcept;   // replaceable
+void* operator new(std::size_t size, std::align_val_t alignment,
+                   const std::nothrow_t&) noexcept;                     // replaceable, C++17
 void  operator delete(void* ptr) noexcept;                              // replaceable
 void  operator delete(void* ptr, std::size_t size) noexcept;            // replaceable, C++14
+void  operator delete(void* ptr, std::align_val_t alignment) noexcept;  // replaceable, C++17
+void  operator delete(void* ptr, std::size_t size,
+                      std::align_val_t alignment) noexcept;             // replaceable, C++17
 void  operator delete(void* ptr, const std::nothrow_t&) noexcept;       // replaceable
+void  operator delete(void* ptr, std:align_val_t alignment,
+                      const std::nothrow_t&) noexcept;                  // replaceable, C++17
 
 void* operator new[](std::size_t size);                                 // replaceable
+void* operator new[](std::size_t size,
+                     std::align_val_t alignment) noexcept;              // replaceable, C++17
 void* operator new[](std::size_t size, const std::nothrow_t&) noexcept; // replaceable
+void* operator new[](std::size_t size, std::align_val_t alignment,
+                     const std::nothrow_t&) noexcept;                   // replaceable, C++17
 void  operator delete[](void* ptr) noexcept;                            // replaceable
 void  operator delete[](void* ptr, std::size_t size) noexcept;          // replaceable, C++14
+void  operator delete[](void* ptr,
+                        std::align_val_t alignment) noexcept;           // replaceable, C++17
+void  operator delete[](void* ptr, std::size_t size,
+                        std::align_val_t alignment) noexcept;           // replaceable, C++17
 void  operator delete[](void* ptr, const std::nothrow_t&) noexcept;     // replaceable
+void  operator delete[](void* ptr, std::align_val_t alignment,
+                        const std::nothrow_t&) noexcept;                // replaceable, C++17
 
 void* operator new  (std::size_t size, void* ptr) noexcept;
 void* operator new[](std::size_t size, void* ptr) noexcept;
@@ -79,6 +98,16 @@
 #pragma GCC system_header
 #endif
 
+#if !(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
+    (defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309))
+# define _LIBCPP_HAS_NO_SIZED_DEALLOCATION
+#endif
+
+#if !(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER > 14 || \
+    (defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606))
+# define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+#endif
+
 namespace std  // purposefully not using versioning namespace
 {
 
@@ -117,6 +146,14 @@
 
 #endif  // defined(_LIBCPP_BUILDING_NEW) || (_LIBCPP_STD_VER > 11)
 
+#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+#ifndef _LIBCPP_CXX03_LANG
+enum class _LIBCPP_ENUM_VIS align_val_t : size_t { };
+#else
+enum align_val_t { __zero = 0, __max = (size_t)-1 };
+#endif
+#endif
+
 struct _LIBCPP_TYPE_VIS nothrow_t {};
 extern _LIBCPP_FUNC_VIS const nothrow_t nothrow;
 typedef void (*new_handler)();
@@ -131,32 +168,46 @@
 # define _LIBCPP_NEW_DELETE_VIS _LIBCPP_FUNC_VIS
 #endif
 
-_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz)
 #if !__has_feature(cxx_noexcept)
-    throw(std::bad_alloc)
+#define _THROW_BAD_ALLOC throw(std::bad_alloc)
+#else
+#define _THROW_BAD_ALLOC
 #endif
-;
+
+_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz) _THROW_BAD_ALLOC;
 _LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
 _LIBCPP_NEW_DELETE_VIS void  operator delete(void* __p) _NOEXCEPT;
 _LIBCPP_NEW_DELETE_VIS void  operator delete(void* __p, const std::nothrow_t&) _NOEXCEPT;
-#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
-    (defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)
+#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
 _LIBCPP_NEW_DELETE_VIS void  operator delete(void* __p, std::size_t __sz) _NOEXCEPT;
 #endif
 
-_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz)
-#if !__has_feature(cxx_noexcept)
-    throw(std::bad_alloc)
-#endif
-;
+_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz) _THROW_BAD_ALLOC;
 _LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
 _LIBCPP_NEW_DELETE_VIS void  operator delete[](void* __p) _NOEXCEPT;
 _LIBCPP_NEW_DELETE_VIS void  operator delete[](void* __p, const std::nothrow_t&) _NOEXCEPT;
-#if defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \
-    (defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)
+#ifdef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
 _LIBCPP_NEW_DELETE_VIS void  operator delete[](void* __p, std::size_t __sz) _NOEXCEPT;
 #endif
 
+#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
+_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
+_LIBCPP_NEW_DELETE_VIS void* operator new(std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
+_LIBCPP_NEW_DELETE_VIS void  operator delete(void* __p, std::align_val_t) _NOEXCEPT;
+_LIBCPP_NEW_DELETE_VIS void  operator delete(void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
+#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
+_LIBCPP_NEW_DELETE_VIS void  operator delete(void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
+#endif
+
+_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, std::align_val_t) _THROW_BAD_ALLOC;
+_LIBCPP_NEW_DELETE_VIS void* operator new[](std::size_t __sz, std::align_val_t, const std::nothrow_t&) _NOEXCEPT _NOALIAS;
+_LIBCPP_NEW_DELETE_VIS void  operator delete[](void* __p, std::align_val_t) _NOEXCEPT;
+_LIBCPP_NEW_DELETE_VIS void  operator delete[](void* __p, std::align_val_t, const std::nothrow_t&) _NOEXCEPT;
+#ifndef _LIBCPP_HAS_NO_SIZED_DEALLOCATION
+_LIBCPP_NEW_DELETE_VIS void  operator delete[](void* __p, std::size_t __sz, std::align_val_t) _NOEXCEPT;
+#endif
+#endif
+
 inline _LIBCPP_INLINE_VISIBILITY void* operator new  (std::size_t, void* __p) _NOEXCEPT {return __p;}
 inline _LIBCPP_INLINE_VISIBILITY void* operator new[](std::size_t, void* __p) _NOEXCEPT {return __p;}
 inline _LIBCPP_INLINE_VISIBILITY void  operator delete  (void*, void*) _NOEXCEPT {}