Skip to content

Commit ac8341e

Browse files
committed
keep type suffixes after constant folding using bit operations
1 parent 4e48737 commit ac8341e

4 files changed

Lines changed: 61 additions & 53 deletions

File tree

lib/mathlib.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
#define ISNAN(x) (std::isnan(x))
3939
#endif
4040

41-
4241
MathLib::value::value(const std::string &s) :
4342
intValue(0), doubleValue(0), isUnsigned(false)
4443
{
@@ -263,6 +262,24 @@ MathLib::value MathLib::value::add(int v) const
263262
return temp;
264263
}
265264

265+
MathLib::value MathLib::value::shiftLeft(const MathLib::value &v) const
266+
{
267+
if (!isInt() || !v.isInt())
268+
throw InternalError(0, "Shift operand is not integer");
269+
MathLib::value ret(*this);
270+
ret.intValue <<= v.intValue;
271+
return ret;
272+
}
273+
274+
MathLib::value MathLib::value::shiftRight(const MathLib::value &v) const
275+
{
276+
if (!isInt() || !v.isInt())
277+
throw InternalError(0, "Shift operand is not integer");
278+
MathLib::value ret(*this);
279+
ret.intValue >>= v.intValue;
280+
return ret;
281+
}
282+
266283

267284
MathLib::biguint MathLib::toULongNumber(const std::string & str)
268285
{
@@ -1250,3 +1267,13 @@ MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2)
12501267
{
12511268
return MathLib::value::calc('^',v1,v2);
12521269
}
1270+
1271+
MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2)
1272+
{
1273+
return v1.shiftLeft(v2);
1274+
}
1275+
1276+
MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2)
1277+
{
1278+
return v1.shiftRight(v2);
1279+
}

lib/mathlib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class CPPCHECKLIB MathLib {
5959
static value calc(char op, const value &v1, const value &v2);
6060
int compare(const value &v) const;
6161
value add(int v) const;
62+
value shiftLeft(const value &v) const;
63+
value shiftRight(const value &v) const;
6264
};
6365

6466
typedef long long bigint;
@@ -128,6 +130,8 @@ MathLib::value operator%(const MathLib::value &v1, const MathLib::value &v2);
128130
MathLib::value operator&(const MathLib::value &v1, const MathLib::value &v2);
129131
MathLib::value operator|(const MathLib::value &v1, const MathLib::value &v2);
130132
MathLib::value operator^(const MathLib::value &v1, const MathLib::value &v2);
133+
MathLib::value operator<<(const MathLib::value &v1, const MathLib::value &v2);
134+
MathLib::value operator>>(const MathLib::value &v1, const MathLib::value &v2);
131135

132136
template<> CPPCHECKLIB std::string MathLib::toString(double value); // Declare specialization to avoid linker problems
133137

lib/templatesimplifier.cpp

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -891,48 +891,6 @@ static bool isLowerEqualThanMulDiv(const Token* lower)
891891
return isLowerThanMulDiv(lower) || Token::Match(lower, "[*/%]");
892892
}
893893

894-
static std::string ShiftInt(const char cop, const Token* left, const Token* right)
895-
{
896-
if (cop == '&' || cop == '|' || cop == '^')
897-
return MathLib::calculate(left->str(), right->str(), cop);
898-
899-
const MathLib::bigint leftInt = MathLib::toLongNumber(left->str());
900-
const MathLib::bigint rightInt = MathLib::toLongNumber(right->str());
901-
const bool rightIntIsPositive = rightInt >= 0;
902-
903-
if (cop == '<') {
904-
const bool leftOperationIsNotLeftShift = left->previous()->str() != "<<";
905-
const bool operandIsLeftShift = right->previous()->str() == "<<";
906-
907-
// Ensure that its not a shift operator as used for streams
908-
if (leftOperationIsNotLeftShift && operandIsLeftShift && rightIntIsPositive) {
909-
const bool leftIntIsPositive = leftInt >= 0;
910-
if (!leftIntIsPositive) { // In case the left integer is negative, e.g. -1000 << 16. Do not simplify.
911-
return left->str() + " << " + right->str();
912-
}
913-
return MathLib::toString(leftInt << rightInt);
914-
}
915-
} else if (rightIntIsPositive) {
916-
return MathLib::toString(leftInt >> rightInt);
917-
}
918-
return "";
919-
}
920-
921-
static std::string ShiftUInt(const char cop, const Token* left, const Token* right)
922-
{
923-
if (cop == '&' || cop == '|' || cop == '^')
924-
return MathLib::calculate(left->str(), right->str(), cop);
925-
926-
const MathLib::biguint leftInt=MathLib::toULongNumber(left->str());
927-
const MathLib::biguint rightInt=MathLib::toULongNumber(right->str());
928-
if (cop == '<') {
929-
if (left->previous()->str() != "<<") // Ensure that its not a shift operator as used for streams
930-
return MathLib::toString(leftInt << rightInt);
931-
} else {
932-
return MathLib::toString(leftInt >> rightInt);
933-
}
934-
return "";
935-
}
936894

937895
bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
938896
{
@@ -968,15 +926,34 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
968926
if (MathLib::isNegative(tok->str()) || MathLib::isNegative(tok->strAt(2)))
969927
continue;
970928

971-
const char cop = op->str()[0];
972-
std::string result;
973-
if (tok->str().find_first_of("uU") != std::string::npos)
974-
result = ShiftUInt(cop, tok, tok->tokAt(2));
975-
else
976-
result = ShiftInt(cop, tok, tok->tokAt(2));
977-
if (result.empty())
929+
const MathLib::value v1(tok->str());
930+
const MathLib::value v2(tok->strAt(2));
931+
932+
if (!v1.isInt() || !v2.isInt())
933+
continue;
934+
935+
switch (op->str()[0]) {
936+
case '<':
937+
tok->str((v1 << v2).str());
938+
ret = true;
939+
break;
940+
case '>':
941+
tok->str((v1 >> v2).str());
942+
ret = true;
943+
break;
944+
case '&':
945+
tok->str((v1 & v2).str());
946+
ret = true;
947+
break;
948+
case '|':
949+
tok->str((v1 | v2).str());
950+
ret = true;
951+
break;
952+
case '^':
953+
tok->str((v1 ^ v2).str());
954+
ret = true;
978955
break;
979-
tok->str(result);
956+
};
980957
}
981958

982959
// Logical operations

test/testtokenize.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,8 +2650,8 @@ class TestTokenizer : public TestFixture {
26502650
}
26512651

26522652
void simplifyKnownVariables57() { // #4724
2653-
ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808 ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true));
2654-
ASSERT_EQUALS("long long x ; x = -9223372036854775808 ;", tokenizeAndStringify("long long x = 1L << 63 ;", true));
2653+
ASSERT_EQUALS("unsigned long long x ; x = 9223372036854775808UL ;", tokenizeAndStringify("unsigned long long x = 1UL << 63 ;", true));
2654+
ASSERT_EQUALS("long long x ; x = -9223372036854775808L ;", tokenizeAndStringify("long long x = 1L << 63 ;", true));
26552655
}
26562656

26572657
void simplifyKnownVariables58() { // #5268

0 commit comments

Comments
 (0)