From e964d4acf3c9c0726f88a265e79846e5c8270a22 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Tue, 31 Oct 2023 12:24:44 +0100 Subject: [PATCH] src/util: change TriBool logic to use a bool template parameter --- src/check/dt_cxxlib.cpp | 41 +++++++++++++++++++++-------------------- src/options.h | 4 ++-- src/p_lx_elf.cpp | 3 +-- src/util/cxxlib.h | 13 +++++++------ 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/check/dt_cxxlib.cpp b/src/check/dt_cxxlib.cpp index 0f68fea6..32180f00 100644 --- a/src/check/dt_cxxlib.cpp +++ b/src/check/dt_cxxlib.cpp @@ -155,7 +155,7 @@ TEST_CASE("noncopyable") { namespace { template struct TestTriBool { - static void test(bool expect_true, int x) noexcept { + static void test(bool expect_true) noexcept { static_assert(std::is_class::value); static_assert(std::is_nothrow_default_constructible::value); static_assert(std::is_nothrow_destructible::value); @@ -171,7 +171,6 @@ struct TestTriBool { #endif static_assert(!bool(T(false))); static_assert(bool(T(true))); - static_assert(bool(T(T::Third)) == (T::Third > T::False)); static_assert(T(false) == T::False); static_assert(T(true) == T::True); static_assert(T(T::False) == T::False); @@ -232,7 +231,7 @@ struct TestTriBool { CHECK(!a.isStrictTrue()); CHECK(!a.isStrictBool()); CHECK(a.isThird()); - a = x; + a = 99; CHECK(a.getValue() == T::Third); if (expect_true) { CHECK(a); @@ -255,26 +254,28 @@ struct TestTriBool { TEST_CASE("TriBool") { using upx::TriBool, upx::tribool; - // static_assert(!tribool(false)); static_assert(tribool(true)); static_assert(!tribool(tribool::Third)); - TestTriBool::test(false, -1); - // - TestTriBool >::test(false, -99990); - TestTriBool >::test(false, -99991); - TestTriBool >::test(false, -99992); - TestTriBool >::test(false, -99993); - // - TestTriBool >::test(true, 99); - TestTriBool >::test(true, 99990); - TestTriBool >::test(true, 99991); - TestTriBool >::test(true, 99992); - TestTriBool >::test(true, 99993); - TestTriBool >::test(true, 99994); - TestTriBool >::test(true, 99995); - TestTriBool >::test(true, 99996); - TestTriBool >::test(true, 99997); + TestTriBool::test(false); +#if DEBUG || 1 + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(false); + TestTriBool >::test(true); + TestTriBool >::test(true); + TestTriBool >::test(true); + TestTriBool >::test(true); + TestTriBool >::test(true); + TestTriBool >::test(true); + TestTriBool >::test(true); + TestTriBool >::test(true); +#endif } /* vim:set ts=4 sw=4 et: */ diff --git a/src/options.h b/src/options.h index c0e2d606..ab949a33 100644 --- a/src/options.h +++ b/src/options.h @@ -170,8 +170,8 @@ struct Options final { struct { int compress_exports; int compress_icons; - upx::TriBool compress_resources; - upx::TriBool compress_rt[25]; // 25 == RT_LAST + upx::TriBool compress_resources; + upx::TriBool compress_rt[25]; // 25 == RT_LAST int strip_relocs; const char *keep_resource; } win32_pe; diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 037115dd..650412dc 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -2974,8 +2974,7 @@ tribool PackLinuxElf64::canUnpack() // bool, except -1: format known, but not pa return false; } -tribool -PackLinuxElf64::canPack() +tribool PackLinuxElf64::canPack() { union { unsigned char buf[MAX_ELF_HDR_64]; diff --git a/src/util/cxxlib.h b/src/util/cxxlib.h index f15aced4..798528ee 100644 --- a/src/util/cxxlib.h +++ b/src/util/cxxlib.h @@ -109,23 +109,23 @@ constexpr bool string_ge(const char *a, const char *b) { return !string_lt(a, b) /************************************************************************* // TriBool - tri-state bool // an enum with an underlying type and 3 values -// bool() checks for > 0, so ThirdValue determines if Third is false or true +// IsThirdTrue determines if Third is false or true **************************************************************************/ -template // ThirdValue is false by default +template // Third is false by default struct TriBool final { // types typedef T underlying_type; static_assert(std::is_integral_v); typedef decltype(T(0) + T(0)) promoted_type; static_assert(std::is_integral_v); - static_assert(ThirdValue != 0 && ThirdValue != 1); - enum value_type : underlying_type { False = 0, True = 1, Third = ThirdValue }; + enum value_type : underlying_type { False = 0, True = 1, Third = 2 }; static_assert(sizeof(value_type) == sizeof(underlying_type)); static_assert(sizeof(underlying_type) <= sizeof(promoted_type)); // constructors forceinline constexpr TriBool() noexcept {} forceinline constexpr TriBool(value_type x) noexcept : value(x) {} + // permissive, converts all other values to Third!! constexpr TriBool(promoted_type x) noexcept : value(x == 0 ? False : (x == 1 ? True : Third)) {} #if __cplusplus >= 202002L forceinline constexpr ~TriBool() noexcept = default; @@ -133,8 +133,9 @@ struct TriBool final { forceinline ~TriBool() noexcept = default; #endif // explicit conversion to bool - // checks for > 0, so ThirdValue determines if Third is false (the default) or true - explicit constexpr operator bool() const noexcept { return value > False; } + explicit constexpr operator bool() const noexcept { + return IsThirdTrue ? (value != False) : (value == True); + } // query; this is NOT the same as operator bool() constexpr bool isStrictFalse() const noexcept { return value == False; } constexpr bool isStrictTrue() const noexcept { return value == True; }