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 {
|
class CPPCHECKLIB MathLib {
|
||||||
public:
|
public:
|
||||||
typedef long long bigint;
|
typedef long long bigint;
|
||||||
|
typedef unsigned long long biguint;
|
||||||
|
|
||||||
static bigint toLongNumber(const std::string & str);
|
static bigint toLongNumber(const std::string & str);
|
||||||
template<class T> static std::string toString(T value) {
|
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, "[*/%]");
|
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)
|
bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
|
||||||
{
|
{
|
||||||
|
@ -828,18 +844,11 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
|
||||||
// Integer operations
|
// Integer operations
|
||||||
if (Token::Match(op, ">>|<<|&|^|%or%")) {
|
if (Token::Match(op, ">>|<<|&|^|%or%")) {
|
||||||
const char cop = op->str()[0];
|
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;
|
std::string result;
|
||||||
|
if (tok->str().find_first_of("uU") != std::string::npos)
|
||||||
if (cop == '&' || cop == '|' || cop == '^')
|
result = typeCorrectShift<MathLib::biguint>(cop, tok, tok->tokAt(2));
|
||||||
result = MathLib::calculate(tok->str(), tok->strAt(2), cop);
|
else
|
||||||
else if (cop == '<') {
|
result = typeCorrectShift<MathLib::bigint>(cop, tok, tok->tokAt(2));
|
||||||
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 (!result.empty()) {
|
if (!result.empty()) {
|
||||||
ret = true;
|
ret = true;
|
||||||
tok->str(result);
|
tok->str(result);
|
||||||
|
|
|
@ -193,6 +193,7 @@ private:
|
||||||
TEST_CASE(simplifyKnownVariables54); // #4913 'x' is not 0 after *--x=0;
|
TEST_CASE(simplifyKnownVariables54); // #4913 'x' is not 0 after *--x=0;
|
||||||
TEST_CASE(simplifyKnownVariables55); // pointer alias
|
TEST_CASE(simplifyKnownVariables55); // pointer alias
|
||||||
TEST_CASE(simplifyKnownVariables56); // ticket #5301 - >>
|
TEST_CASE(simplifyKnownVariables56); // ticket #5301 - >>
|
||||||
|
TEST_CASE(simplifyKnownVariables57); // ticket #4724
|
||||||
TEST_CASE(simplifyKnownVariablesIfEq1); // if (a==5) => a is 5 in the block
|
TEST_CASE(simplifyKnownVariablesIfEq1); // if (a==5) => a is 5 in the block
|
||||||
TEST_CASE(simplifyKnownVariablesIfEq2); // if (a==5) { buf[a++] = 0; }
|
TEST_CASE(simplifyKnownVariablesIfEq2); // if (a==5) { buf[a++] = 0; }
|
||||||
TEST_CASE(simplifyKnownVariablesIfEq3); // #4708 - 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));
|
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() {
|
void simplifyKnownVariablesIfEq1() {
|
||||||
const char code[] = "void f(int x) {\n"
|
const char code[] = "void f(int x) {\n"
|
||||||
" if (x==5) {\n"
|
" if (x==5) {\n"
|
||||||
|
|
Loading…
Reference in New Issue