Fix #4724 (Error in calculation shift operation: wrong sign: 1UL << 63)
This commit is contained in:
parent
b0af67f369
commit
e19129a409
|
@ -33,6 +33,7 @@
|
|||
class CPPCHECKLIB MathLib {
|
||||
public:
|
||||
typedef long long bigint;
|
||||
typedef unsigned long long biguint;
|
||||
|
||||
static bigint toLongNumber(const std::string & str);
|
||||
template<class T> static std::string toString(T value) {
|
||||
|
|
|
@ -800,6 +800,22 @@ static bool isLowerEqualThanMulDiv(const Token* lower)
|
|||
return isLowerThanMulDiv(lower) || Token::Match(lower, "[*/%]");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string typeCorrectShift(const char cop, const Token* left, const Token* right)
|
||||
{
|
||||
const T leftInt=MathLib::toLongNumber(left->str());
|
||||
const T rightInt=MathLib::toLongNumber(right->str());
|
||||
|
||||
if (cop == '&' || cop == '|' || cop == '^')
|
||||
return MathLib::calculate(left->str(), right->str(), cop);
|
||||
else if (cop == '<') {
|
||||
if (left->previous()->str() != "<<" && rightInt > 0) // Ensure that its not a shift operator as used for streams
|
||||
return MathLib::toString(leftInt << rightInt);
|
||||
} else if (rightInt > 0)
|
||||
return MathLib::toString(leftInt >> rightInt);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
|
||||
{
|
||||
|
@ -828,18 +844,11 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
|
|||
// Integer operations
|
||||
if (Token::Match(op, ">>|<<|&|^|%or%")) {
|
||||
const char cop = op->str()[0];
|
||||
const MathLib::bigint leftInt(MathLib::toLongNumber(tok->str()));
|
||||
const MathLib::bigint rightInt(MathLib::toLongNumber(tok->strAt(2)));
|
||||
std::string result;
|
||||
|
||||
if (cop == '&' || cop == '|' || cop == '^')
|
||||
result = MathLib::calculate(tok->str(), tok->strAt(2), cop);
|
||||
else if (cop == '<') {
|
||||
if (tok->previous()->str() != "<<" && rightInt > 0) // Ensure that its not a shift operator as used for streams
|
||||
result = MathLib::toString(leftInt << rightInt);
|
||||
} else if (rightInt > 0)
|
||||
result = MathLib::toString(leftInt >> rightInt);
|
||||
|
||||
if (tok->str().find_first_of("uU") != std::string::npos)
|
||||
result = typeCorrectShift<MathLib::biguint>(cop, tok, tok->tokAt(2));
|
||||
else
|
||||
result = typeCorrectShift<MathLib::bigint>(cop, tok, tok->tokAt(2));
|
||||
if (!result.empty()) {
|
||||
ret = true;
|
||||
tok->str(result);
|
||||
|
|
|
@ -193,6 +193,7 @@ private:
|
|||
TEST_CASE(simplifyKnownVariables54); // #4913 'x' is not 0 after *--x=0;
|
||||
TEST_CASE(simplifyKnownVariables55); // pointer alias
|
||||
TEST_CASE(simplifyKnownVariables56); // ticket #5301 - >>
|
||||
TEST_CASE(simplifyKnownVariables57); // ticket #4724
|
||||
TEST_CASE(simplifyKnownVariablesIfEq1); // if (a==5) => a is 5 in the block
|
||||
TEST_CASE(simplifyKnownVariablesIfEq2); // if (a==5) { buf[a++] = 0; }
|
||||
TEST_CASE(simplifyKnownVariablesIfEq3); // #4708 - if (a==5) { buf[--a] = 0; }
|
||||
|
@ -2923,6 +2924,11 @@ private:
|
|||
tokenizeAndStringify("void f() { int a=0,b=0; *p>>a>>b; return a/b; }", true));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void simplifyKnownVariablesIfEq1() {
|
||||
const char code[] = "void f(int x) {\n"
|
||||
" if (x==5) {\n"
|
||||
|
|
Loading…
Reference in New Issue