Fixed #6290 (Tokenizer: Because 'and' is not simplified to '&&' there are false positives)
This commit is contained in:
parent
d0ff8d87cb
commit
e3892a95b5
|
@ -6175,26 +6175,42 @@ static const std::map<std::string, std::string> cAlternativeTokens(cAlternativeT
|
||||||
// xor_eq => ^=
|
// xor_eq => ^=
|
||||||
bool Tokenizer::simplifyCAlternativeTokens()
|
bool Tokenizer::simplifyCAlternativeTokens()
|
||||||
{
|
{
|
||||||
|
/* For C code: executable scope level */
|
||||||
|
unsigned int executableScopeLevel = 0;
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
Token *start = startOfExecutableScope(tok);
|
if (tok->str() == "{") {
|
||||||
if (start) { // Check for executable scope
|
if (executableScopeLevel > 0 || Token::Match(tok->previous(), ") {"))
|
||||||
tok = start;
|
++executableScopeLevel;
|
||||||
Token * const end = tok->link();
|
continue;
|
||||||
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 (tok->str() == "}") {
|
||||||
if (cOpIt != cAlternativeTokens.end()) {
|
if (executableScopeLevel > 0)
|
||||||
tok2->next()->str(cOpIt->second);
|
--executableScopeLevel;
|
||||||
ret = true;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (Token::Match(tok2, "not|compl %var%|(|%op%") &&
|
if (!tok->isName())
|
||||||
!Token::Match(tok2->previous(), "[;{}]")) { // Don't simplify 'not p;' (in case 'not' is a type)
|
continue;
|
||||||
tok2->str((tok2->str() == "not") ? "!" : "~");
|
|
||||||
ret = true;
|
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;
|
return ret;
|
||||||
|
|
|
@ -316,7 +316,7 @@ private:
|
||||||
return tokenizer.tokens()->stringifyList(0, !simplify);
|
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("");
|
errout.str("");
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
@ -324,7 +324,8 @@ private:
|
||||||
|
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, filename);
|
tokenizer.tokenize(istr, filename);
|
||||||
tokenizer.simplifyTokenList2();
|
if (simplify)
|
||||||
|
tokenizer.simplifyTokenList2();
|
||||||
|
|
||||||
return tokenizer.tokens()->stringifyList(0, false);
|
return tokenizer.tokens()->stringifyList(0, false);
|
||||||
}
|
}
|
||||||
|
@ -1684,68 +1685,71 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void not1() {
|
void not1() {
|
||||||
ASSERT_EQUALS("void f ( ) { if ( ! p ) { ; } }", tok("void f() { if (not p); }", 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); }", 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); }", 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;
|
// Don't simplify 'not' or 'compl' if they are defined as a type;
|
||||||
// in variable declaration and in function declaration/definition
|
// in variable declaration and in function declaration/definition
|
||||||
ASSERT_EQUALS("struct not { int x ; } ;", tok("struct not { int x; };", 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; }", 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);", 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); }", false));
|
ASSERT_EQUALS("int foo ( not i ) { return g ( i ) ; }", tok("int foo(not i) { return g(i); }", "test.c", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void and1() {
|
void and1() {
|
||||||
ASSERT_EQUALS("void f ( ) { if ( p && q ) { ; } }",
|
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 ) { ; } }",
|
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 ( ) ) { ; } }",
|
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 ( ) ) { ; } }",
|
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 ) { ; } }",
|
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 ; }",
|
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 ) ; }",
|
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() {
|
void or1() {
|
||||||
ASSERT_EQUALS("void f ( ) { if ( p || q ) { ; } }",
|
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 ) { ; } }",
|
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 ( ) ) { ; } }",
|
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 ( ) ) { ; } }",
|
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 ) { ; } }",
|
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 ; }",
|
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 ) ; }",
|
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() {
|
void cAlternativeTokens() {
|
||||||
ASSERT_EQUALS("void f ( ) { err = err | ( ( r & s ) && ! t ) ; }",
|
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 ) ; }",
|
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));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue