forked from OSchip/llvm-project
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 <new> 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
This commit is contained in:
parent
a8c8b627f2
commit
98f77828a9
libcxx
include
test
libcxx
experimental/memory/memory.resource.adaptor/memory.resource.adaptor.mem
language.support/support.dynamic
std
containers/sequences/array
depr/depr.c.headers
language.support/support.types
utilities/meta/meta.trans/meta.trans.other
|
@ -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 <stddef.h> max_align_t where possible.
|
||||
#if !defined(_LIBCPP_CXX03_LANG)
|
||||
using ::max_align_t;
|
||||
#else
|
||||
typedef long double max_align_t;
|
||||
#endif
|
||||
|
||||
template <class _Tp> struct __libcpp_is_integral { enum { value = 0 }; };
|
||||
|
|
|
@ -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 <stddef.h> 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
|
||||
|
|
|
@ -36,8 +36,13 @@ int main(int, char**)
|
|||
ex::resource_adaptor<Alloc> r(Alloc{P});
|
||||
ex::memory_resource & m1 = r;
|
||||
|
||||
#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
|
||||
std::size_t maxSize = std::numeric_limits<std::size_t>::max()
|
||||
- __STDCPP_DEFAULT_NEW_ALIGNMENT__;
|
||||
#else
|
||||
std::size_t maxSize = std::numeric_limits<std::size_t>::max()
|
||||
- alignof(std::max_align_t);
|
||||
#endif
|
||||
|
||||
m1.deallocate(nullptr, maxSize);
|
||||
assert(AssertCount == 0);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<T, 0> C;
|
||||
const C c = {};
|
||||
const T* p = c.data();
|
||||
LIBCPP_ASSERT(p != nullptr);
|
||||
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
|
||||
assert(pint % TEST_ALIGNOF(std::max_align_t) == 0);
|
||||
assert(pint % TEST_ALIGNOF(T) == 0);
|
||||
}
|
||||
{
|
||||
typedef NoDefault T;
|
||||
|
|
|
@ -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<T, 0> C;
|
||||
const C c = {};
|
||||
const T* p = c.data();
|
||||
LIBCPP_ASSERT(p != nullptr);
|
||||
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
|
||||
assert(pint % TEST_ALIGNOF(std::max_align_t) == 0);
|
||||
assert(pint % TEST_ALIGNOF(T) == 0);
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
|
|
|
@ -49,6 +49,15 @@ void test_type() {
|
|||
test<T, 0>();
|
||||
}
|
||||
|
||||
#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<int>();
|
||||
test_type<double>();
|
||||
test_type<long double>();
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
test_type<std::max_align_t>();
|
||||
#endif
|
||||
test_type<TestType1>();
|
||||
test_type<TestType2>();
|
||||
|
||||
|
|
|
@ -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<max_align_t>::value,
|
||||
|
@ -65,6 +66,7 @@ int main(int, char**)
|
|||
std::alignment_of<void*>::value,
|
||||
"std::alignment_of<max_align_t>::value >= "
|
||||
"std::alignment_of<void*>::value");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
|
@ -41,5 +43,11 @@ int main(int, char**)
|
|||
"std::alignment_of<std::max_align_t>::value >= "
|
||||
"std::alignment_of<void*>::value");
|
||||
|
||||
#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
|
||||
static_assert(std::alignment_of<std::max_align_t>::value <=
|
||||
__STDCPP_DEFAULT_NEW_ALIGNMENT__,
|
||||
"max_align_t alignment is no larger than new alignment");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,20 @@
|
|||
#include <cstddef> // 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<T1>::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<T1>::value, "");
|
||||
static_assert(std::is_standard_layout<T1>::value, "");
|
||||
static_assert(std::alignment_of<T1>::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<T1>::value == alignment, "");
|
||||
#else
|
||||
static_assert(std::alignment_of<T1>::value >=
|
||||
TEST_ALIGNOF(natural_alignment), "");
|
||||
static_assert(std::alignment_of<T1>::value <= 16, "");
|
||||
#endif
|
||||
static_assert(sizeof(T1) == 16, "");
|
||||
}
|
||||
{
|
||||
|
@ -271,9 +289,17 @@ int main(int, char**)
|
|||
#endif
|
||||
static_assert(std::is_trivial<T1>::value, "");
|
||||
static_assert(std::is_standard_layout<T1>::value, "");
|
||||
static_assert(std::alignment_of<T1>::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<T1>::value == alignment, "");
|
||||
static_assert(sizeof(T1) == 16 + alignment, "");
|
||||
#else
|
||||
static_assert(std::alignment_of<T1>::value >=
|
||||
TEST_ALIGNOF(natural_alignment), "");
|
||||
static_assert(std::alignment_of<T1>::value <= 16);
|
||||
static_assert(sizeof(T1) % TEST_ALIGNOF(natural_alignment) == 0, "");
|
||||
#endif
|
||||
}
|
||||
{
|
||||
typedef std::aligned_storage<10>::type T1;
|
||||
|
|
Loading…
Reference in New Issue