From e3892a95b55eb46bb7059e531d18049ad795f47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 3 Dec 2014 16:32:05 +0100 Subject: [PATCH] Fixed #6290 (Tokenizer: Because 'and' is not simplified to '&&' there are false positives) --- lib/tokenize.cpp | 52 ++++++++++++++++++++++------------- test/testsimplifytokens.cpp | 54 ++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d959a3f80..73acd7601 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6175,26 +6175,42 @@ static const std::map cAlternativeTokens(cAlternativeT // xor_eq => ^= bool Tokenizer::simplifyCAlternativeTokens() { + /* For C code: executable scope level */ + unsigned int executableScopeLevel = 0; + bool ret = false; for (Token *tok = list.front(); tok; tok = tok->next()) { - Token *start = startOfExecutableScope(tok); - if (start) { // Check for executable scope - tok = start; - 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%|(|%op%")) { - 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%|(|%op%") && - !Token::Match(tok2->previous(), "[;{}]")) { // Don't simplify 'not p;' (in case 'not' is a type) - tok2->str((tok2->str() == "not") ? "!" : "~"); - ret = true; - } - } + if (tok->str() == "{") { + if (executableScopeLevel > 0 || Token::Match(tok->previous(), ") {")) + ++executableScopeLevel; + continue; + } + + if (tok->str() == "}") { + if (executableScopeLevel > 0) + --executableScopeLevel; + continue; + } + + if (!tok->isName()) + continue; + + const std::map::const_iterator cOpIt = cAlternativeTokens.find(tok->str()); + if (cOpIt != cAlternativeTokens.end()) { + if (isC() && !Token::Match(tok->previous(), "%var%|%num%|%char%|)|]|> %var% %var%|%num%|%char%|%op%|(")) + continue; + tok->str(cOpIt->second); + ret = true; + } + else if (Token::Match(tok, "not|compl")) { + // Don't simplify 'not p;' (in case 'not' is a type) + if (isC() && (!Token::Match(tok->next(), "%var%|%op%|(") || + Token::Match(tok->previous(), "[;{}]") || + (executableScopeLevel == 0U && tok->strAt(-1) == "("))) + continue; + + tok->str((tok->str() == "not") ? "!" : "~"); + ret = true; } } return ret; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 4f9544db1..1501aa523 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -316,7 +316,7 @@ private: return tokenizer.tokens()->stringifyList(0, !simplify); } - std::string tok(const char code[], const char filename[]) { + std::string tok(const char code[], const char filename[], bool simplify = true) { errout.str(""); Settings settings; @@ -324,7 +324,8 @@ private: std::istringstream istr(code); tokenizer.tokenize(istr, filename); - tokenizer.simplifyTokenList2(); + if (simplify) + tokenizer.simplifyTokenList2(); return tokenizer.tokens()->stringifyList(0, false); } @@ -1684,68 +1685,71 @@ private: } void not1() { - 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)); + ASSERT_EQUALS("void f ( ) { if ( ! p ) { ; } }", tok("void f() { if (not p); }", "test.c", false)); + ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", tok("void f() { if (p && not q); }", "test.c", false)); + ASSERT_EQUALS("void f ( ) { a = ! ( p && q ) ; }", tok("void f() { a = not(p && q); }", "test.c", 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)); + ASSERT_EQUALS("struct not { int x ; } ;", tok("struct not { int x; };", "test.c", false)); + ASSERT_EQUALS("void f ( ) { not p ; compl c ; }", tok(" void f() { not p; compl c; }", "test.c", false)); + ASSERT_EQUALS("void foo ( not i ) ;", tok("void foo(not i);", "test.c", false)); + ASSERT_EQUALS("int foo ( not i ) { return g ( i ) ; }", tok("int foo(not i) { return g(i); }", "test.c", false)); } void and1() { ASSERT_EQUALS("void f ( ) { if ( p && q ) { ; } }", - tok("void f() { if (p and q) ; }", false)); + tok("void f() { if (p and q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) && q ) { ; } }", - tok("void f() { if (foo() and q) ; }", false)); + tok("void f() { if (foo() and q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) && bar ( ) ) { ; } }", - tok("void f() { if (foo() and bar()) ; }", false)); + tok("void f() { if (foo() and bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p && bar ( ) ) { ; } }", - tok("void f() { if (p and bar()) ; }", false)); + tok("void f() { if (p and bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p && ! q ) { ; } }", - tok("void f() { if (p and not q) ; }", false)); + tok("void f() { if (p and not q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = a && b ; }", - tok("void f() { r = a and b; }", false)); + tok("void f() { r = a and b; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = ( a || b ) && ( c || d ) ; }", - tok("void f() { r = (a || b) and (c || d); }", false)); + tok("void f() { r = (a || b) and (c || d); }", "test.c", false)); + + ASSERT_EQUALS("void f ( ) { if ( test1 [ i ] == 'A' && test2 [ i ] == 'C' ) { } }", + tok("void f() { if (test1[i] == 'A' and test2[i] == 'C') {} }", "test.c", false)); } void or1() { ASSERT_EQUALS("void f ( ) { if ( p || q ) { ; } }", - tok("void f() { if (p or q) ; }", false)); + tok("void f() { if (p or q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) || q ) { ; } }", - tok("void f() { if (foo() or q) ; }", false)); + tok("void f() { if (foo() or q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( foo ( ) || bar ( ) ) { ; } }", - tok("void f() { if (foo() or bar()) ; }", false)); + tok("void f() { if (foo() or bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p || bar ( ) ) { ; } }", - tok("void f() { if (p or bar()) ; }", false)); + tok("void f() { if (p or bar()) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { if ( p || ! q ) { ; } }", - tok("void f() { if (p or not q) ; }", false)); + tok("void f() { if (p or not q) ; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = a || b ; }", - tok("void f() { r = a or b; }", false)); + tok("void f() { r = a or b; }", "test.c", false)); ASSERT_EQUALS("void f ( ) { r = ( a && b ) || ( c && d ) ; }", - tok("void f() { r = (a && b) or (c && d); }", false)); + tok("void f() { r = (a && b) or (c && d); }", "test.c", false)); } void cAlternativeTokens() { ASSERT_EQUALS("void f ( ) { err = err | ( ( r & s ) && ! t ) ; }", - tok("void f() { err or_eq ((r bitand s) and not t); }", false)); + tok("void f() { err or_eq ((r bitand s) and not t); }", "test.c", 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)); + tok("void f() const { r = f(a[4] bitor 0x0F, compl c, not d) ; }", "test.c", false)); }