From 5d2c74008e031ac7f1976614ef77fc679e24c467 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Fri, 23 Jun 2023 14:13:08 +0200 Subject: [PATCH] all: cmake and noexcept updates --- CMakeLists.txt | 23 ++++++++++++++++----- src/check/dt_check.cpp | 46 +++++++++++++++++++++++++++++++----------- src/conf.h | 10 ++++----- src/packer.cpp | 8 ++++---- src/packer.h | 15 +++++++------- src/packhead.cpp | 2 +- src/util/membuffer.h | 3 ++- 7 files changed, 71 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aed94b26..e367472f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,12 @@ # Copyright (C) Markus Franz Xaver Johannes Oberhumer # -cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) # CMake >= 3.20 is recommended +# CMake version check; using a somewhat current CMake version is highly recommended +if(NOT DEFINED UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION) + cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) # needed for CXX_STANDARD 17 +else() + cmake_minimum_required(VERSION "${UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION}" FATAL_ERROR) +endif() # Build requirements: # A C++ compiler that fully implements C++17: clang-5, gcc-8 or msvc-2019 16.11 # (older or other compilers may work but are unsupported, use at your own risk) @@ -129,25 +134,33 @@ if(NOT UPX_CONFIG_DISABLE_BZIP2) file(GLOB bzip2_SOURCES "vendor/bzip2/*.c") list(SORT bzip2_SOURCES) add_library(upx_vendor_bzip2 STATIC ${bzip2_SOURCES}) -set_property(TARGET upx_vendor_bzip2 PROPERTY C_STANDARD 11) +if(NOT UPX_CONFIG_DISABLE_C_STANDARD) + set_property(TARGET upx_vendor_bzip2 PROPERTY C_STANDARD 11) endif() +endif() # UPX_CONFIG_DISABLE_BZIP2 file(GLOB ucl_SOURCES "vendor/ucl/src/*.c") list(SORT ucl_SOURCES) add_library(upx_vendor_ucl STATIC ${ucl_SOURCES}) -set_property(TARGET upx_vendor_ucl PROPERTY C_STANDARD 11) +if(NOT UPX_CONFIG_DISABLE_C_STANDARD) + set_property(TARGET upx_vendor_ucl PROPERTY C_STANDARD 11) +endif() file(GLOB zlib_SOURCES "vendor/zlib/*.c") list(SORT zlib_SOURCES) add_library(upx_vendor_zlib STATIC ${zlib_SOURCES}) -set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11) +if(NOT UPX_CONFIG_DISABLE_C_STANDARD) + set_property(TARGET upx_vendor_zlib PROPERTY C_STANDARD 11) +endif() if(NOT UPX_CONFIG_DISABLE_ZSTD) file(GLOB zstd_SOURCES "vendor/zstd/lib/*/*.c") list(SORT zstd_SOURCES) add_library(upx_vendor_zstd STATIC ${zstd_SOURCES}) -set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11) +if(NOT UPX_CONFIG_DISABLE_C_STANDARD) + set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11) endif() +endif() # UPX_CONFIG_DISABLE_ZSTD file(GLOB upx_SOURCES "src/*.cpp" "src/[cfu]*/*.cpp") list(SORT upx_SOURCES) diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index 3c5bf0d3..3600d3b1 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -322,7 +322,7 @@ struct TestBELE { template struct TestNoAliasingStruct { - static noinline bool test(A *a, B *b) { + static noinline bool test(A *a, B *b) noexcept { *a = 0; *b = 0; *b -= 3; @@ -330,13 +330,14 @@ struct TestNoAliasingStruct { } }; template -static forceinline bool testNoAliasing(A *a, B *b) { +static forceinline bool testNoAliasing(A *a, B *b) noexcept { return TestNoAliasingStruct::test(a, b); } template struct TestIntegerWrap { - static inline bool inc(T x) { return x + 1 > x; } - static inline bool dec(T x) { return x - 1 < x; } + static inline bool inc_gt(const T x) noexcept { return x + 1 > x; } + static inline bool dec_lt(const T x) noexcept { return x - 1 < x; } + static inline bool neg_eq(const T x) noexcept { return T(0) - x == x; } }; } // namespace @@ -504,21 +505,42 @@ void upx_compiler_sanity_check(void) { assert(testNoAliasing(&u.v_int, &u.v_llong)); assert(testNoAliasing(&u.v_long, &u.v_llong)); - assert(TestIntegerWrap::inc(0)); - assert(!TestIntegerWrap::inc(UINT_MAX)); - assert(TestIntegerWrap::dec(1)); - assert(!TestIntegerWrap::dec(0)); + assert(TestIntegerWrap::inc_gt(0)); + assert(!TestIntegerWrap::inc_gt(UINT_MAX)); + assert(TestIntegerWrap::dec_lt(1)); + assert(!TestIntegerWrap::dec_lt(0)); + assert(TestIntegerWrap::neg_eq(0)); + assert(!TestIntegerWrap::neg_eq(1)); + assert(!TestIntegerWrap::neg_eq(UINT_MAX)); // check working -fno-strict-overflow - assert(TestIntegerWrap::inc(0)); - assert(!TestIntegerWrap::inc(INT_MAX)); - assert(TestIntegerWrap::dec(0)); - assert(!TestIntegerWrap::dec(INT_MIN)); + assert(TestIntegerWrap::inc_gt(0)); + assert(!TestIntegerWrap::inc_gt(INT_MAX)); + assert(TestIntegerWrap::dec_lt(0)); + assert(!TestIntegerWrap::dec_lt(INT_MIN)); + assert(TestIntegerWrap::neg_eq(0)); + assert(!TestIntegerWrap::neg_eq(1)); + assert(!TestIntegerWrap::neg_eq(INT_MAX)); + assert(TestIntegerWrap::neg_eq(INT_MIN)); // !! } /************************************************************************* // some doctest test cases **************************************************************************/ +TEST_CASE("noncopyable") { + struct Test : private noncopyable { + int v = 1; + }; + Test t = {}; + CHECK(t.v == 1); +#if (ACC_CC_MSC) // MSVC thinks that Test is not std::is_trivially_copyable; compiler bug? + t.v = 0; +#else + mem_clear(&t); +#endif + CHECK(t.v == 0); +} + TEST_CASE("acc_vget") { CHECK_EQ(acc_vget_int(0, 0), 0); CHECK_EQ(acc_vget_long(1, -1), 1); diff --git a/src/conf.h b/src/conf.h index 18ee56fe..ad6ce759 100644 --- a/src/conf.h +++ b/src/conf.h @@ -410,12 +410,12 @@ inline void mem_clear(T (&array)[N]) noexcept = delete; class noncopyable { protected: inline noncopyable() noexcept {} - inline ~noncopyable() noexcept {} + inline ~noncopyable() noexcept = default; private: - noncopyable(const noncopyable &) DELETED_FUNCTION; // copy constructor - noncopyable& operator=(const noncopyable &) DELETED_FUNCTION; // copy assignment - noncopyable(noncopyable &&) DELETED_FUNCTION; // move constructor - noncopyable& operator=(noncopyable &&) DELETED_FUNCTION; // move assignment + 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 }; diff --git a/src/packer.cpp b/src/packer.cpp index 5fbe72f5..5ef092b2 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -148,7 +148,7 @@ bool Packer::testUnpackFormat(int format) const { return canUnpackFormat(format); } -bool ph_skipVerify(const PackHeader &ph) { +bool ph_skipVerify(const PackHeader &ph) noexcept { if (M_IS_DEFLATE(ph.method)) return false; if (M_IS_LZMA(ph.method)) @@ -158,17 +158,17 @@ bool ph_skipVerify(const PackHeader &ph) { return true; } -int force_method(int method) // mark as forced +int force_method(int method) noexcept // mark as forced { return (0x80ul << 24) | method; } -int is_forced_method(int method) // predicate +int is_forced_method(int method) noexcept // predicate { return -0x80 == (method >> 24); } -int forced_method(int method) // extract the forced method +int forced_method(int method) noexcept // extract the forced method { if (is_forced_method(method)) method &= ~(0x80ul << 24); diff --git a/src/packer.h b/src/packer.h index 55daaebf..25177b6b 100644 --- a/src/packer.h +++ b/src/packer.h @@ -36,16 +36,15 @@ class UiPacker; class Filter; /************************************************************************* -// +// PackHeader +// also see stub/src/include/header.S **************************************************************************/ -// see stub/src/include/header.S class PackHeader final { friend class Packer; // these are strictly private to friend Packer - PackHeader(); - + PackHeader() noexcept; void putPackHeader(SPAN_S(byte) p); bool decodePackHeaderFromBuf(SPAN_S(const byte) b, int blen); @@ -91,7 +90,7 @@ public: unsigned overlap_overhead; }; -bool ph_skipVerify(const PackHeader &ph); +bool ph_skipVerify(const PackHeader &ph) noexcept; void ph_decompress(PackHeader &ph, SPAN_P(const byte) in, SPAN_P(byte) out, bool verify_checksum, Filter *ft); bool ph_testOverlappingDecompression(const PackHeader &ph, SPAN_P(const byte) buf, @@ -358,8 +357,8 @@ private: Packer &operator=(Packer &&) = delete; }; -int force_method(int method); // (0x80ul<<24)|method -int forced_method(int method); // (0x80ul<<24)|method ==> method -int is_forced_method(int method); // predicate +int force_method(int method) noexcept; // (0x80ul<<24)|method +int forced_method(int method) noexcept; // (0x80ul<<24)|method ==> method +int is_forced_method(int method) noexcept; // predicate /* vim:set ts=4 sw=4 et: */ diff --git a/src/packhead.cpp b/src/packhead.cpp index 8c8ca279..9148257c 100644 --- a/src/packhead.cpp +++ b/src/packhead.cpp @@ -35,7 +35,7 @@ // least to detect older versions, so this is a little bit messy. **************************************************************************/ -PackHeader::PackHeader() : version(-1), format(-1) {} +PackHeader::PackHeader() noexcept : version(-1), format(-1) {} /************************************************************************* // very simple checksum for the header itself (since version 10) diff --git a/src/util/membuffer.h b/src/util/membuffer.h index 3741777c..e261d2a7 100644 --- a/src/util/membuffer.h +++ b/src/util/membuffer.h @@ -31,6 +31,7 @@ // gets destructed when leaving scope or on exceptions. /************************************************************************* +// MemBufferBase // provides some base functionality for treating a MemBuffer as a pointer **************************************************************************/ @@ -84,7 +85,7 @@ public: // raw access private: // 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] - MemBufferBase *operator&() const DELETED_FUNCTION; + MemBufferBase *operator&() const noexcept DELETED_FUNCTION; }; /*************************************************************************