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();
|
||||
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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -899,7 +899,7 @@ public:
|
|||
}
|
||||
|
||||
// Is there lambda/inline function(s) in this scope?
|
||||
bool hasInlineFunction() const;
|
||||
bool hasInlineOrLambdaFunction() const;
|
||||
|
||||
/**
|
||||
* @brief find a function
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue