diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d710c7486..fd8cae500 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1680,7 +1680,7 @@ bool Tokenizer::tokenizeCondition(const std::string &code) while (TemplateSimplifier::simplifyNumericCalculations(tok)) ; - while (simplifyLogicalOperators()) { } + simplifyCAlternativeTokens(); // Convert e.g. atol("0") into 0 while (simplifyMathFunctions()) {}; @@ -3384,11 +3384,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) // 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()) {} - // Change initialisation of variable to assignment simplifyInitVar(); @@ -3402,6 +3397,9 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) setVarId(); } + // Simplify the C alternative tokens (and, or, etc.) + simplifyCAlternativeTokens(); + // The simplify enum might have inner loops if (_settings->terminated()) return false; @@ -6028,51 +6026,49 @@ void Tokenizer::simplifyIfSameInnerCondition() } } +// Binary operators simplification map +static const std::pair cAlternativeTokens_[] = { + std::make_pair("and", "&&"), std::make_pair("and_eq", "&="), std::make_pair("bitand", "&"), + std::make_pair("bitor", "|"), std::make_pair("not_eq", "!="), std::make_pair("or", "||"), + std::make_pair("or_eq", "|="), std::make_pair("xor", "^"), std::make_pair("xor_eq", "^=") +}; -bool Tokenizer::simplifyLogicalOperators() +static const std::map cAlternativeTokens(cAlternativeTokens_, + cAlternativeTokens_ + sizeof(cAlternativeTokens_)/sizeof(*cAlternativeTokens_)); + +// Simplify the C alternative tokens: +// and => && +// and_eq => &= +// bitand => & +// bitor => | +// compl => ~ +// not => ! +// not_eq => != +// or => || +// or_eq => |= +// xor => ^ +// xor_eq => ^= +bool Tokenizer::simplifyCAlternativeTokens() { bool ret = false; - - // "if (not p)" => "if (!p)" - // "if (p and q)" => "if (p && q)" - // "if (p or q)" => "if (p || q)" for (Token *tok = list.front(); tok; tok = tok->next()) { - if (Token::Match(tok, "if|while ( not|compl %var%")) { - tok->tokAt(2)->str(tok->strAt(2) == "not" ? "!" : "~"); - ret = true; - } else if (Token::Match(tok, "&& not|compl %var%")) { - tok->next()->str(tok->next()->str() == "not" ? "!" : "~"); - ret = true; - } else if (Token::Match(tok, "|| not|compl %var%")) { - tok->next()->str(tok->next()->str() == "not" ? "!" : "~"); - ret = true; - } - // "%var%|) and %var%|(" - else if (Token::Match(tok, "%var% %any%")) { - if (!Token::Match(tok, "and|or|bitand|bitor|xor|not_eq")) - continue; - - const Token *tok2 = tok; - while (nullptr != (tok2 = tok2->previous())) { - if (tok2->str() == ")") - tok2 = tok2->link(); - else if (Token::Match(tok2, "(|;|{|}")) - break; - } - if (tok2 && Token::Match(tok2->previous(), "if|while (")) { - if (tok->str() == "and") - tok->str("&&"); - else if (tok->str() == "or") - tok->str("||"); - else if (tok->str() == "bitand") - tok->str("&"); - else if (tok->str() == "bitor") - tok->str("|"); - else if (tok->str() == "xor") - tok->str("^"); - else if (tok->str() == "not_eq") - tok->str("!="); - ret = true; + if (Token::Match(tok, ") const| {")) { // Check for executable scope + while (tok->str() != "{") + tok = tok->next(); + Token * const end = tok->link(); + for (Token *tok2 = tok->next(); tok2 && tok2 != end; tok2 = tok2->next()) { + if (Token::Match(tok2, "%var%|%num%|)|] %any% %var%|%num%|(")) { + const std::map::const_iterator cOpIt = cAlternativeTokens.find(tok2->next()->str()); + if (cOpIt != cAlternativeTokens.end()) { + tok2->next()->str(cOpIt->second); + ret = true; + } + } + if (Token::Match(tok2, "not|compl %var%|(") && + !Token::Match(tok2->previous(), "[;{}]")) { // Don't simplify 'not p;' (in case 'not' is a type) + tok2->str(Token::Match(tok2, "not") ? "!" : "~"); + ret = true; + } } } } diff --git a/lib/tokenize.h b/lib/tokenize.h index c8d0aa516..d277ba950 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -289,13 +289,13 @@ public: void simplifyIfSameInnerCondition(); /** - * Simplify the "not" and "and" keywords to "!" and "&&" - * accordingly. + * Simplify the 'C Alternative Tokens' * Examples: - * - "if (not p)" => "if (!p)" - * - "if (p and q)" => "if (p && q)" + * "if(s and t)" => "if(s && t)" + * "while((r bitand s) and not t)" => while((r & s) && !t)" + * "a and_eq b;" => "a &= b;" */ - bool simplifyLogicalOperators(); + bool simplifyCAlternativeTokens(); /** * Simplify comma into a semicolon when possible: diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index b9d8aabb0..e6860f32d 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -170,6 +170,8 @@ private: // Simplify "or" to "||" TEST_CASE(or1); + TEST_CASE(cAlternativeTokens); + TEST_CASE(comma_keyword); TEST_CASE(remove_comma); @@ -2695,45 +2697,70 @@ private: ASSERT_EQUALS("if ( ! ( ! fclose ( fd ) ) ) { ; }", tok("if(!(fclose(fd) == 0));", false)); } - void not1() { - ASSERT_EQUALS("if ( ! p ) { ; }", tok("if (not p);", false)); - ASSERT_EQUALS("if ( p && ! q ) { ; }", tok("if (p && not q);", false)); - ASSERT_EQUALS("void foo ( not i )", tok("void foo ( not i )", false)); + ASSERT_EQUALS("void f ( ) { if ( ! p ) { ; } }", tok("void f() { if (not p); }", false)); + ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", tok("void f() { if (p && not q); }", false)); + ASSERT_EQUALS("void f ( ) { a = ! ( p && q ) ; }", tok("void f() { a = not(p && q); }", false)); + // Don't simplify 'not' or 'compl' if they are defined as a type; + // in variable declaration and in function declaration/definition + ASSERT_EQUALS("struct not { int x ; } ;", tok("struct not { int x; };", false)); + ASSERT_EQUALS("void f ( ) { not p ; compl c ; }", tok(" void f() { not p; compl c; }", false)); + ASSERT_EQUALS("void foo ( not i ) ;", tok("void foo(not i);", false)); + ASSERT_EQUALS("int foo ( not i ) { return g ( i ) ; }", tok("int foo(not i) { return g(i); }", false)); } void and1() { - ASSERT_EQUALS("if ( p && q ) { ; }", - tok("if (p and q) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( p && q ) { ; } }", + tok("void f() { if (p and q) ; }", false)); - ASSERT_EQUALS("if ( foo ( ) && q ) { ; }", - tok("if (foo() and q) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( foo ( ) && q ) { ; } }", + tok("void f() { if (foo() and q) ; }", false)); - ASSERT_EQUALS("if ( foo ( ) && bar ( ) ) { ; }", - tok("if (foo() and bar()) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( foo ( ) && bar ( ) ) { ; } }", + tok("void f() { if (foo() and bar()) ; }", false)); - ASSERT_EQUALS("if ( p && bar ( ) ) { ; }", - tok("if (p and bar()) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( p && bar ( ) ) { ; } }", + tok("void f() { if (p and bar()) ; }", false)); - ASSERT_EQUALS("if ( p && ! q ) { ; }", - tok("if (p and not q) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", + tok("void f() { if (p and not q) ; }", false)); + + ASSERT_EQUALS("void f ( ) { r = a && b ; }", + tok("void f() { r = a and b; }", false)); + + ASSERT_EQUALS("void f ( ) { r = ( a || b ) && ( c || d ) ; }", + tok("void f() { r = (a || b) and (c || d); }", false)); } void or1() { - ASSERT_EQUALS("if ( p || q ) { ; }", - tok("if (p or q) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( p || q ) { ; } }", + tok("void f() { if (p or q) ; }", false)); - ASSERT_EQUALS("if ( foo ( ) || q ) { ; }", - tok("if (foo() or q) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( foo ( ) || q ) { ; } }", + tok("void f() { if (foo() or q) ; }", false)); - ASSERT_EQUALS("if ( foo ( ) || bar ( ) ) { ; }", - tok("if (foo() or bar()) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( foo ( ) || bar ( ) ) { ; } }", + tok("void f() { if (foo() or bar()) ; }", false)); - ASSERT_EQUALS("if ( p || bar ( ) ) { ; }", - tok("if (p or bar()) ;", false)); + ASSERT_EQUALS("void f ( ) { if ( p || bar ( ) ) { ; } }", + tok("void f() { if (p or bar()) ; }", false)); + + ASSERT_EQUALS("void f ( ) { if ( p || ! q ) { ; } }", + tok("void f() { if (p or not q) ; }", false)); + + ASSERT_EQUALS("void f ( ) { r = a || b ; }", + tok("void f() { r = a or b; }", false)); + + ASSERT_EQUALS("void f ( ) { r = ( a && b ) || ( c && d ) ; }", + tok("void f() { r = (a && b) or (c && d); }", false)); + } + + void cAlternativeTokens() { + ASSERT_EQUALS("void f ( ) { err |= ( ( r & s ) && ! t ) ; }", + tok("void f() { err or_eq ((r bitand s) and not t); }", false)); + ASSERT_EQUALS("void f ( ) const { r = f ( a [ 4 ] | 15 , ~ c , ! d ) ; }", + tok("void f() const { r = f(a[4] bitor 0x0F, compl c, not d) ; }", false)); - ASSERT_EQUALS("if ( p || ! q ) { ; }", - tok("if (p or not q) ;", false)); } void comma_keyword() { diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 7de04d6c4..12cb43b6f 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -477,7 +477,7 @@ private: TEST_CASE(simplifySQL); - TEST_CASE(simplifyLogicalOperators); + TEST_CASE(simplifyCAlternativeTokens); TEST_CASE(simplifyCalculations); @@ -7811,15 +7811,15 @@ private: } - void simplifyLogicalOperators() { - ASSERT_EQUALS("if ( a && b ) { ; }", tokenizeAndStringify("if (a and b);")); - ASSERT_EQUALS("if ( a || b ) { ; }", tokenizeAndStringify("if (a or b);")); - ASSERT_EQUALS("if ( a & b ) { ; }", tokenizeAndStringify("if (a bitand b);")); - ASSERT_EQUALS("if ( a | b ) { ; }", tokenizeAndStringify("if (a bitor b);")); - ASSERT_EQUALS("if ( a ^ b ) { ; }", tokenizeAndStringify("if (a xor b);")); - ASSERT_EQUALS("if ( ~ b ) { ; }", tokenizeAndStringify("if (compl b);")); - ASSERT_EQUALS("if ( ! b ) { ; }", tokenizeAndStringify("if (not b);")); - ASSERT_EQUALS("if ( a != b ) { ; }", tokenizeAndStringify("if (a not_eq b);")); + void simplifyCAlternativeTokens() { + ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }")); + ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }")); + ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }")); + ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }")); + ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }")); + ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }")); + ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }")); } void simplifyCalculations() {