Fixed #4928 (C++ operator aliases result in false 'assigned a value that is never used' warning)
This commit is contained in:
parent
6fb4ce37fb
commit
9a08da17be
|
@ -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,54 +6026,52 @@ 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" ? "!" : "~");
|
||||
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;
|
||||
}
|
||||
// "%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("!=");
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue