diff --git a/src/check/dt_cxxlib.cpp b/src/check/dt_cxxlib.cpp index 40beda60..28271c37 100644 --- a/src/check/dt_cxxlib.cpp +++ b/src/check/dt_cxxlib.cpp @@ -88,6 +88,26 @@ ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz")) // util **************************************************************************/ +TEST_CASE("ptr_reinterpret_cast") { + using upx::ptr_reinterpret_cast; + byte *an = nullptr; + int *in = nullptr; + CHECK((an == ptr_reinterpret_cast(an))); + CHECK((an == ptr_reinterpret_cast(in))); + CHECK((in == ptr_reinterpret_cast(an))); + CHECK((in == ptr_reinterpret_cast(in))); + const byte *ac = nullptr; + const int *ic = nullptr; + CHECK((ac == ptr_reinterpret_cast(an))); + CHECK((ac == ptr_reinterpret_cast(ac))); + CHECK((ac == ptr_reinterpret_cast(in))); + CHECK((ac == ptr_reinterpret_cast(ic))); + CHECK((ic == ptr_reinterpret_cast(an))); + CHECK((ic == ptr_reinterpret_cast(ac))); + CHECK((ic == ptr_reinterpret_cast(in))); + CHECK((ic == ptr_reinterpret_cast(ic))); +} + TEST_CASE("noncopyable") { struct Test : private upx::noncopyable { int v = 1; diff --git a/src/util/cxxlib.h b/src/util/cxxlib.h index b6e42faf..030bc74e 100644 --- a/src/util/cxxlib.h +++ b/src/util/cxxlib.h @@ -31,6 +31,24 @@ namespace upx { +/************************************************************************* +// misc +**************************************************************************/ + +// a reinterpret_cast that does not trigger -Wcast-align warnings +template +forceinline Result ptr_reinterpret_cast(From *ptr) { + static_assert(std::is_pointer_v); + static_assert(!std::is_const_v >); // enforce same constness + return (Result) (void *) ptr; +} +template +forceinline Result ptr_reinterpret_cast(const From *ptr) { + static_assert(std::is_pointer_v); + static_assert(std::is_const_v >); // required + return (Result) (const void *) ptr; +} + /************************************************************************* // type_traits **************************************************************************/ diff --git a/src/util/xspan.h b/src/util/xspan.h index 0b51ac6f..06d53afc 100644 --- a/src/util/xspan.h +++ b/src/util/xspan.h @@ -158,7 +158,7 @@ inline R *xspan_make_helper__(R * /*dummy*/, MemBuffer &mb) noexcept { #define XSPAN_S_VAR(type, var, first, ...) type *var = XSPAN_S_MAKE(type, (first)) // cast to a different type (creates a new value) -#define XSPAN_TYPE_CAST(type, x) (reinterpret_cast(x)) +#define XSPAN_TYPE_CAST(type, x) (upx::ptr_reinterpret_cast(x)) // poison a pointer: point to a non-null invalid address #define XSPAN_INVALIDATE(x) ptr_invalidate_and_poison(x) diff --git a/src/util/xspan_impl_common.h b/src/util/xspan_impl_common.h index b29bb7e1..595c18d5 100644 --- a/src/util/xspan_impl_common.h +++ b/src/util/xspan_impl_common.h @@ -284,8 +284,8 @@ public: inline CSelf type_cast() const { typedef CSelf R; typedef typename R::pointer rpointer; - return R(R::Unchecked, reinterpret_cast(ptr), size_in_bytes, - reinterpret_cast(base)); + return R(R::Unchecked, upx::ptr_reinterpret_cast(ptr), size_in_bytes, + upx::ptr_reinterpret_cast(base)); } bool operator==(pointer other) const noexcept { return ptr == other; } diff --git a/src/util/xspan_impl_ptr.h b/src/util/xspan_impl_ptr.h index 0a6bd89c..4622803e 100644 --- a/src/util/xspan_impl_ptr.h +++ b/src/util/xspan_impl_ptr.h @@ -127,7 +127,7 @@ public: inline CSelf type_cast() const { typedef CSelf R; typedef typename R::pointer rpointer; - return R(reinterpret_cast(ptr)); + return R(upx::ptr_reinterpret_cast(ptr)); } // comparison