Refactoring handling of comparisons

This commit is contained in:
Daniel Marjamäki 2015-07-22 12:31:18 +02:00
parent c67776c04d
commit b2b4bb49fa
5 changed files with 70 additions and 86 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -1,5 +1,7 @@
#!/bin/bash
set -e
~/cppcheck/cppcheck -q . 2> 1.txt