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) 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) static bool isLowerThanXor(const Token* lower)
{ {
@ -947,7 +951,9 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
(Token::Match(op, ">>|<<") && isLowerThanShift(tok) && isLowerThanPlusMinus(after)) || // NOT associative (Token::Match(op, ">>|<<") && isLowerThanShift(tok) && isLowerThanPlusMinus(after)) || // NOT associative
(op->str() == "&" && isLowerThanShift(tok) && isLowerThanShift(after)) || // associative (op->str() == "&" && isLowerThanShift(tok) && isLowerThanShift(after)) || // associative
(op->str() == "^" && isLowerThanAnd(tok) && isLowerThanAnd(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; break;
tok = tok->next(); tok = tok->next();
@ -964,12 +970,17 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
result = ShiftUInt(cop, tok, tok->tokAt(2)); result = ShiftUInt(cop, tok, tok->tokAt(2));
else else
result = ShiftInt(cop, tok, tok->tokAt(2)); result = ShiftInt(cop, tok, tok->tokAt(2));
if (!result.empty()) { if (result.empty())
ret = true; break;
tok->str(result); tok->str(result);
tok->deleteNext(2); }
continue;
} // 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%")) else if (Token::Match(tok->previous(), "- %num% - %num%"))
@ -986,9 +997,15 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
} }
tok->deleteNext(2); tok->deleteNext(2);
tok = tok->previous();
ret = true; 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; return ret;
} }
@ -1124,12 +1141,8 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
ret = true; ret = true;
} }
if (Token::simpleMatch(tok->previous(), "( 0 ||") || 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(), "| 0 )") ||
Token::simpleMatch(tok->previous(), "( 1 &&") ||
Token::simpleMatch(tok->previous(), "&& 1 )")) {
if (tok->previous()->isConstOp()) if (tok->previous()->isConstOp())
tok = tok->previous(); tok = tok->previous();
tok->deleteNext(); tok->deleteNext();
@ -1173,8 +1186,15 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
tok->deleteNext(2); tok->deleteNext(2);
} }
else { else if (simplifyNumericCalculations(tok)) {
ret |= 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; return ret;

View File

@ -3728,14 +3728,6 @@ bool Tokenizer::simplifyTokenList2()
simplifyCasts(); 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 // 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); // e.g. const static int value = sizeof(X)/sizeof(Y);
simplifyCalculations(); simplifyCalculations();

View File

@ -2091,13 +2091,19 @@ private:
ASSERT_EQUALS("( 4 )", tok("(1 * 2 / 1 * 2)")); // #3722 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.. // don't remove these spaces..
ASSERT_EQUALS("new ( auto ) ( 4 ) ;", tok("new (auto)(4);")); ASSERT_EQUALS("new ( auto ) ( 4 ) ;", tok("new (auto)(4);"));
} }
void comparisons() { void comparisons() {
ASSERT_EQUALS("( 1 )", tok("( 1 < 2 )")); 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("( 5 )", tok("( 1 < 2 && 3 < 4 ? 5 : 6 )"));
ASSERT_EQUALS("( 6 )", tok("( 1 > 2 && 3 > 4 ? 5 : 6 )")); ASSERT_EQUALS("( 6 )", tok("( 1 > 2 && 3 > 4 ? 5 : 6 )"));
} }