keep type suffixes after constant folding using bit operations

This commit is contained in:
Daniel Marjamäki 2016-03-21 21:20:02 +01:00
parent 4e4873772d
commit ac8341e3de
4 changed files with 61 additions and 53 deletions

View File

@ -38,7 +38,6 @@
#define ISNAN(x) (std::isnan(x)) #define ISNAN(x) (std::isnan(x))
#endif #endif
MathLib::value::value(const std::string &s) : MathLib::value::value(const std::string &s) :
intValue(0), doubleValue(0), isUnsigned(false) intValue(0), doubleValue(0), isUnsigned(false)
{ {
@ -263,6 +262,24 @@ MathLib::value MathLib::value::add(int v) const
return temp; 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) 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); 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);
}

View File

@ -59,6 +59,8 @@ public:
static value calc(char op, const value &v1, const value &v2); static value calc(char op, const value &v1, const value &v2);
int compare(const value &v) const; int compare(const value &v) const;
value add(int v) const; value add(int v) const;
value shiftLeft(const value &v) const;
value shiftRight(const value &v) const;
}; };
typedef long long bigint; 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); 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 template<> CPPCHECKLIB std::string MathLib::toString(double value); // Declare specialization to avoid linker problems

View File

@ -891,48 +891,6 @@ static bool isLowerEqualThanMulDiv(const Token* lower)
return isLowerThanMulDiv(lower) || Token::Match(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) bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
{ {
@ -968,15 +926,34 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
if (MathLib::isNegative(tok->str()) || MathLib::isNegative(tok->strAt(2))) if (MathLib::isNegative(tok->str()) || MathLib::isNegative(tok->strAt(2)))
continue; continue;
const char cop = op->str()[0]; const MathLib::value v1(tok->str());
std::string result; const MathLib::value v2(tok->strAt(2));
if (tok->str().find_first_of("uU") != std::string::npos)
result = ShiftUInt(cop, tok, tok->tokAt(2)); if (!v1.isInt() || !v2.isInt())
else continue;
result = ShiftInt(cop, tok, tok->tokAt(2));
if (result.empty()) switch (op->str()[0]) {
case '<':
tok->str((v1 << v2).str());
ret = true;
break; 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 // Logical operations

View File

@ -2650,8 +2650,8 @@ private:
} }
void simplifyKnownVariables57() { // #4724 void simplifyKnownVariables57() { // #4724
ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808 ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true)); ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808UL ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true));
ASSERT_EQUALS("long long x ; x = -9223372036854775808 ;", tokenizeAndStringify("long long x = 1L << 63 ;", true)); ASSERT_EQUALS("long long x ; x = -9223372036854775808L ;", tokenizeAndStringify("long long x = 1L << 63 ;", true));
} }
void simplifyKnownVariables58() { // #5268 void simplifyKnownVariables58() { // #5268