diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 44f1de849..3992345b6 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -38,7 +38,6 @@ #define ISNAN(x) (std::isnan(x)) #endif - MathLib::value::value(const std::string &s) : intValue(0), doubleValue(0), isUnsigned(false) { @@ -263,6 +262,24 @@ MathLib::value MathLib::value::add(int v) const return temp; } +MathLib::value MathLib::value::shiftLeft(const MathLib::value &v) const +{ + if (!isInt() || !v.isInt()) + throw InternalError(0, "Shift operand is not integer"); + MathLib::value ret(*this); + ret.intValue <<= v.intValue; + return ret; +} + +MathLib::value MathLib::value::shiftRight(const MathLib::value &v) const +{ + if (!isInt() || !v.isInt()) + throw InternalError(0, "Shift operand is not integer"); + MathLib::value ret(*this); + ret.intValue >>= v.intValue; + return ret; +} + MathLib::biguint MathLib::toULongNumber(const std::string & str) { @@ -1250,3 +1267,13 @@ MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2) { return MathLib::value::calc('^',v1,v2); } + +MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2) +{ + return v1.shiftLeft(v2); +} + +MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2) +{ + return v1.shiftRight(v2); +} diff --git a/lib/mathlib.h b/lib/mathlib.h index 2639003ca..14decf4a5 100644 --- a/lib/mathlib.h +++ b/lib/mathlib.h @@ -59,6 +59,8 @@ public: static value calc(char op, const value &v1, const value &v2); int compare(const value &v) const; value add(int v) const; + value shiftLeft(const value &v) const; + value shiftRight(const value &v) const; }; typedef long long bigint; @@ -128,6 +130,8 @@ MathLib::value operator%(const MathLib::value &v1, const MathLib::value &v2); MathLib::value operator&(const MathLib::value &v1, const MathLib::value &v2); MathLib::value operator|(const MathLib::value &v1, const MathLib::value &v2); MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2); +MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2); +MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2); template<> CPPCHECKLIB std::string MathLib::toString(double value); // Declare specialization to avoid linker problems diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 0d3d18852..3f0ddb373 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -891,48 +891,6 @@ static bool isLowerEqualThanMulDiv(const Token* lower) return isLowerThanMulDiv(lower) || Token::Match(lower, "[*/%]"); } -static std::string ShiftInt(const char cop, const Token* left, const Token* right) -{ - if (cop == '&' || cop == '|' || cop == '^') - return MathLib::calculate(left->str(), right->str(), cop); - - const MathLib::bigint leftInt = MathLib::toLongNumber(left->str()); - const MathLib::bigint rightInt = MathLib::toLongNumber(right->str()); - const bool rightIntIsPositive = rightInt >= 0; - - if (cop == '<') { - const bool leftOperationIsNotLeftShift = left->previous()->str() != "<<"; - const bool operandIsLeftShift = right->previous()->str() == "<<"; - - // Ensure that its not a shift operator as used for streams - if (leftOperationIsNotLeftShift && operandIsLeftShift && rightIntIsPositive) { - const bool leftIntIsPositive = leftInt >= 0; - if (!leftIntIsPositive) { // In case the left integer is negative, e.g. -1000 << 16. Do not simplify. - return left->str() + " << " + right->str(); - } - return MathLib::toString(leftInt << rightInt); - } - } else if (rightIntIsPositive) { - return MathLib::toString(leftInt >> rightInt); - } - return ""; -} - -static std::string ShiftUInt(const char cop, const Token* left, const Token* right) -{ - if (cop == '&' || cop == '|' || cop == '^') - return MathLib::calculate(left->str(), right->str(), cop); - - const MathLib::biguint leftInt=MathLib::toULongNumber(left->str()); - const MathLib::biguint rightInt=MathLib::toULongNumber(right->str()); - if (cop == '<') { - if (left->previous()->str() != "<<") // Ensure that its not a shift operator as used for streams - return MathLib::toString(leftInt << rightInt); - } else { - return MathLib::toString(leftInt >> rightInt); - } - return ""; -} bool TemplateSimplifier::simplifyNumericCalculations(Token *tok) { @@ -968,15 +926,34 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok) if (MathLib::isNegative(tok->str()) || MathLib::isNegative(tok->strAt(2))) continue; - const char cop = op->str()[0]; - std::string result; - if (tok->str().find_first_of("uU") != std::string::npos) - result = ShiftUInt(cop, tok, tok->tokAt(2)); - else - result = ShiftInt(cop, tok, tok->tokAt(2)); - if (result.empty()) + const MathLib::value v1(tok->str()); + const MathLib::value v2(tok->strAt(2)); + + if (!v1.isInt() || !v2.isInt()) + continue; + + switch (op->str()[0]) { + case '<': + tok->str((v1 << v2).str()); + ret = true; break; - tok->str(result); + case '>': + tok->str((v1 >> v2).str()); + ret = true; + break; + case '&': + tok->str((v1 & v2).str()); + ret = true; + break; + case '|': + tok->str((v1 | v2).str()); + ret = true; + break; + case '^': + tok->str((v1 ^ v2).str()); + ret = true; + break; + }; } // Logical operations diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 9b09eb130..20dd88230 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -2650,8 +2650,8 @@ private: } void simplifyKnownVariables57() { // #4724 - ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808 ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true)); - ASSERT_EQUALS("long long x ; x = -9223372036854775808 ;", tokenizeAndStringify("long long x = 1L << 63 ;", true)); + ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808UL ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true)); + ASSERT_EQUALS("long long x ; x = -9223372036854775808L ;", tokenizeAndStringify("long long x = 1L << 63 ;", true)); } void simplifyKnownVariables58() { // #5268