CheckInternal::checkRedundantTokCheck(): also catch patterns of the form if(!tok || !Token::Match(tok, "foo")).

This commit is contained in:
Matthias Krüger 2018-01-01 04:19:26 +01:00
parent 70817b3d4e
commit f2b2be2166
2 changed files with 56 additions and 10 deletions

View File

@ -88,19 +88,37 @@ void CheckInternal::checkTokenMatchPatterns()
void CheckInternal::checkRedundantTokCheck() void CheckInternal::checkRedundantTokCheck()
{ {
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (!Token::Match(tok, "&& Token :: simpleMatch|Match|findsimplematch|findmatch (")) if (Token::Match(tok, "&& Token :: simpleMatch|Match|findsimplematch|findmatch (")) {
continue; // in code like
// in code like // if (tok->previous() && Token::match(tok->previous(), "bla")) {}
// if (tok->previous() && Token::match(tok->previous(), "bla")) {} // the first tok->previous() check is redundant
// the first tok->previous() check is redundant const Token *astOp1 = tok->astOperand1();
const Token *astOp1 = tok->astOperand1(); const Token *astOp2 = getArguments(tok->tokAt(3))[0];
const Token *astOp2 = getArguments(tok->tokAt(3))[0];
if (astOp1->expressionString() == astOp2->expressionString()) { // std::cout << "\n astOp1: " << tok->astOperand1()->str() << ""; // tok
checkRedundantTokCheckError(astOp2); // std::cout << "\n astOp2: " << getArguments(tok->tokAt(3))[0]->str() << "\n "; // tok
// std::cout << "\n";
if (astOp1->expressionString() == astOp2->expressionString()) {
checkRedundantTokCheckError(astOp2);
}
// if (!tok || !Token::match(tok, "foo"))
} else if (Token::Match(tok, "%oror% ! Token :: simpleMatch|Match|findsimplematch|findmatch (")) {
// the first tok condition is negated
const Token *negTok = tok->next()->astParent()->astOperand1();
if (Token::simpleMatch(negTok, "!")) {
const Token *astOp1 = negTok->astOperand1();
const Token *astOp2 = getArguments(tok->tokAt(4))[0];
if (astOp1->expressionString() == astOp2->expressionString()) {
checkRedundantTokCheckError(astOp2);
}
}
} }
}
} }
}
void CheckInternal::checkRedundantTokCheckError(const Token* tok) void CheckInternal::checkRedundantTokCheckError(const Token* tok)
{ {

View File

@ -467,6 +467,34 @@ private:
" if(tok->previous() && Token::Match(tok->previous()->previous(), \"5str% foobar\")) {};\n" " if(tok->previous() && Token::Match(tok->previous()->previous(), \"5str% foobar\")) {};\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// if a && fn(a) triggers, make sure !a || !fn(a) triggers as well!
check("void f() {\n"
" const Token *tok;\n"
" if(!tok || !Token::simpleMatch(tok, \"foobar\")) {};\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
// if tok || !Token::simpleMatch...
check("void f() {\n"
" const Token *tok;\n"
" if(tok || !Token::simpleMatch(tok, \"foobar\")) {};\n"
"}");
ASSERT_EQUALS("", errout.str());
// if !tok || Token::simpleMatch...
check("void f() {\n"
" const Token *tok;\n"
" if(!tok || Token::simpleMatch(tok, \"foobar\")) {};\n"
"}");
ASSERT_EQUALS("", errout.str());
// something more complex
check("void f() {\n"
" const Token *tok;\n"
" if(!tok->previous()->previous() || !Token::simpleMatch(tok->previous()->previous(), \"foobar\")) {};\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok->previous()->previous()\", match-function already checks if it is null.\n", errout.str());
} }
}; };