From 2737f63f712c75fabfb36d8fe7302a95de6b33db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 25 Nov 2015 16:46:39 +0100 Subject: [PATCH] Wrong calculation of constants (simplifying: +,<<,% operations) --- lib/templatesimplifier.cpp | 52 +++++++++++++++++++++++++------------ lib/tokenize.cpp | 8 ------ test/testsimplifytokens.cpp | 8 +++++- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index b6ca17460..de0652c3d 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -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; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 80d87b2a3..3651dac3e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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(); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 9a92cc3c5..50a400aa2 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -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 )")); }