From 9c50136571fa1dce5aff47f3af7d6988f73409c0 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:11:44 +0100 Subject: [PATCH] Fix #10824 FN unreadVariable for pointer assignment when destructor exists (regression) (#3864) * Fix #10824 FN unreadVariable for pointer assignment when destructor exists (regression) * unused variable * Issue warning for missing cfg * Format --- lib/checkunusedvar.cpp | 43 +++++++++++++++++++++++++++++------------- lib/tokenlist.cpp | 1 - test/testunusedvar.cpp | 17 ++++++++++++++++- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 6764a94dc..7c60c29d8 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -972,13 +972,6 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const } else if (varid1 && Token::Match(tok, "%varid% .", varid1)) { variables.read(varid1, tok); variables.write(varid1, start); - } else if (var && - var->mType == Variables::pointer && - Token::Match(tok, "%name% ;") && - tok->varId() == 0 && - tok->hasKnownIntValue() && - tok->values().front().intvalue == 0) { - variables.use(varid1, tok); } else { variables.write(varid1, tok); } @@ -1156,6 +1149,15 @@ void CheckUnusedVar::checkFunctionVariableUsage() // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); + auto reportLibraryCfgError = [this](const Token* tok, const std::string& typeName) { + if (mSettings->checkLibrary && mSettings->severity.isEnabled(Severity::information)) { + reportError(tok, + Severity::information, + "checkLibraryCheckType", + "--check-library: Provide configuration for " + typeName); + } + }; + // only check functions for (const Scope * scope : symbolDatabase->functionScopes) { // Bailout when there are lambdas or inline functions @@ -1281,12 +1283,7 @@ void CheckUnusedVar::checkFunctionVariableUsage() const Token* scopeEnd = getEndOfExprScope(expr, scope, /*smallest*/ false); if (fwdAnalysis.unusedValue(expr, start, scopeEnd)) { if (!bailoutTypeName.empty() && bailoutTypeName != "auto") { - if (mSettings->checkLibrary && mSettings->severity.isEnabled(Severity::information)) { - reportError(tok, - Severity::information, - "checkLibraryCheckType", - "--check-library: Provide configuration for " + bailoutTypeName); - } + reportLibraryCfgError(tok, bailoutTypeName); continue; } @@ -1339,6 +1336,26 @@ void CheckUnusedVar::checkFunctionVariableUsage() // variable has been read but not written else if (!usage._write && !usage._allocateMemory && var && !var->isStlType() && !isEmptyType(var->type())) unassignedVariableError(usage._var->nameToken(), varname); + else if (!usage._var->isMaybeUnused() && !usage._modified && !usage._read && var) { + if (usage._lastAccess->linenr() == var->nameToken()->linenr() && var->nameToken()->next()->isSplittedVarDeclEq()) { + bool error = true; + if (mTokenizer->isCPP() && var->isClass() && + (!var->valueType() || var->valueType()->type == ValueType::Type::UNKNOWN_TYPE)) { + const std::string typeName = var->getTypeName(); + switch (mSettings->library.getTypeCheck("unusedvar", typeName)) { + case Library::TypeCheck::def: + reportLibraryCfgError(var->nameToken(), typeName); + break; + case Library::TypeCheck::check: + break; + case Library::TypeCheck::suppress: + error = false; + } + } + if (error) + unreadVariableError(usage._var->nameToken(), varname, false); + } + } } } } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 42057a4ed..eb4c74d9f 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -791,7 +791,6 @@ static void compileTerm(Token *&tok, AST_state& state) tok = tok->tokAt(2); } } else if (!state.cpp || !Token::Match(tok, "new|delete %name%|*|&|::|(|[")) { - Token* tok2 = tok; std::vector inner; tok = skipDecl(tok, &inner); for (Token* tok3 : inner) { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 03a990c76..3fc87062a 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -128,6 +128,7 @@ private: TEST_CASE(localvar59); // #9737 TEST_CASE(localvar60); TEST_CASE(localvar61); // #9407 + TEST_CASE(localvar62); // #10824 TEST_CASE(localvarloops); // loops TEST_CASE(localvaralias1); TEST_CASE(localvaralias2); // ticket #1637 @@ -2384,7 +2385,9 @@ private: " int i = 0;\n" " int &j = i;\n" "}"); - ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'j' is assigned a value that is never used.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'j' is assigned a value that is never used.\n" + "[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used.\n", + errout.str()); functionVariableUsage("void foo()\n" "{\n" @@ -3330,6 +3333,18 @@ private: ASSERT_EQUALS("[test.cpp:5]: (style) Variable 'var' is assigned a value that is never used.\n", errout.str()); } + void localvar62() { // #10824 + functionVariableUsage("void f() {\n" + " S* s = nullptr;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Variable 's' is assigned a value that is never used.\n", errout.str()); + + functionVariableUsage("void f() {\n" + " S* s{};\n" + "}\n"); + TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Variable 's' is assigned a value that is never used.\n", "", errout.str()); + } + void localvarloops() { // loops functionVariableUsage("void fun(int c) {\n"