Refactoring handling of comparisons
This commit is contained in:
parent
c67776c04d
commit
b2b4bb49fa
|
@ -140,34 +140,6 @@ void CheckLeakAutoVar::check()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isVariableComparison(const Token *tok, const std::string &comp, const char rhs[], const Token **vartok)
|
|
||||||
{
|
|
||||||
*vartok = nullptr;
|
|
||||||
if (tok->isComparisonOp()) {
|
|
||||||
if (Token::Match(tok->astOperand1(), rhs)) {
|
|
||||||
// Invert comparator
|
|
||||||
std::string s = tok->str();
|
|
||||||
if (s[0] == '>')
|
|
||||||
s[0] = '<';
|
|
||||||
else if (s[0] == '<')
|
|
||||||
s[0] = '>';
|
|
||||||
if (s == comp) {
|
|
||||||
*vartok = tok->astOperand2();
|
|
||||||
}
|
|
||||||
} else if (Token::Match(tok->astOperand2(), rhs) && tok->str() == comp) {
|
|
||||||
*vartok = tok->astOperand1();
|
|
||||||
}
|
|
||||||
} else if (comp == "!=" && rhs == std::string("0")) {
|
|
||||||
*vartok = tok;
|
|
||||||
} else if (comp == "==" && rhs == std::string("0")) {
|
|
||||||
if (tok->str() == "!")
|
|
||||||
*vartok = tok->astOperand1();
|
|
||||||
}
|
|
||||||
if ((*vartok) && (*vartok)->varId() == 0U)
|
|
||||||
*vartok = nullptr;
|
|
||||||
return (*vartok != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
VarInfo *varInfo,
|
VarInfo *varInfo,
|
||||||
std::set<unsigned int> notzero)
|
std::set<unsigned int> notzero)
|
||||||
|
@ -316,42 +288,19 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
VarInfo varInfo1(*varInfo); // VarInfo for if code
|
VarInfo varInfo1(*varInfo); // VarInfo for if code
|
||||||
VarInfo varInfo2(*varInfo); // VarInfo for else code
|
VarInfo varInfo2(*varInfo); // VarInfo for else code
|
||||||
|
|
||||||
// parse condition
|
const Token *vartok = nullptr;
|
||||||
std::stack<const Token *> tokens;
|
if (Token::findVariableComparison(tok->next()->astOperand2(), "!=", "0", &vartok)) {
|
||||||
tokens.push(tok->next()->astOperand2());
|
varInfo2.erase(vartok->varId());
|
||||||
while (!tokens.empty()) {
|
if (notzero.find(vartok->varId()) != notzero.end())
|
||||||
const Token *tok3 = tokens.top();
|
varInfo2.clear();
|
||||||
tokens.pop();
|
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "0", &vartok)) {
|
||||||
if (!tok3)
|
varInfo1.erase(vartok->varId());
|
||||||
continue;
|
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "<", "0", &vartok)) {
|
||||||
if (tok3->str() == "&&") {
|
varInfo1.erase(vartok->varId());
|
||||||
tokens.push(tok3->astOperand1());
|
} else if (Token::findVariableComparison(tok->next()->astOperand2(), ">", "0", &vartok)) {
|
||||||
tokens.push(tok3->astOperand2());
|
varInfo2.erase(vartok->varId());
|
||||||
continue;
|
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "-1", &vartok)) {
|
||||||
}
|
varInfo1.erase(vartok->varId());
|
||||||
if (tok3->str() == "(" &&
|
|
||||||
tok3->astOperand2() &&
|
|
||||||
tok3->astOperand2()->isConstOp()) {
|
|
||||||
tokens.push(tok3->astOperand2());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token *vartok = nullptr;
|
|
||||||
if (isVariableComparison(tok3, "!=", "0", &vartok)) {
|
|
||||||
varInfo2.erase(vartok->varId());
|
|
||||||
if (notzero.find(vartok->varId()) != notzero.end())
|
|
||||||
varInfo2.clear();
|
|
||||||
} else if (isVariableComparison(tok3, "==", "0", &vartok)) {
|
|
||||||
varInfo1.erase(vartok->varId());
|
|
||||||
} else if (Token::Match(tok->next(), "( %name% ( ! %var% ) )|&&")) {
|
|
||||||
varInfo1.erase(tok->tokAt(5)->varId());
|
|
||||||
} else if (isVariableComparison(tok3, "<", "0", &vartok)) {
|
|
||||||
varInfo1.erase(vartok->varId());
|
|
||||||
} else if (isVariableComparison(tok3, ">", "0", &vartok)) {
|
|
||||||
varInfo2.erase(vartok->varId());
|
|
||||||
} else if (isVariableComparison(tok3, "==", "-1", &vartok)) {
|
|
||||||
varInfo1.erase(vartok->varId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkScope(tok2->next(), &varInfo1, notzero);
|
checkScope(tok2->next(), &varInfo1, notzero);
|
||||||
|
|
|
@ -519,28 +519,12 @@ const char *CheckMemoryLeak::functionArgAlloc(const Function *func, unsigned int
|
||||||
|
|
||||||
static bool notvar(const Token *tok, unsigned int varid)
|
static bool notvar(const Token *tok, unsigned int varid)
|
||||||
{
|
{
|
||||||
if (!tok)
|
|
||||||
return false;
|
|
||||||
if (Token::Match(tok, "&&|;"))
|
if (Token::Match(tok, "&&|;"))
|
||||||
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
|
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
|
||||||
|
|
||||||
if (tok->str() == "!")
|
const Token *vartok = Token::findVariableComparison(tok, "==", "0");
|
||||||
tok = tok->astOperand1();
|
|
||||||
else if (tok->str() == "==") {
|
|
||||||
if (Token::simpleMatch(tok->astOperand1(), "0"))
|
|
||||||
tok = tok->astOperand2();
|
|
||||||
else if (Token::simpleMatch(tok->astOperand2(), "0"))
|
|
||||||
tok = tok->astOperand1();
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (tok && tok->str() == ".")
|
return vartok && (vartok->varId() == varid);
|
||||||
tok = tok->astOperand2();
|
|
||||||
|
|
||||||
return tok && tok->varId() == varid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2176,10 +2160,10 @@ void CheckMemoryLeakInFunction::checkReallocUsage()
|
||||||
|
|
||||||
const Token* tokEndRealloc = tok->linkAt(3);
|
const Token* tokEndRealloc = tok->linkAt(3);
|
||||||
// Check that the allocation isn't followed immediately by an 'if (!var) { error(); }' that might handle failure
|
// Check that the allocation isn't followed immediately by an 'if (!var) { error(); }' that might handle failure
|
||||||
if (Token::Match(tokEndRealloc->next(), "; if ( ! %varid% ) {", tok->varId())) {
|
if (Token::simpleMatch(tokEndRealloc->next(), "; if (") &&
|
||||||
const Token* tokEndBrace = tokEndRealloc->linkAt(7);
|
notvar(tokEndRealloc->tokAt(3)->astOperand2(), tok->varId())) {
|
||||||
if (tokEndBrace && Token::simpleMatch(tokEndBrace->tokAt(-2), ") ;") &&
|
const Token* tokEndBrace = tokEndRealloc->linkAt(3)->linkAt(1);
|
||||||
Token::Match(tokEndBrace->linkAt(-2)->tokAt(-2), "{|}|; %name% ("))
|
if (tokEndBrace && _tokenizer->IsScopeNoReturn(tokEndBrace))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1459,6 +1459,52 @@ const Token *Token::getValueTokenDeadPointer() const
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Token * Token::findVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok)
|
||||||
|
{
|
||||||
|
if (!tok)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (tok->str() == "&&") {
|
||||||
|
const Token *ret = findVariableComparison(tok->astOperand1(), comp, rhs, vartok);
|
||||||
|
if (!ret)
|
||||||
|
ret = findVariableComparison(tok->astOperand2(), comp, rhs, vartok);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tok->str() == "(" && tok->astOperand2() && Token::Match(tok->astOperand1(), "UNLIKELY|LIKELY"))
|
||||||
|
return findVariableComparison(tok->astOperand2(), comp, rhs, vartok);
|
||||||
|
|
||||||
|
const Token *ret = nullptr;
|
||||||
|
if (tok->isComparisonOp()) {
|
||||||
|
if (tok->astOperand1() && tok->astOperand1()->str() == rhs) {
|
||||||
|
// Invert comparator
|
||||||
|
std::string s = tok->str();
|
||||||
|
if (s[0] == '>')
|
||||||
|
s[0] = '<';
|
||||||
|
else if (s[0] == '<')
|
||||||
|
s[0] = '>';
|
||||||
|
if (s == comp) {
|
||||||
|
ret = tok->astOperand2();
|
||||||
|
}
|
||||||
|
} else if (tok->str() == comp && tok->astOperand2() && tok->astOperand2()->str() == rhs) {
|
||||||
|
ret = tok->astOperand1();
|
||||||
|
}
|
||||||
|
} else if (comp == "!=" && rhs == std::string("0")) {
|
||||||
|
ret = tok;
|
||||||
|
} else if (comp == "==" && rhs == std::string("0")) {
|
||||||
|
if (tok->str() == "!")
|
||||||
|
ret = tok->astOperand1();
|
||||||
|
}
|
||||||
|
while (ret && ret->str() == ".")
|
||||||
|
ret = ret->astOperand2();
|
||||||
|
if (ret && ret->varId() == 0U)
|
||||||
|
ret = nullptr;
|
||||||
|
if (vartok)
|
||||||
|
*vartok = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void Token::assignProgressValues(Token *tok)
|
void Token::assignProgressValues(Token *tok)
|
||||||
{
|
{
|
||||||
unsigned int total_count = 0;
|
unsigned int total_count = 0;
|
||||||
|
|
|
@ -711,6 +711,9 @@ public:
|
||||||
|
|
||||||
const Token *getValueTokenDeadPointer() const;
|
const Token *getValueTokenDeadPointer() const;
|
||||||
|
|
||||||
|
/** Recursively search for variable comparison against value */
|
||||||
|
static const Token * findVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void next(Token *nextToken) {
|
void next(Token *nextToken) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
~/cppcheck/cppcheck -q . 2> 1.txt
|
~/cppcheck/cppcheck -q . 2> 1.txt
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue