New internal check: checkRedundantNextPrevious().

Fixed findings by new internal check
This commit is contained in:
PKEuS 2012-09-07 12:36:40 +02:00
parent e4a693eaab
commit a4b5824dec
8 changed files with 99 additions and 10 deletions

View File

@ -274,7 +274,7 @@ static const Token *for_init(const Token *tok, unsigned int &varid, std::string
}
varid = tok->tokAt(2)->varId();
varname = tok->tokAt(2)->str();
varname = tok->strAt(2);
tok = tok->tokAt(6);
} else
return 0;

View File

@ -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)
{
reportError(tok, Severity::warning, "simplePatternError",
@ -241,4 +265,10 @@ void CheckInternal::unknownPatternError(const Token* tok, const std::string& pat
"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

View File

@ -54,6 +54,7 @@ public:
checkInternal.checkTokenSimpleMatchPatterns();
checkInternal.checkMissingPercentCharacter();
checkInternal.checkUnknownPattern();
checkInternal.checkRedundantNextPrevious();
}
/** @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 */
void checkMissingPercentCharacter();
/** @brief %Check for for unknown (invalid) complex patterns like "%typ%" */
/** @brief %Check for unknown (invalid) complex patterns like "%typ%" */
void checkUnknownPattern();
/** @brief %Check for inefficient usage of Token::next(), Token::previous() and Token::tokAt() */
void checkRedundantNextPrevious();
private:
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 missingPercentCharacterError(const Token *tok, const std::string &pattern, const std::string &funcname);
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 {
CheckInternal c(0, settings, errorLogger);
@ -80,6 +85,7 @@ private:
c.complexPatternError(0, "%type% ( )", "Match");
c.missingPercentCharacterError(0, "%num", "Match");
c.unknownPatternError(0, "%typ");
c.redundantNextPreviousError(0, "previous", "next");
}
static std::string myName() {

View File

@ -849,8 +849,8 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
vartok = tok->next();
} else if (Token::Match(tok, "( ! ( %var% =")) {
vartok = tok->tokAt(3);
if (Token::simpleMatch(tok->tokAt(2)->link(), ") &&"))
checkConditionStart = tok->tokAt(2)->link();
if (Token::simpleMatch(tok->linkAt(2), ") &&"))
checkConditionStart = tok->linkAt(2);
} else
continue;

View File

@ -2176,7 +2176,7 @@ void CheckOther::checkCCTypeFunctions()
if (tok->varId() == 0 &&
Token::Match(tok, "isalnum|isalpha|iscntrl|isdigit|isgraph|islower|isprint|ispunct|isspace|isupper|isxdigit ( %num% ,|)") &&
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 (Token::Match(tok, "free|g_free")) {
if (freedVariables.find(var) != freedVariables.end())
doubleFreeError(tok, tok->tokAt(2)->str());
doubleFreeError(tok, tok->strAt(2));
else
freedVariables.insert(var);
} else if (tok->str() == "closedir") {
if (closeDirVariables.find(var) != closeDirVariables.end())
doubleCloseDirError(tok, tok->tokAt(2)->str());
doubleCloseDirError(tok, tok->strAt(2));
else
closeDirVariables.insert(var);
}
@ -2500,7 +2500,7 @@ void CheckOther::checkDoubleFree()
unsigned int var = tok->tokAt(varIdx)->varId();
if (var) {
if (freedVariables.find(var) != freedVariables.end())
doubleFreeError(tok, tok->tokAt(varIdx)->str());
doubleFreeError(tok, tok->strAt(varIdx));
else
freedVariables.insert(var);
}

View File

@ -375,7 +375,7 @@ std::list<Token *> TemplateSimplifier::simplifyTemplatesGetTemplateDeclarations(
for (Token *tok = tokens; tok; tok = tok->next()) {
// TODO: handle namespaces. Right now we don't instantiate templates that are defined in namespaces.
if (Token::Match(tok, "namespace %type% {"))
tok = tok->tokAt(2)->link();
tok = tok->linkAt(2);
if (Token::simpleMatch(tok, "template <")) {
codeWithTemplates = true;

View File

@ -8657,7 +8657,7 @@ void Tokenizer::simplifyNamespaceStd()
if (_settings->standards.cpp == Standards::CPP11 && Token::simpleMatch(tok, "std :: tr1 ::"))
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));
tok->deleteThis();
}

View File

@ -38,6 +38,7 @@ private:
TEST_CASE(simplePatternAlternatives)
TEST_CASE(missingPercentCharacter)
TEST_CASE(unknownPattern)
TEST_CASE(redundantNextPrevious)
TEST_CASE(internalError)
}
@ -244,6 +245,58 @@ private:
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() {
// Make sure cppcheck does not raise an internal error of Token::Match ( Ticket #3727 )
check("class DELPHICLASS X;\n"