diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index f77f631a4..3fe35182f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1494,6 +1494,12 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s // simplify function pointers simplifyFunctionPointers(); + + // "if (not p)" => "if (!p)" + // "if (p and q)" => "if (p && q)" + // "if (p or q)" => "if (p || q)" + while (simplifyLogicalOperators()); + //updateClassList(); setVarId(); @@ -3238,7 +3244,6 @@ bool Tokenizer::simplifyTokenList() } } - simplifyLogicalOperators(); simplifyCasts(); // simplify "x=realloc(y,0);" => "free(y); x=0;".. @@ -4895,32 +4900,43 @@ void Tokenizer::simplifyIfSameInnerCondition() } -void Tokenizer::simplifyLogicalOperators() +bool Tokenizer::simplifyLogicalOperators() { + bool ret = false; + // "if (not p)" => "if (!p)" - // "if (p and q)" => "if (p and q)" + // "if (p and q)" => "if (p && q)" + // "if (p or q)" => "if (p || q)" for (Token *tok = _tokens; tok; tok = tok->next()) { if (Token::Match(tok, "if|while ( not %var%")) { tok->tokAt(2)->str("!"); + ret = true; } else if (Token::Match(tok, "&& not %var%")) { tok->next()->str("!"); + ret = true; } else if (Token::Match(tok, "|| not %var%")) { tok->next()->str("!"); + ret = true; } // "%var%|) and %var%|(" - else if (tok->str() == "and" && + else if (Token::Match(tok, "and|or") && ((Token::Match(tok->previous(), "%var%") || tok->previous()->str() == ")") || (Token::Match(tok->next(), "%var%") || tok->next()->str() == "("))) { - tok->str("&&"); + if (tok->str() == "and") + tok->str("&&"); + else + tok->str("||"); + ret = true; } } + return ret; } // int i(0); => int i; i = 0; diff --git a/lib/tokenize.h b/lib/tokenize.h index 0de654c5a..d9855dedf 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -215,7 +215,7 @@ public: * - "if (not p)" => "if (!p)" * - "if (p and q)" => "if (p && q)" */ - void simplifyLogicalOperators(); + bool simplifyLogicalOperators(); /** * Simplify comma into a semicolon when possible: diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 75a77dfd5..b26a7ab9f 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -118,6 +118,9 @@ private: // Simplify "and" to "&&" (#620) TEST_CASE(and1); + // Simplify "or" to "||" + TEST_CASE(or1); + TEST_CASE(comma_keyword); TEST_CASE(remove_comma); @@ -1978,8 +1981,6 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); - tokenizer.simplifyLogicalOperators(); - std::ostringstream ostr; for (const Token *tok1 = tokenizer.tokens(); tok1; tok1 = tok1->next()) ostr << (tok1->previous() ? " " : "") << tok1->str(); @@ -2007,6 +2008,27 @@ private: ASSERT_EQUALS("if ( p && bar ( ) ) { ; }", simplifyLogicalOperators("if (p and bar()) ;")); + + ASSERT_EQUALS("if ( p && ! q )", + simplifyLogicalOperators("if (p and not q)")); + } + + void or1() + { + ASSERT_EQUALS("if ( p || q ) { ; }", + simplifyLogicalOperators("if (p or q) ;")); + + ASSERT_EQUALS("if ( foo ( ) || q ) { ; }", + simplifyLogicalOperators("if (foo() or q) ;")); + + ASSERT_EQUALS("if ( foo ( ) || bar ( ) ) { ; }", + simplifyLogicalOperators("if (foo() or bar()) ;")); + + ASSERT_EQUALS("if ( p || bar ( ) ) { ; }", + simplifyLogicalOperators("if (p or bar()) ;")); + + ASSERT_EQUALS("if ( p || ! q )", + simplifyLogicalOperators("if (p or not q)")); } void comma_keyword()