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();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
if (scope->hasInlineFunction())
if (scope->hasInlineOrLambdaFunction())
continue;
// Empty variable info

View File

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

View File

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

View File

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

View File

@ -168,6 +168,8 @@ private:
TEST_CASE(crash1);
TEST_CASE(crash2);
TEST_CASE(usingNamespace); // #4585
TEST_CASE(lambdaFunction); // #5078
}
void checkStructMemberUsage(const char code[]) {
@ -3192,38 +3194,6 @@ private:
"}");
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'
functionVariableUsage("void f() {\n"
" std::map<int,int> ints;\n"
@ -3969,6 +3939,38 @@ private:
"}"); // #4585
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)