From 7975f4d097e3e85c4565042505bd0e41a84fc086 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 9 Sep 2021 15:56:42 -0500 Subject: [PATCH 01/10] Fix FPs in bitwiseOnBoolean --- lib/checkbool.cpp | 18 ++++++++++++------ test/testbool.cpp | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index bc79340e4e1..11ad9877cda 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -90,12 +90,18 @@ void CheckBool::checkBitwiseOnBoolean() for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (tok->isBinaryOp() && (tok->str() == "&" || tok->str() == "|")) { - if (astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2())) { - if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2()) - continue; - const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() : tok->astOperand2()->expressionString(); - bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); - } + if (tok->str() == "&" && !(astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2()))) + continue; + if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) + continue; + if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) + continue; + if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) + continue; + if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2()) + continue; + const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() : tok->astOperand2()->expressionString(); + bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); } } } diff --git a/test/testbool.cpp b/test/testbool.cpp index c93054593e5..4ab02ca07a1 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -810,6 +810,17 @@ class TestBool : public TestFixture { "}"); ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean expression 'a>0' is used in bitwise operation. Did you mean '&&'?\n", errout.str()); + check("void f(bool a, int b) {\n" + " if(a | b) {}\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f(int a, bool b) {\n" + " if(a | b) {}\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f(int a, int b) {\n" " if(a & b) {}\n" "}"); @@ -824,6 +835,12 @@ class TestBool : public TestFixture { " class C { void foo(bool &b) {} };\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("bool f();\n" + "bool g() {\n" + " return f() | f();\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void incrementBoolean() { From e88b37f1dab07520a4c82b6a29af58d3293d3810 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 9 Sep 2021 16:03:23 -0500 Subject: [PATCH 02/10] Format --- lib/checkbool.cpp | 3 ++- test/testbool.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index 11ad9877cda..87a094434a6 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -100,7 +100,8 @@ void CheckBool::checkBitwiseOnBoolean() continue; if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2()) continue; - const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() : tok->astOperand2()->expressionString(); + const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() + : tok->astOperand2()->expressionString(); bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); } } diff --git a/test/testbool.cpp b/test/testbool.cpp index 4ab02ca07a1..f347d612c96 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -820,7 +820,6 @@ class TestBool : public TestFixture { "}"); ASSERT_EQUALS("", errout.str()); - check("void f(int a, int b) {\n" " if(a & b) {}\n" "}"); From 48d5c27666c452b086387632eb7dbcbbe46a4f9d Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 9 Sep 2021 17:16:53 -0500 Subject: [PATCH 03/10] Update message for a|b --- lib/checkbool.cpp | 28 ++++++++++++++++++++++------ lib/checkbool.h | 2 +- test/testbool.cpp | 4 ++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index 87a094434a6..6a8729288c8 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -90,9 +90,7 @@ void CheckBool::checkBitwiseOnBoolean() for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (tok->isBinaryOp() && (tok->str() == "&" || tok->str() == "|")) { - if (tok->str() == "&" && !(astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2()))) - continue; - if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) + if (!astIsBool(tok->astOperand1()) && !astIsBool(tok->astOperand2())) continue; if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) continue; @@ -102,20 +100,38 @@ void CheckBool::checkBitwiseOnBoolean() continue; const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() : tok->astOperand2()->expressionString(); - bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); + const std::string nonbool = astIsBool(tok->astOperand1()) ? tok->astOperand2()->expressionString() + : tok->astOperand1()->expressionString(); + if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) + bitwiseOnBooleanError(tok, expression, nonbool, tok->expressionString()); + else + bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); } } } } -void CheckBool::bitwiseOnBooleanError(const Token *tok, const std::string &expression, const std::string &op) +void CheckBool::bitwiseOnBooleanError(const Token *tok, const std::string &expression, const std::string &op, const std::string& bitwise) { + std::string msg; + if (bitwise.empty()) + msg = "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?"; + else + msg = "Bitwise expression '" + bitwise + "' with boolean expression '" + expression + "' is equivalent to '" + op + "'?"; reportError(tok, Severity::style, "bitwiseOnBoolean", - "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?", + msg, CWE398, Certainty::inconclusive); } +// void CheckBool::bitwiseOrIntegerError(const Token *tok, const std::string &expression, const std::string &op) +// { +// reportError(tok, Severity::style, "bitwiseOnBoolean", +// "Bitwise expression '" + expression + "' with boolean is used in bitwise operation. Did you mean '" + op + "'?", +// CWE398, +// Certainty::inconclusive); +// } + //--------------------------------------------------------------------------- // if (!x==3) <- Probably meant to be "x!=3" //--------------------------------------------------------------------------- diff --git a/lib/checkbool.h b/lib/checkbool.h index bbff56e298b..2677a7453ed 100644 --- a/lib/checkbool.h +++ b/lib/checkbool.h @@ -104,7 +104,7 @@ class CPPCHECKLIB CheckBool : public Check { void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression); void assignBoolToPointerError(const Token *tok); void assignBoolToFloatError(const Token *tok); - void bitwiseOnBooleanError(const Token *tok, const std::string &expression, const std::string &op); + void bitwiseOnBooleanError(const Token *tok, const std::string &expression, const std::string &op, const std::string& bitwise = ""); void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1); void pointerArithBoolError(const Token *tok); void returnValueBoolError(const Token *tok); diff --git a/test/testbool.cpp b/test/testbool.cpp index f347d612c96..aa41b6bf961 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -813,12 +813,12 @@ class TestBool : public TestFixture { check("void f(bool a, int b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'a' is equivalent to 'b'?\n", errout.str()); check("void f(int a, bool b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'b' is equivalent to 'a'?\n", errout.str()); check("void f(int a, int b) {\n" " if(a & b) {}\n" From 0ac9ba906c2ffe920dbd23931c4dd045de1648b0 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 9 Sep 2021 17:17:38 -0500 Subject: [PATCH 04/10] Format --- lib/checkbool.cpp | 20 ++++++++++---------- lib/checkbool.h | 5 ++++- test/testbool.cpp | 8 ++++++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index 6a8729288c8..a6fe40081f4 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -101,7 +101,7 @@ void CheckBool::checkBitwiseOnBoolean() const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() : tok->astOperand2()->expressionString(); const std::string nonbool = astIsBool(tok->astOperand1()) ? tok->astOperand2()->expressionString() - : tok->astOperand1()->expressionString(); + : tok->astOperand1()->expressionString(); if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) bitwiseOnBooleanError(tok, expression, nonbool, tok->expressionString()); else @@ -111,25 +111,25 @@ void CheckBool::checkBitwiseOnBoolean() } } -void CheckBool::bitwiseOnBooleanError(const Token *tok, const std::string &expression, const std::string &op, const std::string& bitwise) +void CheckBool::bitwiseOnBooleanError(const Token* tok, + const std::string& expression, + const std::string& op, + const std::string& bitwise) { std::string msg; if (bitwise.empty()) msg = "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?"; else - msg = "Bitwise expression '" + bitwise + "' with boolean expression '" + expression + "' is equivalent to '" + op + "'?"; - reportError(tok, Severity::style, "bitwiseOnBoolean", - msg, - CWE398, - Certainty::inconclusive); + msg = "Bitwise expression '" + bitwise + "' with boolean expression '" + expression + "' is equivalent to '" + + op + "'?"; + reportError(tok, Severity::style, "bitwiseOnBoolean", msg, CWE398, Certainty::inconclusive); } // void CheckBool::bitwiseOrIntegerError(const Token *tok, const std::string &expression, const std::string &op) // { // reportError(tok, Severity::style, "bitwiseOnBoolean", -// "Bitwise expression '" + expression + "' with boolean is used in bitwise operation. Did you mean '" + op + "'?", -// CWE398, -// Certainty::inconclusive); +// "Bitwise expression '" + expression + "' with boolean is used in bitwise operation. Did you mean '" + +// op + "'?", CWE398, Certainty::inconclusive); // } //--------------------------------------------------------------------------- diff --git a/lib/checkbool.h b/lib/checkbool.h index 2677a7453ed..f7ddcbf6552 100644 --- a/lib/checkbool.h +++ b/lib/checkbool.h @@ -104,7 +104,10 @@ class CPPCHECKLIB CheckBool : public Check { void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression); void assignBoolToPointerError(const Token *tok); void assignBoolToFloatError(const Token *tok); - void bitwiseOnBooleanError(const Token *tok, const std::string &expression, const std::string &op, const std::string& bitwise = ""); + void bitwiseOnBooleanError(const Token* tok, + const std::string& expression, + const std::string& op, + const std::string& bitwise = ""); void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1); void pointerArithBoolError(const Token *tok); void returnValueBoolError(const Token *tok); diff --git a/test/testbool.cpp b/test/testbool.cpp index aa41b6bf961..31f7959d74e 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -813,12 +813,16 @@ class TestBool : public TestFixture { check("void f(bool a, int b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'a' is equivalent to 'b'?\n", errout.str()); + ASSERT_EQUALS( + "[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'a' is equivalent to 'b'?\n", + errout.str()); check("void f(int a, bool b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'b' is equivalent to 'a'?\n", errout.str()); + ASSERT_EQUALS( + "[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'b' is equivalent to 'a'?\n", + errout.str()); check("void f(int a, int b) {\n" " if(a & b) {}\n" From 969354ebf6bc90d9484caff3c20a0995d2f60134 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 9 Sep 2021 17:55:33 -0500 Subject: [PATCH 05/10] Remove commented code --- lib/checkbool.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index a6fe40081f4..d1e0b18ceb1 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -125,13 +125,6 @@ void CheckBool::bitwiseOnBooleanError(const Token* tok, reportError(tok, Severity::style, "bitwiseOnBoolean", msg, CWE398, Certainty::inconclusive); } -// void CheckBool::bitwiseOrIntegerError(const Token *tok, const std::string &expression, const std::string &op) -// { -// reportError(tok, Severity::style, "bitwiseOnBoolean", -// "Bitwise expression '" + expression + "' with boolean is used in bitwise operation. Did you mean '" + -// op + "'?", CWE398, Certainty::inconclusive); -// } - //--------------------------------------------------------------------------- // if (!x==3) <- Probably meant to be "x!=3" //--------------------------------------------------------------------------- From 4ce0d0001daaec878cd05b9e6fed3bce2ac71100 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 12 Sep 2021 14:14:37 -0500 Subject: [PATCH 06/10] Update message --- lib/checkbool.cpp | 11 ++++------- test/testbool.cpp | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index d1e0b18ceb1..3110950912b 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -90,7 +90,9 @@ void CheckBool::checkBitwiseOnBoolean() for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (tok->isBinaryOp() && (tok->str() == "&" || tok->str() == "|")) { - if (!astIsBool(tok->astOperand1()) && !astIsBool(tok->astOperand2())) + if (tok->str() == "&" && !(astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2()))) + continue; + if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) continue; if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) continue; @@ -100,12 +102,7 @@ void CheckBool::checkBitwiseOnBoolean() continue; const std::string expression = astIsBool(tok->astOperand1()) ? tok->astOperand1()->expressionString() : tok->astOperand2()->expressionString(); - const std::string nonbool = astIsBool(tok->astOperand1()) ? tok->astOperand2()->expressionString() - : tok->astOperand1()->expressionString(); - if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) - bitwiseOnBooleanError(tok, expression, nonbool, tok->expressionString()); - else - bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); + bitwiseOnBooleanError(tok, expression, tok->str() == "&" ? "&&" : "||"); } } } diff --git a/test/testbool.cpp b/test/testbool.cpp index 31f7959d74e..c2a258d5638 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -814,14 +814,14 @@ class TestBool : public TestFixture { " if(a | b) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'a' is equivalent to 'b'?\n", + "", errout.str()); check("void f(int a, bool b) {\n" " if(a | b) {}\n" "}"); ASSERT_EQUALS( - "[test.cpp:2]: (style, inconclusive) Bitwise expression 'a|b' with boolean expression 'b' is equivalent to 'a'?\n", + "", errout.str()); check("void f(int a, int b) {\n" From 3dad9a8fe339c2771601e52b2b0396d72b160584 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 12 Sep 2021 14:17:30 -0500 Subject: [PATCH 07/10] Remove extra parameter --- lib/checkbool.cpp | 11 ++--------- lib/checkbool.h | 3 +-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index 3110950912b..f0e689421a8 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -110,16 +110,9 @@ void CheckBool::checkBitwiseOnBoolean() void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expression, - const std::string& op, - const std::string& bitwise) + const std::string& op) { - std::string msg; - if (bitwise.empty()) - msg = "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?"; - else - msg = "Bitwise expression '" + bitwise + "' with boolean expression '" + expression + "' is equivalent to '" + - op + "'?"; - reportError(tok, Severity::style, "bitwiseOnBoolean", msg, CWE398, Certainty::inconclusive); + reportError(tok, Severity::style, "bitwiseOnBoolean", "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?", CWE398, Certainty::inconclusive); } //--------------------------------------------------------------------------- diff --git a/lib/checkbool.h b/lib/checkbool.h index f7ddcbf6552..55d2d537441 100644 --- a/lib/checkbool.h +++ b/lib/checkbool.h @@ -106,8 +106,7 @@ class CPPCHECKLIB CheckBool : public Check { void assignBoolToFloatError(const Token *tok); void bitwiseOnBooleanError(const Token* tok, const std::string& expression, - const std::string& op, - const std::string& bitwise = ""); + const std::string& op); void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1); void pointerArithBoolError(const Token *tok); void returnValueBoolError(const Token *tok); From 53853c55610743fce7d0dee2acae5c6ded4e1b04 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 12 Sep 2021 14:18:02 -0500 Subject: [PATCH 08/10] Format --- lib/checkbool.cpp | 11 +++++++---- lib/checkbool.h | 4 +--- test/testbool.cpp | 8 ++------ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index f0e689421a8..0fb6b4c3e31 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -108,11 +108,14 @@ void CheckBool::checkBitwiseOnBoolean() } } -void CheckBool::bitwiseOnBooleanError(const Token* tok, - const std::string& expression, - const std::string& op) +void CheckBool::bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op) { - reportError(tok, Severity::style, "bitwiseOnBoolean", "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?", CWE398, Certainty::inconclusive); + reportError(tok, + Severity::style, + "bitwiseOnBoolean", + "Boolean expression '" + expression + "' is used in bitwise operation. Did you mean '" + op + "'?", + CWE398, + Certainty::inconclusive); } //--------------------------------------------------------------------------- diff --git a/lib/checkbool.h b/lib/checkbool.h index 55d2d537441..e192a8f7171 100644 --- a/lib/checkbool.h +++ b/lib/checkbool.h @@ -104,9 +104,7 @@ class CPPCHECKLIB CheckBool : public Check { void comparisonOfBoolWithInvalidComparator(const Token *tok, const std::string &expression); void assignBoolToPointerError(const Token *tok); void assignBoolToFloatError(const Token *tok); - void bitwiseOnBooleanError(const Token* tok, - const std::string& expression, - const std::string& op); + void bitwiseOnBooleanError(const Token* tok, const std::string& expression, const std::string& op); void comparisonOfBoolExpressionWithIntError(const Token *tok, bool not0or1); void pointerArithBoolError(const Token *tok); void returnValueBoolError(const Token *tok); diff --git a/test/testbool.cpp b/test/testbool.cpp index c2a258d5638..f347d612c96 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -813,16 +813,12 @@ class TestBool : public TestFixture { check("void f(bool a, int b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS( - "", - errout.str()); + ASSERT_EQUALS("", errout.str()); check("void f(int a, bool b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS( - "", - errout.str()); + ASSERT_EQUALS("", errout.str()); check("void f(int a, int b) {\n" " if(a & b) {}\n" From 7f1df8fdae49da37e7e89e496f52088413e824fd Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 15 Sep 2021 22:48:32 -0500 Subject: [PATCH 09/10] Fix copy and paste error --- lib/checkbool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index d1e0b18ceb1..39e18cc5a97 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -94,7 +94,7 @@ void CheckBool::checkBitwiseOnBoolean() continue; if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) continue; - if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) + if (!isConstExpression(tok->astOperand2(), mSettings->library, true, mTokenizer->isCPP())) continue; if (tok->astOperand2()->variable() && tok->astOperand2()->variable()->nameToken() == tok->astOperand2()) continue; From d33255969e5be469572efeae2f4f0fed7c9adeb1 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 17 Sep 2021 21:13:26 -0500 Subject: [PATCH 10/10] Check if converted to boolean --- lib/checkbool.cpp | 11 +++++++++-- test/testbool.cpp | 12 +++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index d49bb2482f3..d2f2868d1a5 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -72,6 +72,13 @@ void CheckBool::incrementBooleanError(const Token *tok) ); } +static bool isConvertedToBool(const Token* tok) +{ + if (!tok->astParent()) + return false; + return astIsBool(tok->astParent()) || Token::Match(tok->astParent()->previous(), "if|while ("); +} + //--------------------------------------------------------------------------- // if (bool & bool) -> if (bool && bool) // if (bool | bool) -> if (bool || bool) @@ -90,9 +97,9 @@ void CheckBool::checkBitwiseOnBoolean() for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (tok->isBinaryOp() && (tok->str() == "&" || tok->str() == "|")) { - if (tok->str() == "&" && !(astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2()))) + if (!(astIsBool(tok->astOperand1()) || astIsBool(tok->astOperand2()))) continue; - if (tok->str() == "|" && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) + if (tok->str() == "|" && !isConvertedToBool(tok) && !(astIsBool(tok->astOperand1()) && astIsBool(tok->astOperand2()))) continue; if (!isConstExpression(tok->astOperand1(), mSettings->library, true, mTokenizer->isCPP())) continue; diff --git a/test/testbool.cpp b/test/testbool.cpp index f347d612c96..c4e44c847aa 100644 --- a/test/testbool.cpp +++ b/test/testbool.cpp @@ -813,13 +813,23 @@ class TestBool : public TestFixture { check("void f(bool a, int b) {\n" " if(a | b) {}\n" "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean expression 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str()); check("void f(int a, bool b) {\n" " if(a | b) {}\n" "}"); + ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean expression 'b' is used in bitwise operation. Did you mean '||'?\n", errout.str()); + + check("int f(bool a, int b) {\n" + " return a | b;\n" + "}"); ASSERT_EQUALS("", errout.str()); + check("bool f(bool a, int b) {\n" + " return a | b;\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Boolean expression 'a' is used in bitwise operation. Did you mean '||'?\n", errout.str()); + check("void f(int a, int b) {\n" " if(a & b) {}\n" "}");