/
auroraos
/
mirror_SafeInt
Обзор
Документация
Войти
/
auroraos
/
mirror_SafeInt
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
master
Test/ConstExpr.cpp
700 строк
19 KB
David LeBlanc
Strict warnings (#54)
01 май 2023, 21:07
Не верифицирован
01 май 2023, 21:07
eeb5103
Код
Авторство
О чём код?
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #if !defined __GNUC__ // relative include path contains '..', specific to this file #pragma warning( disable: 4464 ) #else #pragma GCC diagnostic ignored "-Wunused-variable" #endif #if !defined __clang__ && defined __GNUC__ && __cplusplus >= 201402L // The gcc compiler isn't smart enough to sort out that the constexpr exception functions // are never hit, so create a null exception handler. Nothing in this file is tested at runtime in any case. class SafeIntGccCompileOnly { public: constexpr static void SafeIntOnOverflow() { } constexpr static void SafeIntOnDivZero() { } }; #define SafeIntDefaultExceptionHandler SafeIntGccCompileOnly #endif #include "../SafeInt.hpp" namespace TestConstExpr { template <typename T, typename U> SAFEINT_CONSTEXPR11 bool LessThanTest() { return (U)2 < SafeInt<T>(3) && SafeInt<T>(4) < (U)5 && SafeInt<T>(6) < SafeInt<U>(7); } template <typename T, typename U> SAFEINT_CONSTEXPR11 bool GreaterThanTest() { return (U)2 > SafeInt<T>(3) && SafeInt<T>(4) > (U)5 && SafeInt<T>(6) > SafeInt<U>(7); } template <typename T, typename U> SAFEINT_CONSTEXPR11 bool LessThanEqualTest() { return (U)2 <= SafeInt<T>(3) && SafeInt<T>(4) <= (U)5 && SafeInt<T>(6) <= SafeInt<U>(7); } template <typename T, typename U> SAFEINT_CONSTEXPR11 bool GreaterThanEqualTest() { return (U)2 >= SafeInt<T>(3) && SafeInt<T>(4) >= (U)5 && SafeInt<T>(6) >= SafeInt<U>(7); } template <typename T, typename U> SAFEINT_CONSTEXPR11 bool EqualTest() { return (U)2 == SafeInt<T>(3) && SafeInt<T>(4) == (U)5 && SafeInt<T>(6) == SafeInt<U>(7) && true == SafeInt<T>(1) && false == SafeInt<T>(0); } template <typename T, typename U> SAFEINT_CONSTEXPR11 bool NotEqualTest() { return (U)2 != SafeInt<T>(3) && SafeInt<T>(4) != (U)5 && SafeInt<T>(6) != SafeInt<U>(7) && true != SafeInt<T>(1) && false != SafeInt<T>(0); } template <typename T, typename U> void ComparisonTestTU() { static bool b1 = LessThanTest<T, U>(); static bool b2 = LessThanEqualTest<T, U>(); static bool b3 = GreaterThanTest<T, U>(); static bool b4 = GreaterThanEqualTest<T, U>(); static bool b5 = EqualTest<T, U>(); static bool b6 = NotEqualTest<T, U>(); } template <typename T> void ComparisonTestT() { ComparisonTestTU<T, char>(); ComparisonTestTU<T, signed char>(); ComparisonTestTU<T, unsigned char>(); ComparisonTestTU<T, signed short>(); ComparisonTestTU<T, unsigned short>(); ComparisonTestTU<T, signed int>(); ComparisonTestTU<T, unsigned int>(); ComparisonTestTU<T, signed long>(); ComparisonTestTU<T, unsigned long>(); ComparisonTestTU<T, signed long long>(); ComparisonTestTU<T, unsigned long long>(); } template <typename T> SAFEINT_CONSTEXPR11 T ConstConstructor() { // Constructors, also add in the useless unary + operator return SafeInt<T>() + SafeInt<T>(1) + SafeInt<T>(false) + (+SafeInt<T>(3)); } template <typename T> SAFEINT_CONSTEXPR11 bool ConstBool() { return (bool)SafeInt<T>(2) && !SafeInt<T>(0); } template <typename T> void ConstTestT() { static const T t = ConstConstructor<T>(); static const bool b = ConstBool<T>(); } template <typename T> SAFEINT_CONSTEXPR11 SafeInt<T> ConstSafeInt() { return SafeInt<T>(1); } template <typename T> void ConstCastTestT() { static const bool b = ConstSafeInt<T>(); static const wchar_t w = ConstSafeInt<T>(); static const char c = ConstSafeInt<T>(); static const signed char sc = ConstSafeInt<T>(); static const unsigned char uc = ConstSafeInt<T>(); static const signed short s = ConstSafeInt<T>(); static const unsigned short us = ConstSafeInt<T>(); static const signed int i = ConstSafeInt<T>(); static const unsigned int ui = ConstSafeInt<T>(); static const signed long l = ConstSafeInt<T>(); static const unsigned long ul = ConstSafeInt<T>(); static const signed long long ll = ConstSafeInt<T>(); static const unsigned long long ull = ConstSafeInt<T>(); static const size_t st = ConstSafeInt<T>(); static const ptrdiff_t pt = ConstSafeInt<T>(); // Also catch the useless unary + operator static const int pl = +ConstSafeInt<T>(); } #if CPLUSPLUS_STD == CPLUSPLUS_14 template <typename T, typename U> SAFEINT_CONSTEXPR14 T DivOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(2); T& r = operator /=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T AddOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(2); T& r = operator +=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T SubOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(2); T& r = operator -=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T LShiftOperator() { // Have to explicitly force this operator // to be used // T& operator <<=(T& lhs, SafeInt< U, E > rhs) T lhs = 3; SafeInt<U> s(2); T& r = operator <<=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 U LShiftOperator2() { // Have to explicitly force this operator // to be used U lhs = 3; SafeInt<T> s(2); SafeInt<U> r = operator <<(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T RShiftOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(1); T& r = operator >>=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 U RShiftOperator2() { // Have to explicitly force this operator // to be used U lhs = 3; SafeInt<T> s(1); SafeInt<U> r = operator >>(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T AndOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(1); T& r = operator &=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 U AndOperator2() { // Have to explicitly force this operator // to be used U lhs = 3; SafeInt<T> s(1); SafeInt<T> r = operator &(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T XorOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(1); T& r = operator ^=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 U XorOperator2() { // Have to explicitly force this operator // to be used U lhs = 3; SafeInt<T> s(1); SafeInt<T> r = operator ^(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 T OrOperator() { // Have to explicitly force this operator // to be used T lhs = 3; SafeInt<U> s(1); T& r = operator |=(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 U OrOperator2() { // Have to explicitly force this operator // to be used U lhs = 3; SafeInt<T> s(1); SafeInt<T> r = operator |(lhs, s); return r; } template <typename T, typename U> SAFEINT_CONSTEXPR14 bool SafeCastTest() { U to = 0; return SafeCast((T)3, to); } template <typename T, typename U> SAFEINT_CONSTEXPR14 bool SafeModulusTest() { U u = 2; T result = 0; return SafeModulus((T)3, u, result); } template <typename T, typename U> SAFEINT_CONSTEXPR14 bool SafeMultiplyTest() { U u = 2; T result = 0; return SafeMultiply((T)3, u, result); } template <typename T, typename U> SAFEINT_CONSTEXPR14 bool SafeDivideTest() { U u = 2; T result = 0; return SafeDivide((T)3, u, result); } template <typename T, typename U> SAFEINT_CONSTEXPR14 bool SafeAddTest() { U u = 2; T result = 0; return SafeAdd((T)3, u, result); } template <typename T, typename U> void StaticAssertTU() { // Constructors static_assert(SafeInt<T>(SafeInt<U>(1)), "SafeInt U constr"); static_assert(SafeInt<T>((U)1), "U constr"); // Assignment operators static_assert((SafeInt<T>() = (U)1), "Assignment U"); static_assert((SafeInt<T>() = (T)1), "Assignment T"); static_assert((SafeInt<T>() = SafeInt<U>(1)), "Assignment SafeInt U"); // Next one happens when T == U, so already included // static_assert((SafeInt<T>() = SafeInt<T>(1)), "Assignment SafeInt T"); // Test the casting operators static_assert((U)(SafeInt<T>((T)1)), "Casting"); // Modulus static_assert(SafeInt<T>((T)3) % (U)2, "Modulus"); static_assert(SafeInt<T>((T)3) % SafeInt<T>(2), "Modulus"); static_assert((SafeInt<T>((T)3) %= (U)2), "Modulus"); static_assert((SafeInt<T>((T)3) %= SafeInt<U>(2)), "Modulus"); static_assert((U)3 % SafeInt<T>(2), "Modulus"); static_assert((T)3 % SafeInt<U>(2), "Modulus"); // Multiplication // Multiplication must either use intrinsics OR constexpr, but not both because the intrinsics aren't marked constexpr #if !SAFEINT_USE_INTRINSICS static_assert(SafeInt<T>((T)3) * (U)2, "Multiplication"); static_assert(SafeInt<T>((T)3) * SafeInt<T>(2), "Multiplication"); static_assert((SafeInt<T>((T)3) *= (U)2), "Multiplication"); static_assert((SafeInt<T>((T)3) *= SafeInt<U>(2)), "Multiplication"); static_assert((U)3 * SafeInt<T>(2), "Multiplication"); static_assert(((T)3 * SafeInt<U>(2)), "Multiplication"); #endif // Division static_assert(SafeInt<T>((T)3) / (U)2, "Division"); static_assert(SafeInt<T>((T)3) / SafeInt<T>(2), "Division"); static_assert((SafeInt<T>((T)3) /= (U)2), "Division"); #if SAFEINT_COMPILER != GCC_COMPILER // gcc is not happy with this one static_assert((SafeInt<T>((T)3) /= SafeInt<U>(2)), "Division"); static_assert((U)3 / SafeInt<T>(2), "Division"); #endif static_assert(DivOperator<T,U>(), "Division"); // Addition static_assert(SafeInt<T>((T)3) + (U)2, "Addition"); static_assert(SafeInt<T>((T)3) + SafeInt<T>(2), "Addition"); static_assert((SafeInt<T>((T)3) += (U)2), "Addition"); static_assert((SafeInt<T>((T)3) += SafeInt<U>(2)), "Addition"); static_assert((U)3 + SafeInt<T>(2), "Addition"); static_assert(AddOperator<T, U>(), "Addition"); // Subtraction static_assert(SafeInt<T>((T)3) - (U)2, "Subtraction"); static_assert(SafeInt<T>((T)3) - SafeInt<T>(2), "Subtraction"); static_assert((SafeInt<T>((T)3) -= (U)2), "Subtraction"); static_assert((SafeInt<T>((T)3) -= SafeInt<U>(2)), "Subtraction"); static_assert((U)3 - SafeInt<T>(2), "Subtraction"); static_assert(SubOperator<T, U>(), "Subtraction"); // Shift // Left static_assert(SafeInt<T>((T)3) << (U)2, "Shift"); static_assert(SafeInt<T>((T)3) << SafeInt<U>(2), "Shift"); static_assert((SafeInt<T>((T)3) <<= (U)2), "Shift"); static_assert((SafeInt<T>((T)3) <<= SafeInt<U>(2)), "Shift"); static_assert(LShiftOperator<T, U>(), "Shift"); static_assert(LShiftOperator2<T, U>(), "Shift"); // Right static_assert(SafeInt<T>((T)3) >> (U)1, "Shift"); static_assert(SafeInt<T>((T)3) >> SafeInt<U>(1), "Shift"); static_assert((SafeInt<T>((T)3) >>= (U)1), "Shift"); static_assert((SafeInt<T>((T)3) >>= SafeInt<U>(1)), "Shift"); static_assert(RShiftOperator<T, U>(), "Shift"); static_assert(RShiftOperator2<T, U>(), "Shift"); // Binary And static_assert(SafeInt<T>((T)3) & SafeInt<T>(1), "And"); static_assert(SafeInt<T>((T)3) & (U)1, "And"); static_assert((SafeInt<T>((T)3) &= (U)(1)), "And"); static_assert((SafeInt<T>((T)3) &= SafeInt<U>(1)), "And"); static_assert(AndOperator<T, U>(), "And"); static_assert(AndOperator2<T, U>(), "And"); // Binary Xor static_assert(SafeInt<T>((T)3) ^ SafeInt<T>(1), "Xor"); static_assert(SafeInt<T>((T)3) ^ (U)1, "Xor"); static_assert((SafeInt<T>((T)3) ^= (U)(1)), "Xor"); static_assert((SafeInt<T>((T)3) ^= SafeInt<U>(1)), "Xor"); static_assert(XorOperator<T, U>(), "Xor"); static_assert(XorOperator2<T, U>(), "Xor"); // Binary Or static_assert(SafeInt<T>((T)3) | SafeInt<T>(1), "Or"); static_assert(SafeInt<T>((T)3) | (U)1, "Or"); static_assert((SafeInt<T>((T)3) |= (U)(1)), "Or"); static_assert((SafeInt<T>((T)3) |= SafeInt<U>(1)), "Or"); static_assert(OrOperator<T, U>(), "Or"); static_assert(OrOperator2<T, U>(), "Or"); // Comparisons // Less than static_assert(SafeInt<T>((T)2) < (U)3, "LT"); static_assert((T)2 < SafeInt<U>((U)3), "LT"); static_assert(SafeInt<T>((T)2) < SafeInt<U>((U)3), "LT"); // Less than or equal static_assert(SafeInt<T>((T)2) <= (U)3, "LTE"); static_assert((T)2 <= SafeInt<U>((U)3), "LTE"); static_assert(SafeInt<T>((T)2) <= SafeInt<U>((U)3), "LTE"); // Greater than static_assert(SafeInt<T>((T)4) > (U)3, "GT"); static_assert((T)4 > SafeInt<U>((U)3), "GT"); static_assert(SafeInt<T>((T)4) > SafeInt<U>((U)3), "GT"); // Less than or equal static_assert(SafeInt<T>((T)4) >= (U)3, "GTE"); static_assert((T)4 >= SafeInt<U>((U)3), "GTE"); static_assert((SafeInt<T>((T)4) >= SafeInt<U>((U)3)), "GTE"); // Equals static_assert(SafeInt<T>((T)3) == (U)3, "EQ"); static_assert((T)3 == SafeInt<U>((U)3), "EQ"); static_assert(SafeInt<T>((T)3) == SafeInt<U>((U)3), "EQ"); // Not equal static_assert(SafeInt<T>((T)4) != (U)3, "NEQ"); static_assert((T)4 != SafeInt<U>((U)3), "NEQ"); static_assert(SafeInt<T>((T)4) != SafeInt<U>((U)3), "NEQ"); // Now need coverage for these: static_assert(SafeCastTest<T,U>(), "SafeCast"); static_assert(SafeEquals((T)2, (U)2), "SafeEquals"); static_assert(SafeNotEquals((T)3, (U)2), "SafeNotEquals"); static_assert(SafeGreaterThan((T)3, (U)2), "SafeGreaterThan"); static_assert(SafeGreaterThanEquals((T)3, (U)2), "SafeGreaterThanEquals"); static_assert(SafeLessThan((T)1, (U)2), "SafeLessThan"); static_assert(SafeLessThanEquals((T)1, (U)2), "SafeLessThanEquals"); static_assert(SafeModulusTest<T, U>(), "SafeModulus"); #if !SAFEINT_USE_INTRINSICS static_assert(SafeMultiplyTest<T, U>(), "SafeMultiply"); #endif static_assert(SafeDivideTest<T, U>(), "SafeDivide"); static_assert(SafeAddTest<T, U>(), "SafeAdd"); } template <typename T> void StaticAssertTest() { static_assert(SafeInt<T>() == 0, "Default constr"); static_assert(SafeInt<T>((T)1), "T constr"); static_assert(SafeInt<T>(true), "bool constr"); // Floating point will not work due to presence of fpclassify // static_assert(SafeInt<T>((float)1.0), "float constr"); StaticAssertTU<T, char>(); StaticAssertTU<T, signed char>(); StaticAssertTU<T, unsigned char>(); StaticAssertTU<T, signed short>(); StaticAssertTU<T, unsigned short>(); StaticAssertTU<T, signed int>(); StaticAssertTU<T, unsigned int>(); StaticAssertTU<T, signed long>(); StaticAssertTU<T, unsigned long>(); StaticAssertTU<T, signed long long>(); StaticAssertTU<T, unsigned long long>(); // Special case casting static_assert((bool)(SafeInt<T>((T)1)), "Casting"); static_assert((wchar_t)(SafeInt<T>((T)1)), "Casting"); static_assert((float)(SafeInt<T>((T)1)), "Casting"); static_assert((double)(SafeInt<T>((T)1)), "Casting"); static_assert((long double)(SafeInt<T>((T)1)), "Casting"); // Unary operations static_assert(!SafeInt<T>((T)0), "operator !"); static_assert(++SafeInt<T>((T)1), "operator ++"); static_assert(SafeInt<T>((T)1)++, "operator ++"); static_assert(--SafeInt<T>((T)2), "operator --"); static_assert(SafeInt<T>((T)2)--, "operator --"); static_assert(~SafeInt<T>((T)0), "operator ~"); } template <typename T, typename U> SAFEINT_CONSTEXPR14 T ConstMultiplyTU() { return (SafeInt<T>(2) * (U)1) + (U(4) * SafeInt<T>(3)) + (SafeInt<T>(6) * SafeInt<T>(5)); } template <typename T> void ConstMultiplyT() { static const T c = ConstMultiplyTU< T, char >(); static const T sc = ConstMultiplyTU< T, signed char >(); static const T uc = ConstMultiplyTU< T, unsigned char >(); static const T ss = ConstMultiplyTU< T, signed short >(); static const T us = ConstMultiplyTU< T, unsigned short >(); static const T si = ConstMultiplyTU< T, signed int >(); static const T ui = ConstMultiplyTU< T, unsigned int >(); static const T sl = ConstMultiplyTU< T, signed long >(); static const T ul = ConstMultiplyTU< T, unsigned long >(); static const T sll = ConstMultiplyTU< T, signed long long >(); static const T ull = ConstMultiplyTU< T, unsigned long long >(); } template <typename T, typename U> SAFEINT_CONSTEXPR14 T ConstSubtractTU() { return (SafeInt<T>(2) - (U)1) + (U(4) - SafeInt<T>(3)) + (SafeInt<T>(6) - SafeInt<T>(5)); } template <typename T> void ConstSubtractT() { static const T c = ConstSubtractTU< T, char >(); static const T sc = ConstSubtractTU< T, signed char >(); static const T uc = ConstSubtractTU< T, unsigned char >(); static const T ss = ConstSubtractTU< T, signed short >(); static const T us = ConstSubtractTU< T, unsigned short >(); static const T si = ConstSubtractTU< T, signed int >(); static const T ui = ConstSubtractTU< T, unsigned int >(); static const T sl = ConstSubtractTU< T, signed long >(); static const T ul = ConstSubtractTU< T, unsigned long >(); static const T sll = ConstSubtractTU< T, signed long long >(); static const T ull = ConstSubtractTU< T, unsigned long long >(); } template <typename T, typename U> SAFEINT_CONSTEXPR14 T ConstAddTU() { return (SafeInt<T>(1) + (U)2) + (U(3) + SafeInt<T>(4)) + (SafeInt<T>(5) + SafeInt<T>(6)); } template <typename T> void ConstAddT() { static const T c = ConstAddTU< T, char >(); static const T sc = ConstAddTU< T, signed char >(); static const T uc = ConstAddTU< T, unsigned char >(); static const T ss = ConstAddTU< T, signed short >(); static const T us = ConstAddTU< T, unsigned short >(); static const T si = ConstAddTU< T, signed int >(); static const T ui = ConstAddTU< T, unsigned int >(); static const T sl = ConstAddTU< T, signed long >(); static const T ul = ConstAddTU< T, unsigned long >(); static const T sll = ConstAddTU< T, signed long long >(); static const T ull = ConstAddTU< T, unsigned long long >(); } template <typename T> SAFEINT_CONSTEXPR14 T PrefixInc(T i) { return ++SafeInt<T>(i); } template <typename T> SAFEINT_CONSTEXPR14 T PostfixInc(T i) { return SafeInt<T>(i)++; } template <typename T> SAFEINT_CONSTEXPR14 void SignedOnly() { static_assert(-SafeInt<T>((T)1), "operator -"); } void TestSignedOnly() { SignedOnly<signed char>(); SignedOnly<signed short>(); SignedOnly<signed int>(); SignedOnly<signed long>(); SignedOnly<signed long long>(); } #endif // CPLUSPLUS_14 template <typename T> void ConstExprTestT() { ConstTestT<T>(); ComparisonTestT<T>(); ConstCastTestT<T>(); #if CPLUSPLUS_STD == CPLUSPLUS_14 StaticAssertTest<T>(); TestSignedOnly(); ConstAddT<T>(); ConstSubtractT<T>(); ConstMultiplyT<T>(); #endif } void ConstExprTest() { ConstExprTestT<char>(); ConstExprTestT<signed char>(); ConstExprTestT<unsigned char>(); ConstExprTestT<signed short>(); ConstExprTestT<unsigned short>(); ConstExprTestT<signed int>(); ConstExprTestT<unsigned int>(); ConstExprTestT<signed long>(); ConstExprTestT<unsigned long>(); ConstExprTestT<signed long long>(); ConstExprTestT<unsigned long long>(); // Catch the SafePtrDiff function, since it is marked. Can't think of a scenario for this being constexpr, though. const char* p1 = (char*)1; const char* p2 = nullptr; static const SafeInt<ptrdiff_t> pt = SafePtrDiff(p1, p2); if (pt > 0) return; } } void ConstExpr() { TestConstExpr::ConstExprTest(); }