From 98f77828a98fd05760987598db1355cf08b643bd Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Sat, 4 Apr 2020 00:48:02 +0200 Subject: [PATCH] Avoid using std::max_align_t in pre-C++11 mode Always depend on the compiler to have a correct implementation of max_align_t in stddef.h and don't provide a fallback. For pre-C++11, require __STDCPP_NEW_ALIGNMENT__ in as provided by clang in all standard modes. Adjust test cases to avoid testing or using max_align_t in pre-C++11 mode and also to better deal with alignof(max_align_t)>16. Document requirements of the alignment tests around natural alignment of power-of-two-sized types. Differential revision: https://reviews.llvm.org/D73245 --- libcxx/include/cstddef | 8 ++--- libcxx/include/stddef.h | 8 +---- .../db_deallocate.pass.cpp | 5 +++ .../support.dynamic/libcpp_deallocate.sh.cpp | 4 +++ .../sequences/array/array.data/data.pass.cpp | 14 +++++++- .../sequences/array/array.data/data_const.pass.cpp | 15 +++++++- .../sequences/array/size_and_alignment.pass.cpp | 13 +++++++ .../test/std/depr/depr.c.headers/stddef_h.pass.cpp | 2 ++ .../support.types/max_align_t.pass.cpp | 8 +++++ .../meta.trans.other/aligned_storage.pass.cpp | 42 +++++++++++++++++----- 10 files changed, 96 insertions(+), 23 deletions(-) diff --git a/libcxx/include/cstddef b/libcxx/include/cstddef index 87eee4b..2a0bfeb 100644 --- a/libcxx/include/cstddef +++ b/libcxx/include/cstddef @@ -25,7 +25,7 @@ Types: ptrdiff_t size_t - max_align_t + max_align_t // C++11 nullptr_t byte // C++17 @@ -49,12 +49,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD using ::ptrdiff_t; using ::size_t; -#if defined(__CLANG_MAX_ALIGN_T_DEFINED) || defined(_GCC_MAX_ALIGN_T) || \ - defined(__DEFINED_max_align_t) || defined(__NetBSD__) -// Re-use the compiler's max_align_t where possible. +#if !defined(_LIBCPP_CXX03_LANG) using ::max_align_t; -#else -typedef long double max_align_t; #endif template struct __libcpp_is_integral { enum { value = 0 }; }; diff --git a/libcxx/include/stddef.h b/libcxx/include/stddef.h index 6497dcd..35c680b 100644 --- a/libcxx/include/stddef.h +++ b/libcxx/include/stddef.h @@ -31,7 +31,7 @@ Types: ptrdiff_t size_t - max_align_t + max_align_t // C++11 nullptr_t */ @@ -51,12 +51,6 @@ extern "C++" { using std::nullptr_t; } -// Re-use the compiler's max_align_t where possible. -#if !defined(__CLANG_MAX_ALIGN_T_DEFINED) && !defined(_GCC_MAX_ALIGN_T) && \ - !defined(__DEFINED_max_align_t) && !defined(__NetBSD__) -typedef long double max_align_t; -#endif - #endif #endif // _LIBCPP_STDDEF_H diff --git a/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp b/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp index ec8926b..03f7a74 100644 --- a/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp +++ b/libcxx/test/libcxx/experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem/db_deallocate.pass.cpp @@ -36,8 +36,13 @@ int main(int, char**) ex::resource_adaptor r(Alloc{P}); ex::memory_resource & m1 = r; +#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ + std::size_t maxSize = std::numeric_limits::max() + - __STDCPP_DEFAULT_NEW_ALIGNMENT__; +#else std::size_t maxSize = std::numeric_limits::max() - alignof(std::max_align_t); +#endif m1.deallocate(nullptr, maxSize); assert(AssertCount == 0); diff --git a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp index da5f3b6..8eb2770 100644 --- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp +++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp @@ -142,7 +142,11 @@ void operator delete(void* p, size_t n, std::align_val_t a)TEST_NOEXCEPT { void test_libcpp_dealloc() { void* p = nullptr; +#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ + size_t over_align_val = __STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2; +#else size_t over_align_val = TEST_ALIGNOF(std::max_align_t) * 2; +#endif size_t under_align_val = TEST_ALIGNOF(int); size_t with_size_val = 2; diff --git a/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp b/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp index ce1843e..434cbc5f 100644 --- a/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/array.data/data.pass.cpp @@ -24,6 +24,14 @@ struct NoDefault { NoDefault(int) {} }; +#if TEST_STD_VER < 11 +struct natural_alignment { + long t1; + long long t2; + double t3; + long double t4; +}; +#endif int main(int, char**) { @@ -52,13 +60,17 @@ int main(int, char**) LIBCPP_ASSERT(p != nullptr); } { +#if TEST_STD_VER < 11 + typedef natural_alignment T; +#else typedef std::max_align_t T; +#endif typedef std::array C; const C c = {}; const T* p = c.data(); LIBCPP_ASSERT(p != nullptr); std::uintptr_t pint = reinterpret_cast(p); - assert(pint % TEST_ALIGNOF(std::max_align_t) == 0); + assert(pint % TEST_ALIGNOF(T) == 0); } { typedef NoDefault T; diff --git a/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp b/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp index 32c05d7..92828ee 100644 --- a/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/array.data/data_const.pass.cpp @@ -24,6 +24,15 @@ struct NoDefault { NoDefault(int) {} }; +#if TEST_STD_VER < 11 +struct natural_alignment { + long t1; + long long t2; + double t3; + long double t4; +}; +#endif + int main(int, char**) { { @@ -50,13 +59,17 @@ int main(int, char**) LIBCPP_ASSERT(p != nullptr); } { +#if TEST_STD_VER < 11 + typedef natural_alignment T; +#else typedef std::max_align_t T; +#endif typedef std::array C; const C c = {}; const T* p = c.data(); LIBCPP_ASSERT(p != nullptr); std::uintptr_t pint = reinterpret_cast(p); - assert(pint % TEST_ALIGNOF(std::max_align_t) == 0); + assert(pint % TEST_ALIGNOF(T) == 0); } #if TEST_STD_VER > 14 { 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 f585da6..51982ea 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 @@ -49,6 +49,15 @@ void test_type() { test(); } +#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ +struct TEST_ALIGNAS(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) TestType1 { + +}; + +struct TEST_ALIGNAS(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) TestType2 { + char data[1000]; +}; +#else struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType1 { }; @@ -56,6 +65,7 @@ struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType1 { struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType2 { char data[1000]; }; +#endif //static_assert(sizeof(void*) == 4, ""); @@ -64,7 +74,10 @@ int main(int, char**) { test_type(); test_type(); test_type(); + +#if TEST_STD_VER >= 11 test_type(); +#endif test_type(); test_type(); diff --git a/libcxx/test/std/depr/depr.c.headers/stddef_h.pass.cpp b/libcxx/test/std/depr/depr.c.headers/stddef_h.pass.cpp index c54c976..1fe48b5 100644 --- a/libcxx/test/std/depr/depr.c.headers/stddef_h.pass.cpp +++ b/libcxx/test/std/depr/depr.c.headers/stddef_h.pass.cpp @@ -43,6 +43,7 @@ int main(int, char**) "decltype(nullptr) == nullptr_t"); static_assert(sizeof(nullptr_t) == sizeof(void*), "sizeof(nullptr_t) == sizeof(void*)"); +#if TEST_STD_VER >= 11 #if TEST_STD_VER > 17 // P0767 static_assert(std::is_trivial::value, @@ -65,6 +66,7 @@ int main(int, char**) std::alignment_of::value, "std::alignment_of::value >= " "std::alignment_of::value"); +#endif return 0; } diff --git a/libcxx/test/std/language.support/support.types/max_align_t.pass.cpp b/libcxx/test/std/language.support/support.types/max_align_t.pass.cpp index a49f598..3a90d8a 100644 --- a/libcxx/test/std/language.support/support.types/max_align_t.pass.cpp +++ b/libcxx/test/std/language.support/support.types/max_align_t.pass.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03 + #include #include @@ -41,5 +43,11 @@ int main(int, char**) "std::alignment_of::value >= " "std::alignment_of::value"); +#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__ + static_assert(std::alignment_of::value <= + __STDCPP_DEFAULT_NEW_ALIGNMENT__, + "max_align_t alignment is no larger than new alignment"); +#endif + return 0; } 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 e761532..496004b 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 @@ -17,6 +17,20 @@ #include // for std::max_align_t #include "test_macros.h" +// The following tests assume naturally aligned types exist +// up to 64bit (double). For larger types, max_align_t should +// give the correct alignment. For pre-C++11 testing, only +// the lower bound is checked. + +#if TEST_STD_VER < 11 +struct natural_alignment { + long t1; + long long t2; + double t3; + long double t4; +}; +#endif + int main(int, char**) { { @@ -250,9 +264,6 @@ int main(int, char**) static_assert(std::alignment_of::value == 8, ""); static_assert(sizeof(T1) == 16, ""); } - // 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.) { typedef std::aligned_storage<16>::type T1; #if TEST_STD_VER > 11 @@ -260,8 +271,15 @@ int main(int, char**) #endif static_assert(std::is_trivial::value, ""); static_assert(std::is_standard_layout::value, ""); - static_assert(std::alignment_of::value == TEST_ALIGNOF(std::max_align_t), - ""); +#if TEST_STD_VER >= 11 + const size_t alignment = TEST_ALIGNOF(std::max_align_t) > 16 ? + 16 : TEST_ALIGNOF(std::max_align_t); + static_assert(std::alignment_of::value == alignment, ""); +#else + static_assert(std::alignment_of::value >= + TEST_ALIGNOF(natural_alignment), ""); + static_assert(std::alignment_of::value <= 16, ""); +#endif static_assert(sizeof(T1) == 16, ""); } { @@ -271,9 +289,17 @@ int main(int, char**) #endif static_assert(std::is_trivial::value, ""); static_assert(std::is_standard_layout::value, ""); - static_assert(std::alignment_of::value == TEST_ALIGNOF(std::max_align_t), - ""); - static_assert(sizeof(T1) == 16 + TEST_ALIGNOF(std::max_align_t), ""); +#if TEST_STD_VER >= 11 + const size_t alignment = TEST_ALIGNOF(std::max_align_t) > 16 ? + 16 : TEST_ALIGNOF(std::max_align_t); + static_assert(std::alignment_of::value == alignment, ""); + static_assert(sizeof(T1) == 16 + alignment, ""); +#else + static_assert(std::alignment_of::value >= + TEST_ALIGNOF(natural_alignment), ""); + static_assert(std::alignment_of::value <= 16); + static_assert(sizeof(T1) % TEST_ALIGNOF(natural_alignment) == 0, ""); +#endif } { typedef std::aligned_storage<10>::type T1; -- 2.7.4