New internal check: checkRedundantNextPrevious().
Fixed findings by new internal check
This commit is contained in:
parent
e4a693eaab
commit
a4b5824dec
|
@ -274,7 +274,7 @@ static const Token *for_init(const Token *tok, unsigned int &varid, std::string
|
||||||
}
|
}
|
||||||
|
|
||||||
varid = tok->tokAt(2)->varId();
|
varid = tok->tokAt(2)->varId();
|
||||||
varname = tok->tokAt(2)->str();
|
varname = tok->strAt(2);
|
||||||
tok = tok->tokAt(6);
|
tok = tok->tokAt(6);
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -214,6 +214,30 @@ void CheckInternal::checkUnknownPattern()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckInternal::checkRedundantNextPrevious()
|
||||||
|
{
|
||||||
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, ". previous ( ) . next|tokAt|strAt|linkAt (") || Token::Match(tok, ". next ( ) . previous|tokAt|strAt|linkAt (") ||
|
||||||
|
(Token::simpleMatch(tok, ". tokAt (") && Token::Match(tok->linkAt(2), ") . previous|next|tokAt|strAt|linkAt|str|link ("))) {
|
||||||
|
const std::string& func1 = tok->strAt(1);
|
||||||
|
const std::string& func2 = tok->linkAt(2)->strAt(2);
|
||||||
|
|
||||||
|
if ((func2 == "previous" || func2 == "next" || func2 == "str" || func2 == "link") && tok->linkAt(2)->strAt(4) != ")")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
redundantNextPreviousError(tok, func1, func2);
|
||||||
|
} else if (Token::Match(tok, ". next|previous ( ) . next|previous ( ) . next|previous|linkAt|strAt|link|str (")) {
|
||||||
|
const std::string& func1 = tok->strAt(1);
|
||||||
|
const std::string& func2 = tok->strAt(9);
|
||||||
|
|
||||||
|
if ((func2 == "previous" || func2 == "next" || func2 == "str" || func2 == "link") && tok->strAt(11) != ")")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
redundantNextPreviousError(tok, func1, func2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
|
void CheckInternal::simplePatternError(const Token* tok, const std::string& pattern, const std::string &funcname)
|
||||||
{
|
{
|
||||||
reportError(tok, Severity::warning, "simplePatternError",
|
reportError(tok, Severity::warning, "simplePatternError",
|
||||||
|
@ -241,4 +265,10 @@ void CheckInternal::unknownPatternError(const Token* tok, const std::string& pat
|
||||||
"Unknown pattern used: \"" + pattern + "\"");
|
"Unknown pattern used: \"" + pattern + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckInternal::redundantNextPreviousError(const Token* tok, const std::string& func1, const std::string& func2)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::style, "redundantNextPrevious",
|
||||||
|
"Call to 'Token::" + func1 + "()' followed by 'Token::" + func2 + "()' can be simplified.");
|
||||||
|
}
|
||||||
|
|
||||||
#endif // #ifndef NDEBUG
|
#endif // #ifndef NDEBUG
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
checkInternal.checkTokenSimpleMatchPatterns();
|
checkInternal.checkTokenSimpleMatchPatterns();
|
||||||
checkInternal.checkMissingPercentCharacter();
|
checkInternal.checkMissingPercentCharacter();
|
||||||
checkInternal.checkUnknownPattern();
|
checkInternal.checkUnknownPattern();
|
||||||
|
checkInternal.checkRedundantNextPrevious();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */
|
/** @brief %Check if a simple pattern is used inside Token::Match or Token::findmatch */
|
||||||
|
@ -65,14 +66,18 @@ public:
|
||||||
/** @brief %Check for missing % end character in Token::Match pattern */
|
/** @brief %Check for missing % end character in Token::Match pattern */
|
||||||
void checkMissingPercentCharacter();
|
void checkMissingPercentCharacter();
|
||||||
|
|
||||||
/** @brief %Check for for unknown (invalid) complex patterns like "%typ%" */
|
/** @brief %Check for unknown (invalid) complex patterns like "%typ%" */
|
||||||
void checkUnknownPattern();
|
void checkUnknownPattern();
|
||||||
|
|
||||||
|
/** @brief %Check for inefficient usage of Token::next(), Token::previous() and Token::tokAt() */
|
||||||
|
void checkRedundantNextPrevious();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void simplePatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
void simplePatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
||||||
void complexPatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
void complexPatternError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
||||||
void missingPercentCharacterError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
void missingPercentCharacterError(const Token *tok, const std::string &pattern, const std::string &funcname);
|
||||||
void unknownPatternError(const Token* tok, const std::string& pattern);
|
void unknownPatternError(const Token* tok, const std::string& pattern);
|
||||||
|
void redundantNextPreviousError(const Token* tok, const std::string& func1, const std::string& func2);
|
||||||
|
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
CheckInternal c(0, settings, errorLogger);
|
CheckInternal c(0, settings, errorLogger);
|
||||||
|
@ -80,6 +85,7 @@ private:
|
||||||
c.complexPatternError(0, "%type% ( )", "Match");
|
c.complexPatternError(0, "%type% ( )", "Match");
|
||||||
c.missingPercentCharacterError(0, "%num", "Match");
|
c.missingPercentCharacterError(0, "%num", "Match");
|
||||||
c.unknownPatternError(0, "%typ");
|
c.unknownPatternError(0, "%typ");
|
||||||
|
c.redundantNextPreviousError(0, "previous", "next");
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string myName() {
|
static std::string myName() {
|
||||||
|
|
|
@ -849,8 +849,8 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||||
vartok = tok->next();
|
vartok = tok->next();
|
||||||
} else if (Token::Match(tok, "( ! ( %var% =")) {
|
} else if (Token::Match(tok, "( ! ( %var% =")) {
|
||||||
vartok = tok->tokAt(3);
|
vartok = tok->tokAt(3);
|
||||||
if (Token::simpleMatch(tok->tokAt(2)->link(), ") &&"))
|
if (Token::simpleMatch(tok->linkAt(2), ") &&"))
|
||||||
checkConditionStart = tok->tokAt(2)->link();
|
checkConditionStart = tok->linkAt(2);
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -2176,7 +2176,7 @@ void CheckOther::checkCCTypeFunctions()
|
||||||
if (tok->varId() == 0 &&
|
if (tok->varId() == 0 &&
|
||||||
Token::Match(tok, "isalnum|isalpha|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit ( %num% ,|)") &&
|
Token::Match(tok, "isalnum|isalpha|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit ( %num% ,|)") &&
|
||||||
MathLib::isNegative(tok->strAt(2))) {
|
MathLib::isNegative(tok->strAt(2))) {
|
||||||
cctypefunctionCallError(tok, tok->str(), tok->tokAt(2)->str());
|
cctypefunctionCallError(tok, tok->str(), tok->strAt(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2481,12 +2481,12 @@ void CheckOther::checkDoubleFree()
|
||||||
if (var) {
|
if (var) {
|
||||||
if (Token::Match(tok, "free|g_free")) {
|
if (Token::Match(tok, "free|g_free")) {
|
||||||
if (freedVariables.find(var) != freedVariables.end())
|
if (freedVariables.find(var) != freedVariables.end())
|
||||||
doubleFreeError(tok, tok->tokAt(2)->str());
|
doubleFreeError(tok, tok->strAt(2));
|
||||||
else
|
else
|
||||||
freedVariables.insert(var);
|
freedVariables.insert(var);
|
||||||
} else if (tok->str() == "closedir") {
|
} else if (tok->str() == "closedir") {
|
||||||
if (closeDirVariables.find(var) != closeDirVariables.end())
|
if (closeDirVariables.find(var) != closeDirVariables.end())
|
||||||
doubleCloseDirError(tok, tok->tokAt(2)->str());
|
doubleCloseDirError(tok, tok->strAt(2));
|
||||||
else
|
else
|
||||||
closeDirVariables.insert(var);
|
closeDirVariables.insert(var);
|
||||||
}
|
}
|
||||||
|
@ -2500,7 +2500,7 @@ void CheckOther::checkDoubleFree()
|
||||||
unsigned int var = tok->tokAt(varIdx)->varId();
|
unsigned int var = tok->tokAt(varIdx)->varId();
|
||||||
if (var) {
|
if (var) {
|
||||||
if (freedVariables.find(var) != freedVariables.end())
|
if (freedVariables.find(var) != freedVariables.end())
|
||||||
doubleFreeError(tok, tok->tokAt(varIdx)->str());
|
doubleFreeError(tok, tok->strAt(varIdx));
|
||||||
else
|
else
|
||||||
freedVariables.insert(var);
|
freedVariables.insert(var);
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,7 +375,7 @@ std::list<Token *> TemplateSimplifier::simplifyTemplatesGetTemplateDeclarations(
|
||||||
for (Token *tok = tokens; tok; tok = tok->next()) {
|
for (Token *tok = tokens; tok; tok = tok->next()) {
|
||||||
// TODO: handle namespaces. Right now we don't instantiate templates that are defined in namespaces.
|
// TODO: handle namespaces. Right now we don't instantiate templates that are defined in namespaces.
|
||||||
if (Token::Match(tok, "namespace %type% {"))
|
if (Token::Match(tok, "namespace %type% {"))
|
||||||
tok = tok->tokAt(2)->link();
|
tok = tok->linkAt(2);
|
||||||
|
|
||||||
if (Token::simpleMatch(tok, "template <")) {
|
if (Token::simpleMatch(tok, "template <")) {
|
||||||
codeWithTemplates = true;
|
codeWithTemplates = true;
|
||||||
|
|
|
@ -8657,7 +8657,7 @@ void Tokenizer::simplifyNamespaceStd()
|
||||||
if (_settings->standards.cpp == Standards::CPP11 && Token::simpleMatch(tok, "std :: tr1 ::"))
|
if (_settings->standards.cpp == Standards::CPP11 && Token::simpleMatch(tok, "std :: tr1 ::"))
|
||||||
Token::eraseTokens(tok, tok->tokAt(3));
|
Token::eraseTokens(tok, tok->tokAt(3));
|
||||||
|
|
||||||
else if (Token::Match(tok, "using namespace std ;")) {
|
else if (Token::simpleMatch(tok, "using namespace std ;")) {
|
||||||
Token::eraseTokens(tok, tok->tokAt(4));
|
Token::eraseTokens(tok, tok->tokAt(4));
|
||||||
tok->deleteThis();
|
tok->deleteThis();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ private:
|
||||||
TEST_CASE(simplePatternAlternatives)
|
TEST_CASE(simplePatternAlternatives)
|
||||||
TEST_CASE(missingPercentCharacter)
|
TEST_CASE(missingPercentCharacter)
|
||||||
TEST_CASE(unknownPattern)
|
TEST_CASE(unknownPattern)
|
||||||
|
TEST_CASE(redundantNextPrevious)
|
||||||
TEST_CASE(internalError)
|
TEST_CASE(internalError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +245,58 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void redundantNextPrevious() {
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->next()->previous();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::previous()' can be simplified.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->tokAt(5)->previous();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::tokAt()' followed by 'Token::previous()' can be simplified.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->previous()->linkAt(5);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::previous()' followed by 'Token::linkAt()' can be simplified.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" tok->next()->previous(foo);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->next()->next();\n" // Simplification won't make code much shorter/readable
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->previous()->previous();\n" // Simplification won't make code much shorter/readable
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->tokAt(foo+bar)->tokAt();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::tokAt()' followed by 'Token::tokAt()' can be simplified.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->tokAt(foo+bar)->link();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::tokAt()' followed by 'Token::link()' can be simplified.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" tok->tokAt(foo+bar)->link(foo);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" return tok->next()->next()->str();\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::str()' can be simplified.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void internalError() {
|
void internalError() {
|
||||||
// Make sure cppcheck does not raise an internal error of Token::Match ( Ticket #3727 )
|
// Make sure cppcheck does not raise an internal error of Token::Match ( Ticket #3727 )
|
||||||
check("class DELPHICLASS X;\n"
|
check("class DELPHICLASS X;\n"
|
||||||
|
|
Loading…
Reference in New Issue