Unused var: Limit bailout for foreach loops. Only bailout if name contains 'foreach' or 'for_each'. Only bailout variables that are used more than once in the body. Ticket: #4155
This commit is contained in:
parent
72ea94bf75
commit
1e2fb4f1a4
|
@ -20,7 +20,7 @@
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include "checkunusedvar.h"
|
#include "checkunusedvar.h"
|
||||||
#include "symboldatabase.h"
|
#include "symboldatabase.h"
|
||||||
|
#include <algorithm>
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Register this check class (by creating a static instance of it)
|
// Register this check class (by creating a static instance of it)
|
||||||
|
@ -746,13 +746,26 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok,"%var% (") && Token::simpleMatch(tok->linkAt(1),") {") && !Token::Match(tok, "for|while|if|catch")) {
|
// bailout when for_each is used
|
||||||
|
if (Token::Match(tok,"%var% (") && Token::simpleMatch(tok->linkAt(1),") {")) {
|
||||||
|
// does the name contain "for_each" or "foreach"?
|
||||||
|
std::string name(tok->str());
|
||||||
|
std::transform(name.begin(),name.end(),name.begin(),static_cast<int(*)(int)>(std::tolower));
|
||||||
|
if (name.find("foreach") != std::string::npos || name.find("for_each") != std::string::npos) {
|
||||||
|
// bailout all variables in the body that are used more than once.
|
||||||
|
// TODO: there is no need to bailout if variable is only read or only written
|
||||||
|
std::set<unsigned int> varid;
|
||||||
const Token * const endTok = tok->linkAt(1)->linkAt(1);
|
const Token * const endTok = tok->linkAt(1)->linkAt(1);
|
||||||
for (const Token *tok2 = endTok->link(); tok2 && tok2 != endTok; tok2 = tok2->next()) {
|
for (const Token *tok2 = endTok->link(); tok2 && tok2 != endTok; tok2 = tok2->next()) {
|
||||||
if (tok2->varId())
|
if (tok2->varId()) {
|
||||||
|
if (varid.find(tok2->varId()) == varid.end())
|
||||||
|
varid.insert(tok2->varId());
|
||||||
|
else
|
||||||
variables.erase(tok2->varId());
|
variables.erase(tok2->varId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Token::Match(tok->previous(), "[;{}]")) {
|
if (Token::Match(tok->previous(), "[;{}]")) {
|
||||||
for (const Token* tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
for (const Token* tok2 = tok->next(); tok2; tok2 = tok2->next()) {
|
||||||
|
|
|
@ -135,7 +135,7 @@ private:
|
||||||
TEST_CASE(localvarIfElse); // return tmp1 ? tmp2 : tmp3;
|
TEST_CASE(localvarIfElse); // return tmp1 ? tmp2 : tmp3;
|
||||||
TEST_CASE(localvarOpAssign); // a |= b;
|
TEST_CASE(localvarOpAssign); // a |= b;
|
||||||
TEST_CASE(localvarFor); // for ( ; var; )
|
TEST_CASE(localvarFor); // for ( ; var; )
|
||||||
TEST_CASE(localvarForEach); // BOOST_FOREACH, hlist_for_each, etc
|
TEST_CASE(localvarForEach); // #4155 - BOOST_FOREACH, hlist_for_each, etc
|
||||||
TEST_CASE(localvarShift1); // 1 >> var
|
TEST_CASE(localvarShift1); // 1 >> var
|
||||||
TEST_CASE(localvarShift2); // x = x >> 1
|
TEST_CASE(localvarShift2); // x = x >> 1
|
||||||
TEST_CASE(localvarShift3); // x << y
|
TEST_CASE(localvarShift3); // x << y
|
||||||
|
@ -2949,7 +2949,7 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarForEach() {
|
void localvarForEach() { // #4155 - foreach
|
||||||
functionVariableUsage("void foo() {\n"
|
functionVariableUsage("void foo() {\n"
|
||||||
" int i = -1;\n"
|
" int i = -1;\n"
|
||||||
" int a[] = {1,2,3};\n"
|
" int a[] = {1,2,3};\n"
|
||||||
|
@ -2959,6 +2959,25 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo() {\n"
|
||||||
|
" int i = -1;\n"
|
||||||
|
" int a[] = {1,2,3};\n"
|
||||||
|
" FOREACH_X (int x, a) {\n"
|
||||||
|
" i = x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (style) Variable 'i' is assigned a value that is never used.\n", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("void foo() {\n"
|
||||||
|
" int i = -1;\n"
|
||||||
|
" int a[] = {1,2,3};\n"
|
||||||
|
" X (int x, a) {\n"
|
||||||
|
" if (i==x) return x;\n"
|
||||||
|
" i = x;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (style) Variable 'i' is assigned a value that is never used.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvarShift1() {
|
void localvarShift1() {
|
||||||
|
|
Loading…
Reference in New Issue