Skip to content

cppcheck

Suresoft-GLaDOS edited this page May 26, 2023 · 9 revisions

#1

Link : https://github.com/danmar/cppcheck/commit/007b5d3e8d6d83237d425fdddd0c40089dcab59b
Description: Memory leak false positive when return with cast

At lib/checkleakautovar.cpp

@@ -930,21 +930,13 @@ void CheckLeakAutoVar::ret(const Token *tok, const VarInfo &varInfo)
         if (var) {
             bool used = false;
             for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) {
+                if (tok2->str() == ";" || Token::simpleMatch(tok2, "return ;"))
-                if (tok2->str() == ";")
                     break;
+                if (!Token::Match(tok2, "return|(|{|,"))
+                    continue;
+
+                tok2 = tok2->next();
+                while (tok2 && tok2->isCast() && (tok2->valueType()->pointer || (tok2->valueType()->typeSize(*mSettings) >= mSettings->sizeof_pointer)))
+                    tok2 = tok2->astOperand2() ? tok2->astOperand2() : tok2->astOperand1();
+                if (Token::Match(tok2, "%varid%", varid))
+                    tok2 = tok2->next();
+                else if (Token::Match(tok2, "& %varid% . %name%", varid))
+                    tok2 = tok2->tokAt(4);
+                else
+                    continue;
+                if (Token::Match(tok2, "[});,]")) {
-                if (Token::Match(tok2, "return|(|{|, %varid% [});,]", varid)) {
-                    used = true;
-                    break;
-                }
-                if (Token::Match(tok2, "return|(|{|, & %varid% . %name% [});,]", varid)) {
                     used = true;
                     break;
                 }

Tags
#Memory-error #Multi-line #Modified

#2

Link : https://github.com/danmar/cppcheck/commit/00fae7fb428b0b055135d6b972a1b52dd2c08d03
Description: Inconsistent violation report between using global enum and namespaced enum.

At lib/checkother.cpp

@@ -443,8 +443,6 @@ void CheckOther::checkRedundantAssignment()
                             return ChildrenToVisit::none;
                         if (Token::Match(rhs, "%str%|%num%|%name%") && !rhs->varId())
                             return ChildrenToVisit::none;
+                        if (Token::Match(rhs, ":: %name%") && rhs->hasKnownIntValue())
+                            return ChildrenToVisit::none;
                         if (rhs->isCast())
                             return ChildrenToVisit::op2;
                         trivial = false;

Tags
#Logical-error #Multi-line #Added

#3

Link : https://github.com/danmar/cppcheck/commit/02287d9d34fac41315124c9e02ba083da13766ef
Description: ValueFlowForward : decrement

At lib/forwardanalyzer.cpp

@@ -211,8 +211,6 @@ struct ForwardTraversal {
     Progress updateLoop(Token* endBlock, Token* condTok, Token* initTok = nullptr, Token* stepTok = nullptr) {
         ForwardAnalyzer::Action bodyAnalysis = analyzeScope(endBlock);
         ForwardAnalyzer::Action allAnalysis = bodyAnalysis;
+        if (condTok)
+            allAnalysis |= analyzeRecursive(condTok);
         if (initTok)
             allAnalysis |= analyzeRecursive(initTok);
         if (stepTok)
@@ -424,13 +422,9 @@ struct ForwardTraversal {
                 tok = endBlock;
             } else if (Token::simpleMatch(tok, "do {")) {
                 Token* endBlock = tok->next()->link();
+                Token* condTok = Token::simpleMatch(endBlock, "} while (") ? endBlock->tokAt(2)->astOperand2() : nullptr;
+                if (updateLoop(endBlock, condTok) == Progress::Break)
-                if (updateLoop(endBlock, nullptr) == Progress::Break)
                     return Progress::Break;
+                if (condTok)
+                    tok = endBlock->linkAt(2)->next();
+                else
+                    tok = endBlock;
-                tok = endBlock;
             } else if (Token::Match(tok, "assert|ASSERT (")) {
                 const Token* condTok = tok->next()->astOperand2();
                 bool checkThen, checkElse;

At lib/valueflow.cpp

@@ -790,38 +790,10 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
         }
     }
     // increment
+    else if (parent->str() == "++") {
+        for (const ValueFlow::Value &val : tok->values()) {
+            if (!val.isIntValue() && !val.isFloatValue())
+                continue;
+            ValueFlow::Value v(val);
+            if (parent == tok->previous()) {
+                if (v.isIntValue())
+                    v.intvalue = v.intvalue + 1;
+                else
+                    v.floatValue = v.floatValue + 1.0;
+            }
+            setTokenValue(parent, v, settings);
+        }
+    }
     // decrement
+    else if (parent->str() == "--") {
+        for (const ValueFlow::Value &val : tok->values()) {
+            if (!val.isIntValue() && !val.isFloatValue())
+                continue;
+            ValueFlow::Value v(val);
+            if (parent == tok->previous()) {
+                if (v.isIntValue())
+                    v.intvalue = v.intvalue - 1;
+                else
+                    v.floatValue = v.floatValue - 1.0;
+            }
+            setTokenValue(parent, v, settings);
+        }
+    }
     // Array element
     else if (parent->str() == "[" && parent->isBinaryOp()) {
         for (const ValueFlow::Value &value1 : parent->astOperand1()->values()) {

Tags
#Etc #Multi-line #Modified

#4

Link : https://github.com/danmar/cppcheck/commit/02682ab17dd5ef57e45a2727f52045c46112b83c
Description: Missing return

At lib/checkfunctions.cpp

@@ -338,7 +338,7 @@ static const Token *checkMissingReturnScope(const Token *tok, const Library &lib
             return nullptr;
         if (tok->str() == "goto" && !isForwardJump(tok))
             return nullptr;
+        if (Token::Match(tok, "%name% (") && !library.isnotnoreturn(tok))
-        if (Token::Match(tok, "%name% (") && library.isnoreturn(tok))
             return nullptr;
         if (Token::Match(tok, "[;{}] %name% :"))
             return tok;

Tags
#Invalid-condition #Single-line #Modified

#5

Link : https://github.com/danmar/cppcheck/commit/02ae71917a8b8f7890ef5e950243b987a8a43892
Description: False positive: Reference to temporary returned when using operator()

At lib/astutils.cpp

@@ -254,11 +254,6 @@ bool isTemporary(bool cpp, const Token* tok, const Library* library, bool unknow
             return unknown;
         }
     }
+    if (tok->isCast())
+        return false;
+    // Currying a function is unknown in cppcheck
+    if (Token::simpleMatch(tok, "(") && Token::simpleMatch(tok->astOperand1(), "("))
+        return unknown;
     return true;
 }

Tags
#Omission #Multi-line #Added

#6

Link : https://github.com/danmar/cppcheck/commit/02eaf6fa93530af3e2f9dd94a36820a9781767d1
Description: False positive: uninitStructMember related to reference to member

At lib/checkuninitvar.cpp

@@ -753,10 +753,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
                     return true;
                 }
+                if (Token::Match(tok->previous(), "[(,] %name% [,)]"))
+                    return true;
+                if (Token::Match(tok->previous(), "= %var% . %var% ;") && membervar == tok->strAt(2))
-                else if (Token::Match(tok->previous(), "[(,] %name% [,)]"))
                     return true;
             } else {

Tags
#Omission #Multi-line #Modified

#7

Link : https://github.com/danmar/cppcheck/commit/033640310b5dc53f290dc4563a9b96b9eb881f6b
Description: Unknown macro is not reported and then Cppcheck is silent about issues

At lib/tokenize.cpp

@@ -5037,10 +5037,7 @@ void Tokenizer::removeMacrosInGlobalScope()
             if (tok2 && tok2->str() == "(")
                 tok2 = tok2->link()->next();
+            // Several unknown macros...
+            while (Token::Match(tok2, "%type% (") && tok2->isUpperCaseName())
+                tok2 = tok2->linkAt(1)->next();
             if (Token::Match(tok, "%name% (") && Token::Match(tok2, "%name% *|&|::|<| %name%") && !Token::Match(tok2, "namespace|class|struct|union"))
                 unknownMacroError(tok);

Tags
#Omission #Multi-line #Added

#8

Link : https://github.com/danmar/cppcheck/commit/03b41ac9878cc15f483f6aa3f696bab3875be17b
Description: False positive: Parameter can be declared const when written to via stream extraction operator

At lib/astutils.cpp

@@ -1578,7 +1578,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op)
     const Token *parent = op;
     while (parent->astParent() && parent->astParent()->str() == op->str())
         parent = parent->astParent();
+    if (parent->astParent() && !Token::Match(parent->astParent(), "%oror%|&&|(|,|.|!"))
-    if (parent->astParent() && !Token::Match(parent->astParent(), "%oror%|&&|(|,|!"))
         return false;
     if (op->str() == "&" && parent->astParent())
         return false;

Tags
#Invalid-condition #Single-line #Modified

#9

Link : https://github.com/danmar/cppcheck/commit/03cefd5d7035aaaa019aca3b64254b9a1fd4e00c
Description: False positive: returnReference when using a pointer to container

At lib/valueflow.cpp

@@ -3063,7 +3063,7 @@ std::vector<LifetimeToken> getLifetimeTokens(const Token* tok, ValueFlow::Value:
                 }
             }
             return result;
+        } else if (Token::Match(tok->tokAt(-2), ". %name% (") && tok->tokAt(-2)->originalName() != "->" && astIsContainer(tok->tokAt(-2)->astOperand1())) {
-        } else if (Token::Match(tok->tokAt(-2), ". %name% (") && astIsContainer(tok->tokAt(-2)->astOperand1())) {
             const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1());
             Library::Container::Yield y = library->getYield(tok->previous()->str());
             if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) {

Tags
#Invalid-condition #Single-line #Modified

#10

Link : https://github.com/danmar/cppcheck/commit/045f21ee48c278ffc645c3ed56acbbe2746548b1
Description: False positive: uninitMemberVar with std::map

At lib/symboldatabase.cpp

@@ -1955,7 +1955,7 @@ const Token * Variable::declEndToken() const
 {
     Token const * declEnd = typeStartToken();
     while (declEnd && !Token::Match(declEnd, "[;,)={]")) {
+        if (declEnd->link() && Token::Match(declEnd,"(|[|<"))
-        if (declEnd->link() && Token::Match(declEnd,"(|["))
             declEnd = declEnd->link();
         declEnd = declEnd->next();
     }

Tags
#Invalid-condition #Single-line #Modified

#11

Link : https://github.com/danmar/cppcheck/commit/047c3ed6baef4b7cfdc91f9dc1fe245b9d8384c7
Description: False positive: knownConditionTrueFalse value flow doesn't account for virtual functions

At lib/valueflow.cpp

@@ -5858,7 +5858,7 @@ static bool isContainerSizeChangedByFunction(const Token *tok, int depth = 20)
     if (!ftok)
         return false; // not a function => variable not changed
     const Function * fun = ftok->function();
+    if (fun && !fun->hasVirtualSpecifier()) {
-    if (fun) {
         const Variable *arg = fun->getArgumentVar(narg);
         if (arg) {
             if (!arg->isReference() && !addressOf)

Tags
#Invalid-condition #Single-line #Modified

#12

Link : https://github.com/danmar/cppcheck/commit/04c85baf030bdac59d51177faace7f7c71d5d72d
Description: false negative: (error) Invalid v.at() argument nr 1

At lib/checkstl.cpp

@@ -59,11 +59,7 @@ static const struct CWE CWE825(825U);   // Expired Pointer Dereference
 static const struct CWE CWE833(833U);   // Deadlock
 static const struct CWE CWE834(834U);   // Excessive Iteration
+static bool isElementAccessYield(const Library::Container::Yield& yield)
+{
+    return yield == Library::Container::Yield::ITEM || yield == Library::Container::Yield::AT_INDEX;
+}
 void CheckStl::outOfBounds()
 {
     for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) {
@@ -81,27 +76,10 @@ void CheckStl::outOfBounds()
                     continue;
                 if (!value.errorSeverity() && !mSettings->isEnabled(Settings::WARNING))
                     continue;
+                if (Token::Match(parent, ". %name% (") && isElementAccessYield(container->getYield(parent->strAt(1)))) {
+                    if (value.intvalue == 0) {
+                        outOfBoundsError(parent->tokAt(2), tok->expressionString(), &value, parent->strAt(1), nullptr);
+                        continue;
+                    }
+                    const Token* indexTok = parent->tokAt(2)->astOperand2();
+                    if (!indexTok)
+                        continue;
+                    const ValueFlow::Value *indexValue = indexTok ? indexTok->getMaxValue(false) : nullptr;
+                    if (indexValue && indexValue->intvalue >= value.intvalue) {
+                        outOfBoundsError(parent, tok->expressionString(), &value, indexTok->expressionString(), indexValue);
+                        continue;
+                    }
+                    if (mSettings->isEnabled(Settings::WARNING)) {
+                        indexValue = indexTok ? indexTok->getMaxValue(true) : nullptr;
+                        if (indexValue && indexValue->intvalue >= value.intvalue) {
+                            outOfBoundsError(parent, tok->expressionString(), &value, indexTok->expressionString(), indexValue);
+                            continue;
+                        }
+                    }
-                if (value.intvalue == 0 && Token::Match(parent, ". %name% (") && container->getYield(parent->strAt(1)) == Library::Container::Yield::ITEM) {
-                    outOfBoundsError(parent->tokAt(2), tok->expressionString(), &value, parent->strAt(1), nullptr);
-                    continue;
                 }
                 if (Token::Match(tok, "%name% . %name% (") && container->getYield(tok->strAt(2)) == Library::Container::Yield::START_ITERATOR) {
                     const Token *fparent = tok->tokAt(3)->astParent();

Tags
#Etc #Multi-line #Modified

#13

Link : https://github.com/danmar/cppcheck/commit/0619b873d0837c639da54ef1057734d08e490980
Description: False positive: nullPointerRedundantCheck with ternary and null condition first

At lib/reverseanalyzer.cpp

@@ -78,6 +78,8 @@ struct ReverseTraversal {
         int opSide = 0;
         for (; tok && tok->astParent(); tok = tok->astParent()) {
             Token* parent = tok->astParent();
-            if (tok != parent->astOperand2())
-                continue;
             if (Token::simpleMatch(parent, ":")) {
                 if (astIsLHS(tok))
                     opSide = 1;
@@ -86,8 +88,6 @@ struct ReverseTraversal {
                 else
                     opSide = 0;
             }
+            if (tok != parent->astOperand2())
+                continue;
             if (!Token::Match(parent, "%oror%|&&|?"))
                 continue;
             Token* condTok = parent->astOperand1();
@@ -103,9 +103,9 @@ struct ReverseTraversal {
             }
             if (parent->str() == "?") {
+                if (checkElse && opSide == 1)
-                if (!checkElse && opSide == 1)
                     return parent;
+                if (checkThen && opSide == 2)
-                if (!checkThen && opSide == 2)
                     return parent;
             }
             if (!checkThen && parent->str() == "&&")
@@ -128,8 +128,6 @@ struct ReverseTraversal {
                 break;
             if (Token::Match(tok, "%name% :"))
                 break;
+            if (Token::simpleMatch(tok, ":"))
+                continue;
             // Evaluate LHS of assignment before RHS
             if (Token* assignTok = assignExpr(tok)) {
                 // If assignTok has broken ast then stop

Tags
#Invalid-condition #Multi-line #Modified

#14

Link : https://github.com/danmar/cppcheck/commit/06752d75a5b2de3c9f83b4e50c749fef8edae250
Description: False positive: knownConditionTrueFalse with integer constant

At lib/checkother.cpp

@@ -1987,15 +1987,7 @@ void CheckOther::checkDuplicateExpression()
             if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=")) {
                 if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true))
                     continue;
+                const bool followVar = !isConstVarExpression(tok) || Token::Match(tok, "%comp%|%oror%|&&");
+                if (isSameExpression(mTokenizer->isCPP(),
+                                     true,
+                                     tok->astOperand1(),
+                                     tok->astOperand2(),
+                                     mSettings->library,
+                                     true,
+                                     followVar,
+                                     &errorPath)) {
-                if (isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true, &errorPath)) {
                     if (isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
                         const bool assignment = tok->str() == "=";
                         if (assignment && warningEnabled)
@@ -2013,39 +2005,17 @@ void CheckOther::checkDuplicateExpression()
                             duplicateExpressionError(tok->astOperand1(), tok->astOperand2(), tok, errorPath);
                         }
                     }
+                } else if (tok->str() == "=" && Token::simpleMatch(tok->astOperand2(), "=") &&
+                           isSameExpression(mTokenizer->isCPP(),
+                                            false,
+                                            tok->astOperand1(),
+                                            tok->astOperand2()->astOperand1(),
+                                            mSettings->library,
+                                            true,
+                                            false)) {
-                } else if (tok->str() == "=" && Token::simpleMatch(tok->astOperand2(), "=") && isSameExpression(mTokenizer->isCPP(), false, tok->astOperand1(), tok->astOperand2()->astOperand1(), mSettings->library, true, false)) {
                     if (warningEnabled && isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
                         selfAssignmentError(tok, tok->astOperand1()->expressionString());
                     }
                 } else if (styleEnabled &&
+                           isOppositeExpression(mTokenizer->isCPP(),
+                                                tok->astOperand1(),
+                                                tok->astOperand2(),
+                                                mSettings->library,
+                                                false,
+                                                true,
+                                                &errorPath) &&
-                           isOppositeExpression(mTokenizer->isCPP(), tok->astOperand1(), tok->astOperand2(), mSettings->library, false, true, &errorPath) &&
                            !Token::Match(tok, "=|-|-=|/|/=") &&
                            isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand1())) {
                     oppositeExpressionError(tok, errorPath);
                 } else if (!Token::Match(tok, "[-/%]")) { // These operators are not associative
+                    if (styleEnabled && tok->astOperand2() && tok->str() == tok->astOperand1()->str() &&
+                        isSameExpression(mTokenizer->isCPP(),
+                                         true,
+                                         tok->astOperand2(),
+                                         tok->astOperand1()->astOperand2(),
+                                         mSettings->library,
+                                         true,
+                                         followVar,
+                                         &errorPath) &&
+                        isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand2()))
-                    if (styleEnabled && tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand2(), tok->astOperand1()->astOperand2(), mSettings->library, true, true, &errorPath) && isWithoutSideEffects(mTokenizer->isCPP(), tok->astOperand2()))
                         duplicateExpressionError(tok->astOperand2(), tok->astOperand1()->astOperand2(), tok, errorPath);
                     else if (tok->astOperand2() && isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) {
                         const Token *ast1 = tok->astOperand1();

Tags
#Invalid-condition #Multi-line #Modified

#15

Link : https://github.com/danmar/cppcheck/commit/06ea1a2b538e0ad67f711fec1b9493ca673d0cac
Description: False positive: variable is assigned a value that is never used (static)

At lib/checkunusedvar.cpp

@@ -1180,11 +1180,8 @@ void CheckUnusedVar::checkFunctionVariableUsage()
             if (iteratorToken && iteratorToken->variable() && iteratorToken->variable()->typeEndToken()->str().find("iterator") != std::string::npos)
                 continue;
+            const Token *op1tok = tok->astOperand1();
+            while (Token::Match(op1tok, ".|[|*"))
+                op1tok = op1tok->astOperand1();
+            const Variable *op1Var = op1tok ? op1tok->variable() : nullptr;
-            const Variable *op1Var = tok->astOperand1() ? tok->astOperand1()->variable() : nullptr;
             if (op1Var && op1Var->isReference() && op1Var->nameToken() != tok->astOperand1())
                 // todo: check references
                 continue;

Tags
#Invalid-condition #Multi-line #Modified

#16

Link : https://github.com/danmar/cppcheck/commit/06ed088bd075271ad9a39889a62b5e89a6b7acc4
Description: Wrong lifetime caused by std::function

At lib/forwardanalyzer.cpp

@@ -47,7 +47,7 @@ struct ForwardTraversal {
             if (checkScope(lambdaEndToken).isModified())
                 return Progress::Break;
             if (out)
+                *out = lambdaEndToken->next();
-                *out = lambdaEndToken;
             // Skip class scope
         } else if (tok->str() == "{" && tok->scope() && tok->scope()->isClassOrStruct()) {
             if (out)
@@ -291,9 +291,6 @@ struct ForwardTraversal {
                 if (!analyzer->lowerToPossible())
                     return Progress::Break;
             } else if (tok->link() && tok->str() == "}") {
+                const Scope* scope = tok->scope();
+                if(!scope)
+                    return Progress::Break;
                 if (Token::Match(tok->link()->previous(), ")|else {")) {
                     const bool inElse = Token::simpleMatch(tok->link()->previous(), "else {");
                     const Token* condTok = getCondTokFromEnd(tok);
@@ -308,11 +305,9 @@ struct ForwardTraversal {
                     analyzer->assume(condTok, !inElse, tok);
                     if (Token::simpleMatch(tok, "} else {"))
                         tok = tok->linkAt(2);
+                } else if (scope->type == Scope::eTry) {
-                } else if (Token::simpleMatch(tok->link()->previous(), "try {")) {
                     if (!analyzer->lowerToPossible())
                         return Progress::Break;
+                } else if (scope->type == Scope::eLambda) {
+                    return Progress::Break;
                 } else if (Token::simpleMatch(tok->next(), "else {")) {
                     tok = tok->linkAt(2);
                 }

Tags
#Etc #Multi-line #Modified

#17

Link : https://github.com/danmar/cppcheck/commit/0832830a959b9463b70834bd52eccd710e787a1b
Description: ValueFlow: Comparison is always false, but ValueFlow says it is always true

At lib/valueflow.cpp

@@ -4321,19 +4321,9 @@ static void valueFlowInferCondition(TokenList* tokenlist,
         } else if (tok->isComparisonOp()) {
             MathLib::bigint val = 0;
             const Token* varTok = nullptr;
+            std::string op = tok->str();
             if (tok->astOperand1()->hasKnownIntValue()) {
                 val = tok->astOperand1()->values().front().intvalue;
                 varTok = tok->astOperand2();
+                // Flip the operator
+                if (op == ">")
+                    op = "<";
+                else if (op == "<")
+                    op = ">";
+                else if (op == ">=")
+                    op = "<=";
+                else if (op == "<=")
+                    op = ">=";
             } else if (tok->astOperand2()->hasKnownIntValue()) {
                 val = tok->astOperand2()->values().front().intvalue;
                 varTok = tok->astOperand1();
@@ -4346,22 +4336,22 @@ static void valueFlowInferCondition(TokenList* tokenlist,
                 continue;
             const ValueFlow::Value* result = nullptr;
             bool known = false;
+            if (op == "==" || op == "!=") {
-            if (Token::Match(tok, "==|!=")) {
                 result = proveNotEqual(varTok->values(), val);
+                known = op == "!=";
+            } else if (op == "<" || op == ">=") {
-                known = tok->str() == "!=";
-            } else if (Token::Match(tok, "<|>=")) {
                 result = proveLessThan(varTok->values(), val);
+                known = op == "<";
-                known = tok->str() == "<";
                 if (!result && !isSaturated(val)) {
                     result = proveGreaterThan(varTok->values(), val - 1);
+                    known = op == ">=";
-                    known = tok->str() == ">=";
                 }
+            } else if (op == ">" || op == "<=") {
-            } else if (Token::Match(tok, ">|<=")) {
                 result = proveGreaterThan(varTok->values(), val);
+                known = op == ">";
-                known = tok->str() == ">";
                 if (!result && !isSaturated(val)) {
                     result = proveLessThan(varTok->values(), val + 1);
+                    known = op == "<=";
-                    known = tok->str() == "<=";
                 }
             }
             if (!result)

Tags
#Etc #Multi-line #Modified

#18

Link : https://github.com/danmar/cppcheck/commit/090eba7e7fff6ef1e01362337a588a0071ea4490
Description: ValueFlow: valueFlowForward, loop

At lib/forwardanalyzer.cpp

@@ -65,19 +65,13 @@ struct ForwardTraversal {
             return Progress::Continue;
         if (recursion > 10000)
             return Progress::Skip;
+        T* firstOp = tok->astOperand1();
+        T* secondOp = tok->astOperand2();
         // Evaluate RHS of assignment before LHS
+        if (tok->isAssignmentOp())
+            std::swap(firstOp, secondOp);
+        if (firstOp && traverseRecursive(firstOp, f, traverseUnknown, recursion+1) == Progress::Break)
-        if (tok->astOperand1() && traverseRecursive(tok->astOperand1(), f, traverseUnknown, recursion+1) == Progress::Break)
             return Progress::Break;
+        Progress p = tok->isAssignmentOp() ? Progress::Continue : traverseTok(tok, f, traverseUnknown);
-        Progress p = traverseTok(tok, f, traverseUnknown);
         if (p == Progress::Break)
             return Progress::Break;
+        if (p == Progress::Continue && secondOp && traverseRecursive(secondOp, f, traverseUnknown, recursion+1) == Progress::Break)
+            return Progress::Break;
+        if (tok->isAssignmentOp() && traverseTok(tok, f, traverseUnknown) == Progress::Break)
-        if (p == Progress::Continue && tok->astOperand2() && traverseRecursive(tok->astOperand2(), f, traverseUnknown, recursion+1) == Progress::Break)
             return Progress::Break;
         return Progress::Continue;
     }
@@ -278,7 +271,11 @@ struct ForwardTraversal {
             // Evaluate RHS of assignment before LHS
             if (Token* assignTok = assignExpr(tok)) {
+                if (updateRecursive(assignTok) == Progress::Break)
-                if (updateRecursive(assignTok->astOperand2()) == Progress::Break)
-                    return Progress::Break;
-                if (updateRecursive(assignTok->astOperand1()) == Progress::Break)
-                    return Progress::Break;
-                if (update(assignTok) == Progress::Break)
                     return Progress::Break;
                 tok = nextAfterAstRightmostLeaf(assignTok);
                 if (!tok)
@@ -302,7 +299,7 @@ struct ForwardTraversal {
                     return Progress::Break;
                 if (Token::Match(tok->link()->previous(), ")|else {")) {
                     const bool inElse = Token::simpleMatch(tok->link()->previous(), "else {");
+                    Token* condTok = getCondTokFromEnd(tok);
-                    const Token* condTok = getCondTokFromEnd(tok);
                     if (!condTok)
                         return Progress::Break;
                     if (!condTok->hasKnownIntValue()) {
@@ -311,16 +308,7 @@ struct ForwardTraversal {
                     } else if (condTok->values().front().intvalue == inElse) {
                         return Progress::Break;
                     }
                     // Handle for loop
+                    Token* stepTok = getStepTokFromEnd(tok);
+                    bool checkThen, checkElse;
+                    std::tie(checkThen, checkElse) = evalCond(condTok);
+                    if (stepTok && !checkElse) {
+                        if (updateRecursive(stepTok) == Progress::Break)
+                            return Progress::Break;
+                        if (updateRecursive(condTok) == Progress::Break)
+                            return Progress::Break;
+                    }
                     analyzer->assume(condTok, !inElse, tok);
                     if (Token::simpleMatch(tok, "} else {"))
                         tok = tok->linkAt(2);
@@ -541,15 +528,7 @@ struct ForwardTraversal {
         return tok->astOperand2()->astOperand2()->astOperand2();
     }
+    static Token* getStepTokFromEnd(Token* tok) {
+        if (!Token::simpleMatch(tok, "}"))
+            return nullptr;
+        Token* end = tok->link()->previous();
+        if (!Token::simpleMatch(end, ")"))
+            return nullptr;
+        return getStepTok(end->link());
+    }
 };
 void valueFlowGenericForward(Token* start, const Token* end, const ValuePtr<ForwardAnalyzer>& fa, const Settings* settings)

Tags
#Etc #Multi-line #Modified

#19

Link : https://github.com/danmar/cppcheck/commit/0a718694afae837010f68a2bdbb8f158e1ea81aa
Description: False positive: danglingTemporaryLifetime when returning a vector of vectors

At lib/checkautovariables.cpp

@@ -445,17 +445,8 @@ static bool isDeadTemporary(bool cpp, const Token* tok, const Token* expr, const
 {
     if (!isTemporary(cpp, tok, library))
         return false;
+    if (expr) {
+        if (!precedes(nextAfterAstRightmostLeaf(tok->astTop()), nextAfterAstRightmostLeaf(expr->astTop())))
+            return false;
+        const Token* parent = tok->astParent();
+        // Is in a for loop
+        if (astIsRHS(tok) && Token::simpleMatch(parent, ":") && Token::simpleMatch(parent->astParent(), "(") && Token::simpleMatch(parent->astParent()->previous(), "for (")) {
+            const Token* braces = parent->astParent()->link()->next();
+            if (precedes(braces, expr) && precedes(expr, braces->link()))
+                return false;
+        }
+    }
-    if (expr && !precedes(nextAfterAstRightmostLeaf(tok->astTop()), nextAfterAstRightmostLeaf(expr->astTop())))
-        return false;
     return true;
 }

Tags
#Invalid-condition #Multi-line #Modified

#20

Link : https://github.com/danmar/cppcheck/commit/0a84ad874c7ba5dbd4acc1c7e84a78807a45a6a9
Description: Fix case ranges with single quotes and escape sequences

At lib/tokenize.cpp

@@ -3243,7 +3243,7 @@ void Tokenizer::simplifyLabelsCaseDefault()
 void Tokenizer::simplifyCaseRange()
 {
     for (Token* tok = list.front(); tok; tok = tok->next()) {
+        if (Token::Match(tok, "case %num%|%char% ... %num%|%char% :")) {
-        if (Token::Match(tok, "case %num% ... %num% :")) {
             const MathLib::bigint start = MathLib::toLongNumber(tok->strAt(1));
             MathLib::bigint end = MathLib::toLongNumber(tok->strAt(3));
             end = std::min(start + 50, end); // Simplify it 50 times at maximum
@@ -3257,6 +3257,23 @@ void Tokenizer::simplifyCaseRange()
                     tok->insertToken("case");
                 }
             }
-        } else if (Token::Match(tok, "case %char% ... %char% :")) {
-            const char start = tok->strAt(1)[1];
-            const char end = tok->strAt(3)[1];
-            if (start < end) {
-                tok = tok->tokAt(2);
-                tok->str(":");
-                tok->insertToken("case");
-                for (char i = end - 1; i > start; i--) {
-                    tok->insertToken(":");
-                    if (i == '\\') {
-                        tok->insertToken(std::string("\'\\") + i + '\'');
-                    } else {
-                        tok->insertToken(std::string(1, '\'') + i + '\'');
-                    }
-                    tok->insertToken("case");
-                }
-            }
         }
     }
 }

Tags
#Invalid-condition #Multi-line #Modified

#21

Link : https://github.com/danmar/cppcheck/commit/0adf09c5077402f3d158fb877a704aa243995641
Description: ClangImport: fixed output for anonymous enum

At lib/clangimport.cpp

@@ -497,9 +497,7 @@ const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const s
         return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope);
     }
+    if (str.compare(0, 16, "'enum (anonymous") == 0)
+        return nullptr;
     std::string type;
     if (str.find(" (") != std::string::npos) {
         if (str.find("<") != std::string::npos)

Tags
#Omission #Multi-line #Added

#22

Link : https://github.com/danmar/cppcheck/commit/0aebc32ae0b1f548b96daa9e5ebb298172a22622
Description: Uninitialized variables: fixed false positive for 'cin >> x[0]'

At lib/checkuninitvar.cpp

@@ -1163,9 +1163,7 @@ const Token* CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer,
             return nullptr;
         }
     }
+    if (astIsRhs(derefValue) && isLikelyStreamRead(mTokenizer->isCPP(), derefValue->astParent()))
+        return nullptr;
     if (mTokenizer->isCPP() && Token::simpleMatch(valueExpr->astParent(), "&") && !valueExpr->astParent()->astParent() && astIsRhs(valueExpr) && Token::Match(valueExpr->astSibling(), "%type%"))
         return nullptr;

Tags
#Omission #Multi-line #Added

#23

Link : https://github.com/danmar/cppcheck/commit/0b7649ca9bb51a2f8b587afc2e085bf1d82d1013
Description: Tell cppcheck that strcpy returns its first argument

At lib/checkleakautovar.cpp

@@ -743,31 +743,8 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
                 deallocUseError(tok, tok->str());
             } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) {
                 varInfo->erase(tok->varId());
+            } else {
+                // check if tok is assigned into another variable
+                const Token *rhs = tok;
+                while (rhs->astParent()) {
+                    if (rhs->astParent()->str() == "=")
+                        break;
+                    rhs = rhs->astParent();
+                }
+                if (rhs->varId() == tok->varId()) {
+                    // simple assignment
+                    varInfo->erase(tok->varId());
+                } else if (rhs->str() == "(" && mSettings->library.returnValue(rhs->astOperand1()) != emptyString) {
+                    // #9298, assignment through return value of a function
+                    const std::string &returnValue = mSettings->library.returnValue(rhs->astOperand1());
+                    if (returnValue.compare(0, 3, "arg") == 0) {
+                        int argn;
+                        const Token *func = getTokenArgumentFunction(tok, argn);
+                        if (func) {
+                            const std::string arg = "arg" + std::to_string(argn + 1);
+                            if (returnValue == arg) {
+                                varInfo->erase(tok->varId());
+                            }
+                        }
+                    }
+                }
-            } else if (Token::Match(tok->previous(), "= %var% [;,)]")) {
-                varInfo->erase(tok->varId());
             }
         } else if (Token::Match(tok->previous(), "& %name% = %var% ;")) {
             varInfo->referenced.insert(tok->tokAt(2)->varId());
@@ -782,7 +759,7 @@ const Token * CheckLeakAutoVar::checkTokenInsideExpression(const Token * const t
         if (alloc.type == 0)
             alloc.status = VarInfo::NOALLOC;
         functionCall(tok, openingPar, varInfo, alloc, nullptr);
+        return openingPar;
-        return openingPar->link();
     }
     return nullptr;

Tags
#Omission #Multi-line #Modified

#24

Link : https://github.com/danmar/cppcheck/commit/0c659a149953b9a67901a5b30259b7ef534bbaad
Description: Fix incorrect logic for condition

At lib/forwardanalyzer.cpp

@@ -299,7 +299,7 @@ struct ForwardTraversal {
                     if (!condTok->hasKnownIntValue()) {
                         if (!analyzer->lowerToPossible())
                             return Progress::Break;
+                    } else if (condTok->values().front().intvalue == inElse) {
-                    } else if (condTok->values().front().intvalue == !inElse) {
                         return Progress::Break;
                     }
                     analyzer->assume(condTok, !inElse, tok);

Tags
#Invalid-condition #Single-line #Modified

#25

Link : https://github.com/danmar/cppcheck/commit/0cc1f69862fd4cb0e8e1a6d8ac1d6427b0310af5
Description: False position: returnDanglingLifetime for class method taking const char* and returning std::string

At lib/valueflow.cpp

@@ -3068,7 +3068,7 @@ static bool isLifetimeBorrowed(const ValueType *vt, const ValueType *vtParent)
         return false;
     if (!vt)
         return false;
+    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE && vtParent->container == vt->container) {
-    if (vt->type != ValueType::UNKNOWN_TYPE && vtParent->type != ValueType::UNKNOWN_TYPE) {
         if (vtParent->pointer > vt->pointer)
             return true;
         if (vtParent->pointer < vt->pointer && vtParent->isIntegral())

Tags
#Invalid-condition #Single-line #Modified

#26

Link : https://github.com/danmar/cppcheck/commit/0d31486264911f7a7fbd959add91afab95da7333
Description: Wrong AST for destructor call

At lib/tokenlist.cpp

@@ -728,7 +728,7 @@ static void compileBinOp(Token *&tok, AST_state& state, void (*f)(Token *&tok, A
     Token *binop = tok;
     if (f) {
         tok = tok->next();
+        if (Token::Match(binop, "::|. ~"))
-        if (Token::simpleMatch(binop, ":: ~"))
             tok = tok->next();
         state.depth++;
         if (tok && state.depth <= AST_MAX_DEPTH)
@@ -934,8 +934,8 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
                 state.op.push(tok);
                 tok = tok->tokAt(3);
                 break;
+            }
+            compileBinOp(tok, state, compileScope);
-            } else
-                compileBinOp(tok, state, compileScope);
         } else if (tok->str() == "[") {
             if (state.cpp && isPrefixUnary(tok, state.cpp) && Token::Match(tok->link(), "] (|{")) { // Lambda
                 // What we do here:

Tags
#Invalid-condition #Multi-line #Modified

#27

Link : https://github.com/danmar/cppcheck/commit/0df4876059d2c1d39c6cac3574298ad7db95fddb
Description: False positive: knownConditionTrueFalse

At lib/valueflow.cpp

@@ -766,10 +766,12 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
              parent->astOperand1() &&
              parent->astOperand2()) {
+        const bool noninvertible = parent->isComparisonOp() || Token::Match(parent, "%|/|&|%or%");
-        // Dont compare impossible values
-        if (parent->isComparisonOp() && value.isImpossible())
-            return;
         // Skip operators with impossible values that are not invertible
+        if (noninvertible && value.isImpossible())
-        if (Token::Match(parent, "%|/|&|%or%") && value.isImpossible())
             return;
         // known result when a operand is 0.
@@ -791,15 +793,11 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
         }
         for (const ValueFlow::Value &value1 : parent->astOperand1()->values()) {
+            if (noninvertible && value1.isImpossible())
+                continue;
             if (!value1.isIntValue() && !value1.isFloatValue() && !value1.isTokValue())
                 continue;
             if (value1.isTokValue() && (!parent->isComparisonOp() || value1.tokvalue->tokType() != Token::eString))
                 continue;
             for (const ValueFlow::Value &value2 : parent->astOperand2()->values()) {
+                if (noninvertible && value2.isImpossible())
+                    continue;
                 if (!value2.isIntValue() && !value2.isFloatValue() && !value2.isTokValue())
                     continue;
                 if (value2.isTokValue() && (!parent->isComparisonOp() || value2.tokvalue->tokType() != Token::eString || value1.isTokValue()))

Tags
#Invalid-condition #Multi-line #Modified

#28

Link : https://github.com/danmar/cppcheck/commit/0ecac8e23b70f97cbe6308089bc14fff5a1d97c7
Description: ValueFlow: Wrong lifetime, pointer member is not allocated on stack

At lib/checkautovariables.cpp

@@ -593,8 +593,6 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
                             continue;
                         if (!isLifetimeBorrowed(tok, mSettings))
                             continue;
+                        if (tokvalue->exprId() == tok->exprId() && !(tok->variable() && tok->variable()->isArray()))
+                            continue;
                         if ((tokvalue->variable() && !isEscapedReference(tokvalue->variable()) &&
                              isInScope(tokvalue->variable()->nameToken(), scope)) ||
                             isDeadTemporary(mTokenizer->isCPP(), tokvalue, tok, &mSettings->library)) {

Tags
#Omission #Multi-line #Modified

#29

Link : https://github.com/danmar/cppcheck/commit/0fed6f00915561fdea445c4de1a02ba380e54f37
Description: Clang testsuite crash

At lib/tokenize.cpp

@@ -10890,8 +10890,6 @@ void Tokenizer::simplifyOperatorName()
                 op += par->strAt(1);
                 par = par->tokAt(2);
                 done = true;
+            } else if (par->str() != "(") {
+                syntaxError(par);
             }
         }

Tags
#Omission #Multi-line #Modified

#30

Link : https://github.com/danmar/cppcheck/commit/120c57225256ea7a62d80c85afed512d28a22609
Description: Chained stream operation gives uninitvar error

At lib/astutils.cpp

@@ -1353,7 +1353,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings,
         }
     }
+    if (cpp && Token::simpleMatch(tok2->astParent(), ">>") && tok2->astParent()->astOperand2() == tok2 && isLikelyStreamRead(cpp, tok2->astParent()))
-    if (isLikelyStreamRead(cpp, tok->previous()))
         return true;
     if (isLikelyStream(cpp, tok2))

Tags
#Invalid-condition #Multi-line #Modified

Clone this wiki locally