Fixed #7026 (Cppcheck does not recognizes the use of a variabile inside lambda function)
This commit is contained in:
parent
38741868b5
commit
54be403f64
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue