diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 3b35a4fc0..dbdf484c4 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -974,7 +974,6 @@ void CheckIO::checkFormatString(const Token * const tok, bool done = false; while (!done) { if (i == formatString.end()) { - done = true; break; } switch (*i) { diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 37734f1af..086836f35 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1278,7 +1278,8 @@ void CheckUnusedVar::checkFunctionVariableUsage() continue; FwdAnalysis fwdAnalysis(mTokenizer->isCPP(), mSettings->library); - if (fwdAnalysis.unusedValue(expr, start, scope->bodyEnd)) { + 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, diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 34b75d3bc..80e002c66 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1646,7 +1646,6 @@ void CppCheck::analyseClangTidy(const ImportProject::FileSettings &fileSettings) const std::string lineNumString = line.substr(endNamePos + 1, endLinePos - endNamePos - 1); const std::string columnNumString = line.substr(endLinePos + 1, endColumnPos - endLinePos - 1); - const std::string errorTypeString = line.substr(endColumnPos + 1, endMsgTypePos - endColumnPos - 1); const std::string messageString = line.substr(endMsgTypePos + 1, endErrorPos - endMsgTypePos - 1); const std::string errorString = line.substr(endErrorPos, line.length()); diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index a532bfdfa..d97696c22 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -941,7 +941,6 @@ void TemplateSimplifier::getTemplateInstantiations() // Add outer template.. if (templateParameters(tok->next()) || tok->strAt(2) == ">") { - const std::string scopeName1(scopeName); while (true) { const std::string fullName = scopeName + (scopeName.empty()?"":" :: ") + qualification + (qualification.empty()?"":" :: ") + tok->str(); @@ -1141,6 +1140,8 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration) "noparamend", "TemplateSimplifier couldn't find end of template parameter.", Certainty::normal); + if (mErrorLogger && mSettings->severity.isEnabled(Severity::debug)) + mErrorLogger->reportErr(errmsg); } break; } @@ -1936,20 +1937,11 @@ void TemplateSimplifier::expandTemplate( // replace type with given type.. if (itype < typeParametersInDeclaration.size() && itype < mTypesUsedInTemplateInstantiation.size()) { - unsigned int typeindentlevel = 0; std::stack brackets1; // holds "(" and "{" tokens for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token(); - typetok && (typeindentlevel>0 || !Token::Match(typetok, ",|>")); + typetok && !Token::Match(typetok, ",|>"); typetok = typetok->next()) { if (!Token::simpleMatch(typetok, "...")) { - if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next()))) - ++typeindentlevel; - else if (typeindentlevel > 0 && typetok->str() == ">") - --typeindentlevel; - else if (typetok->str() == "(") - ++typeindentlevel; - else if (typetok->str() == ")") - --typeindentlevel; mTokenList.addtoken(typetok, tok5); Token *back = mTokenList.back(); if (Token::Match(back, "{|(|[")) { diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 0df1cc485..fad16a45e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3427,7 +3427,7 @@ static const Token* getEndOfVarScope(const Variable* var) return innerScope->bodyEnd; } -static const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr) +const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope, bool smallest) { const Token* end = nullptr; bool local = false; @@ -3436,7 +3436,7 @@ static const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScop local |= var->isLocal(); if (var->isLocal() || var->isArgument()) { const Token* varEnd = getEndOfVarScope(var); - if (!end || precedes(varEnd, end)) + if (!end || (smallest ? precedes(varEnd, end) : succeeds(varEnd, end))) end = varEnd; } } @@ -3477,8 +3477,9 @@ static const Token* getEndOfVarScope(const Token* tok, const std::vectornestedIn; } } - if (varScope && (!endOfVarScope || precedes(varScope->bodyEnd, endOfVarScope))) + if (varScope && (!endOfVarScope || precedes(endOfVarScope, varScope->bodyEnd))) { endOfVarScope = varScope->bodyEnd; + } } return endOfVarScope; } diff --git a/lib/valueflow.h b/lib/valueflow.h index c61218677..683f756cb 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -42,6 +42,7 @@ class Token; class TokenList; class ValueType; class Variable; +class Scope; template class ValuePtr; @@ -518,4 +519,6 @@ CPPCHECKLIB std::vector getLifetimeObjValues(const Token* tok, bool inconclusive = false, MathLib::bigint path = 0); +const Token* getEndOfExprScope(const Token* tok, const Scope* defaultScope = nullptr, bool smallest = true); + #endif // valueflowH diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 57ffca263..79bfc6037 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -3362,6 +3362,61 @@ private: "}"); ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'sum' is assigned a value that is never used.\n" "[test.cpp:5]: (style) Variable 'sum' is assigned a value that is never used.\n", errout.str()); + + functionVariableUsage("void f(int c) {\n" // #7908 + " int b = 0;\n" + " while (g()) {\n" + " int a = c;\n" + " b = a;\n" + " if (a == 4)\n" + " a = 5;\n" + " }\n" + " h(b);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:7]: (style) Variable 'a' is assigned a value that is never used.\n", errout.str()); + + functionVariableUsage("void f(const std::vector& v) {\n" + " while (g()) {\n" + " const std::vector& v2 = h();\n" + " if (std::vector{ 1, 2, 3 }.size() > v2.size()) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + functionVariableUsage("void f(const std::vector& v) {\n" + " while (g()) {\n" + " const std::vector& v2 = h();\n" + " if (std::vector({ 1, 2, 3 }).size() > v2.size()) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + functionVariableUsage("void f(const std::string &c) {\n" + " std::string s = str();\n" + " if (s[0] == '>')\n" + " s[0] = '<';\n" + " if (s == c) {}\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + functionVariableUsage("void f(bool b) {\n" + " std::map> m;\n" + " if (b) {\n" + " const std::string n = g();\n" + " std::vector c = h();\n" + " m[n] = c;\n" + " }\n" + " j(m);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + functionVariableUsage("struct S { int i; };\n" + "S f(S s, bool b) {\n" + " if (b)\n" + " s.i = 1;\n" + " return s;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void localvaralias1() {