CI updates; cxxlib.h cleanups
This commit is contained in:
@@ -17,5 +17,5 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with: { submodules: false }
|
with: { submodules: false }
|
||||||
- name: 'Spell check with crate-ci/typos'
|
- name: 'Spell check with crate-ci/typos'
|
||||||
uses: crate-ci/typos@5bd389de715c63ba86568420809e324fcea78660 # v1.16.25
|
uses: crate-ci/typos@45a880d9f898547e8bfe6525b6059d4b3dea4d71 # v1.16.26
|
||||||
with: { config: ./.github/typos_config.toml }
|
with: { config: ./.github/typos_config.toml }
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ jobs:
|
|||||||
- { container: 'alpine:3.19', release: debug, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
- { container: 'alpine:3.19', release: debug, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
||||||
- { container: 'alpine:3.19', release: release, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
- { container: 'alpine:3.19', release: release, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
||||||
- { container: 'alpine:edge', release: release, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
- { container: 'alpine:edge', release: release, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
||||||
|
- { container: 'i386/alpine:3.19', release: release, qemu: 'qemu-i386' }
|
||||||
- { container: 'i386/alpine:edge', release: release, qemu: 'qemu-i386' }
|
- { container: 'i386/alpine:edge', release: release, qemu: 'qemu-i386' }
|
||||||
name: ${{ format('{0} {1}', matrix.container, matrix.release) }}
|
name: ${{ format('{0} {1}', matrix.container, matrix.release) }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -45,7 +46,8 @@ jobs:
|
|||||||
|
|
||||||
- name: 'Build clang-static'
|
- name: 'Build clang-static'
|
||||||
run: |
|
run: |
|
||||||
export CC="clang -static" CXX="clang++ -static"
|
flags="-static -fno-omit-frame-pointer"
|
||||||
|
export CC="clang $flags" CXX="clang++ $flags"
|
||||||
make UPX_XTARGET=clang-static xtarget/$release
|
make UPX_XTARGET=clang-static xtarget/$release
|
||||||
- name: 'Build clang-asan'
|
- name: 'Build clang-asan'
|
||||||
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: ASAN not supported
|
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: ASAN not supported
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ function(upx_print_var) # ARGV
|
|||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(upx_print_have_symbol) # ARGV
|
function(upx_print_have_symbol) # ARGV; needs include(CheckSymbolExists)
|
||||||
foreach(symbol ${ARGV})
|
foreach(symbol ${ARGV})
|
||||||
set(cache_var_name "HAVE_symbol_${symbol}")
|
set(cache_var_name "HAVE_symbol_${symbol}")
|
||||||
check_symbol_exists(${symbol} "limits.h;stddef.h;stdint.h" ${cache_var_name})
|
check_symbol_exists(${symbol} "limits.h;stddef.h;stdint.h" ${cache_var_name})
|
||||||
@@ -147,7 +147,7 @@ endfunction()
|
|||||||
# compilation flags
|
# compilation flags
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
|
|
||||||
function(upx_internal_add_definitions_with_prefix) # ARGV
|
function(upx_internal_add_definitions_with_prefix) # ARGV; needs include(CheckCCompilerFlag)
|
||||||
set(flag_prefix "${ARGV0}")
|
set(flag_prefix "${ARGV0}")
|
||||||
if(flag_prefix MATCHES "^empty$") # need "empty" to work around bug in old CMake versions
|
if(flag_prefix MATCHES "^empty$") # need "empty" to work around bug in old CMake versions
|
||||||
set(flag_prefix "")
|
set(flag_prefix "")
|
||||||
@@ -168,7 +168,7 @@ function(upx_internal_add_definitions_with_prefix) # ARGV
|
|||||||
set(failed_flags "${failed}" PARENT_SCOPE) # return value
|
set(failed_flags "${failed}" PARENT_SCOPE) # return value
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(upx_add_definitions) # ARGV
|
function(upx_add_definitions) # ARGV; needs include(CheckCCompilerFlag)
|
||||||
set(failed_flags "")
|
set(failed_flags "")
|
||||||
if(MSVC_FRONTEND AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
if(MSVC_FRONTEND AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
# for clang-cl try "-clang:" flag prefix first
|
# for clang-cl try "-clang:" flag prefix first
|
||||||
|
|||||||
+6
-15
@@ -79,12 +79,9 @@ struct AbstractPolicy {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// disable copy and move
|
// disable copy and move
|
||||||
AbstractPolicy(const AbstractPolicy &) DELETED_FUNCTION;
|
UPX_CXX_DISABLE_COPY_MOVE(AbstractPolicy)
|
||||||
AbstractPolicy &operator=(const AbstractPolicy &) DELETED_FUNCTION;
|
|
||||||
AbstractPolicy(AbstractPolicy &&) noexcept DELETED_FUNCTION;
|
|
||||||
AbstractPolicy &operator=(AbstractPolicy &&) noexcept DELETED_FUNCTION;
|
|
||||||
// disable dynamic allocation
|
// disable dynamic allocation
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(AbstractPolicy)
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -147,12 +144,9 @@ struct BEPolicy
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// disable copy and move
|
// disable copy and move
|
||||||
BEPolicy(const BEPolicy &) DELETED_FUNCTION;
|
UPX_CXX_DISABLE_COPY_MOVE(BEPolicy)
|
||||||
BEPolicy &operator=(const BEPolicy &) DELETED_FUNCTION;
|
|
||||||
BEPolicy(BEPolicy &&) noexcept DELETED_FUNCTION;
|
|
||||||
BEPolicy &operator=(BEPolicy &&) noexcept DELETED_FUNCTION;
|
|
||||||
// disable dynamic allocation
|
// disable dynamic allocation
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(BEPolicy)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LEPolicy
|
struct LEPolicy
|
||||||
@@ -209,12 +203,9 @@ struct LEPolicy
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// disable copy and move
|
// disable copy and move
|
||||||
LEPolicy(const LEPolicy &) DELETED_FUNCTION;
|
UPX_CXX_DISABLE_COPY_MOVE(LEPolicy)
|
||||||
LEPolicy &operator=(const LEPolicy &) DELETED_FUNCTION;
|
|
||||||
LEPolicy(LEPolicy &&) noexcept DELETED_FUNCTION;
|
|
||||||
LEPolicy &operator=(LEPolicy &&) noexcept DELETED_FUNCTION;
|
|
||||||
// disable dynamic allocation
|
// disable dynamic allocation
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(LEPolicy)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Native Endianness policy (aka host policy)
|
// Native Endianness policy (aka host policy)
|
||||||
|
|||||||
@@ -564,6 +564,17 @@ TEST_CASE("acc_vget") {
|
|||||||
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
|
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("ptr_invalidate_and_poison") {
|
||||||
|
int *ip = nullptr;
|
||||||
|
ptr_invalidate_and_poison(ip);
|
||||||
|
assert(ip != nullptr);
|
||||||
|
(void) ip;
|
||||||
|
double *dp;
|
||||||
|
ptr_invalidate_and_poison(dp);
|
||||||
|
assert(dp != nullptr);
|
||||||
|
(void) dp;
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("working -fno-strict-aliasing") {
|
TEST_CASE("working -fno-strict-aliasing") {
|
||||||
bool ok;
|
bool ok;
|
||||||
long v = 0;
|
long v = 0;
|
||||||
|
|||||||
+54
-9
@@ -98,9 +98,54 @@ ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_ge("abc", "abz"))
|
|||||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
|
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// UPX_CXX_DISABLE_NEW_DELETE
|
// UPX_CXX_DISABLE_xxx
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <class TA, class TB, int TC = 0>
|
||||||
|
struct MyType1 {
|
||||||
|
MyType1() noexcept {}
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(MyType1)
|
||||||
|
UPX_CXX_DISABLE_COPY_MOVE(MyType1)
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(MyType1)
|
||||||
|
};
|
||||||
|
template <class TA, class TB, int TC = 0>
|
||||||
|
struct MyType2 {
|
||||||
|
MyType2() noexcept {}
|
||||||
|
UPX_CXX_DISABLE_COPY_MOVE(MyType2)
|
||||||
|
typedef MyType2<TA, TB, TC> Self;
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(Self)
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(Self)
|
||||||
|
};
|
||||||
|
template <class TA, class TB, int TC = 0>
|
||||||
|
struct MyVType1 {
|
||||||
|
MyVType1() noexcept {}
|
||||||
|
virtual ~MyVType1() noexcept {}
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(MyVType1)
|
||||||
|
UPX_CXX_DISABLE_COPY_MOVE(MyVType1)
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE(MyVType1)
|
||||||
|
};
|
||||||
|
template <class TA, class TB, int TC = 0>
|
||||||
|
struct MyVType2 {
|
||||||
|
MyVType2() noexcept {}
|
||||||
|
virtual ~MyVType2() noexcept {}
|
||||||
|
UPX_CXX_DISABLE_COPY_MOVE(MyVType2)
|
||||||
|
typedef MyVType2<TA, TB, TC> Self;
|
||||||
|
UPX_CXX_DISABLE_ADDRESS(Self)
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE(Self)
|
||||||
|
};
|
||||||
|
TEST_CASE("upx_cxx_disable") {
|
||||||
|
MyType1<char, int, 1> dummy1;
|
||||||
|
MyType2<char, int, 2> dummy2;
|
||||||
|
MyVType1<char, int, 1> vdummy1;
|
||||||
|
MyVType2<char, int, 2> vdummy2;
|
||||||
|
(void) dummy1;
|
||||||
|
(void) dummy2;
|
||||||
|
(void) vdummy1;
|
||||||
|
(void) vdummy2;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace test_disable_new_delete {
|
namespace test_disable_new_delete {
|
||||||
|
|
||||||
struct A1 {
|
struct A1 {
|
||||||
@@ -108,7 +153,7 @@ struct A1 {
|
|||||||
};
|
};
|
||||||
struct A2 {
|
struct A2 {
|
||||||
int a;
|
int a;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(A2)
|
||||||
};
|
};
|
||||||
struct B1_A1 : public A1 {
|
struct B1_A1 : public A1 {
|
||||||
int b;
|
int b;
|
||||||
@@ -118,11 +163,11 @@ struct B1_A2 : public A2 {
|
|||||||
};
|
};
|
||||||
struct B2_A1 : public A1 {
|
struct B2_A1 : public A1 {
|
||||||
int b;
|
int b;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(B2_A1)
|
||||||
};
|
};
|
||||||
struct B2_A2 : public A2 {
|
struct B2_A2 : public A2 {
|
||||||
int b;
|
int b;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(B2_A2)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct X1 {
|
struct X1 {
|
||||||
@@ -132,7 +177,7 @@ struct X1 {
|
|||||||
struct X2 {
|
struct X2 {
|
||||||
virtual ~X2() noexcept {}
|
virtual ~X2() noexcept {}
|
||||||
int x;
|
int x;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(X2)
|
||||||
};
|
};
|
||||||
struct Y1_X1 : public X1 {
|
struct Y1_X1 : public X1 {
|
||||||
int y;
|
int y;
|
||||||
@@ -142,11 +187,11 @@ struct Y1_X2 : public X2 {
|
|||||||
};
|
};
|
||||||
struct Y2_X1 : public X1 {
|
struct Y2_X1 : public X1 {
|
||||||
int y;
|
int y;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(Y2_X1)
|
||||||
};
|
};
|
||||||
struct Y2_X2 : public X2 {
|
struct Y2_X2 : public X2 {
|
||||||
int y;
|
int y;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(Y2_X2)
|
||||||
};
|
};
|
||||||
struct Z1_X1 : public X1 {
|
struct Z1_X1 : public X1 {
|
||||||
virtual ~Z1_X1() noexcept {}
|
virtual ~Z1_X1() noexcept {}
|
||||||
@@ -159,12 +204,12 @@ struct Z1_X2 : public X2 {
|
|||||||
struct Z2_X1 : public X1 {
|
struct Z2_X1 : public X1 {
|
||||||
virtual ~Z2_X1() noexcept {}
|
virtual ~Z2_X1() noexcept {}
|
||||||
int z;
|
int z;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(Z2_X1)
|
||||||
};
|
};
|
||||||
struct Z2_X2 : public X2 {
|
struct Z2_X2 : public X2 {
|
||||||
virtual ~Z2_X2() noexcept {}
|
virtual ~Z2_X2() noexcept {}
|
||||||
int z;
|
int z;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(Z2_X2)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace test_disable_new_delete
|
} // namespace test_disable_new_delete
|
||||||
|
|||||||
+5
-6
@@ -43,7 +43,7 @@ protected:
|
|||||||
Throwable(const char *m = nullptr, int e = 0, bool w = false) noexcept;
|
Throwable(const char *m = nullptr, int e = 0, bool w = false) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Throwable(const Throwable &) noexcept;
|
Throwable(const Throwable &) noexcept; // copy constructor
|
||||||
virtual ~Throwable() noexcept;
|
virtual ~Throwable() noexcept;
|
||||||
const char *getMsg() const noexcept { return msg; }
|
const char *getMsg() const noexcept { return msg; }
|
||||||
int getErrno() const noexcept { return err; }
|
int getErrno() const noexcept { return err; }
|
||||||
@@ -57,14 +57,13 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// disable copy assignment and move
|
// disable copy assignment and move
|
||||||
Throwable &operator=(const Throwable &) DELETED_FUNCTION;
|
Throwable &operator=(const Throwable &) noexcept DELETED_FUNCTION; // copy assignment
|
||||||
Throwable(Throwable &&) noexcept DELETED_FUNCTION;
|
UPX_CXX_DISABLE_MOVE(Throwable)
|
||||||
Throwable &operator=(Throwable &&) noexcept DELETED_FUNCTION;
|
|
||||||
// disable dynamic allocation => force throwing by value
|
// disable dynamic allocation => force throwing by value
|
||||||
UPX_CXX_DISABLE_NEW_DELETE
|
UPX_CXX_DISABLE_NEW_DELETE(Throwable)
|
||||||
// disable taking the address => force passing by reference
|
// disable taking the address => force passing by reference
|
||||||
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||||
Throwable *operator&() const noexcept DELETED_FUNCTION;
|
UPX_CXX_DISABLE_ADDRESS(Throwable)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static upx_std_atomic(size_t) debug_counter; // for debugging
|
static upx_std_atomic(size_t) debug_counter; // for debugging
|
||||||
|
|||||||
+1
-4
@@ -321,10 +321,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// disable copy and move
|
// disable copy and move
|
||||||
Packer(const Packer &) DELETED_FUNCTION;
|
UPX_CXX_DISABLE_COPY_MOVE(Packer)
|
||||||
Packer &operator=(const Packer &) DELETED_FUNCTION;
|
|
||||||
Packer(Packer &&) noexcept DELETED_FUNCTION;
|
|
||||||
Packer &operator=(Packer &&) noexcept DELETED_FUNCTION;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|||||||
+97
-50
@@ -33,55 +33,105 @@
|
|||||||
namespace upx {
|
namespace upx {
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// core
|
// core util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
// disable taking the address => force passing by reference (instead of pointer)
|
||||||
|
#define UPX_CXX_DISABLE_ADDRESS(Klass) \
|
||||||
|
private: \
|
||||||
|
Klass *operator&() const noexcept DELETED_FUNCTION;
|
||||||
|
|
||||||
|
// disable copy and move
|
||||||
|
#define UPX_CXX_DISABLE_COPY(KlassName) \
|
||||||
|
private: \
|
||||||
|
KlassName(const KlassName &) noexcept DELETED_FUNCTION; /* copy constructor */ \
|
||||||
|
KlassName &operator=(const KlassName &) noexcept DELETED_FUNCTION; /* copy assignment */
|
||||||
|
#define UPX_CXX_DISABLE_MOVE(KlassName) \
|
||||||
|
private: \
|
||||||
|
KlassName(KlassName &&) noexcept DELETED_FUNCTION; /* move constructor */ \
|
||||||
|
KlassName &operator=(KlassName &&) noexcept DELETED_FUNCTION; /* move assignment */
|
||||||
|
#define UPX_CXX_DISABLE_COPY_MOVE(KlassName) \
|
||||||
|
UPX_CXX_DISABLE_COPY(KlassName) \
|
||||||
|
UPX_CXX_DISABLE_MOVE(KlassName)
|
||||||
|
|
||||||
// fun with C++: disable common "new" and ALL "delete" operators
|
// fun with C++: disable common "new" and ALL "delete" operators
|
||||||
#define UPX_CXX_DISABLE_NEW_DELETE_COMMON__ \
|
// https://en.cppreference.com/w/cpp/memory/new/operator_delete
|
||||||
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL__(Klass) \
|
||||||
private: \
|
private: \
|
||||||
/* common allocation functions (4) */ \
|
/* common allocation functions (4) */ \
|
||||||
static void *operator new(std::size_t) = delete; \
|
static void *operator new(std::size_t) DELETED_FUNCTION; \
|
||||||
static void *operator new[](std::size_t) = delete; \
|
static void *operator new[](std::size_t) DELETED_FUNCTION; \
|
||||||
static void *operator new(std::size_t, void *) = delete; \
|
static void *operator new(std::size_t, void *) DELETED_FUNCTION; \
|
||||||
static void *operator new[](std::size_t, void *) = delete; \
|
static void *operator new[](std::size_t, void *) DELETED_FUNCTION; \
|
||||||
/* replaceable placement deallocation functions (4) */ \
|
/* replaceable placement deallocation functions (4) */ \
|
||||||
static void operator delete(void *, const std::nothrow_t &) noexcept = delete; \
|
static void operator delete(void *, const std::nothrow_t &) noexcept DELETED_FUNCTION; \
|
||||||
static void operator delete[](void *, const std::nothrow_t &) noexcept = delete; \
|
static void operator delete[](void *, const std::nothrow_t &) noexcept DELETED_FUNCTION; \
|
||||||
static void operator delete(void *, std::align_val_t, const std::nothrow_t &) noexcept = \
|
static void operator delete(void *, std::align_val_t, const std::nothrow_t &) \
|
||||||
delete; \
|
noexcept DELETED_FUNCTION; \
|
||||||
static void operator delete[](void *, std::align_val_t, const std::nothrow_t &) noexcept = \
|
static void operator delete[](void *, std::align_val_t, const std::nothrow_t &) \
|
||||||
delete; \
|
noexcept DELETED_FUNCTION; \
|
||||||
/* non-allocating placement deallocation functions (2) */ \
|
/* non-allocating placement deallocation functions (2) */ \
|
||||||
static void operator delete(void *, void *) noexcept = delete; \
|
static void operator delete(void *, void *) noexcept DELETED_FUNCTION; \
|
||||||
static void operator delete[](void *, void *) noexcept = delete;
|
static void operator delete[](void *, void *) noexcept DELETED_FUNCTION;
|
||||||
|
|
||||||
// for classes with virtual methods
|
/* class-specific usual deallocation functions (8) */
|
||||||
#define UPX_CXX_DISABLE_NEW_DELETE \
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_A__(Klass) \
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_COMMON__ \
|
|
||||||
/* replaceable usual deallocation functions (8) */ \
|
|
||||||
protected: \
|
protected: \
|
||||||
static void operator delete(void *) noexcept {} \
|
static void operator delete(void *) noexcept {} \
|
||||||
static void operator delete[](void *) noexcept = delete; \
|
static void operator delete(void *, std::align_val_t) noexcept {} \
|
||||||
static void operator delete(void *, std::align_val_t) {} \
|
static void operator delete(void *, std::size_t) noexcept {} \
|
||||||
static void operator delete[](void *, std::align_val_t) noexcept = delete; \
|
static void operator delete(void *, std::size_t, std::align_val_t) noexcept {} \
|
||||||
static void operator delete(void *, std::size_t) {} \
|
private: \
|
||||||
static void operator delete[](void *, std::size_t) noexcept = delete; \
|
static void operator delete[](void *) noexcept DELETED_FUNCTION; \
|
||||||
static void operator delete(void *, std::size_t, std::align_val_t) {} \
|
static void operator delete[](void *, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||||
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept = delete; \
|
static void operator delete[](void *, std::size_t) noexcept DELETED_FUNCTION; \
|
||||||
private:
|
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept DELETED_FUNCTION;
|
||||||
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_B__(Klass) \
|
||||||
|
private: \
|
||||||
|
static void operator delete(void *) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete[](void *) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete(void *, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete[](void *, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete(void *, std::size_t) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete[](void *, std::size_t) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete(void *, std::size_t, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept DELETED_FUNCTION;
|
||||||
|
|
||||||
// for classes WITHOUT any virtual methods
|
/* class-specific usual destroying deallocation functions (4) */
|
||||||
#define UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL \
|
#if __cplusplus >= 202002L
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_COMMON__ \
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_A__(Klass) \
|
||||||
/* replaceable usual deallocation functions (8) */ \
|
protected: \
|
||||||
static void operator delete(void *) noexcept = delete; \
|
static void operator delete(Klass *, std::destroying_delete_t) noexcept {} \
|
||||||
static void operator delete[](void *) noexcept = delete; \
|
static void operator delete(Klass *, std::destroying_delete_t, std::align_val_t) noexcept {} \
|
||||||
static void operator delete(void *, std::align_val_t) = delete; \
|
static void operator delete(Klass *, std::destroying_delete_t, std::size_t) noexcept {} \
|
||||||
static void operator delete[](void *, std::align_val_t) noexcept = delete; \
|
static void operator delete(Klass *, std::destroying_delete_t, std::size_t, std::align_val_t) \
|
||||||
static void operator delete(void *, std::size_t) = delete; \
|
noexcept {} \
|
||||||
static void operator delete[](void *, std::size_t) noexcept = delete; \
|
private:
|
||||||
static void operator delete(void *, std::size_t, std::align_val_t) = delete; \
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_B__(Klass) \
|
||||||
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept = delete;
|
private: \
|
||||||
|
static void operator delete(Klass *, std::destroying_delete_t) noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete(Klass *, std::destroying_delete_t, std::align_val_t) \
|
||||||
|
noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete(Klass *, std::destroying_delete_t, std::size_t) \
|
||||||
|
noexcept DELETED_FUNCTION; \
|
||||||
|
static void operator delete(Klass *, std::destroying_delete_t, std::size_t, std::align_val_t) \
|
||||||
|
noexcept DELETED_FUNCTION;
|
||||||
|
#else
|
||||||
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_A__(Klass) private:
|
||||||
|
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_B__(Klass) private:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// for classes which may have virtual methods
|
||||||
|
#define UPX_CXX_DISABLE_NEW_DELETE(Klass) \
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_IMPL__(Klass) \
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_A__(Klass) \
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_A__(Klass)
|
||||||
|
|
||||||
|
// this only works for classes WITHOUT any virtual methods
|
||||||
|
#define UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(Klass) \
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_IMPL__(Klass) \
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_B__(Klass) \
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_B__(Klass)
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// type_traits
|
// type_traits
|
||||||
@@ -137,11 +187,7 @@ protected:
|
|||||||
#else
|
#else
|
||||||
forceinline ~noncopyable() noexcept = default;
|
forceinline ~noncopyable() noexcept = default;
|
||||||
#endif
|
#endif
|
||||||
private:
|
UPX_CXX_DISABLE_COPY_MOVE(noncopyable)
|
||||||
noncopyable(const noncopyable &) noexcept DELETED_FUNCTION; // copy constructor
|
|
||||||
noncopyable &operator=(const noncopyable &) noexcept DELETED_FUNCTION; // copy assignment
|
|
||||||
noncopyable(noncopyable &&) noexcept DELETED_FUNCTION; // move constructor
|
|
||||||
noncopyable &operator=(noncopyable &&) noexcept DELETED_FUNCTION; // move assignment
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace compile_time {
|
namespace compile_time {
|
||||||
@@ -178,7 +224,7 @@ struct TriBool final {
|
|||||||
// constructors
|
// constructors
|
||||||
forceinline constexpr TriBool() noexcept {}
|
forceinline constexpr TriBool() noexcept {}
|
||||||
forceinline constexpr TriBool(value_type x) noexcept : value(x) {}
|
forceinline constexpr TriBool(value_type x) noexcept : value(x) {}
|
||||||
// permissive, converts all other values to Third!!
|
// IMPORTANT NOTE: permissive, converts all other values to Third!
|
||||||
constexpr TriBool(promoted_type x) noexcept : value(x == 0 ? False : (x == 1 ? True : Third)) {}
|
constexpr TriBool(promoted_type x) noexcept : value(x == 0 ? False : (x == 1 ? True : Third)) {}
|
||||||
#if __cplusplus >= 202002L
|
#if __cplusplus >= 202002L
|
||||||
forceinline constexpr ~TriBool() noexcept = default;
|
forceinline constexpr ~TriBool() noexcept = default;
|
||||||
@@ -214,8 +260,8 @@ struct TriBool final {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
value_type value = False; // the actual value of this type
|
value_type value = False; // the actual value of this type
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL // UPX convention
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(TriBool) // UPX convention
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TriBool<> tribool;
|
typedef TriBool<> tribool;
|
||||||
@@ -245,7 +291,7 @@ struct OptVar final {
|
|||||||
void assertValue() const noexcept { assertValue(value); }
|
void assertValue() const noexcept { assertValue(value); }
|
||||||
|
|
||||||
constexpr OptVar() noexcept {}
|
constexpr OptVar() noexcept {}
|
||||||
OptVar &operator=(const T &other) noexcept {
|
OptVar &operator=(const T &other) noexcept { // copy constructor
|
||||||
assertValue(other);
|
assertValue(other);
|
||||||
value = other;
|
value = other;
|
||||||
is_set = true;
|
is_set = true;
|
||||||
@@ -259,6 +305,7 @@ struct OptVar final {
|
|||||||
|
|
||||||
value_type value = default_value;
|
value_type value = default_value;
|
||||||
bool is_set = false;
|
bool is_set = false;
|
||||||
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(OptVar) // UPX convention
|
||||||
};
|
};
|
||||||
|
|
||||||
// optional assignments
|
// optional assignments
|
||||||
@@ -312,9 +359,9 @@ struct OwningPointer final {
|
|||||||
constexpr const_pointer operator->() const noexcept { return ptr; }
|
constexpr const_pointer operator->() const noexcept { return ptr; }
|
||||||
private:
|
private:
|
||||||
pointer ptr;
|
pointer ptr;
|
||||||
reference operator[](std::ptrdiff_t) noexcept = delete;
|
reference operator[](std::ptrdiff_t) noexcept DELETED_FUNCTION;
|
||||||
const_reference operator[](std::ptrdiff_t) const noexcept = delete;
|
const_reference operator[](std::ptrdiff_t) const noexcept DELETED_FUNCTION;
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL // UPX convention
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(OwningPointer) // UPX convention
|
||||||
};
|
};
|
||||||
// must overload mem_clear()
|
// must overload mem_clear()
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
+3
-10
@@ -84,7 +84,7 @@ public: // raw access
|
|||||||
private:
|
private:
|
||||||
// disable taking the address => force passing by reference
|
// disable taking the address => force passing by reference
|
||||||
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
// [I'm not too sure about this design decision, but we can always allow it if needed]
|
||||||
MemBufferBase<T> *operator&() const noexcept DELETED_FUNCTION;
|
UPX_CXX_DISABLE_ADDRESS(MemBufferBase)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@@ -209,15 +209,8 @@ private:
|
|||||||
Debug debug;
|
Debug debug;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// disable copy and move
|
UPX_CXX_DISABLE_COPY_MOVE(MemBuffer) // disable copy and move
|
||||||
MemBuffer(const MemBuffer &) DELETED_FUNCTION;
|
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(MemBuffer) // disable dynamic allocation
|
||||||
MemBuffer &operator=(const MemBuffer &) DELETED_FUNCTION;
|
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
MemBuffer(MemBuffer &&) noexcept DELETED_FUNCTION;
|
|
||||||
MemBuffer &operator=(MemBuffer &&) noexcept DELETED_FUNCTION;
|
|
||||||
#endif
|
|
||||||
// disable dynamic allocation
|
|
||||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
|||||||
+3
-1
@@ -128,8 +128,10 @@ forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void *
|
|||||||
// invalidate and poison a pointer: point to a non-null invalid address
|
// invalidate and poison a pointer: point to a non-null invalid address
|
||||||
// - resulting pointer should crash on dereference
|
// - resulting pointer should crash on dereference
|
||||||
// - this should be efficient, so no mmap() guard page etc.
|
// - this should be efficient, so no mmap() guard page etc.
|
||||||
// - this should play nice with runtime checkers like ASAN, MSAN, valgrind, etc.
|
// - this should play nice with runtime checkers like ASAN, MSAN, UBSAN, valgrind, etc.
|
||||||
// - this should play nice with static analyzers like clang-tidy etc.
|
// - this should play nice with static analyzers like clang-tidy etc.
|
||||||
|
// NOTE: this is clearly UB (Undefined Behaviour), and stricter compilers or
|
||||||
|
// architectures may need a more advanced/costly implementation in the future
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
|
inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
|
||||||
ptr = (T *) (void *) 251; // 0x000000fb // NOLINT(performance-no-int-to-ptr)
|
ptr = (T *) (void *) 251; // 0x000000fb // NOLINT(performance-no-int-to-ptr)
|
||||||
|
|||||||
Reference in New Issue
Block a user