Fixed #7026 (Cppcheck does not recognizes the use of a variabile inside lambda function)

This commit is contained in:
Daniel Marjamäki 2016-05-26 18:07:56 +02:00
parent 38741868b5
commit 54be403f64
6 changed files with 47 additions and 37 deletions

View File

@ -140,7 +140,7 @@ void CheckLeakAutoVar::check()
const std::size_t functions = symbolDatabase->functionScopes.size(); const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) { for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
if (scope->hasInlineFunction()) if (scope->hasInlineOrLambdaFunction())
continue; continue;
// Empty variable info // Empty variable info

View File

@ -2177,7 +2177,7 @@ void CheckMemoryLeakInFunction::check()
const std::size_t functions = symbolDatabase->functionScopes.size(); const std::size_t functions = symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) { for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
if (!scope->hasInlineFunction()) if (!scope->hasInlineOrLambdaFunction())
checkScope(scope->classStart->next(), "", 0, scope->functionOf != nullptr, 1); checkScope(scope->classStart->next(), "", 0, scope->functionOf != nullptr, 1);
} }
@ -2197,7 +2197,7 @@ void CheckMemoryLeakInFunction::check()
if (var->isPointer() && var->type() && !var->typeScope()) if (var->isPointer() && var->type() && !var->typeScope())
continue; continue;
if (var->scope()->hasInlineFunction()) if (var->scope()->hasInlineOrLambdaFunction())
continue; continue;
unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken()); unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken());

View File

@ -1136,6 +1136,11 @@ void CheckUnusedVar::checkFunctionVariableUsage()
for (std::size_t i = 0; i < functions; ++i) { for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
// Bailout when there are lambdas or inline functions
// TODO: Handle lambdas and inline functions properly
if (scope->hasInlineOrLambdaFunction())
continue;
// varId, usage {read, write, modified} // varId, usage {read, write, modified}
Variables variables; Variables variables;

View File

@ -3493,13 +3493,16 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
return nullptr; return nullptr;
} }
bool Scope::hasInlineFunction() const bool Scope::hasInlineOrLambdaFunction() const
{ {
for (std::list<Scope*>::const_iterator it = nestedList.begin(); it != nestedList.end(); ++it) { for (std::list<Scope*>::const_iterator it = nestedList.begin(); it != nestedList.end(); ++it) {
const Scope *s = *it; const Scope *s = *it;
// Inline function // Inline function
if (s->type == Scope::eUnconditional && Token::Match(s->classStart->previous(), ") {")) if (s->type == Scope::eUnconditional && Token::Match(s->classStart->previous(), ") {"))
return true; return true;
// Lambda function
if (s->type == Scope::eLambda)
return true;
} }
return false; return false;
} }

View File

@ -899,7 +899,7 @@ public:
} }
// Is there lambda/inline function(s) in this scope? // Is there lambda/inline function(s) in this scope?
bool hasInlineFunction() const; bool hasInlineOrLambdaFunction() const;
/** /**
* @brief find a function * @brief find a function

View File

@ -168,6 +168,8 @@ private:
TEST_CASE(crash1); TEST_CASE(crash1);
TEST_CASE(crash2); TEST_CASE(crash2);
TEST_CASE(usingNamespace); // #4585 TEST_CASE(usingNamespace); // #4585
TEST_CASE(lambdaFunction); // #5078
} }
void checkStructMemberUsage(const char code[]) { void checkStructMemberUsage(const char code[]) {
@ -3192,38 +3194,6 @@ private:
"}"); "}");
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"
"}");
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"
"}");
ASSERT_EQUALS("[test.cpp:6]: (style) Variable 'i' is assigned a value that is never used.\n", errout.str());
// #4956 - assignment in for_each
functionVariableUsage("void f(std::vector<int> ints) {\n"
" int x = 0;\n"
" std::for_each(ints.begin(), ints.end(), [&x](int i){ dostuff(x); x = i; });\n"
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void f(std::vector<int> ints) {\n"
" int x = 0;\n"
" std::for_each(ints.begin(), ints.end(), [&x](int i){ x += i; });\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'x' is assigned a value that is never used.\n", errout.str());
// #5154 - MSVC 'for each' // #5154 - MSVC 'for each'
functionVariableUsage("void f() {\n" functionVariableUsage("void f() {\n"
" std::map<int,int> ints;\n" " std::map<int,int> ints;\n"
@ -3969,6 +3939,38 @@ private:
"}"); // #4585 "}"); // #4585
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void lambdaFunction() {
// #7026
functionVariableUsage("void f() {\n"
" bool first = true;\n"
"\n"
" auto do_something = [&first]() {\n"
" if (first) {\n"
" first = false;\n"
" } else {\n"
" dostuff();\n"
" }\n"
" };\n"
" do_something();\n"
" do_something();\n"
"}");
ASSERT_EQUALS("", errout.str());
// #4956 - assignment in for_each
functionVariableUsage("void f(std::vector<int> ints) {\n"
" int x = 0;\n"
" std::for_each(ints.begin(), ints.end(), [&x](int i){ dostuff(x); x = i; });\n"
"}");
ASSERT_EQUALS("", errout.str());
functionVariableUsage("void f(std::vector<int> ints) {\n"
" int x = 0;\n"
" std::for_each(ints.begin(), ints.end(), [&x](int i){ x += i; });\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'x' is assigned a value that is never used.\n", "", errout.str());
}
}; };
REGISTER_TEST(TestUnusedVar) REGISTER_TEST(TestUnusedVar)