Fixed #9680 (false positive: style: Variable 'x' is assigned a value that is never used with smart pointers)
This commit is contained in:
parent
65ac94aa88
commit
ba84303501
|
@ -45,6 +45,53 @@ namespace {
|
||||||
static const struct CWE CWE563(563U); // Assignment to Variable without Use ('Unused Variable')
|
static const struct CWE CWE563(563U); // Assignment to Variable without Use ('Unused Variable')
|
||||||
static const struct CWE CWE665(665U); // Improper Initialization
|
static const struct CWE CWE665(665U); // Improper Initialization
|
||||||
|
|
||||||
|
/** Is scope a raii class scope */
|
||||||
|
static bool isRaiiClassScope(const Scope *classScope)
|
||||||
|
{
|
||||||
|
return classScope && classScope->getDestructor() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Is ValueType a raii class? */
|
||||||
|
static bool isRaiiClass(const ValueType *valueType, bool cpp, bool defaultReturn = true)
|
||||||
|
{
|
||||||
|
if (!cpp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!valueType)
|
||||||
|
return defaultReturn;
|
||||||
|
|
||||||
|
if (valueType->smartPointerType && isRaiiClassScope(valueType->smartPointerType->classScope))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (valueType->type) {
|
||||||
|
case ValueType::Type::UNKNOWN_TYPE:
|
||||||
|
case ValueType::Type::NONSTD:
|
||||||
|
return defaultReturn;
|
||||||
|
|
||||||
|
case ValueType::Type::RECORD:
|
||||||
|
if (isRaiiClassScope(valueType->typeScope))
|
||||||
|
return true;
|
||||||
|
return defaultReturn;
|
||||||
|
|
||||||
|
case ValueType::Type::CONTAINER:
|
||||||
|
case ValueType::Type::ITERATOR:
|
||||||
|
case ValueType::Type::VOID:
|
||||||
|
case ValueType::Type::BOOL:
|
||||||
|
case ValueType::Type::CHAR:
|
||||||
|
case ValueType::Type::SHORT:
|
||||||
|
case ValueType::Type::WCHAR_T:
|
||||||
|
case ValueType::Type::INT:
|
||||||
|
case ValueType::Type::LONG:
|
||||||
|
case ValueType::Type::LONGLONG:
|
||||||
|
case ValueType::Type::UNKNOWN_INT:
|
||||||
|
case ValueType::Type::FLOAT:
|
||||||
|
case ValueType::Type::DOUBLE:
|
||||||
|
case ValueType::Type::LONGDOUBLE:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultReturn;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class is used create a list of variables within a function.
|
* @brief This class is used create a list of variables within a function.
|
||||||
|
@ -1136,38 +1183,12 @@ void CheckUnusedVar::checkFunctionVariableUsage()
|
||||||
if (isIncrementOrDecrement && tok->astParent() && precedes(tok, tok->astOperand1()))
|
if (isIncrementOrDecrement && tok->astParent() && precedes(tok, tok->astOperand1()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (tok->str() == "=" && isRaiiClass(tok->valueType(), mTokenizer->isCPP(), false))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (tok->isName()) {
|
if (tok->isName()) {
|
||||||
if (mTokenizer->isCPP()) {
|
if (isRaiiClass(tok->valueType(), mTokenizer->isCPP(), true))
|
||||||
// do not check RAII/scope_lock objects
|
continue;
|
||||||
if (!tok->valueType())
|
|
||||||
continue;
|
|
||||||
bool check = false;
|
|
||||||
switch (tok->valueType()->type) {
|
|
||||||
case ValueType::Type::UNKNOWN_TYPE:
|
|
||||||
case ValueType::Type::NONSTD:
|
|
||||||
case ValueType::Type::RECORD:
|
|
||||||
check = tok->valueType()->typeScope && !tok->valueType()->typeScope->getDestructor();
|
|
||||||
break;
|
|
||||||
case ValueType::Type::CONTAINER:
|
|
||||||
case ValueType::Type::ITERATOR:
|
|
||||||
case ValueType::Type::VOID:
|
|
||||||
case ValueType::Type::BOOL:
|
|
||||||
case ValueType::Type::CHAR:
|
|
||||||
case ValueType::Type::SHORT:
|
|
||||||
case ValueType::Type::WCHAR_T:
|
|
||||||
case ValueType::Type::INT:
|
|
||||||
case ValueType::Type::LONG:
|
|
||||||
case ValueType::Type::LONGLONG:
|
|
||||||
case ValueType::Type::UNKNOWN_INT:
|
|
||||||
case ValueType::Type::FLOAT:
|
|
||||||
case ValueType::Type::DOUBLE:
|
|
||||||
case ValueType::Type::LONGDOUBLE:
|
|
||||||
check = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!check)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
if (tok->astParent() && tok->str() != "(") {
|
if (tok->astParent() && tok->str() != "(") {
|
||||||
|
|
|
@ -159,6 +159,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(localVarStd);
|
TEST_CASE(localVarStd);
|
||||||
TEST_CASE(localVarClass);
|
TEST_CASE(localVarClass);
|
||||||
|
TEST_CASE(localVarSmartPtr);
|
||||||
|
|
||||||
// Don't give false positives for variables in structs/unions
|
// Don't give false positives for variables in structs/unions
|
||||||
TEST_CASE(localvarStruct1);
|
TEST_CASE(localvarStruct1);
|
||||||
|
@ -4433,6 +4434,36 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void localVarSmartPtr() {
|
||||||
|
// handling of smart pointers (#9680)
|
||||||
|
functionVariableUsage("static int s_i = 0;\n"
|
||||||
|
"\n"
|
||||||
|
"class A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" ~A() {\n"
|
||||||
|
" ++s_i;\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"static void func() {\n"
|
||||||
|
" auto a = std::make_shared<A>();\n"
|
||||||
|
" auto a2 = std::unique_ptr<A>(new A());\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
functionVariableUsage("class A {\n"
|
||||||
|
"public:\n"
|
||||||
|
" std::string x;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"static void func() {\n"
|
||||||
|
" auto a = std::make_shared<A>();\n"
|
||||||
|
" auto a2 = std::unique_ptr<A>(new A());\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:7]: (style) Variable 'a' is assigned a value that is never used.\n"
|
||||||
|
"[test.cpp:8]: (style) Variable 'a2' is assigned a value that is never used.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// ticket #3104 - false positive when variable is read with "if (NOT var)"
|
// ticket #3104 - false positive when variable is read with "if (NOT var)"
|
||||||
void localvarIfNOT() {
|
void localvarIfNOT() {
|
||||||
functionVariableUsage("void f() {\n"
|
functionVariableUsage("void f() {\n"
|
||||||
|
|
Loading…
Reference in New Issue