parent
4cef2e94e7
commit
d5a478d5c5
|
@ -138,8 +138,8 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
|
|||
|
||||
static bool hasToken(const Token * startTok, const Token * stopTok, const Token * tok)
|
||||
{
|
||||
for(const Token * tok2 = startTok;tok2 != stopTok;tok2 = tok2->next()) {
|
||||
if(tok2 == tok)
|
||||
for (const Token * tok2 = startTok; tok2 != stopTok; tok2 = tok2->next()) {
|
||||
if (tok2 == tok)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -156,9 +156,9 @@ const Token * nextAfterAstRightmostLeaf(const Token * tok)
|
|||
else
|
||||
rightmostLeaf = rightmostLeaf->astOperand1();
|
||||
} while (rightmostLeaf->astOperand1());
|
||||
while(Token::Match(rightmostLeaf->next(), "]|)") && !hasToken(rightmostLeaf->next()->link(), rightmostLeaf->next(), tok))
|
||||
while (Token::Match(rightmostLeaf->next(), "]|)") && !hasToken(rightmostLeaf->next()->link(), rightmostLeaf->next(), tok))
|
||||
rightmostLeaf = rightmostLeaf->next();
|
||||
if(rightmostLeaf->str() == "{" && rightmostLeaf->link())
|
||||
if (rightmostLeaf->str() == "{" && rightmostLeaf->link())
|
||||
rightmostLeaf = rightmostLeaf->link();
|
||||
return rightmostLeaf->next();
|
||||
}
|
||||
|
@ -963,9 +963,9 @@ const Token *findLambdaEndToken(const Token *first)
|
|||
{
|
||||
if (!first || first->str() != "[")
|
||||
return nullptr;
|
||||
if(!Token::Match(first->link(), "] (|{"))
|
||||
if (!Token::Match(first->link(), "] (|{"))
|
||||
return nullptr;
|
||||
if(first->astOperand1() != first->link()->next())
|
||||
if (first->astOperand1() != first->link()->next())
|
||||
return nullptr;
|
||||
const Token * tok = first;
|
||||
|
||||
|
|
|
@ -590,23 +590,23 @@ void CheckAutoVariables::returnReference()
|
|||
|
||||
static bool isInScope(const Token * tok, const Scope * scope)
|
||||
{
|
||||
if(!tok)
|
||||
if (!tok)
|
||||
return false;
|
||||
if(!scope)
|
||||
if (!scope)
|
||||
return false;
|
||||
const Variable * var = tok->variable();
|
||||
if(var && (var->isGlobal() || var->isStatic() || var->isExtern()))
|
||||
if (var && (var->isGlobal() || var->isStatic() || var->isExtern()))
|
||||
return false;
|
||||
if(tok->scope() && tok->scope()->isNestedIn(scope))
|
||||
if (tok->scope() && tok->scope()->isNestedIn(scope))
|
||||
return true;
|
||||
if(!var)
|
||||
if (!var)
|
||||
return false;
|
||||
if(var->isArgument() && !var->isReference()) {
|
||||
if (var->isArgument() && !var->isReference()) {
|
||||
const Scope * tokScope = tok->scope();
|
||||
if(!tokScope)
|
||||
if (!tokScope)
|
||||
return false;
|
||||
for(const Scope * argScope:tokScope->nestedList) {
|
||||
if(argScope && argScope->isNestedIn(scope))
|
||||
for (const Scope * argScope:tokScope->nestedList) {
|
||||
if (argScope && argScope->isNestedIn(scope))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -615,27 +615,27 @@ static bool isInScope(const Token * tok, const Scope * scope)
|
|||
|
||||
void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end)
|
||||
{
|
||||
if(!start)
|
||||
if (!start)
|
||||
return;
|
||||
const Scope * scope = start->scope();
|
||||
if(!scope)
|
||||
if (!scope)
|
||||
return;
|
||||
// If the scope is not set correctly then skip checking it
|
||||
if(scope->bodyStart != start)
|
||||
if (scope->bodyStart != start)
|
||||
return;
|
||||
for (const Token *tok = start; tok && tok != end; tok = tok->next()) {
|
||||
// Skip duplicate warning from dangling references
|
||||
if(Token::Match(tok, "& %var%"))
|
||||
if (Token::Match(tok, "& %var%"))
|
||||
continue;
|
||||
if(tok->variable() && tok->variable()->isPointer())
|
||||
if (tok->variable() && tok->variable()->isPointer())
|
||||
continue;
|
||||
if(std::any_of(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isTokValue)))
|
||||
if (std::any_of(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isTokValue)))
|
||||
continue;
|
||||
|
||||
for(const ValueFlow::Value& val:tok->values()) {
|
||||
if(!val.isLifetimeValue())
|
||||
for (const ValueFlow::Value& val:tok->values()) {
|
||||
if (!val.isLifetimeValue())
|
||||
continue;
|
||||
if(Token::Match(tok->astParent(), "return|throw")) {
|
||||
if (Token::Match(tok->astParent(), "return|throw")) {
|
||||
if (isInScope(val.tokvalue, scope)) {
|
||||
errorReturnDanglingLifetime(tok, &val);
|
||||
break;
|
||||
|
@ -643,7 +643,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
|
|||
}
|
||||
}
|
||||
const Token *lambdaEndToken = findLambdaEndToken(tok);
|
||||
if(lambdaEndToken) {
|
||||
if (lambdaEndToken) {
|
||||
checkVarLifetimeScope(lambdaEndToken->link(), lambdaEndToken);
|
||||
tok = lambdaEndToken;
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ void CheckAutoVariables::errorReturnDanglingLifetime(const Token *tok, const Val
|
|||
const Token *vartok = val->tokvalue;
|
||||
ErrorPath errorPath = val->errorPath;
|
||||
std::string msg = "";
|
||||
switch(val->lifetimeKind) {
|
||||
switch (val->lifetimeKind) {
|
||||
case ValueFlow::Value::Object:
|
||||
msg = "Returning object";
|
||||
break;
|
||||
|
@ -680,11 +680,11 @@ void CheckAutoVariables::errorReturnDanglingLifetime(const Token *tok, const Val
|
|||
msg = "Returning iterator";
|
||||
break;
|
||||
}
|
||||
if(vartok) {
|
||||
if (vartok) {
|
||||
errorPath.emplace_back(vartok, "Variable created here.");
|
||||
const Variable * var = vartok->variable();
|
||||
if(var) {
|
||||
switch(val->lifetimeKind) {
|
||||
if (var) {
|
||||
switch (val->lifetimeKind) {
|
||||
case ValueFlow::Value::Object:
|
||||
msg += " that points to local variable";
|
||||
break;
|
||||
|
|
|
@ -53,10 +53,10 @@ namespace {
|
|||
|
||||
bool CheckCondition::diag(const Token* tok, bool insert)
|
||||
{
|
||||
if(!tok)
|
||||
if (!tok)
|
||||
return false;
|
||||
if(mCondDiags.find(tok) == mCondDiags.end()) {
|
||||
if(insert)
|
||||
if (mCondDiags.find(tok) == mCondDiags.end()) {
|
||||
if (insert)
|
||||
mCondDiags.insert(tok);
|
||||
return false;
|
||||
}
|
||||
|
@ -717,7 +717,7 @@ static std::string innerSmtString(const Token * tok)
|
|||
|
||||
void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath)
|
||||
{
|
||||
if(diag(tok1) & diag(tok2))
|
||||
if (diag(tok1) & diag(tok2))
|
||||
return;
|
||||
const std::string s1(tok1 ? tok1->expressionString() : "x");
|
||||
const std::string s2(tok2 ? tok2->expressionString() : "!x");
|
||||
|
@ -732,7 +732,7 @@ void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token*
|
|||
|
||||
void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath)
|
||||
{
|
||||
if(diag(tok1) & diag(tok2))
|
||||
if (diag(tok1) & diag(tok2))
|
||||
return;
|
||||
const std::string s1(tok1 ? tok1->expressionString() : "x");
|
||||
const std::string s2(tok2 ? tok2->expressionString() : "x");
|
||||
|
@ -747,7 +747,7 @@ void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token
|
|||
|
||||
void CheckCondition::identicalConditionAfterEarlyExitError(const Token *cond1, const Token* cond2, ErrorPath errorPath)
|
||||
{
|
||||
if(diag(cond1) & diag(cond2))
|
||||
if (diag(cond1) & diag(cond2))
|
||||
return;
|
||||
const std::string cond(cond1 ? cond1->expressionString() : "x");
|
||||
errorPath.emplace_back(ErrorPathItem(cond1, "first condition"));
|
||||
|
@ -1278,7 +1278,7 @@ void CheckCondition::alwaysTrueFalse()
|
|||
if (!tok->hasKnownIntValue())
|
||||
continue;
|
||||
// Skip already diagnosed values
|
||||
if(diag(tok, false))
|
||||
if (diag(tok, false))
|
||||
continue;
|
||||
if (Token::Match(tok, "%num%|%bool%|%char%"))
|
||||
continue;
|
||||
|
|
|
@ -959,16 +959,15 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool isNestedIn(const Scope * outer) const
|
||||
{
|
||||
if(!outer)
|
||||
bool isNestedIn(const Scope * outer) const {
|
||||
if (!outer)
|
||||
return false;
|
||||
if(outer == this)
|
||||
if (outer == this)
|
||||
return true;
|
||||
const Scope * parent = nestedIn;
|
||||
while(outer != parent && parent)
|
||||
while (outer != parent && parent)
|
||||
parent = parent->nestedIn;
|
||||
if(parent && parent == outer)
|
||||
if (parent && parent == outer)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1115,35 +1115,35 @@ static void valueFlowTerminatingCondition(TokenList *tokenlist, SymbolDatabase*
|
|||
continue;
|
||||
const Token * blockTok = condTok->link()->tokAt(1);
|
||||
// Check if the block terminates early
|
||||
if(!isEscapeScope(blockTok, tokenlist))
|
||||
if (!isEscapeScope(blockTok, tokenlist))
|
||||
continue;
|
||||
// Check if any variables are modified in scope
|
||||
bool bail = false;
|
||||
for(const Token * tok2=condTok->next();tok2 != condTok->link();tok2 = tok2->next()) {
|
||||
for (const Token * tok2=condTok->next(); tok2 != condTok->link(); tok2 = tok2->next()) {
|
||||
const Variable * var = tok2->variable();
|
||||
if(!var)
|
||||
if (!var)
|
||||
continue;
|
||||
const Token * endToken = var->scope()->bodyEnd;
|
||||
if(!var->isLocal() && !var->isConst() && !var->isArgument()) {
|
||||
if (!var->isLocal() && !var->isConst() && !var->isArgument()) {
|
||||
bail = true;
|
||||
break;
|
||||
}
|
||||
if(var->isStatic() && !var->isConst()) {
|
||||
if (var->isStatic() && !var->isConst()) {
|
||||
bail = true;
|
||||
break;
|
||||
}
|
||||
if(!var->isConst() && var->declEndToken() && isVariableChanged(var->declEndToken()->next(), endToken, tok2->varId(), false, settings, cpp)) {
|
||||
if (!var->isConst() && var->declEndToken() && isVariableChanged(var->declEndToken()->next(), endToken, tok2->varId(), false, settings, cpp)) {
|
||||
bail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(bail)
|
||||
if (bail)
|
||||
continue;
|
||||
// TODO: Handle multiple conditions
|
||||
if(Token::Match(condTok->astOperand2(), "%oror%|%or%|&|&&"))
|
||||
if (Token::Match(condTok->astOperand2(), "%oror%|%or%|&|&&"))
|
||||
continue;
|
||||
const Scope * condScope = nullptr;
|
||||
for(const Scope * parent = condTok->scope();parent;parent = parent->nestedIn) {
|
||||
for (const Scope * parent = condTok->scope(); parent; parent = parent->nestedIn) {
|
||||
if (parent->type == Scope::eIf ||
|
||||
parent->type == Scope::eWhile ||
|
||||
parent->type == Scope::eSwitch) {
|
||||
|
@ -1154,37 +1154,37 @@ static void valueFlowTerminatingCondition(TokenList *tokenlist, SymbolDatabase*
|
|||
conds.emplace_back(condTok->astOperand2(), condScope);
|
||||
|
||||
}
|
||||
for(Condition cond:conds) {
|
||||
if(!cond.first)
|
||||
for (Condition cond:conds) {
|
||||
if (!cond.first)
|
||||
continue;
|
||||
for (Token* tok = cond.first->next(); tok != scope->bodyEnd; tok = tok->next()) {
|
||||
if(tok == cond.first)
|
||||
if (tok == cond.first)
|
||||
continue;
|
||||
if (!Token::Match(tok, "%comp%"))
|
||||
continue;
|
||||
// Skip known values
|
||||
if (tok->hasKnownValue())
|
||||
continue;
|
||||
if(cond.second) {
|
||||
if (cond.second) {
|
||||
bool bail = true;
|
||||
for(const Scope * parent = tok->scope()->nestedIn;parent;parent = parent->nestedIn) {
|
||||
if(parent == cond.second) {
|
||||
for (const Scope * parent = tok->scope()->nestedIn; parent; parent = parent->nestedIn) {
|
||||
if (parent == cond.second) {
|
||||
bail = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(bail)
|
||||
if (bail)
|
||||
continue;
|
||||
}
|
||||
ErrorPath errorPath;
|
||||
if(isOppositeCond(true, cpp, tok, cond.first, settings->library, true, &errorPath)) {
|
||||
if (isOppositeCond(true, cpp, tok, cond.first, settings->library, true, &errorPath)) {
|
||||
ValueFlow::Value val(1);
|
||||
val.setKnown();
|
||||
val.condition = cond.first;
|
||||
val.errorPath = errorPath;
|
||||
val.errorPath.emplace_back(cond.first, "Assuming condition '" + cond.first->expressionString() + "' is false");
|
||||
setTokenValue(tok, val, tokenlist->getSettings());
|
||||
} else if(isSameExpression(cpp, true, tok, cond.first, settings->library, true, &errorPath)) {
|
||||
} else if (isSameExpression(cpp, true, tok, cond.first, settings->library, true, &errorPath)) {
|
||||
ValueFlow::Value val(0);
|
||||
val.setKnown();
|
||||
val.condition = cond.first;
|
||||
|
@ -2940,15 +2940,15 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
|
|||
static const Variable * getLifetimeVariable(const Token * tok, ErrorPath& errorPath)
|
||||
{
|
||||
const Variable * var = tok->variable();
|
||||
if(!var)
|
||||
if (!var)
|
||||
return nullptr;
|
||||
if(var->isReference() || var->isRValueReference()) {
|
||||
for(const ValueFlow::Value& v:tok->values()) {
|
||||
if(!v.isLifetimeValue() && !v.tokvalue)
|
||||
if (var->isReference() || var->isRValueReference()) {
|
||||
for (const ValueFlow::Value& v:tok->values()) {
|
||||
if (!v.isLifetimeValue() && !v.tokvalue)
|
||||
continue;
|
||||
errorPath.insert(errorPath.end(), v.errorPath.begin(), v.errorPath.end());
|
||||
const Variable * var2 = getLifetimeVariable(v.tokvalue, errorPath);
|
||||
if(var2)
|
||||
if (var2)
|
||||
return var2;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2956,23 +2956,21 @@ static const Variable * getLifetimeVariable(const Token * tok, ErrorPath& errorP
|
|||
return var;
|
||||
}
|
||||
|
||||
struct Lambda
|
||||
{
|
||||
struct Lambda {
|
||||
explicit Lambda(const Token * tok)
|
||||
: capture(nullptr), arguments(nullptr), returnTok(nullptr), bodyTok(nullptr)
|
||||
{
|
||||
if(!Token::simpleMatch(tok, "[") || !tok->link())
|
||||
: capture(nullptr), arguments(nullptr), returnTok(nullptr), bodyTok(nullptr) {
|
||||
if (!Token::simpleMatch(tok, "[") || !tok->link())
|
||||
return;
|
||||
capture = tok;
|
||||
|
||||
if(Token::simpleMatch(capture->link(), "] (")) {
|
||||
if (Token::simpleMatch(capture->link(), "] (")) {
|
||||
arguments = capture->link()->next();
|
||||
}
|
||||
const Token * afterArguments = arguments ? arguments->link()->next() : capture->link()->next();
|
||||
if(afterArguments && afterArguments->originalName() == "->") {
|
||||
if (afterArguments && afterArguments->originalName() == "->") {
|
||||
returnTok = afterArguments->next();
|
||||
bodyTok = Token::findsimplematch(returnTok, "{");
|
||||
} else if(Token::simpleMatch(afterArguments, "{")) {
|
||||
} else if (Token::simpleMatch(afterArguments, "{")) {
|
||||
bodyTok = afterArguments;
|
||||
}
|
||||
}
|
||||
|
@ -2982,8 +2980,7 @@ struct Lambda
|
|||
const Token * returnTok;
|
||||
const Token * bodyTok;
|
||||
|
||||
bool isLambda() const
|
||||
{
|
||||
bool isLambda() const {
|
||||
return capture && bodyTok;
|
||||
}
|
||||
};
|
||||
|
@ -2993,7 +2990,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* symboldataba
|
|||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
||||
Lambda lam(tok);
|
||||
// Lamdas
|
||||
if(lam.isLambda()) {
|
||||
if (lam.isLambda()) {
|
||||
const Scope * bodyScope = lam.bodyTok->scope();
|
||||
|
||||
std::set<const Scope *> scopes;
|
||||
|
@ -3002,16 +2999,16 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* symboldataba
|
|||
bool captureByRef = Token::Match(lam.capture, "[ & ]");
|
||||
bool captureByValue = Token::Match(lam.capture, "[ = ]");
|
||||
|
||||
for(const Token * tok2 = lam.bodyTok;tok2 != lam.bodyTok->link();tok2 = tok2->next()) {
|
||||
for (const Token * tok2 = lam.bodyTok; tok2 != lam.bodyTok->link(); tok2 = tok2->next()) {
|
||||
ErrorPath errorPath;
|
||||
if(captureByRef) {
|
||||
if (captureByRef) {
|
||||
const Variable * var = getLifetimeVariable(tok2, errorPath);
|
||||
if(!var)
|
||||
if (!var)
|
||||
continue;
|
||||
const Scope * scope = var->scope();
|
||||
if(scopes.count(scope) > 0)
|
||||
if (scopes.count(scope) > 0)
|
||||
continue;
|
||||
if(scope->isNestedIn(bodyScope))
|
||||
if (scope->isNestedIn(bodyScope))
|
||||
continue;
|
||||
scopes.insert(scope);
|
||||
errorPath.emplace_back(tok2, "Lambda captures variable by reference here.");
|
||||
|
@ -3024,19 +3021,19 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* symboldataba
|
|||
setTokenValue(tok, value, tokenlist->getSettings());
|
||||
|
||||
valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
|
||||
} else if(captureByValue) {
|
||||
for(const ValueFlow::Value& v:tok2->values()) {
|
||||
if(!v.isLifetimeValue() && !v.tokvalue)
|
||||
} else if (captureByValue) {
|
||||
for (const ValueFlow::Value& v:tok2->values()) {
|
||||
if (!v.isLifetimeValue() && !v.tokvalue)
|
||||
continue;
|
||||
const Token * tok3 = v.tokvalue;
|
||||
errorPath = v.errorPath;
|
||||
const Variable * var = getLifetimeVariable(tok3, errorPath);
|
||||
if(!var)
|
||||
if (!var)
|
||||
continue;
|
||||
const Scope * scope = var->scope();
|
||||
if(scopes.count(scope) > 0)
|
||||
if (scopes.count(scope) > 0)
|
||||
continue;
|
||||
if(scope->isNestedIn(bodyScope))
|
||||
if (scope->isNestedIn(bodyScope))
|
||||
continue;
|
||||
scopes.insert(scope);
|
||||
errorPath.emplace_back(tok2, "Lambda captures variable by value here.");
|
||||
|
@ -3067,7 +3064,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* symboldataba
|
|||
break;
|
||||
}
|
||||
|
||||
if(!vartok)
|
||||
if (!vartok)
|
||||
continue;
|
||||
const Variable * var = getLifetimeVariable(vartok, errorPath);
|
||||
if (!(var && !var->isPointer()))
|
||||
|
@ -3087,12 +3084,12 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* symboldataba
|
|||
else if (tok->variable() && Token::Match(tok, "%var% . begin|cbegin|rbegin|crbegin|end|cend|rend|crend|data|c_str (")) {
|
||||
ErrorPath errorPath;
|
||||
const Library::Container * container = settings->library.detectContainer(tok->variable()->typeStartToken());
|
||||
if(!container)
|
||||
if (!container)
|
||||
continue;
|
||||
const Variable * var = tok->variable();
|
||||
|
||||
bool isIterator = !Token::Match(tok->tokAt(2), "data|c_str");
|
||||
if(isIterator)
|
||||
if (isIterator)
|
||||
errorPath.emplace_back(tok, "Iterator to container is created here.");
|
||||
else
|
||||
errorPath.emplace_back(tok, "Pointer to container is created here.");
|
||||
|
|
Loading…
Reference in New Issue