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,
|
||||
VarInfo *varInfo,
|
||||
std::set<unsigned int> notzero)
|
||||
|
@ -316,43 +288,20 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
|||
VarInfo varInfo1(*varInfo); // VarInfo for if code
|
||||
VarInfo varInfo2(*varInfo); // VarInfo for else code
|
||||
|
||||
// parse condition
|
||||
std::stack<const Token *> tokens;
|
||||
tokens.push(tok->next()->astOperand2());
|
||||
while (!tokens.empty()) {
|
||||
const Token *tok3 = tokens.top();
|
||||
tokens.pop();
|
||||
if (!tok3)
|
||||
continue;
|
||||
if (tok3->str() == "&&") {
|
||||
tokens.push(tok3->astOperand1());
|
||||
tokens.push(tok3->astOperand2());
|
||||
continue;
|
||||
}
|
||||
if (tok3->str() == "(" &&
|
||||
tok3->astOperand2() &&
|
||||
tok3->astOperand2()->isConstOp()) {
|
||||
tokens.push(tok3->astOperand2());
|
||||
continue;
|
||||
}
|
||||
|
||||
const Token *vartok = nullptr;
|
||||
if (isVariableComparison(tok3, "!=", "0", &vartok)) {
|
||||
if (Token::findVariableComparison(tok->next()->astOperand2(), "!=", "0", &vartok)) {
|
||||
varInfo2.erase(vartok->varId());
|
||||
if (notzero.find(vartok->varId()) != notzero.end())
|
||||
varInfo2.clear();
|
||||
} else if (isVariableComparison(tok3, "==", "0", &vartok)) {
|
||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "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)) {
|
||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "<", "0", &vartok)) {
|
||||
varInfo1.erase(vartok->varId());
|
||||
} else if (isVariableComparison(tok3, ">", "0", &vartok)) {
|
||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), ">", "0", &vartok)) {
|
||||
varInfo2.erase(vartok->varId());
|
||||
} else if (isVariableComparison(tok3, "==", "-1", &vartok)) {
|
||||
} else if (Token::findVariableComparison(tok->next()->astOperand2(), "==", "-1", &vartok)) {
|
||||
varInfo1.erase(vartok->varId());
|
||||
}
|
||||
}
|
||||
|
||||
checkScope(tok2->next(), &varInfo1, notzero);
|
||||
tok2 = tok2->linkAt(1);
|
||||
|
|
|
@ -519,28 +519,12 @@ const char *CheckMemoryLeak::functionArgAlloc(const Function *func, unsigned int
|
|||
|
||||
static bool notvar(const Token *tok, unsigned int varid)
|
||||
{
|
||||
if (!tok)
|
||||
return false;
|
||||
if (Token::Match(tok, "&&|;"))
|
||||
return notvar(tok->astOperand1(),varid) || notvar(tok->astOperand2(),varid);
|
||||
|
||||
if (tok->str() == "!")
|
||||
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;
|
||||
}
|
||||
const Token *vartok = Token::findVariableComparison(tok, "==", "0");
|
||||
|
||||
while (tok && tok->str() == ".")
|
||||
tok = tok->astOperand2();
|
||||
|
||||
return tok && tok->varId() == varid;
|
||||
return vartok && (vartok->varId() == varid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2176,10 +2160,10 @@ void CheckMemoryLeakInFunction::checkReallocUsage()
|
|||
|
||||
const Token* tokEndRealloc = tok->linkAt(3);
|
||||
// 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())) {
|
||||
const Token* tokEndBrace = tokEndRealloc->linkAt(7);
|
||||
if (tokEndBrace && Token::simpleMatch(tokEndBrace->tokAt(-2), ") ;") &&
|
||||
Token::Match(tokEndBrace->linkAt(-2)->tokAt(-2), "{|}|; %name% ("))
|
||||
if (Token::simpleMatch(tokEndRealloc->next(), "; if (") &&
|
||||
notvar(tokEndRealloc->tokAt(3)->astOperand2(), tok->varId())) {
|
||||
const Token* tokEndBrace = tokEndRealloc->linkAt(3)->linkAt(1);
|
||||
if (tokEndBrace && _tokenizer->IsScopeNoReturn(tokEndBrace))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1459,6 +1459,52 @@ const Token *Token::getValueTokenDeadPointer() const
|
|||
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)
|
||||
{
|
||||
unsigned int total_count = 0;
|
||||
|
|
|
@ -711,6 +711,9 @@ public:
|
|||
|
||||
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:
|
||||
|
||||
void next(Token *nextToken) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
~/cppcheck/cppcheck -q . 2> 1.txt
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue