Merge pull request #665 from simartin/todo_condition

Fixed TODO-test for CheckCondition::checkBadBitmaskCheck by handling functions return bool.
This commit is contained in:
PKEuS 2015-09-03 22:53:33 +02:00
commit b49c5d7193
2 changed files with 49 additions and 2 deletions

View File

@ -217,6 +217,24 @@ static void getnumchildren(const Token *tok, std::list<MathLib::bigint> &numchil
getnumchildren(tok->astOperand2(), numchildren);
}
/* Return whether tok is in the body for a function returning a boolean. */
static bool inBooleanFunction(const Token *tok)
{
const Scope *scope = tok ? tok->scope() : 0;
while (scope && scope->isLocal())
scope = scope->nestedIn;
if (scope && scope->type == Scope::eFunction) {
const Function *func = scope->function;
if (func) {
const Token *ret = func->retDef;
while (ret && Token::Match(ret, "static|const"))
ret = ret->next();
return ret && (ret->str() == "bool");
}
}
return false;
}
void CheckCondition::checkBadBitmaskCheck()
{
if (!_settings->isEnabled("warning"))
@ -228,7 +246,8 @@ void CheckCondition::checkBadBitmaskCheck()
const bool isBoolean = Token::Match(parent, "&&|%oror%") ||
(parent->str() == "?" && parent->astOperand1() == tok) ||
(parent->str() == "=" && parent->astOperand2() == tok && parent->astOperand1() && parent->astOperand1()->variable() && parent->astOperand1()->variable()->typeStartToken()->str() == "bool") ||
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while"));
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while")) ||
(parent->str() == "return" && parent->astOperand1() == tok && inBooleanFunction(tok));
const bool isTrue = (tok->astOperand1()->values.size() == 1 && tok->astOperand1()->values.front().intvalue != 0 && !tok->astOperand1()->values.front().conditional) ||
(tok->astOperand2()->values.size() == 1 && tok->astOperand2()->values.front().intvalue != 0 && !tok->astOperand2()->values.front().conditional);

View File

@ -528,7 +528,35 @@ private:
check("bool f(int x) {\n"
" return x | 0x02;\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", "", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout.str());
check("bool f(int x) {\n"
" if (x) {\n"
" return x | 0x02;\n"
" }\n"
" return 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout.str());
check("const bool f(int x) {\n"
" return x | 0x02;\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout.str());
check("struct F {\n"
" static const bool f(int x) {\n"
" return x | 0x02;\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:3]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout.str());
check("struct F {\n"
" typedef bool b_t;\n"
"};\n"
"F::b_t f(int x) {\n"
" return x | 0x02;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (warning) Result of operator '|' is always true if one operand is non-zero. Did you intend to use '&'?\n", errout.str());
check("int f(int x) {\n"
" return x | 0x02;\n"