Index: include/new =================================================================== --- include/new +++ 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 {} Index: lib/abi/CHANGELOG.TXT =================================================================== --- lib/abi/CHANGELOG.TXT +++ lib/abi/CHANGELOG.TXT @@ -16,6 +16,22 @@ Version 4.0 ----------- +* rTBD - Implement C++17 aligned allocation in + + x86_64-linux-gnu + ---------------- + Symbol added: posix_memalign@GLIBC_2.2.5 + Symbol added: _ZdaPvSt11align_val_t + Symbol added: _ZdlPvSt11align_val_t + Symbol added: _ZnamSt11align_val_t + Symbol added: _ZdaPvmSt11align_val_t + Symbol added: _ZdlPvmSt11align_val_t + Symbol added: _ZdlPvSt11align_val_tRKSt9nothrow_t + Symbol added: _ZnwmSt11align_val_tRKSt9nothrow_t + Symbol added: _ZnamSt11align_val_tRKSt9nothrow_t + Symbol added: _ZdaPvSt11align_val_tRKSt9nothrow_t + Symbol added: _ZnwmSt11align_val_t + * r283980 - Implement C++17 x86_64-linux-gnu Index: lib/abi/x86_64-linux-gnu.abilist =================================================================== --- lib/abi/x86_64-linux-gnu.abilist +++ lib/abi/x86_64-linux-gnu.abilist @@ -1,60 +1,60 @@ {'type': 'FUNC', 'name': '__cxa_finalize@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'wcsnrtombs@GLIBC_2.2.5'} {'type': 'FUNC', 'name': '_Unwind_Resume@GCC_3.0'} -{'type': 'FUNC', 'name': 'wctob@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'wcsxfrm_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'freelocale@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'iswblank_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'iswalpha_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'iswdigit_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'iswcntrl_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'catclose@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'catgets@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'catopen@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': '__ctype_get_mb_cur_max@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'btowc@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'vsnprintf@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'vasprintf@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'wcscoll_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'towupper_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'uselocale@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'wctob@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'strxfrm_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'wcsnrtombs@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'tolower_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'toupper_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'wcrtomb@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'vsscanf@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'towlower_l@GLIBC_2.3'} {'type': 'FUNC', 'name': '_ZSt9terminatev'} {'type': 'FUNC', 'name': 'strtof_l@GLIBC_2.3'} {'type': 'FUNC', 'name': 'setlocale@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'strtod_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'sscanf@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'strtold_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'strxfrm_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'mbsnrtowcs@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'mbsrtowcs@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'toupper_l@GLIBC_2.3'} {'type': 'FUNC', 'name': 'mbtowc@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'tolower_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'towupper_l@GLIBC_2.3'} -{'type': 'OBJECT', 'name': '_ZTVN10__cxxabiv120__si_class_type_infoE', 'size': 0} -{'type': 'FUNC', 'name': 'towlower_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'localeconv@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'uselocale@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'mbsrtowcs@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'mbsnrtowcs@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'strcoll_l@GLIBC_2.3'} {'type': 'FUNC', 'name': 'mbrtowc@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'wcscoll_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'localeconv@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'strftime_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'strtod_l@GLIBC_2.3'} +{'type': 'OBJECT', 'name': '_ZTVN10__cxxabiv120__si_class_type_infoE', 'size': 0} +{'type': 'FUNC', 'name': 'newlocale@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'iswxdigit_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'sscanf@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'iswprint_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'vsnprintf@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'vsscanf@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'iswlower_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'iswspace_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'wcrtomb@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'iswpunct_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'iswspace_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'catopen@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'catgets@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'iswupper_l@GLIBC_2.3'} {'type': 'FUNC', 'name': '__cxa_atexit@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'iswxdigit_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'iswblank_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'catclose@GLIBC_2.2.5'} {'type': 'FUNC', 'name': '__cxa_begin_catch'} -{'type': 'FUNC', 'name': 'iswupper_l@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'btowc@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'iswcntrl_l@GLIBC_2.3'} {'type': 'FUNC', 'name': '__gxx_personality_v0'} +{'type': 'FUNC', 'name': '__ctype_get_mb_cur_max@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'iswdigit_l@GLIBC_2.3'} {'type': 'FUNC', 'name': 'fflush@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'vasprintf@GLIBC_2.2.5'} +{'type': 'FUNC', 'name': 'iswlower_l@GLIBC_2.3'} {'type': 'FUNC', 'name': 'fwrite@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'getc@GLIBC_2.2.5'} {'type': 'OBJECT', 'name': 'stderr@GLIBC_2.2.5', 'size': 0} -{'type': 'FUNC', 'name': 'newlocale@GLIBC_2.3'} +{'type': 'FUNC', 'name': 'freelocale@GLIBC_2.3'} {'type': 'OBJECT', 'name': 'stdin@GLIBC_2.2.5', 'size': 0} +{'type': 'FUNC', 'name': 'iswalpha_l@GLIBC_2.3'} {'type': 'OBJECT', 'name': 'stdout@GLIBC_2.2.5', 'size': 0} {'type': 'FUNC', 'name': 'ungetc@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'strftime_l@GLIBC_2.3'} -{'type': 'FUNC', 'name': 'strcoll_l@GLIBC_2.3'} {'type': 'FUNC', 'name': '__cxa_guard_acquire'} {'type': 'FUNC', 'name': '__cxa_guard_release'} {'type': 'FUNC', 'name': 'pthread_mutex_lock@GLIBC_2.2.5'} @@ -89,6 +89,7 @@ {'type': 'FUNC', 'name': '_ZSt15get_new_handlerv'} {'type': 'OBJECT', 'name': '_ZTISt9bad_alloc', 'size': 0} {'type': 'FUNC', 'name': '__cxa_end_catch'} +{'type': 'FUNC', 'name': 'posix_memalign@GLIBC_2.2.5'} {'type': 'FUNC', 'name': '__errno_location@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'close@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'open@GLIBC_2.2.5'} @@ -160,8 +161,8 @@ {'type': 'FUNC', 'name': 'pthread_cond_timedwait@GLIBC_2.3.2'} {'type': 'FUNC', 'name': 'pthread_getspecific@GLIBC_2.2.5'} {'type': 'FUNC', 'name': 'pthread_setspecific@GLIBC_2.2.5'} -{'type': 'FUNC', 'name': 'strtoll_l@GLIBC_2.3.3'} {'type': 'FUNC', 'name': 'strtoull_l@GLIBC_2.3.3'} +{'type': 'FUNC', 'name': 'strtoll_l@GLIBC_2.3.3'} {'type': 'FUNC', 'name': '_ZNSt13runtime_errorD1Ev'} {'type': 'FUNC', 'name': '_ZNSt8bad_castC1Ev'} {'type': 'FUNC', 'name': '_ZNSt8bad_castD1Ev'} @@ -319,6 +320,7 @@ {'type': 'FUNC', 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev'} {'type': 'FUNC', 'name': '_ZNSt3__19to_stringEx'} {'type': 'FUNC', 'name': '_ZNKSt3__17num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE23__do_get_floating_pointIdEES4_S4_S4_RNS_8ios_baseERjRT_'} +{'type': 'FUNC', 'name': '_ZdaPvSt11align_val_t'} {'type': 'FUNC', 'name': '_ZNSt3__110to_wstringEi'} {'type': 'FUNC', 'name': '_ZNSt3__19to_stringEy'} {'type': 'FUNC', 'name': '_ZNSt3__17__sort5IRNS_6__lessIjjEEPjEEjT0_S5_S5_S5_S5_T_'} @@ -631,6 +633,7 @@ {'type': 'FUNC', 'name': '_ZNKSt3__114__codecvt_utf8IDiE11do_encodingEv'} {'type': 'FUNC', 'name': '_ZNKSt3__18messagesIwE6do_getEliiRKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEE'} {'type': 'OBJECT', 'name': '_ZTINSt3__114error_categoryE', 'size': 16} +{'type': 'FUNC', 'name': '_ZdlPvSt11align_val_t'} {'type': 'FUNC', 'name': '_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EE'} {'type': 'FUNC', 'name': '_ZNKSt3__115__codecvt_utf16IDsLb0EE13do_max_lengthEv'} {'type': 'OBJECT', 'name': '_ZTINSt3__19money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 56} @@ -649,6 +652,7 @@ {'type': 'OBJECT', 'name': '_ZTSNSt3__116__narrow_to_utf8ILm32EEE', 'size': 34} {'type': 'FUNC', 'name': '_ZNSt3__17promiseIvEC2Ev'} {'type': 'FUNC', 'name': '_ZNKSt3__17num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE17__do_get_unsignedItEES4_S4_S4_RNS_8ios_baseERjRT_'} +{'type': 'FUNC', 'name': '_ZnamSt11align_val_t'} {'type': 'FUNC', 'name': '_ZNKSt3__115__codecvt_utf16IDsLb0EE9do_lengthER11__mbstate_tPKcS5_m'} {'type': 'FUNC', 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_'} {'type': 'FUNC', 'name': '_ZNKSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4copyEPcmm'} @@ -660,6 +664,7 @@ {'type': 'OBJECT', 'name': '_ZTINSt3__19__num_putIcEE', 'size': 40} {'type': 'FUNC', 'name': '_ZNKSt3__114error_category23default_error_conditionEi'} {'type': 'FUNC', 'name': '_ZNSt3__16localeC2EPKc'} +{'type': 'FUNC', 'name': '_ZdaPvmSt11align_val_t'} {'type': 'FUNC', 'name': '_ZNSt3__17codecvtIwc11__mbstate_tED0Ev'} {'type': 'OBJECT', 'name': '_ZTSNSt3__114__shared_countE', 'size': 25} {'type': 'FUNC', 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignERKS5_mm'} @@ -855,6 +860,7 @@ {'type': 'OBJECT', 'name': '_ZNSt3__110ctype_base5alnumE', 'size': 2} {'type': 'OBJECT', 'name': '_ZTCNSt3__110ostrstreamE0_NS_13basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 80} {'type': 'OBJECT', 'name': '_ZTINSt3__117moneypunct_bynameIcLb0EEE', 'size': 24} +{'type': 'FUNC', 'name': '_ZdlPvmSt11align_val_t'} {'type': 'FUNC', 'name': '_ZNSt3__115__thread_struct27__make_ready_at_thread_exitEPNS_17__assoc_sub_stateE'} {'type': 'FUNC', 'name': '_ZNKSt3__120__codecvt_utf8_utf16IDiE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_'} {'type': 'FUNC', 'name': '_ZNSt3__112system_errorD0Ev'} @@ -1114,6 +1120,7 @@ {'type': 'FUNC', 'name': '_ZNSt3__112__next_primeEm'} {'type': 'FUNC', 'name': '_ZNSt3__111__call_onceERVmPvPFvS2_E'} {'type': 'FUNC', 'name': '_ZNSt3__110__time_getC1EPKc'} +{'type': 'FUNC', 'name': '_ZdlPvSt11align_val_tRKSt9nothrow_t'} {'type': 'OBJECT', 'name': '_ZNSt3__16chrono12system_clock9is_steadyE', 'size': 1} {'type': 'FUNC', 'name': '_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERs'} {'type': 'FUNC', 'name': '_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsERt'} @@ -1227,6 +1234,7 @@ {'type': 'FUNC', 'name': '_ZNSt3__115numpunct_bynameIwEC2EPKcm'} {'type': 'FUNC', 'name': '_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE6sentryD2Ev'} {'type': 'FUNC', 'name': '_ZNSt3__15mutexD1Ev'} +{'type': 'FUNC', 'name': '_ZnwmSt11align_val_tRKSt9nothrow_t'} {'type': 'FUNC', 'name': '_ZNSt3__115__thread_structC2Ev'} {'type': 'FUNC', 'name': '_ZNSt3__120__codecvt_utf8_utf16IDsED0Ev'} {'type': 'OBJECT', 'name': '_ZTVNSt3__115basic_streambufIwNS_11char_traitsIwEEEE', 'size': 128} @@ -1313,6 +1321,7 @@ {'type': 'FUNC', 'name': '_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPNS_15basic_streambufIwS2_EE'} {'type': 'OBJECT', 'name': '_ZTINSt3__16locale5facetE', 'size': 24} {'type': 'FUNC', 'name': '_ZNSt13exception_ptrD2Ev'} +{'type': 'FUNC', 'name': '_ZnamSt11align_val_tRKSt9nothrow_t'} {'type': 'OBJECT', 'name': '_ZTSNSt3__115basic_streambufIcNS_11char_traitsIcEEEE', 'size': 49} {'type': 'FUNC', 'name': '_ZNSt3__15mutexD2Ev'} {'type': 'FUNC', 'name': '_ZNSt3__113random_deviceD1Ev'} @@ -1478,6 +1487,7 @@ {'type': 'FUNC', 'name': '_ZNKSt3__112ctype_bynameIwE10do_tolowerEPwPKw'} {'type': 'OBJECT', 'name': '_ZTINSt3__112strstreambufE', 'size': 24} {'type': 'FUNC', 'name': '_ZNKSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE16find_last_not_ofEPKwmm'} +{'type': 'FUNC', 'name': '_ZdaPvSt11align_val_tRKSt9nothrow_t'} {'type': 'FUNC', 'name': '_ZNSt3__119__shared_mutex_base6unlockEv'} {'type': 'FUNC', 'name': '_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE4swapERS3_'} {'type': 'FUNC', 'name': '_ZNSt3__114codecvt_bynameIDic11__mbstate_tED0Ev'} @@ -1734,6 +1744,7 @@ {'type': 'FUNC', 'name': '_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEEC1Ev'} {'type': 'FUNC', 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignERKS5_mm'} {'type': 'FUNC', 'name': '_ZNKSt3__112ctype_bynameIcE10do_toupperEc'} +{'type': 'FUNC', 'name': '_ZnwmSt11align_val_t'} {'type': 'FUNC', 'name': '_ZNKSt3__18time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE16do_get_monthnameES4_S4_RNS_8ios_baseERjP2tm'} {'type': 'FUNC', 'name': '_ZNSt3__116__narrow_to_utf8ILm16EED1Ev'} {'type': 'OBJECT', 'name': '_ZTSNSt3__19__num_getIwEE', 'size': 22} Index: src/new.cpp =================================================================== --- src/new.cpp +++ 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(alignment) < sizeof(void*)) + alignment = std::align_val_t(sizeof(void*)); + void* p; + while (::posix_memalign(&p, static_cast(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 Index: test/libcxx/language.support/support.dynamic/new_faligned_allocation.sh.cpp =================================================================== --- /dev/null +++ test/libcxx/language.support/support.dynamic/new_faligned_allocation.sh.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test libc++'s implementation of align_val_t, and the relevent new/delete +// overloads in all dialects when -faligned-allocation is present. + +// REQUIRES: -faligned-allocation + +// RUN: %build -faligned-allocation +// RUN: %run + +#include +#include +#include +#include + +#include "test_macros.h" + +int main() { + { + static_assert(std::is_enum::value, ""); + typedef std::underlying_type::type UT; + static_assert((std::is_same::value), ""); + } + { + static_assert((!std::is_constructible::value), ""); +#if TEST_STD_VER >= 11 + static_assert(!std::is_constructible::value, ""); +#else + static_assert((std::is_constructible::value), ""); +#endif + } + { + std::align_val_t a = std::align_val_t(0); + std::align_val_t b = std::align_val_t(32); + assert(a != b); + assert(a == std::align_val_t(0)); + assert(b == std::align_val_t(32)); + } + { + void *ptr = ::operator new(1, std::align_val_t(128)); + assert(ptr); + assert(reinterpret_cast(ptr) % 128 == 0); + ::operator delete(ptr, std::align_val_t(128)); + } + { + void *ptr = ::operator new(1, std::align_val_t(128), std::nothrow); + assert(ptr); + assert(reinterpret_cast(ptr) % 128 == 0); + ::operator delete(ptr, std::align_val_t(128), std::nothrow); + } + { + void *ptr = ::operator new[](1, std::align_val_t(128)); + assert(ptr); + assert(reinterpret_cast(ptr) % 128 == 0); + ::operator delete[](ptr, std::align_val_t(128)); + } + { + void *ptr = ::operator new[](1, std::align_val_t(128), std::nothrow); + assert(ptr); + assert(reinterpret_cast(ptr) % 128 == 0); + ::operator delete[](ptr, std::align_val_t(128), std::nothrow); + } +#ifndef TEST_HAS_NO_RTTI + { + // Check that libc++ doesn't define align_val_t in a versioning namespace. + // And that it mangles the same in C++03 through C++17 + assert(typeid(std::align_val_t).name() == std::string("St11align_val_t")); + } +#endif +} \ No newline at end of file Index: test/libcxx/test/config.py =================================================================== --- test/libcxx/test/config.py +++ test/libcxx/test/config.py @@ -313,6 +313,9 @@ if self.cxx.hasCompileFlag('-fsized-deallocation'): self.config.available_features.add('fsized-deallocation') + if self.cxx.hasCompileFlag('-faligned-allocation'): + self.config.available_features.add('-faligned-allocation') + if self.get_lit_bool('has_libatomic', False): self.config.available_features.add('libatomic') Index: test/std/language.support/support.dynamic/align_val_t.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/align_val_t.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// enum class align_val_t : size_t {} + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include + +#include "test_macros.h" + +int main() { + { + static_assert(std::is_enum::value, ""); + static_assert(std::is_same::type, std::size_t>::value, ""); + static_assert(!std::is_constructible::value, ""); + static_assert(!std::is_constructible::value, ""); + } + { + constexpr auto a = std::align_val_t(0); + constexpr auto b = std::align_val_t(32); + constexpr auto c = std::align_val_t(-1); + static_assert(a != b, ""); + static_assert(a == std::align_val_t(0), ""); + static_assert(b == std::align_val_t(32), ""); + static_assert(static_cast(c) == (std::size_t)-1, ""); + } +} \ No newline at end of file Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test aligned operator delete replacement. + +// UNSUPPORTED: sanitizer-new-delete, c++98, c++03, c++11, c++14 + +// Older Clang versions do not support this +// XFAIL: clang-3, apple-clang + +// None of the current GCC compilers support this. +// XFAIL: gcc-4, gcc-5, gcc-6 + +#include +#include +#include +#include + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int unsized_delete_called = 0; +int unsized_delete_nothrow_called = 0; +int aligned_delete_called = 0; + +void reset() { + unsized_delete_called = 0; + unsized_delete_nothrow_called = 0; + aligned_delete_called = 0; +} + +void operator delete(void* p) throw() +{ + ++unsized_delete_called; + std::free(p); +} + +void operator delete(void* p, const std::nothrow_t&) throw() +{ + ++unsized_delete_nothrow_called; + std::free(p); +} + +void operator delete [] (void* p, std::align_val_t a) throw() +{ + ++aligned_delete_called; + std::free(p); +} + +struct alignas(OverAligned) A {}; +struct alignas(std::max_align_t) B {}; + +int main() +{ + { + B *x = new B; + assert(0 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(0 == aligned_delete_called); + + delete x; + assert(1 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(0 == aligned_delete_called); + } + reset(); + { + A *x = new A; + assert(0 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(0 == aligned_delete_called); + + delete x; + assert(0 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(1 == aligned_delete_called); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int new_handler_called = 0; + +void new_handler() +{ + ++new_handler_called; + std::set_new_handler(0); +} + +int A_constructed = 0; + +struct alignas(OverAligned) A +{ + A() { ++A_constructed;} + ~A() { --A_constructed;} +}; + +void test_throw_max_size() { +#ifndef TEST_HAS_NO_EXCEPTIONS + std::set_new_handler(new_handler); + try + { + void* vp = operator new[] (std::numeric_limits::max(), + static_cast(32)); + ((void)vp); + assert(false); + } + catch (std::bad_alloc&) + { + assert(new_handler_called == 1); + } + catch (...) + { + assert(false); + } +#endif +} + +int main() +{ + { + A* ap = new A[2]; + assert(ap); + assert(reinterpret_cast(ap) % OverAligned == 0); + assert(A_constructed == 2); + delete [] ap; + assert(A_constructed == 0); + } + { + test_throw_max_size(); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new (nothrow) + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int new_handler_called = 0; + +void new_handler() +{ + ++new_handler_called; + std::set_new_handler(0); +} + +int A_constructed = 0; + +struct alignas(OverAligned) A +{ + A() { ++A_constructed; } + ~A() { --A_constructed; } +}; + +void test_max_alloc() { + std::set_new_handler(new_handler); + auto do_test = []() { + void* vp = operator new [](std::numeric_limits::max(), + std::align_val_t(OverAligned), + std::nothrow); + assert(new_handler_called == 1); + assert(vp == 0); + }; +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + do_test(); + } + catch (...) + { + assert(false); + } +#else + do_test(); +#endif +} + +int main() +{ + { + A* ap = new(std::nothrow) A[3]; + assert(ap); + assert(reinterpret_cast(ap) % OverAligned == 0); + assert(A_constructed == 3); + delete [] ap; + assert(!A_constructed); + } + { + test_max_alloc(); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new nothrow by replacing only operator new + +// UNSUPPORTED: sanitizer-new-delete + +// TODO Investigate why UBSAN prevents nothrow new from calling our replacement. +// XFAIL: ubsan + +#include +#include +#include +#include +#include + + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int A_constructed = 0; + +struct alignas(OverAligned) A +{ + A() {++A_constructed;} + ~A() {--A_constructed;} +}; + +int B_constructed = 0; + +struct B { + std::max_align_t member; + B() { ++B_constructed; } + ~B() { --B_constructed; } +}; + +int new_called = 0; +alignas(OverAligned) char Buff[OverAligned * 3]; + +void* operator new[](std::size_t s, std::align_val_t a) throw(std::bad_alloc) +{ + assert(!new_called); + assert(s <= sizeof(Buff)); + assert(static_cast(a) == OverAligned); + ++new_called; + return Buff; +} + +void operator delete[](void* p, std::align_val_t a) throw() +{ + assert(p == Buff); + assert(static_cast(a) == OverAligned); + assert(new_called); + --new_called; +} + +int main() +{ + { + A* ap = new (std::nothrow) A[2]; + assert(ap); + assert(A_constructed == 2); + assert(new_called); + delete [] ap; + assert(A_constructed == 0); + assert(!new_called); + } + { + B* bp = new (std::nothrow) B[2]; + assert(bp); + assert(B_constructed == 2); + assert(!new_called); + delete [] bp; + assert(!new_called); + assert(!B_constructed); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_replace.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_replace.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new replacement + +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include +#include +#include + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int A_constructed = 0; + +struct alignas(OverAligned) A { + A() { ++A_constructed;} + ~A() { --A_constructed;} +}; + + +int B_constructed = 0; + +struct alignas(std::max_align_t) B +{ + std::max_align_t member; + B() { ++B_constructed;} + ~B() { --B_constructed;} +}; + +int new_called = 0; + +alignas(OverAligned) char DummyData[OverAligned * 4]; + +void* operator new[](std::size_t s, std::align_val_t a) throw(std::bad_alloc) +{ + assert(new_called == 0); // We already allocated + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == OverAligned); + ++new_called; + return DummyData; +} + +void operator delete[](void* p, std::align_val_t a) throw() +{ + assert(new_called == 1); + --new_called; + assert(p == DummyData); +} + + +int main() +{ + { + A* ap = new A[3]; + assert(ap); + assert(A_constructed == 3); + assert(new_called); + delete [] ap; + assert(!A_constructed); + assert(!new_called); + } + { + B* bp = new B[3]; + assert(bp); + assert(B_constructed == 3); + assert(!new_called); + delete [] bp; + assert(!new_called); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// test aligned operator delete replacement. + +// UNSUPPORTED: sanitizer-new-delete, c++98, c++03, c++11, c++14 + +// Older Clang versions do not support this +// XFAIL: clang-3, apple-clang + +// None of the current GCC compilers support this. +// XFAIL: gcc-4, gcc-5, gcc-6 + +#include +#include +#include +#include + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int unsized_delete_called = 0; +int unsized_delete_nothrow_called = 0; +int aligned_delete_called = 0; + +void reset() { + unsized_delete_called = 0; + unsized_delete_nothrow_called = 0; + aligned_delete_called = 0; +} + +void operator delete(void* p) throw() +{ + ++unsized_delete_called; + std::free(p); +} + +void operator delete(void* p, const std::nothrow_t&) throw() +{ + ++unsized_delete_nothrow_called; + std::free(p); +} + +void operator delete(void* p, std::align_val_t a) throw() +{ + ++aligned_delete_called; + std::free(p); +} + +struct alignas(OverAligned) A {}; +struct alignas(std::max_align_t) B {}; + +int main() +{ + { + B *x = new B; + assert(0 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(0 == aligned_delete_called); + + delete x; + assert(1 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(0 == aligned_delete_called); + } + reset(); + { + A *x = new A; + assert(0 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(0 == aligned_delete_called); + + delete x; + assert(0 == unsized_delete_called); + assert(0 == unsized_delete_nothrow_called); + assert(1 == aligned_delete_called); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int new_handler_called = 0; + +void new_handler() +{ + ++new_handler_called; + std::set_new_handler(0); +} + +bool A_constructed = false; + +struct alignas(OverAligned) A +{ + A() {A_constructed = true;} + ~A() {A_constructed = false;} +}; + +void test_throw_max_size() { +#ifndef TEST_HAS_NO_EXCEPTIONS + std::set_new_handler(new_handler); + try + { + void* vp = operator new (std::numeric_limits::max(), + static_cast(32)); + ((void)vp); + assert(false); + } + catch (std::bad_alloc&) + { + assert(new_handler_called == 1); + } + catch (...) + { + assert(false); + } +#endif +} + +int main() +{ + { + A* ap = new A; + assert(ap); + assert(reinterpret_cast(ap) % OverAligned == 0); + assert(A_constructed); + delete ap; + assert(!A_constructed); + } + { + test_throw_max_size(); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new (nothrow) + +// asan and msan will not call the new handler. +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +int new_handler_called = 0; + +void new_handler() +{ + ++new_handler_called; + std::set_new_handler(0); +} + +bool A_constructed = false; + +struct alignas(OverAligned) A +{ + A() {A_constructed = true;} + ~A() {A_constructed = false;} +}; + +void test_max_alloc() { + std::set_new_handler(new_handler); + auto do_test = []() { + void* vp = operator new (std::numeric_limits::max(), + std::align_val_t(OverAligned), + std::nothrow); + assert(new_handler_called == 1); + assert(vp == 0); + }; +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + do_test(); + } + catch (...) + { + assert(false); + } +#else + do_test(); +#endif +} + +int main() +{ + { + A* ap = new(std::nothrow) A; + assert(ap); + assert(reinterpret_cast(ap) % OverAligned == 0); + assert(A_constructed); + delete ap; + assert(!A_constructed); + } + { + test_max_alloc(); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new nothrow by replacing only operator new + +// UNSUPPORTED: sanitizer-new-delete + +// TODO Investigate why UBSAN prevents nothrow new from calling our replacement. +// XFAIL: ubsan + +#include +#include +#include +#include +#include + + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +bool A_constructed = false; + +struct alignas(OverAligned) A +{ + A() {A_constructed = true;} + ~A() {A_constructed = false;} +}; + +bool B_constructed = false; + +struct B { + std::max_align_t member; + B() { B_constructed = true; } + ~B() { B_constructed = false; } +}; + +int new_called = 0; +alignas(OverAligned) char Buff[OverAligned * 2]; + +void* operator new(std::size_t s, std::align_val_t a) throw(std::bad_alloc) +{ + assert(!new_called); + assert(s <= sizeof(Buff)); + assert(static_cast(a) == OverAligned); + ++new_called; + return Buff; +} + +void operator delete(void* p, std::align_val_t a) throw() +{ + assert(p == Buff); + assert(static_cast(a) == OverAligned); + assert(new_called); + --new_called; +} + + +int main() +{ + { + A* ap = new (std::nothrow) A; + assert(ap); + assert(A_constructed); + assert(new_called); + delete ap; + assert(!A_constructed); + assert(!new_called); + } + { + B* bp = new (std::nothrow) B; + assert(bp); + assert(B_constructed); + assert(!new_called); + delete bp; + assert(!new_called); + assert(!B_constructed); + } +} Index: test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_replace.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_replace.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// test operator new replacement + +// UNSUPPORTED: sanitizer-new-delete + +#include +#include +#include +#include +#include +#include + +constexpr auto OverAligned = alignof(std::max_align_t) * 2; + +bool A_constructed = false; + +struct alignas(OverAligned) A { + A() {A_constructed = true;} + ~A() {A_constructed = false;} +}; + + +bool B_constructed = false; + +struct alignas(std::max_align_t) B +{ + std::max_align_t member; + B() {B_constructed = true;} + ~B() {B_constructed = false;} +}; + +int new_called = 0; + +alignas(OverAligned) char DummyData[OverAligned]; + +void* operator new(std::size_t s, std::align_val_t a) throw(std::bad_alloc) +{ + assert(new_called == 0); // We already allocated + assert(s <= sizeof(DummyData)); + assert(static_cast(a) == OverAligned); + ++new_called; + return DummyData; +} + +void operator delete(void* p, std::align_val_t a) throw() +{ + assert(new_called == 1); + --new_called; + assert(p == DummyData); +} + + +int main() +{ + { + A* ap = new A; + assert(ap); + assert(A_constructed); + assert(new_called); + delete ap; + assert(!A_constructed); + assert(!new_called); + } + { + B* bp = new B; + assert(bp); + assert(B_constructed); + assert(!new_called); + delete bp; + assert(!new_called); + } +}