From c2b831cab86e884b89c1363e4dd3ec7b96484f0c Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 16 Jan 2019 01:51:12 +0000 Subject: Move internal usages of `alignof`/`__alignof` to use `_LIBCPP_ALIGNOF`. Summary: Starting in Clang 8.0 and GCC 8.0, `alignof` and `__alignof` return different values in same cases. Specifically `alignof` and `_Alignof` return the minimum alignment for a type, where as `__alignof` returns the preferred alignment. libc++ currently uses `__alignof` but means to use `alignof`. See llvm.org/PR39713 This patch introduces the macro `_LIBCPP_ALIGNOF` so we can control which spelling gets used. This patch does not introduce any ABI guard to provide the old behavior with newer compilers. However, if we decide that is needed, this patch makes it trivial to implement. I think we should commit this change immediately, and decide what we want to do about the ABI afterwards. Reviewers: ldionne, EricWF Reviewed By: ldionne, EricWF Subscribers: jyknight, christof, libcxx-commits Differential Revision: https://reviews.llvm.org/D54814 --- libcxx/include/__config | 18 ++++++++-- libcxx/include/__sso_allocator | 4 +-- libcxx/include/experimental/coroutine | 6 ++-- libcxx/include/experimental/memory_resource | 8 ++--- libcxx/include/functional | 2 +- libcxx/include/memory | 16 ++++----- libcxx/include/type_traits | 8 ++--- libcxx/include/valarray | 40 +++++++++++----------- libcxx/test/libcxx/libcpp_alignof.pass.cpp | 37 ++++++++++++++++++++ .../sequences/array/size_and_alignment.pass.cpp | 2 -- .../meta.trans.other/aligned_storage.pass.cpp | 9 ++--- .../meta.unary.prop.query/alignment_of.pass.cpp | 8 ++++- libcxx/test/support/test_macros.h | 6 +++- 13 files changed, 109 insertions(+), 55 deletions(-) create mode 100644 libcxx/test/libcxx/libcpp_alignof.pass.cpp diff --git a/libcxx/include/__config b/libcxx/include/__config index e82d7fec566..f0bc3483fac 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -353,6 +353,18 @@ # endif // __linux__ #endif +#ifndef _LIBCPP_CXX03_LANG +# define _LIBCPP_ALIGNOF(_Tp) alignof(_Tp) +#elif defined(_LIBCPP_COMPILER_CLANG) +# define _LIBCPP_ALIGNOF(_Tp) _Alignof(_Tp) +#else +// This definition is potentially buggy, but it's only taken with GCC in C++03, +// which we barely support anyway. See llvm.org/PR39713 +# define _LIBCPP_ALIGNOF(_Tp) __alignof(_Tp) +#endif + +#define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) + #if defined(_LIBCPP_COMPILER_CLANG) // _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for @@ -367,7 +379,7 @@ # define _ALIGNAS_TYPE(x) alignas(x) # define _ALIGNAS(x) alignas(x) #else -# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) +# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x)))) # define _ALIGNAS(x) __attribute__((__aligned__(x))) #endif @@ -494,7 +506,7 @@ typedef __char32_t char32_t; #elif defined(_LIBCPP_COMPILER_GCC) #define _ALIGNAS(x) __attribute__((__aligned__(x))) -#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) +#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x)))) #define _LIBCPP_NORETURN __attribute__((noreturn)) @@ -607,7 +619,7 @@ typedef __char32_t char32_t; #elif defined(_LIBCPP_COMPILER_IBM) #define _ALIGNAS(x) __attribute__((__aligned__(x))) -#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) +#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(_LIBCPP_ALIGNOF(x)))) #define _ATTRIBUTE(x) __attribute__((x)) #define _LIBCPP_NORETURN __attribute__((noreturn)) diff --git a/libcxx/include/__sso_allocator b/libcxx/include/__sso_allocator index e16b680ec55..8aca0495d75 100644 --- a/libcxx/include/__sso_allocator +++ b/libcxx/include/__sso_allocator @@ -55,14 +55,14 @@ public: __allocated_ = true; return (pointer)&buf_; } - return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp))); + return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); } _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) { if (__p == (pointer)&buf_) __allocated_ = false; else - _VSTD::__libcpp_deallocate(__p, __n * sizeof(_Tp), __alignof(_Tp)); + _VSTD::__libcpp_deallocate(__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)); } _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} diff --git a/libcxx/include/experimental/coroutine b/libcxx/include/experimental/coroutine index 1eb224a535a..7cb39b81b48 100644 --- a/libcxx/include/experimental/coroutine +++ b/libcxx/include/experimental/coroutine @@ -214,7 +214,7 @@ public: _LIBCPP_INLINE_VISIBILITY _Promise& promise() const { return *static_cast<_Promise*>( - __builtin_coro_promise(this->__handle_, __alignof(_Promise), false)); + __builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false)); } public: @@ -254,7 +254,7 @@ public: coroutine_handle __tmp; __tmp.__handle_ = __builtin_coro_promise( _VSTD::addressof(const_cast<_RawPromise&>(__promise)), - __alignof(_Promise), true); + _LIBCPP_ALIGNOF(_Promise), true); return __tmp; } }; @@ -272,7 +272,7 @@ public: _LIBCPP_INLINE_VISIBILITY _Promise& promise() const { return *static_cast<_Promise*>( - __builtin_coro_promise(this->__handle_, __alignof(_Promise), false)); + __builtin_coro_promise(this->__handle_, _LIBCPP_ALIGNOF(_Promise), false)); } _LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return true; } diff --git a/libcxx/include/experimental/memory_resource b/libcxx/include/experimental/memory_resource index 221ce5b8eac..83781d46203 100644 --- a/libcxx/include/experimental/memory_resource +++ b/libcxx/include/experimental/memory_resource @@ -98,7 +98,7 @@ size_t __aligned_allocation_size(size_t __s, size_t __a) _NOEXCEPT // 8.5, memory.resource class _LIBCPP_TYPE_VIS memory_resource { - static const size_t __max_align = alignof(max_align_t); + static const size_t __max_align = _LIBCPP_ALIGNOF(max_align_t); // 8.5.2, memory.resource.public public: @@ -190,7 +190,7 @@ public: " 'n' exceeds maximum supported size"); } return static_cast<_ValueType*>( - __res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType)) + __res_->allocate(__n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)) ); } @@ -198,7 +198,7 @@ public: void deallocate(_ValueType * __p, size_t __n) _NOEXCEPT { _LIBCPP_ASSERT(__n <= __max_size(), "deallocate called for size which exceeds max_size()"); - __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType)); + __res_->deallocate(__p, __n * sizeof(_ValueType), _LIBCPP_ALIGNOF(_ValueType)); } template @@ -345,7 +345,7 @@ class _LIBCPP_TEMPLATE_VIS __resource_adaptor_imp && is_same::value && is_same::value, ""); - static const size_t _MaxAlign = alignof(max_align_t); + static const size_t _MaxAlign = _LIBCPP_ALIGNOF(max_align_t); using _Alloc = typename _CTraits::template rebind_alloc< typename aligned_storage<_MaxAlign, _MaxAlign>::type diff --git a/libcxx/include/functional b/libcxx/include/functional index 1fb44f27148..95491879b0c 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -1872,7 +1872,7 @@ template struct __use_small_storage : public _VSTD::integral_constant< bool, sizeof(_Fun) <= sizeof(__policy_storage) && - alignof(_Fun) <= alignof(__policy_storage) && + _LIBCPP_ALIGNOF(_Fun) <= _LIBCPP_ALIGNOF(__policy_storage) && _VSTD::is_trivially_copy_constructible<_Fun>::value && _VSTD::is_trivially_destructible<_Fun>::value> {}; diff --git a/libcxx/include/memory b/libcxx/include/memory index 93f04c6faff..ce2c3576623 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -1811,10 +1811,10 @@ public: if (__n > max_size()) __throw_length_error("allocator::allocate(size_t n)" " 'n' exceeds maximum supported size"); - return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp))); + return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); } _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) _NOEXCEPT - {_VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), __alignof(_Tp));} + {_VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return size_type(~0) / sizeof(_Tp);} #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) @@ -1912,10 +1912,10 @@ public: if (__n > max_size()) __throw_length_error("allocator::allocate(size_t n)" " 'n' exceeds maximum supported size"); - return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), __alignof(_Tp))); + return static_cast(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp))); } _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) _NOEXCEPT - {_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), __alignof(_Tp));} + {_VSTD::__libcpp_deallocate((void*) const_cast<_Tp *>(__p), __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));} _LIBCPP_INLINE_VISIBILITY size_type max_size() const _NOEXCEPT {return size_type(~0) / sizeof(_Tp);} #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) @@ -2031,7 +2031,7 @@ get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT while (__n > 0) { #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) - if (__is_overaligned_for_new(__alignof(_Tp))) + if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) { std::align_val_t __al = std::align_val_t(std::alignment_of<_Tp>::value); @@ -2042,7 +2042,7 @@ get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT __n * sizeof(_Tp), nothrow)); } #else - if (__is_overaligned_for_new(__alignof(_Tp))) + if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) { // Since aligned operator new is unavailable, return an empty // buffer rather than one with invalid alignment. @@ -2066,7 +2066,7 @@ template inline _LIBCPP_INLINE_VISIBILITY void return_temporary_buffer(_Tp* __p) _NOEXCEPT { - _VSTD::__libcpp_deallocate_unsized((void*)__p, __alignof(_Tp)); + _VSTD::__libcpp_deallocate_unsized((void*)__p, _LIBCPP_ALIGNOF(_Tp)); } #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) @@ -5642,7 +5642,7 @@ template struct __temp_value { typedef allocator_traits<_Alloc> _Traits; - typename aligned_storage::type __v; + typename aligned_storage::type __v; _Alloc &__a; _Tp *__addr() { return reinterpret_cast<_Tp *>(addressof(__v)); } diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index ab010716f00..8b30511a4ec 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1652,7 +1652,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool has_unique_object_representations_v // alignment_of template struct _LIBCPP_TEMPLATE_VIS alignment_of - : public integral_constant {}; + : public integral_constant {}; #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template @@ -1682,7 +1682,7 @@ struct __nat template struct __align_type { - static const size_t value = alignment_of<_Tp>::value; + static const size_t value = _LIBCPP_PREFERRED_ALIGNOF(_Tp); typedef _Tp type; }; @@ -1815,8 +1815,8 @@ struct __static_max<_I0, _I1, _In...> template struct aligned_union { - static const size_t alignment_value = __static_max<__alignof__(_Type0), - __alignof__(_Types)...>::value; + static const size_t alignment_value = __static_max<_LIBCPP_PREFERRED_ALIGNOF(_Type0), + _LIBCPP_PREFERRED_ALIGNOF(_Types)...>::value; static const size_t __len = __static_max<_Len, sizeof(_Type0), sizeof(_Types)...>::value; typedef typename aligned_storage<__len, alignment_value>::type type; diff --git a/libcxx/include/valarray b/libcxx/include/valarray index 3188b6af49b..07f38c81150 100644 --- a/libcxx/include/valarray +++ b/libcxx/include/valarray @@ -2740,7 +2740,7 @@ __val_expr<_ValExpr>::operator valarray<__val_expr::result_type>() const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(result_type), __alignof(result_type))); + _VSTD::__libcpp_allocate(__n * sizeof(result_type), _LIBCPP_ALIGNOF(result_type))); for (size_t __i = 0; __i != __n; ++__r.__end_, ++__i) ::new (__r.__end_) result_type(__expr_[__i]); } @@ -2758,7 +2758,7 @@ valarray<_Tp>::valarray(size_t __n) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2793,7 +2793,7 @@ valarray<_Tp>::valarray(const value_type* __p, size_t __n) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2819,7 +2819,7 @@ valarray<_Tp>::valarray(const valarray& __v) if (__v.size()) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__v.size() * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__v.size() * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2857,7 +2857,7 @@ valarray<_Tp>::valarray(initializer_list __il) if (__n) { __begin_ = __end_ = static_cast( -_VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); +_VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2887,7 +2887,7 @@ valarray<_Tp>::valarray(const slice_array& __sa) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2915,7 +2915,7 @@ valarray<_Tp>::valarray(const gslice_array& __ga) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2945,7 +2945,7 @@ valarray<_Tp>::valarray(const mask_array& __ma) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -2975,7 +2975,7 @@ valarray<_Tp>::valarray(const indirect_array& __ia) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -3012,7 +3012,7 @@ valarray<_Tp>::__assign_range(const value_type* __f, const value_type* __l) { __clear(size()); __begin_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); __end_ = __begin_ + __n; _VSTD::uninitialized_copy(__f, __l, __begin_); } else { @@ -3268,7 +3268,7 @@ valarray<_Tp>::operator+() const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(+*__p); } @@ -3286,7 +3286,7 @@ valarray<_Tp>::operator-() const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(-*__p); } @@ -3304,7 +3304,7 @@ valarray<_Tp>::operator~() const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(~*__p); } @@ -3321,7 +3321,7 @@ valarray<_Tp>::operator!() const { __r.__begin_ = __r.__end_ = - static_cast(_VSTD::__libcpp_allocate(__n * sizeof(bool), __alignof(bool))); + static_cast(_VSTD::__libcpp_allocate(__n * sizeof(bool), _LIBCPP_ALIGNOF(bool))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) bool(!*__p); } @@ -3642,7 +3642,7 @@ valarray<_Tp>::shift(int __i) const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); const value_type* __sb; value_type* __tb; value_type* __te; @@ -3681,7 +3681,7 @@ valarray<_Tp>::cshift(int __i) const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); __i %= static_cast(__n); const value_type* __m = __i >= 0 ? __begin_ + __i : __end_ + __i; for (const value_type* __s = __m; __s != __end_; ++__r.__end_, ++__s) @@ -3703,7 +3703,7 @@ valarray<_Tp>::apply(value_type __f(value_type)) const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(__f(*__p)); } @@ -3721,7 +3721,7 @@ valarray<_Tp>::apply(value_type __f(const value_type&)) const __r.__begin_ = __r.__end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) ::new (__r.__end_) value_type(__f(*__p)); } @@ -3736,7 +3736,7 @@ void valarray<_Tp>::__clear(size_t __capacity) { while (__end_ != __begin_) (--__end_)->~value_type(); - _VSTD::__libcpp_deallocate(__begin_, __capacity * sizeof(value_type), __alignof(value_type)); + _VSTD::__libcpp_deallocate(__begin_, __capacity * sizeof(value_type), _LIBCPP_ALIGNOF(value_type)); __begin_ = __end_ = nullptr; } } @@ -3749,7 +3749,7 @@ valarray<_Tp>::resize(size_t __n, value_type __x) if (__n) { __begin_ = __end_ = static_cast( - _VSTD::__libcpp_allocate(__n * sizeof(value_type), __alignof(value_type))); + _VSTD::__libcpp_allocate(__n * sizeof(value_type), _LIBCPP_ALIGNOF(value_type))); #ifndef _LIBCPP_NO_EXCEPTIONS try { diff --git a/libcxx/test/libcxx/libcpp_alignof.pass.cpp b/libcxx/test/libcxx/libcpp_alignof.pass.cpp new file mode 100644 index 00000000000..ba0df807e82 --- /dev/null +++ b/libcxx/test/libcxx/libcpp_alignof.pass.cpp @@ -0,0 +1,37 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 that _LIBCPP_ALIGNOF acts the same as the C++11 keyword `alignof`, and +// not as the GNU extension `__alignof`. The former returns the minimal required +// alignment for a type, whereas the latter returns the preferred alignment. +// +// See llvm.org/PR39713 + +#include +#include "test_macros.h" + +template +void test() { + static_assert(_LIBCPP_ALIGNOF(T) == std::alignment_of::value, ""); + static_assert(_LIBCPP_ALIGNOF(T) == TEST_ALIGNOF(T), ""); +#if TEST_STD_VER >= 11 + static_assert(_LIBCPP_ALIGNOF(T) == alignof(T), ""); +#endif +#ifdef TEST_COMPILER_CLANG + static_assert(_LIBCPP_ALIGNOF(T) == _Alignof(T), ""); +#endif +} + +int main() { + test(); + test(); + test(); + test(); +} diff --git a/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp b/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp index 966d063fe17..d73182bd5ca 100644 --- a/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/size_and_alignment.pass.cpp @@ -58,8 +58,6 @@ struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType2 { char data[1000]; }; -//static_assert(sizeof(void*) == 4, ""); - int main() { test_type(); test_type(); diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_storage.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_storage.pass.cpp index d7e35a62f8f..012741ff6c7 100644 --- a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_storage.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/aligned_storage.pass.cpp @@ -254,9 +254,6 @@ int main() // Use alignof(std::max_align_t) below to find the max alignment instead of // hardcoding it, because it's different on different platforms. // (For example 8 on arm and 16 on x86.) -#if TEST_STD_VER < 11 -#define alignof __alignof__ -#endif { typedef std::aligned_storage<16>::type T1; #if TEST_STD_VER > 11 @@ -264,7 +261,7 @@ int main() #endif static_assert(std::is_trivial::value, ""); static_assert(std::is_standard_layout::value, ""); - static_assert(std::alignment_of::value == alignof(std::max_align_t), + static_assert(std::alignment_of::value == TEST_ALIGNOF(std::max_align_t), ""); static_assert(sizeof(T1) == 16, ""); } @@ -275,9 +272,9 @@ int main() #endif static_assert(std::is_trivial::value, ""); static_assert(std::is_standard_layout::value, ""); - static_assert(std::alignment_of::value == alignof(std::max_align_t), + static_assert(std::alignment_of::value == TEST_ALIGNOF(std::max_align_t), ""); - static_assert(sizeof(T1) == 16 + alignof(std::max_align_t), ""); + static_assert(sizeof(T1) == 16 + TEST_ALIGNOF(std::max_align_t), ""); } { typedef std::aligned_storage<10>::type T1; diff --git a/libcxx/test/std/utilities/meta/meta.unary.prop.query/alignment_of.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary.prop.query/alignment_of.pass.cpp index 0f55db64719..bd02da96978 100644 --- a/libcxx/test/std/utilities/meta/meta.unary.prop.query/alignment_of.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary.prop.query/alignment_of.pass.cpp @@ -19,6 +19,9 @@ template void test_alignment_of() { + const unsigned AlignofResult = TEST_ALIGNOF(T); + static_assert( AlignofResult == A, "Golden value does not match result of alignof keyword"); + static_assert( std::alignment_of::value == AlignofResult, ""); static_assert( std::alignment_of::value == A, ""); static_assert( std::alignment_of::value == A, ""); static_assert( std::alignment_of::value == A, ""); @@ -45,7 +48,10 @@ int main() test_alignment_of(); test_alignment_of(); test_alignment_of(); - test_alignment_of(); + // The test case below is a hack. It's hard to detect what golden value + // we should expect. In most cases it should be 8. But in i386 builds + // with Clang >= 8 or GCC >= 8 the value is '4'. + test_alignment_of(); #if (defined(__ppc__) && !defined(__ppc64__)) test_alignment_of(); // 32-bit PPC has four byte bool #else diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h index 5af07247122..2813d1ff068 100644 --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -116,7 +116,11 @@ # define TEST_THROW_SPEC(...) throw(__VA_ARGS__) # endif #else -#define TEST_ALIGNOF(...) __alignof(__VA_ARGS__) +#if defined(TEST_COMPILER_CLANG) +# define TEST_ALIGNOF(...) _Alignof(__VA_ARGS__) +#else +# define TEST_ALIGNOF(...) __alignof(__VA_ARGS__) +#endif #define TEST_ALIGNAS(...) __attribute__((__aligned__(__VA_ARGS__))) #define TEST_CONSTEXPR #define TEST_CONSTEXPR_CXX14 -- cgit v1.2.3