EricWF created this revision. EricWF added reviewers: vsapsai, mclow.lists. Herald added a subscriber: christof.
Currently libc++ silently ignores over-aligned allocation requests made through __libcpp_allocate when aligned new/delete is not available. This patch uses the `diagnose_if` attribute to generate a warning in that case instead of being silent. The change required converting __is_overaligned_for_new to a macro so that the diagnose_if condition is still a potential constant expression in C++03. Repository: rCXX libc++ https://reviews.llvm.org/D45013 Files: include/memory include/new test/libcxx/utilities/memory/default.allocation/allocator.members/overaligned_new_not_supported.fail.cpp
Index: test/libcxx/utilities/memory/default.allocation/allocator.members/overaligned_new_not_supported.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/utilities/memory/default.allocation/allocator.members/overaligned_new_not_supported.fail.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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: diagnose-if-support, verify-support + +// <memory> + +// allocator: +// pointer allocate(size_type n, allocator<void>::const_pointer hint=0); + +// Test that a warning is generated when aligned allocation is not supported +// but an over-aligned allocation is requested. + +#include <memory> + +#include "test_macros.h" + +#ifndef TEST_HAS_NO_ALIGNED_ALLOCATION +// expected-no-diagnostics +#endif + + +#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ +static const size_t MaxAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__; +#else +static const size_t MaxAligned = std::alignment_of<std::max_align_t>::value; +#endif + +static const size_t OverAligned = MaxAligned * 2; + + +template <size_t Align> +struct TEST_ALIGNAS(Align) AlignedType { + char data; + AlignedType() { } + AlignedType(AlignedType const&) { } + ~AlignedType() {} +}; + + +void test_builtin_new() { + { + typedef AlignedType<MaxAligned> T; + void* ptr = std::__libcpp_allocate(sizeof(T), __alignof(T)); + std::__libcpp_deallocate(ptr, __alignof(T)); + } + { +#if defined(TEST_HAS_NO_ALIGNED_ALLOCATION) + // expected-warning@+3 1 {{over-aligned allocation using 'operator new' is not supported}} +#endif + typedef AlignedType<OverAligned> T; + void* ptr = std::__libcpp_allocate(sizeof(T), __alignof(T)); + std::__libcpp_deallocate(ptr, __alignof(T)); + } +} + +void test_std_allocator() { + { + typedef AlignedType<MaxAligned> T; + std::allocator<T> a; + T* ptr = a.allocate(1); // OK + a.deallocate(ptr, 1); + } + { +#if defined(TEST_HAS_NO_ALIGNED_ALLOCATION) + // expected-warning@memory:* 1 {{over-aligned allocation using 'operator new' is not supported}} + // expected-note@+4 {{requested here}} +#endif + typedef AlignedType<OverAligned> T; + std::allocator<T> a; + T* ptr = a.allocate(1); + a.deallocate(ptr, 1); + } +} + +int main() { + test_std_allocator(); + test_builtin_new(); +} Index: include/new =================================================================== --- include/new +++ include/new @@ -232,17 +232,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_CONSTEXPR inline _LIBCPP_INLINE_VISIBILITY bool __is_overaligned_for_new(size_t __align) _NOEXCEPT { #ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ - return __align > __STDCPP_DEFAULT_NEW_ALIGNMENT__; +#define _LIBCPP_IS_OVERALIGNED_FOR_NEW(__align) __align > __STDCPP_DEFAULT_NEW_ALIGNMENT__ #else - return __align > alignment_of<max_align_t>::value; +#define _LIBCPP_ISOVERALIGNED_FOR_NEW(__align) __align > _VSTD::alignment_of<_VSTD::max_align_t>::value #endif -} -inline _LIBCPP_INLINE_VISIBILITY void *__libcpp_allocate(size_t __size, size_t __align) { +inline _LIBCPP_INLINE_VISIBILITY void *__libcpp_allocate(size_t __size, size_t __align) +#if defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) +_LIBCPP_DIAGNOSE_WARNING(_LIBCPP_IS_OVERALIGNED_FOR_NEW(__align), + "over-aligned allocation using 'operator new' is not supported") +#endif +{ #ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION - if (__is_overaligned_for_new(__align)) { + if (_LIBCPP_IS_OVERALIGNED_FOR_NEW(__align)) { const align_val_t __align_val = static_cast<align_val_t>(__align); # ifdef _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE return ::operator new(__size, __align_val); @@ -262,7 +265,7 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __align) { #ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION - if (__is_overaligned_for_new(__align)) { + if (_LIBCPP_IS_OVERALIGNED_FOR_NEW(__align)) { const align_val_t __align_val = static_cast<align_val_t>(__align); # ifdef _LIBCPP_HAS_NO_BUILTIN_ALIGNED_OPERATOR_NEW_DELETE return ::operator delete(__ptr, __align_val); Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -2016,7 +2016,7 @@ while (__n > 0) { #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) - if (__is_overaligned_for_new(__alignof(_Tp))) + if (_LIBCPP_IS_OVERALIGNED_FOR_NEW(__alignof(_Tp))) { std::align_val_t __al = std::align_val_t(std::alignment_of<_Tp>::value); @@ -2027,7 +2027,7 @@ __n * sizeof(_Tp), nothrow)); } #else - if (__is_overaligned_for_new(__alignof(_Tp))) + if (_LIBCPP_IS_OVERALIGNED_FOR_NEW(__alignof(_Tp))) { // Since aligned operator new is unavailable, return an empty // buffer rather than one with invalid alignment.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits