add check for same expression on both sides of an operator (part of #2700)

This commit is contained in:
Robert Reif 2011-04-10 10:25:02 -04:00
parent 434783530a
commit 56212370d1
3 changed files with 80 additions and 0 deletions

View File

@ -3230,6 +3230,56 @@ void CheckOther::duplicateBranchError(const Token *tok1, const Token *tok2)
"carefully to determine if it is correct.");
}
//---------------------------------------------------------------------------
// check for the same expression on both sides of an operator
// (x == x), (x && x), (x || x)
// (x.y == x.y), (x.y && x.y), (x.y || x.y)
//---------------------------------------------------------------------------
void CheckOther::checkDuplicateExpression()
{
if (!_settings->_checkCodingStyle)
return;
// Parse all executing scopes..
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
std::list<Scope>::const_iterator scope;
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope)
{
// only check functions
if (scope->type != Scope::eFunction)
continue;
for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next())
{
if (Token::Match(tok, "(|&&|%oror% %var% &&|%oror%|==|!=|<=|>=|<|>|-|%or% %var% )|&&|%oror%") &&
tok->strAt(1) == tok->strAt(3))
{
duplicateExpressionError(tok->next(), tok->tokAt(3), tok->strAt(2));
}
else if (Token::Match(tok, "(|&&|%oror% %var% . %var% &&|%oror%|==|!=|<=|>=|<|>|-|%or% %var% . %var% )|&&|%oror%") &&
tok->strAt(1) == tok->strAt(5) && tok->strAt(3) == tok->strAt(7))
{
duplicateExpressionError(tok->next(), tok->tokAt(6), tok->strAt(4));
}
}
}
}
void CheckOther::duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op)
{
std::list<const Token *> toks;
toks.push_back(tok2);
toks.push_back(tok1);
reportError(toks, Severity::style, "duplicateExpression", "Same expression on both sides of \'" + op + "\'.\n"
"Finding the same expression on both sides of an operator is suspicious and might "
"indicate a cut and paste or logic error. Please examine this code carefully to "
"determine if it is correct.");
}
//-----------------------------------------------------------------------------
void CheckOther::cstyleCastError(const Token *tok)

View File

@ -65,6 +65,7 @@ public:
checkOther.checkSelfAssignment();
checkOther.checkDuplicateIf();
checkOther.checkDuplicateBranch();
checkOther.checkDuplicateExpression();
// information checks
checkOther.checkVariableScope();
@ -212,6 +213,9 @@ public:
/** @brief %Check for suspicious code where if and else branch are the same (e.g "if (a) b = true; else b = true;") */
void checkDuplicateBranch();
/** @brief %Check for suspicious code with the same expression on both sides of operator (e.g "if (a && a)") */
void checkDuplicateExpression();
// Error messages..
void cstyleCastError(const Token *tok);
void dangerousUsageStrtolError(const Token *tok);
@ -242,6 +246,7 @@ public:
void comparisonOfBoolWithIntError(const Token *tok, const std::string &varname);
void duplicateIfError(const Token *tok1, const Token *tok2);
void duplicateBranchError(const Token *tok1, const Token *tok2);
void duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op);
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
{
@ -288,6 +293,7 @@ public:
c.comparisonOfBoolWithIntError(0, "varname");
c.duplicateIfError(0, 0);
c.duplicateBranchError(0, 0);
c.duplicateExpressionError(0, 0, "&&");
}
std::string myName() const

View File

@ -115,6 +115,7 @@ private:
TEST_CASE(duplicateIf);
TEST_CASE(duplicateBranch);
TEST_CASE(duplicateExpression);
}
void check(const char code[], const char *filename = NULL)
@ -140,6 +141,7 @@ private:
checkOther.clarifyCondition();
checkOther.checkDuplicateIf();
checkOther.checkDuplicateBranch();
checkOther.checkDuplicateExpression();
// Simplify token list..
tokenizer.simplifyTokenList();
@ -2487,6 +2489,28 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
}
void duplicateExpression()
{
check("voif foo() {\n"
" if (a == a) { }\n"
"}");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Same expression on both sides of '=='.\n", errout.str());
check("void fun() {\n"
" return (a && a ||\n"
" b == b &&\n"
" c - c &&\n"
" d > d &&\n"
" e < e &&\n"
" f);\n"
"}");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Same expression on both sides of '&&'.\n"
"[test.cpp:3] -> [test.cpp:3]: (style) Same expression on both sides of '=='.\n"
"[test.cpp:4] -> [test.cpp:4]: (style) Same expression on both sides of '-'.\n"
"[test.cpp:5] -> [test.cpp:5]: (style) Same expression on both sides of '>'.\n"
"[test.cpp:6] -> [test.cpp:6]: (style) Same expression on both sides of '<'.\n", errout.str());
}
};
REGISTER_TEST(TestOther)