Fixed #6290 (Tokenizer: Because 'and' is not simplified to '&&' there are false positives)

This commit is contained in:
Daniel Marjamäki 2014-12-03 16:32:05 +01:00
parent d0ff8d87cb
commit e3892a95b5
2 changed files with 63 additions and 43 deletions

View File

@ -6175,26 +6175,42 @@ static const std::map<std::string, std::string> 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<std::string, std::string>::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<std::string, std::string>::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;

View File

@ -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));
}