diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index f5f2729d6..d23bb5a0e 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -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); diff --git a/lib/checkunusedvar.h b/lib/checkunusedvar.h index 833713590..eabca9e0c 100644 --- a/lib/checkunusedvar.h +++ b/lib/checkunusedvar.h @@ -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); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index e2d600d1a..db870bf8c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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() != ":")) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index caf3c34ba..0c3f8d86e 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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"