Fixed #2494 (New check: clarify calculation when using ?: operator)

This commit is contained in:
Daniel Marjamäki 2011-01-24 21:40:49 +01:00
parent c7b8bd543f
commit a596a7a8fe
3 changed files with 76 additions and 0 deletions

View File

@ -35,6 +35,60 @@ CheckOther instance;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void CheckOther::clarifyCalculation()
{
if (!_settings->_checkCodingStyle)
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (tok->str() == "?")
{
// condition
const Token *cond = tok->previous();
if (cond->isName() || cond->isNumber())
cond = cond->previous();
else if (cond->str() == ")")
cond = cond->link()->previous();
else
continue;
// multiplication
if (cond->str() == "*")
cond = cond->previous();
else
continue;
// skip previous multiplications..
while (cond && cond->strAt(-1) == "*" && (cond->isName() || cond->isNumber()))
cond = cond->tokAt(-2);
if (!cond)
continue;
// first multiplication operand
if (cond->str() == ")")
{
clarifyCalculationError(cond);
}
else if (cond->isName() || cond->isNumber())
{
if (Token::Match(cond->previous(),"return|+|-|,|("))
clarifyCalculationError(cond);
}
}
}
}
void CheckOther::clarifyCalculationError(const Token *tok)
{
reportError(tok,
Severity::information,
"clarifyCalculation",
"Please clarify precedence: 'a*b?..'\n"
"Found a suspicious multiplication of condition. Please use parantheses to clarify the code. "
"The code 'a*b?1:2' should be written as either '(a*b)?1:2' or 'a*(b?1:2)'.");
}
void CheckOther::warningOldStylePointerCast() void CheckOther::warningOldStylePointerCast()
{ {

View File

@ -70,6 +70,8 @@ public:
{ {
CheckOther checkOther(tokenizer, settings, errorLogger); CheckOther checkOther(tokenizer, settings, errorLogger);
checkOther.clarifyCalculation();
// Coding style checks // Coding style checks
checkOther.checkConstantFunctionParameter(); checkOther.checkConstantFunctionParameter();
checkOther.checkIncompleteStatement(); checkOther.checkIncompleteStatement();
@ -87,6 +89,10 @@ public:
checkOther.checkMemsetZeroBytes(); checkOther.checkMemsetZeroBytes();
} }
/** @brief Clarify calculation for ".. a * b ? .." */
void clarifyCalculation();
void clarifyCalculationError(const Token *tok);
/** @brief Are there C-style pointer casts in a c++ file? */ /** @brief Are there C-style pointer casts in a c++ file? */
void warningOldStylePointerCast(); void warningOldStylePointerCast();
@ -236,6 +242,7 @@ public:
c.unassignedVariableError(0, "varname"); c.unassignedVariableError(0, "varname");
c.catchExceptionByValueError(0); c.catchExceptionByValueError(0);
c.memsetZeroBytesError(0, "varname"); c.memsetZeroBytesError(0, "varname");
c.clarifyCalculationError(0);
} }
std::string name() const std::string name() const
@ -274,6 +281,7 @@ public:
"* assignment of a variable to itself\n" "* assignment of a variable to itself\n"
"* mutual exclusion over || always evaluating to true\n" "* mutual exclusion over || always evaluating to true\n"
"* exception caught by value instead of by reference\n" "* exception caught by value instead of by reference\n"
"* Clarify calculation with parantheses\n"
// optimisations // optimisations
"* optimisation: detect post increment/decrement\n"; "* optimisation: detect post increment/decrement\n";

View File

@ -99,6 +99,8 @@ private:
TEST_CASE(memsetZeroBytes); TEST_CASE(memsetZeroBytes);
TEST_CASE(sizeofForArrayParameter); TEST_CASE(sizeofForArrayParameter);
TEST_CASE(clarifyCalculation);
} }
void check(const char code[], const char *filename = NULL) void check(const char code[], const char *filename = NULL)
@ -134,6 +136,7 @@ private:
checkOther.checkIncorrectLogicOperator(); checkOther.checkIncorrectLogicOperator();
checkOther.checkCatchExceptionByValue(); checkOther.checkCatchExceptionByValue();
checkOther.checkMemsetZeroBytes(); checkOther.checkMemsetZeroBytes();
checkOther.clarifyCalculation();
} }
@ -1748,8 +1751,19 @@ private:
"}\n" "}\n"
); );
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
}
void clarifyCalculation()
{
check("int f(char c) {\n"
" return 10 * (c == 0) ? 1 : 2;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (information) Please clarify precedence: 'a*b?..'\n", errout.str());
check("void f(char c) {\n"
" printf(\"%i\", 10 * (c == 0) ? 1 : 2);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (information) Please clarify precedence: 'a*b?..'\n", errout.str());
} }
}; };