-
Notifications
You must be signed in to change notification settings - Fork 21
cppcheck
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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))