Fixed #3672: bitwise and operator in if/while does no longer confuse setVarId code
Improvements to CheckUnusedVar: - Improved handling of arrays of struct/class instances - Differ between addressof and bitwise-and operator - Made some members private to improve encapsulation - Replaced some simple patterns by direct function calls - Removed an unnecessary condition
This commit is contained in:
parent
f079ee7c31
commit
7055526f4a
|
@ -620,6 +620,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (i->isArray() && i->isClass()) // Array of class/struct members. Initialized by ctor.
|
||||
variables.write(i->varId());
|
||||
if (i->isArray() && Token::Match(i->nameToken(), "%var% [ %var% ]")) // Array index variable read.
|
||||
variables.read(i->nameToken()->tokAt(2)->varId());
|
||||
|
||||
|
@ -706,7 +708,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
|||
}
|
||||
}
|
||||
|
||||
else if (Token::Match(tok, "return|throw %var%")) {
|
||||
else if (Token::Match(tok, "return|throw")) {
|
||||
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
||||
if (tok2->varId())
|
||||
variables.readAll(tok2->varId());
|
||||
|
@ -838,7 +840,12 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
|||
}
|
||||
}
|
||||
|
||||
else if (Token::Match(tok, ">>|& %var%"))
|
||||
else if (Token::Match(tok, "& %var%")) {
|
||||
if (tok->previous()->isName() || tok->previous()->isNumber()) { // bitop
|
||||
variables.read(tok->next()->varId());
|
||||
} else // addressof
|
||||
variables.use(tok->next()->varId()); // use = read + write
|
||||
} else if (Token::Match(tok, ">> %var%"))
|
||||
variables.use(tok->next()->varId()); // use = read + write
|
||||
else if (Token::Match(tok, "%var% >>|&") && Token::Match(tok->previous(), "[{};:]"))
|
||||
variables.read(tok->varId());
|
||||
|
@ -865,8 +872,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
|||
else if (Token::Match(tok, "%var% ."))
|
||||
variables.use(tok->varId()); // use = read + write
|
||||
|
||||
else if ((Token::Match(tok, "[(=&!]") || tok->isExtendedOp()) &&
|
||||
(Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new")) && tok->strAt(2) != "=")
|
||||
else if (tok->isExtendedOp() &&
|
||||
Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new") && tok->strAt(2) != "=")
|
||||
variables.readAll(tok->next()->varId());
|
||||
|
||||
else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || tok->next()->isExtendedOp()))
|
||||
|
@ -994,9 +1001,9 @@ void CheckUnusedVar::checkStructMemberUsage()
|
|||
|
||||
if (Token::Match(tok, "struct|union %type% {")) {
|
||||
structname.clear();
|
||||
if (Token::simpleMatch(tok->previous(), "extern"))
|
||||
if (tok->strAt(-1) == "extern")
|
||||
continue;
|
||||
if ((!tok->previous() || Token::simpleMatch(tok->previous(), ";")) && Token::Match(tok->linkAt(2), ("} ; " + tok->strAt(1) + " %var% ;").c_str()))
|
||||
if ((!tok->previous() || tok->previous()->str() == ";") && Token::Match(tok->linkAt(2), ("} ; " + tok->strAt(1) + " %var% ;").c_str()))
|
||||
continue;
|
||||
|
||||
structname = tok->strAt(1);
|
||||
|
|
|
@ -70,6 +70,7 @@ public:
|
|||
/** @brief %Check that all struct members are used */
|
||||
void checkStructMemberUsage();
|
||||
|
||||
private:
|
||||
// Error messages..
|
||||
void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname);
|
||||
void unusedVariableError(const Token *tok, const std::string &varname);
|
||||
|
|
|
@ -2814,7 +2814,7 @@ void Tokenizer::setVarId()
|
|||
if (Token::Match(tok, "( %type% *|& %var% [),]") && !tok->next()->isStandardType()) {
|
||||
if (!Token::Match(tok->previous(), "%type%"))
|
||||
continue;
|
||||
if (tok->previous() && tok->previous()->str() == "return")
|
||||
if (Token::Match(tok->previous(), "return|if|while"))
|
||||
continue;
|
||||
if (tok->link() && !Token::Match(tok->link()->next(), "const| {") &&
|
||||
(!tok->link()->next() || tok->link()->next()->str() != ":"))
|
||||
|
|
|
@ -206,6 +206,7 @@ private:
|
|||
TEST_CASE(varid40); // ticket #3279
|
||||
TEST_CASE(varid41); // ticket #3340 (varid for union type)
|
||||
TEST_CASE(varid42); // ticket #3316 (varid for array)
|
||||
TEST_CASE(varid43);
|
||||
TEST_CASE(varid44);
|
||||
TEST_CASE(varidFunctionCall1);
|
||||
TEST_CASE(varidFunctionCall2);
|
||||
|
@ -3248,6 +3249,13 @@ private:
|
|||
tokenizeDebugListing(code));
|
||||
}
|
||||
|
||||
void varid43() {
|
||||
const std::string code("int main(int flag) { if(a & flag) { return 1; } }");
|
||||
ASSERT_EQUALS("\n\n##file 0\n"
|
||||
"1: int main ( int flag@1 ) { if ( a & flag@1 ) { return 1 ; } }\n",
|
||||
tokenizeDebugListing(code));
|
||||
}
|
||||
|
||||
void varid44() {
|
||||
const std::string code("class A:public B,public C,public D {};");
|
||||
ASSERT_EQUALS("\n\n##file 0\n"
|
||||
|
|
Loading…
Reference in New Issue