mirror of
https://github.com/upx/upx.git
synced 2024-11-23 04:39:59 +00:00
src: yet more constexpr updates
This commit is contained in:
parent
f65c8f8c6f
commit
9f4d18baac
@ -180,6 +180,10 @@ struct CheckIntegral {
|
||||
assert_noexcept(x[0] == 0 && x[1] == 0);
|
||||
assert_noexcept(y[0] == 0 && y[1] == 0);
|
||||
assert_noexcept(z[0] == 0 && z[1] == 0);
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
static_assert(c == 0);
|
||||
static_assert(z[0] == 0 && z[1] == 0);
|
||||
#endif
|
||||
}
|
||||
{
|
||||
TestU<U> t;
|
||||
@ -191,18 +195,18 @@ struct CheckIntegral {
|
||||
assert_noexcept(t.z[0] == 0 && t.z[1] == 0);
|
||||
}
|
||||
#if __cplusplus <= 201703L
|
||||
COMPILE_TIME_ASSERT(std::is_pod<U>::value) // std::is_pod is deprecated in C++20
|
||||
static_assert(std::is_pod<U>::value); // std::is_pod is deprecated in C++20
|
||||
#endif
|
||||
COMPILE_TIME_ASSERT(std::is_standard_layout<U>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_trivial<U>::value)
|
||||
static_assert(std::is_standard_layout<U>::value);
|
||||
static_assert(std::is_trivial<U>::value);
|
||||
// more checks, these are probably implied by std::is_trivial
|
||||
COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible<U>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_nothrow_destructible<U>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_trivially_copyable<U>::value)
|
||||
COMPILE_TIME_ASSERT(std::is_trivially_default_constructible<U>::value)
|
||||
static_assert(std::is_nothrow_default_constructible<U>::value);
|
||||
static_assert(std::is_nothrow_destructible<U>::value);
|
||||
static_assert(std::is_trivially_copyable<U>::value);
|
||||
static_assert(std::is_trivially_default_constructible<U>::value);
|
||||
// UPX extras
|
||||
COMPILE_TIME_ASSERT(upx_is_integral<U>::value)
|
||||
COMPILE_TIME_ASSERT(upx_is_integral_v<U>)
|
||||
static_assert(upx_is_integral<U>::value);
|
||||
static_assert(upx_is_integral_v<U>);
|
||||
}
|
||||
static void check(void) noexcept {
|
||||
{
|
||||
@ -286,10 +290,10 @@ struct CheckAlignment {
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(Test2)
|
||||
Test1 t1[7];
|
||||
Test2 t2[7];
|
||||
COMPILE_TIME_ASSERT(sizeof(Test1) == 1 + sizeof(T))
|
||||
COMPILE_TIME_ASSERT(sizeof(t1) == 7 + 7 * sizeof(T))
|
||||
COMPILE_TIME_ASSERT(sizeof(Test2) == 1 + 3 * sizeof(T))
|
||||
COMPILE_TIME_ASSERT(sizeof(t2) == 7 + 21 * sizeof(T))
|
||||
static_assert(sizeof(Test1) == 1 + sizeof(T));
|
||||
static_assert(sizeof(t1) == 7 + 7 * sizeof(T));
|
||||
static_assert(sizeof(Test2) == 1 + 3 * sizeof(T));
|
||||
static_assert(sizeof(t2) == 7 + 21 * sizeof(T));
|
||||
UNUSED(t1);
|
||||
UNUSED(t2);
|
||||
}
|
||||
@ -416,6 +420,9 @@ struct TestBELE {
|
||||
constexpr T zero = {};
|
||||
constexpr T zero_copy = T::make(zero);
|
||||
assert_noexcept(zero_copy == 0);
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
static_assert(zero_copy == 0);
|
||||
#endif
|
||||
}
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
{
|
||||
@ -443,7 +450,12 @@ struct TestBELE {
|
||||
static_assert(upx::max(one, U(4)) == 4);
|
||||
static_assert(upx::align_down(one, four) == 0);
|
||||
static_assert(upx::align_up(one, four) == 4);
|
||||
static_assert(upx::align_up(one, four) == four);
|
||||
static_assert(upx::align_gap(one, four) == 3);
|
||||
static_assert(upx::align_gap(one, four) == T::make(four - 1));
|
||||
static_assert(upx::align_gap(one, four) == T::make(four - one));
|
||||
static_assert(upx::align_gap(one, four) == T::make(four + one - one - one));
|
||||
static_assert(upx::align_gap(one, four) == T::make(four + one - 2 * one));
|
||||
constexpr T one_copy = T::make(one);
|
||||
static_assert(one_copy == one);
|
||||
static_assert(one_copy == 1);
|
||||
@ -457,10 +469,10 @@ template <class T, bool T_is_signed>
|
||||
struct CheckSignedness {
|
||||
template <class U, bool U_is_signed>
|
||||
static inline void checkU(void) noexcept {
|
||||
COMPILE_TIME_ASSERT(sizeof(U) == sizeof(T));
|
||||
COMPILE_TIME_ASSERT(alignof(U) == alignof(T));
|
||||
static_assert(sizeof(U) == sizeof(T));
|
||||
static_assert(alignof(U) == alignof(T));
|
||||
constexpr U all_bits = (U) (U(0) - U(1));
|
||||
COMPILE_TIME_ASSERT(U_is_signed ? (all_bits < 0) : (all_bits > 0));
|
||||
static_assert(U_is_signed ? (all_bits < 0) : (all_bits > 0));
|
||||
}
|
||||
static void check(void) noexcept {
|
||||
checkU<T, T_is_signed>();
|
||||
@ -620,9 +632,9 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
auto a = +0;
|
||||
constexpr auto b = -0;
|
||||
const auto &c = -1;
|
||||
COMPILE_TIME_ASSERT((std::is_same<int, decltype(a)>::value))
|
||||
COMPILE_TIME_ASSERT((std::is_same<const int, decltype(b)>::value))
|
||||
COMPILE_TIME_ASSERT((std::is_same<const int &, decltype(c)>::value))
|
||||
static_assert((std::is_same<int, decltype(a)>::value));
|
||||
static_assert((std::is_same<const int, decltype(b)>::value));
|
||||
static_assert((std::is_same<const int &, decltype(c)>::value));
|
||||
UNUSED(a);
|
||||
UNUSED(b);
|
||||
UNUSED(c);
|
||||
@ -634,18 +646,18 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
#include "../util/miniacc.h"
|
||||
#undef ACCCHK_ASSERT
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(char) == 1)
|
||||
COMPILE_TIME_ASSERT(sizeof(short) == 2)
|
||||
COMPILE_TIME_ASSERT(sizeof(int) == 4)
|
||||
COMPILE_TIME_ASSERT(sizeof(long) >= 4)
|
||||
COMPILE_TIME_ASSERT(sizeof(void *) >= 4)
|
||||
static_assert(sizeof(char) == 1);
|
||||
static_assert(sizeof(short) == 2);
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long) >= 4);
|
||||
static_assert(sizeof(void *) >= 4);
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(BE16) == 2)
|
||||
COMPILE_TIME_ASSERT(sizeof(BE32) == 4)
|
||||
COMPILE_TIME_ASSERT(sizeof(BE64) == 8)
|
||||
COMPILE_TIME_ASSERT(sizeof(LE16) == 2)
|
||||
COMPILE_TIME_ASSERT(sizeof(LE32) == 4)
|
||||
COMPILE_TIME_ASSERT(sizeof(LE64) == 8)
|
||||
static_assert(sizeof(BE16) == 2);
|
||||
static_assert(sizeof(BE32) == 4);
|
||||
static_assert(sizeof(BE64) == 8);
|
||||
static_assert(sizeof(LE16) == 2);
|
||||
static_assert(sizeof(LE32) == 4);
|
||||
static_assert(sizeof(LE64) == 8);
|
||||
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(BE16)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(BE32)
|
||||
@ -684,9 +696,9 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
CheckSignedness<upx_sptraddr_t, true>::check();
|
||||
CheckSignedness<upx_uintptr_t, false>::check();
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(upx_charptr_unit_type) == 1)
|
||||
static_assert(sizeof(upx_charptr_unit_type) == 1);
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type)
|
||||
COMPILE_TIME_ASSERT(sizeof(*((charptr) nullptr)) == 1)
|
||||
static_assert(sizeof(*((charptr) nullptr)) == 1);
|
||||
|
||||
// check UPX_VERSION_xxx
|
||||
{
|
||||
|
@ -120,8 +120,10 @@ static_assert(!compile_time::string_gt("abc", "abz"));
|
||||
static_assert(!compile_time::string_ge("abc", "abz"));
|
||||
static_assert(compile_time::string_le("abc", "abz"));
|
||||
|
||||
static_assert(compile_time::mem_eq((const char *) nullptr, nullptr, 0));
|
||||
static_assert(compile_time::mem_eq((const byte *) nullptr, nullptr, 0));
|
||||
static_assert(compile_time::mem_eq((const char *) nullptr, (const char *) nullptr, 0));
|
||||
static_assert(compile_time::mem_eq((const char *) nullptr, (const byte *) nullptr, 0));
|
||||
static_assert(compile_time::mem_eq((const byte *) nullptr, (const char *) nullptr, 0));
|
||||
static_assert(compile_time::mem_eq((const byte *) nullptr, (const byte *) nullptr, 0));
|
||||
static_assert(compile_time::mem_eq("", "", 0));
|
||||
static_assert(compile_time::mem_eq("abc", "abc", 3));
|
||||
static_assert(!compile_time::mem_eq("abc", "abz", 3));
|
||||
@ -408,6 +410,7 @@ TEST_CASE("upx::ObjectDeleter 2") {
|
||||
TEST_CASE("upx::ptr_static_cast") {
|
||||
// check that we do not trigger any -Wcast-align warnings
|
||||
using upx::ptr_static_cast;
|
||||
|
||||
void *vp = nullptr;
|
||||
byte *bp = nullptr;
|
||||
int *ip = nullptr;
|
||||
@ -445,6 +448,110 @@ TEST_CASE("upx::ptr_static_cast") {
|
||||
assert((ic == ptr_static_cast<const int *>(ic)));
|
||||
}
|
||||
|
||||
TEST_CASE("upx::ptr_static_cast constexpr 1") {
|
||||
// check that casts work at compile-time
|
||||
using upx::ptr_static_cast;
|
||||
|
||||
constexpr void *vp = nullptr;
|
||||
constexpr byte *bp = nullptr;
|
||||
constexpr int *ip = nullptr;
|
||||
constexpr double *dp = nullptr;
|
||||
static_assert((vp == ptr_static_cast<void *>(vp)));
|
||||
static_assert((bp == ptr_static_cast<byte *>(bp)));
|
||||
static_assert((ip == ptr_static_cast<int *>(ip)));
|
||||
static_assert((dp == ptr_static_cast<double *>(dp)));
|
||||
|
||||
constexpr const void *vc = nullptr;
|
||||
constexpr const byte *bc = nullptr;
|
||||
constexpr const int *ic = nullptr;
|
||||
constexpr const double *dc = nullptr;
|
||||
static_assert((vc == ptr_static_cast<const void *>(vc)));
|
||||
static_assert((bc == ptr_static_cast<const byte *>(bc)));
|
||||
static_assert((ic == ptr_static_cast<const int *>(ic)));
|
||||
static_assert((dc == ptr_static_cast<const double *>(dc)));
|
||||
|
||||
constexpr void **vpp = nullptr;
|
||||
constexpr byte **bpp = nullptr;
|
||||
constexpr int **ipp = nullptr;
|
||||
constexpr double **dpp = nullptr;
|
||||
static_assert((vpp == ptr_static_cast<void **>(vpp)));
|
||||
static_assert((bpp == ptr_static_cast<byte **>(bpp)));
|
||||
static_assert((ipp == ptr_static_cast<int **>(ipp)));
|
||||
static_assert((dpp == ptr_static_cast<double **>(dpp)));
|
||||
|
||||
constexpr const void **vcp = nullptr;
|
||||
constexpr const byte **bcp = nullptr;
|
||||
constexpr const int **icp = nullptr;
|
||||
constexpr const double **dcp = nullptr;
|
||||
static_assert((vcp == ptr_static_cast<const void **>(vcp)));
|
||||
static_assert((bcp == ptr_static_cast<const byte **>(bcp)));
|
||||
static_assert((icp == ptr_static_cast<const int **>(icp)));
|
||||
static_assert((dcp == ptr_static_cast<const double **>(dcp)));
|
||||
|
||||
constexpr void *const *vpc = nullptr;
|
||||
constexpr byte *const *bpc = nullptr;
|
||||
constexpr int *const *ipc = nullptr;
|
||||
constexpr double *const *dpc = nullptr;
|
||||
static_assert((vpc == ptr_static_cast<void *const *>(vpc)));
|
||||
static_assert((bpc == ptr_static_cast<byte *const *>(bpc)));
|
||||
static_assert((ipc == ptr_static_cast<int *const *>(ipc)));
|
||||
static_assert((dpc == ptr_static_cast<double *const *>(dpc)));
|
||||
|
||||
constexpr const void *const *vcc = nullptr;
|
||||
constexpr const byte *const *bcc = nullptr;
|
||||
constexpr const int *const *icc = nullptr;
|
||||
constexpr const double *const *dcc = nullptr;
|
||||
static_assert((vcc == ptr_static_cast<const void *const *>(vcc)));
|
||||
static_assert((bcc == ptr_static_cast<const byte *const *>(bcc)));
|
||||
static_assert((icc == ptr_static_cast<const int *const *>(icc)));
|
||||
static_assert((dcc == ptr_static_cast<const double *const *>(dcc)));
|
||||
}
|
||||
|
||||
TEST_CASE("upx::ptr_static_cast constexpr 2") {
|
||||
// check that casts work at compile-time
|
||||
using upx::ptr_static_cast;
|
||||
|
||||
constexpr void *vp = nullptr;
|
||||
constexpr byte *bp = nullptr;
|
||||
constexpr int *ip = nullptr;
|
||||
constexpr double *dp = nullptr;
|
||||
static_assert((vp == static_cast<void *>(vp)));
|
||||
static_assert((vp == static_cast<void *>(bp)));
|
||||
static_assert((vp == static_cast<void *>(ip)));
|
||||
static_assert((vp == static_cast<void *>(dp)));
|
||||
static_assert((vp == ptr_static_cast<void *>(vp)));
|
||||
static_assert((vp == ptr_static_cast<void *>(bp)));
|
||||
static_assert((vp == ptr_static_cast<void *>(ip)));
|
||||
static_assert((vp == ptr_static_cast<void *>(dp)));
|
||||
|
||||
constexpr const void *vc = nullptr;
|
||||
constexpr const byte *bc = nullptr;
|
||||
constexpr const int *ic = nullptr;
|
||||
constexpr const double *dc = nullptr;
|
||||
static_assert((vc == static_cast<const void *>(vp)));
|
||||
static_assert((vc == static_cast<const void *>(bp)));
|
||||
static_assert((vc == static_cast<const void *>(ip)));
|
||||
static_assert((vc == static_cast<const void *>(dp)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(vp)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(dp)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(bp)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(ip)));
|
||||
static_assert((vc == static_cast<const void *>(vc)));
|
||||
static_assert((vc == static_cast<const void *>(bc)));
|
||||
static_assert((vc == static_cast<const void *>(ic)));
|
||||
static_assert((vc == static_cast<const void *>(dc)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(vc)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(dc)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(bc)));
|
||||
static_assert((vc == ptr_static_cast<const void *>(ic)));
|
||||
|
||||
// these are invalid:
|
||||
//// constexpr char *cc1 = static_cast<char *>(bp);
|
||||
//// constexpr char *cc2 = ptr_static_cast<char *>(bp);
|
||||
//// constexpr unsigned *uc1 = static_cast<unsigned *>(ip);
|
||||
//// constexpr unsigned *uc2 = ptr_static_cast<unsigned *>(ip);
|
||||
}
|
||||
|
||||
TEST_CASE("upx::noncopyable") {
|
||||
struct Test : private upx::noncopyable {
|
||||
int v = 1;
|
||||
|
@ -239,7 +239,7 @@ forceinline constexpr T wrapping_sub(const T &a, const T &b) noexcept {
|
||||
**************************************************************************/
|
||||
|
||||
template <std::size_t Size>
|
||||
struct UnsignedSizeOf {
|
||||
struct UnsignedSizeOf final {
|
||||
static_assert(Size >= 1 && Size <= UPX_RSIZE_MAX_MEM);
|
||||
static constexpr unsigned value = unsigned(Size);
|
||||
};
|
||||
@ -248,9 +248,9 @@ struct UnsignedSizeOf {
|
||||
template <class Result, class From>
|
||||
forceinline constexpr Result ptr_static_cast(From *ptr) noexcept {
|
||||
static_assert(std::is_pointer_v<Result>);
|
||||
static_assert(!std::is_const_v<std::remove_pointer_t<Result> >); // enforce same constness
|
||||
// don't cast through "void *" if types already match
|
||||
typedef std::conditional_t<std::is_same_v<Result, decltype(ptr)>, Result, void *> VoidPtr;
|
||||
// don't cast through "void *" if type is convertible
|
||||
typedef std::conditional_t<std::is_convertible_v<decltype(ptr), Result>, Result, void *>
|
||||
VoidPtr;
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
return static_cast<Result>(static_cast<VoidPtr>(ptr));
|
||||
}
|
||||
@ -258,8 +258,9 @@ template <class Result, class From>
|
||||
forceinline constexpr Result ptr_static_cast(const From *ptr) noexcept {
|
||||
static_assert(std::is_pointer_v<Result>);
|
||||
static_assert(std::is_const_v<std::remove_pointer_t<Result> >); // required
|
||||
// don't cast through "void *" if types already match
|
||||
typedef std::conditional_t<std::is_same_v<Result, decltype(ptr)>, Result, const void *> VoidPtr;
|
||||
// don't cast through "const void *" if type is convertible
|
||||
typedef std::conditional_t<std::is_convertible_v<decltype(ptr), Result>, Result, const void *>
|
||||
VoidPtr;
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
return static_cast<Result>(static_cast<VoidPtr>(ptr));
|
||||
}
|
||||
@ -387,6 +388,12 @@ constexpr bool mem_eq(const char *a, const char *b, std::size_t n) noexcept {
|
||||
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) noexcept {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
constexpr bool mem_eq(const char *a, const unsigned char *b, std::size_t n) noexcept {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
constexpr bool mem_eq(const unsigned char *a, const char *b, std::size_t n) noexcept {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
|
||||
forceinline constexpr upx_uint16_t bswap16(upx_uint16_t v) noexcept {
|
||||
return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
|
||||
|
Loading…
Reference in New Issue
Block a user