From f273323cd0f594c9f583c4145c44f97555590677 Mon Sep 17 00:00:00 2001 From: Simon Martin Date: Wed, 2 Sep 2015 23:00:29 +0200 Subject: [PATCH] Fixed TODO-test for CheckCondition::checkBadBitmaskCheck by handling functions return bool. --- lib/checkcondition.cpp | 21 ++++++++++++++++++++- test/testcondition.cpp | 30 +++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index e4db81551..f1a42cef7 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -217,6 +217,24 @@ static void getnumchildren(const Token *tok, std::list &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); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index e539ef720..9eb868846 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -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"