Fixed #4928 (C++ operator aliases result in false 'assigned a value that is never used' warning)

This commit is contained in:
Lucas Manuel Rodriguez 2014-03-16 14:51:05 -03:00
parent 6fb4ce37fb
commit 9a08da17be
4 changed files with 109 additions and 86 deletions

View File

@ -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<std::string, std::string> 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<std::string, std::string> 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<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%|(") &&
!Token::Match(tok2->previous(), "[;{}]")) { // Don't simplify 'not p;' (in case 'not' is a type)
tok2->str(Token::Match(tok2, "not") ? "!" : "~");
ret = true;
}
}
}
}

View File

@ -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:

View File

@ -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() {

View File

@ -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() {