CheckInternal: Extend redundant null pointer check before Token::Match() (#1789)

Improve the internal check for redundant null pointer check before
calling Token::Match() (and friends). Now, warn about code snippets like

    if (a && tok && Token::Match(tok, "foo"))

Also, extend the check for the inverted case.

There is still no warning for

    if (tok && a && Token::Match(tok, "foo"))

since that would require checking if a is independent of tok.
This commit is contained in:
Rikard Falkeborn 2019-04-06 07:44:44 +02:00 committed by Daniel Marjamäki
parent d23e987941
commit 82a1e3c61c
2 changed files with 36 additions and 1 deletions

View File

@ -94,13 +94,18 @@ void CheckInternal::checkRedundantTokCheck()
// the first tok->previous() check is redundant
const Token *astOp1 = tok->astOperand1();
const Token *astOp2 = getArguments(tok->tokAt(3))[0];
if (Token::simpleMatch(astOp1, "&&")) {
astOp1 = astOp1->astOperand2();
}
if (astOp1->expressionString() == astOp2->expressionString()) {
checkRedundantTokCheckError(astOp2);
}
// if (!tok || !Token::match(tok, "foo"))
} else if (Token::Match(tok, "%oror% ! Token :: simpleMatch|Match|findsimplematch|findmatch (")) {
const Token *negTok = tok->next()->astParent()->astOperand1();
if (Token::simpleMatch(negTok, "||")) {
negTok = negTok->astOperand2();
}
// the first tok condition is negated
if (Token::simpleMatch(negTok, "!")) {
const Token *astOp1 = negTok->astOperand1();

View File

@ -431,6 +431,30 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
check("void f() {\n"
" const Token *tok;\n"
" if(a && tok && Token::Match(tok, \"5str% foobar\")) {};\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
check("void f() {\n"
" const Token *tok;\n"
" if(a && b && tok && Token::Match(tok, \"5str% foobar\")) {};\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
check("void f() {\n"
" const Token *tok;\n"
" if(a && b && && c && tok && Token::Match(tok, \"5str% foobar\")) {};\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
check("void f() {\n"
" const Token *tok;\n"
" if(a && b && && c && tok && d && Token::Match(tok, \"5str% foobar\")) {};\n"
"}");
ASSERT_EQUALS("", errout.str());
// simpleMatch
check("void f() {\n"
" const Token *tok;\n"
@ -474,6 +498,12 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
check("void f() {\n"
" const Token *tok;\n"
" if(a || !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"