errmsg: Added 'condition is always true/false'

This commit is contained in:
Daniel Marjamäki 2009-01-14 19:43:28 +00:00
parent 22583269c1
commit 03cfe18c9b
5 changed files with 82 additions and 67 deletions

View File

@ -194,87 +194,92 @@ void CheckOther::redundantCondition2()
void CheckOther::WarningIf() void CheckOther::WarningIf()
{ {
// Search for 'if (condition);' if (ErrorMessage::ifNoAction(_settings))
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
if (!Token::simpleMatch(tok, "if (")) // Search for 'if (condition);'
continue; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
// Search for the end paranthesis for the condition..
int parlevel = 0;
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
{ {
if (tok2->str() == "(") if (!Token::simpleMatch(tok, "if ("))
++parlevel; continue;
else if (tok2->str() == ")")
// Search for the end paranthesis for the condition..
int parlevel = 0;
for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next())
{ {
--parlevel; if (tok2->str() == "(")
if (parlevel <= 0) ++parlevel;
else if (tok2->str() == ")")
{ {
if (Token::Match(tok2, ") ; !!else")) --parlevel;
if (parlevel <= 0)
{ {
_errorLogger->reportErr(ErrorMessage::ifNoAction(_tokenizer, tok)); if (Token::Match(tok2, ") ; !!else"))
{
_errorLogger->reportErr(ErrorMessage::ifNoAction(_tokenizer, tok));
}
break;
} }
break;
} }
} }
} }
} }
// Search for 'a=b; if (a==b)' if (ErrorMessage::conditionAlwaysTrueFalse(_settings))
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{ {
// Begin statement? // Search for 'a=b; if (a==b)'
if (! Token::Match(tok, "[;{}]")) for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
continue;
tok = tok->next();
if (! tok)
break;
if (!Token::Match(tok, "%var% = %var% ; if ( %var%"))
continue;
if (strcmp(tok->strAt(9), ")") != 0)
continue;
// var1 = var2 ; if ( var3 cond var4 )
const char *var1 = tok->strAt(0);
const char *var2 = tok->strAt(2);
const char *var3 = tok->strAt(6);
const char *cond = tok->strAt(7);
const char *var4 = tok->strAt(8);
// Check that var3 is equal with either var1 or var2
if (strcmp(var1, var3) && strcmp(var2, var3))
continue;
// Check that var4 is equal with either var1 or var2
if (strcmp(var1, var4) && strcmp(var2, var4))
continue;
// Check that there is a condition..
const char *p[6] = {"==", "<=", ">=", "!=", "<", ">"};
bool iscond = false;
for (int i = 0; i < 6; i++)
{ {
if (strcmp(cond, p[i]) == 0) // Begin statement?
{ if (! Token::Match(tok, "[;{}]"))
iscond = true; continue;
tok = tok->next();
if (! tok)
break; break;
}
}
if (!iscond)
break;
// we found the error. Report. if (!Token::Match(tok, "%var% = %var% ; if ( %var%"))
std::ostringstream ostr; continue;
ostr << _tokenizer->fileLine(tok->tokAt(4)) << ": The condition is always ";
for (int i = 0; i < 6; i++) if (strcmp(tok->strAt(9), ")") != 0)
{ continue;
if (strcmp(cond, p[i]) == 0)
ostr << (i < 3 ? "True" : "False"); // var1 = var2 ; if ( var3 cond var4 )
const char *var1 = tok->strAt(0);
const char *var2 = tok->strAt(2);
const char *var3 = tok->strAt(6);
const char *cond = tok->strAt(7);
const char *var4 = tok->strAt(8);
// Check that var3 is equal with either var1 or var2
if (strcmp(var1, var3) && strcmp(var2, var3))
continue;
// Check that var4 is equal with either var1 or var2
if (strcmp(var1, var4) && strcmp(var2, var4))
continue;
// Check that there is a condition..
const char *p[6] = {"==", "<=", ">=", "!=", "<", ">"};
bool iscond = false;
for (int i = 0; i < 6; i++)
{
if (strcmp(cond, p[i]) == 0)
{
iscond = true;
break;
}
}
if (!iscond)
break;
// we found the error. Report.
bool b = false;
for (int i = 0; i < 6; i++)
{
if (strcmp(cond, p[i]) == 0)
b = (i < 3);
}
_errorLogger->reportErr(ErrorMessage::conditionAlwaysTrueFalse(_tokenizer, tok->tokAt(4), b ? "True" : "False"));
} }
_errorLogger->reportErr(ostr.str());
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -313,7 +313,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
checkClass.operatorEq(); checkClass.operatorEq();
// if (condition); // if (condition);
if (ErrorMessage::ifNoAction(_settings)) if (ErrorMessage::ifNoAction(_settings) || ErrorMessage::conditionAlwaysTrueFalse(_settings))
checkOther.WarningIf(); checkOther.WarningIf();
// Unused struct members.. // Unused struct members..

View File

@ -318,5 +318,14 @@ public:
return s._checkCodingStyle; return s._checkCodingStyle;
} }
static std::string conditionAlwaysTrueFalse(const Tokenizer *tokenizer, const Token *Location, const std::string &truefalse)
{
return msg1(tokenizer, Location) + "Condition is always " + truefalse + "";
}
static bool conditionAlwaysTrueFalse(const Settings &s)
{
return s._checkCodingStyle;
}
}; };
#endif #endif

View File

@ -160,7 +160,7 @@ private:
"\n" "\n"
"private:\n" "private:\n"
" ECODES _code;\n" " ECODES _code;\n"
"};\n" ); "};\n");
ASSERT_EQUALS("[test.cpp:10]: Uninitialized member variable 'Fred::_code'\n", errout.str()); ASSERT_EQUALS("[test.cpp:10]: Uninitialized member variable 'Fred::_code'\n", errout.str());
} }

View File

@ -93,6 +93,7 @@ int main()
err.push_back(Message("charBitOp", Message::style, "Warning - using char variable in bit operation")); err.push_back(Message("charBitOp", Message::style, "Warning - using char variable in bit operation"));
err.push_back(Message("variableScope", Message::never, "The scope of the variable %1 can be limited", "varname")); err.push_back(Message("variableScope", Message::never, "The scope of the variable %1 can be limited", "varname"));
err.push_back(Message("ifAssignment", Message::style, "Assignment in if-condition")); err.push_back(Message("ifAssignment", Message::style, "Assignment in if-condition"));
err.push_back(Message("conditionAlwaysTrueFalse", Message::style, "Condition is always %1", "truefalse"));
// Generate code.. // Generate code..
std::cout << "Generate code.." << std::endl; std::cout << "Generate code.." << std::endl;