Wrong calculation of constants (simplifying: +,<<,% operations)

This commit is contained in:
Daniel Marjamäki 2015-11-25 16:46:39 +01:00
parent f84af529af
commit 2737f63f71
3 changed files with 43 additions and 25 deletions

View File

@ -860,9 +860,13 @@ void TemplateSimplifier::expandTemplate(
}
}
static bool isLowerThanLogicalAnd(const Token *lower)
{
return lower->isAssignmentOp() || Token::Match(lower, "}|;|(|[|]|)|,|?|:|%oror%|return|throw|case");
}
static bool isLowerThanOr(const Token* lower)
{
return lower->isAssignmentOp() || Token::Match(lower, "}|;|(|[|]|)|,|?|:|%oror%|&&|return|throw|case");
return isLowerThanLogicalAnd(lower) || lower->str() == "&&";
}
static bool isLowerThanXor(const Token* lower)
{
@ -947,7 +951,9 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
(Token::Match(op, ">>|<<") && isLowerThanShift(tok) && isLowerThanPlusMinus(after)) || // NOT associative
(op->str() == "&" && isLowerThanShift(tok) && isLowerThanShift(after)) || // associative
(op->str() == "^" && isLowerThanAnd(tok) && isLowerThanAnd(after)) || // associative
(op->str() == "|" && isLowerThanXor(tok) && isLowerThanXor(after)))) // associative
(op->str() == "|" && isLowerThanXor(tok) && isLowerThanXor(after)) || // associative
(op->str() == "&&" && isLowerThanOr(tok) && isLowerThanOr(after)) ||
(op->str() == "||" && isLowerThanLogicalAnd(tok) && isLowerThanLogicalAnd(after))))
break;
tok = tok->next();
@ -964,12 +970,17 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
result = ShiftUInt(cop, tok, tok->tokAt(2));
else
result = ShiftInt(cop, tok, tok->tokAt(2));
if (!result.empty()) {
ret = true;
tok->str(result);
tok->deleteNext(2);
continue;
}
if (result.empty())
break;
tok->str(result);
}
// Logical operations
else if (Token::Match(op, "%oror%|&&")) {
int op1 = !MathLib::isNullValue(tok->str());
int op2 = !MathLib::isNullValue(tok->strAt(2));
int result = (op->str() == "||") ? (op1 || op2) : (op1 && op2);
tok->str(result ? "1" : "0");
}
else if (Token::Match(tok->previous(), "- %num% - %num%"))
@ -986,9 +997,15 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
}
tok->deleteNext(2);
tok = tok->previous();
ret = true;
}
if (Token::Match(tok, "%oror%|&& %num% %oror%|&&|,|)") || Token::Match(tok, "[(,] %num% %oror%|&&")) {
tok->next()->str(MathLib::isNullValue(tok->next()->str()) ? "0" : "1");
}
return ret;
}
@ -1124,12 +1141,8 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
ret = true;
}
if (Token::simpleMatch(tok->previous(), "( 0 ||") ||
Token::simpleMatch(tok->previous(), "|| 0 )") ||
Token::simpleMatch(tok->previous(), "( 0 |") ||
Token::simpleMatch(tok->previous(), "| 0 )") ||
Token::simpleMatch(tok->previous(), "( 1 &&") ||
Token::simpleMatch(tok->previous(), "&& 1 )")) {
if (Token::simpleMatch(tok->previous(), "( 0 |") ||
Token::simpleMatch(tok->previous(), "| 0 )")) {
if (tok->previous()->isConstOp())
tok = tok->previous();
tok->deleteNext();
@ -1173,8 +1186,15 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
tok->deleteNext(2);
}
else {
ret |= simplifyNumericCalculations(tok);
else if (simplifyNumericCalculations(tok)) {
ret = true;
while (Token::Match(tok->tokAt(-2), "%cop%|,|( %num% %cop% %num% %cop%|,|)")) {
Token *before = tok->tokAt(-2);
if (simplifyNumericCalculations(before))
tok = before;
else
break;
}
}
}
return ret;

View File

@ -3728,14 +3728,6 @@ bool Tokenizer::simplifyTokenList2()
simplifyCasts();
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "%oror%|&& %num% %oror%|&&|,|)") ||
Token::Match(tok, "[(,] %num% %oror%|&&")) {
tok = tok->next();
tok->str(MathLib::isNullValue(tok->str()) ? "0" : "1");
}
}
// Simplify simple calculations before replace constants, this allows the replacement of constants that are calculated
// e.g. const static int value = sizeof(X)/sizeof(Y);
simplifyCalculations();

View File

@ -2091,13 +2091,19 @@ private:
ASSERT_EQUALS("( 4 )", tok("(1 * 2 / 1 * 2)")); // #3722
ASSERT_EQUALS("x ( 60129542144 )", tok("x(14<<4+17<<300%17)")); // #4931
ASSERT_EQUALS("x ( 1 )", tok("x(8|5&6+0 && 7)")); // #6104
ASSERT_EQUALS("x ( 1 )", tok("x(2 && 4<<4<<5 && 4)")); // #4933
ASSERT_EQUALS("x ( 1 )", tok("x(9&&8%5%4/3)")); // #4931
ASSERT_EQUALS("x ( 1 )", tok("x(2 && 2|5<<2%4)")); // #4931
// don't remove these spaces..
ASSERT_EQUALS("new ( auto ) ( 4 ) ;", tok("new (auto)(4);"));
}
void comparisons() {
ASSERT_EQUALS("( 1 )", tok("( 1 < 2 )"));
ASSERT_EQUALS("( x )", tok("( x && 1 < 2 )"));
ASSERT_EQUALS("( x && true )", tok("( x && 1 < 2 )"));
ASSERT_EQUALS("( 5 )", tok("( 1 < 2 && 3 < 4 ? 5 : 6 )"));
ASSERT_EQUALS("( 6 )", tok("( 1 > 2 && 3 > 4 ? 5 : 6 )"));
}