Skip to content

Commit 6e0302f

Browse files
committed
Refactorized CheckBool::checkComparisonOfBoolWithInt(), CheckBool::checkComparisonOfBoolExpressionWithInt() and CheckBool::pointerArithBool():
- Support more patterns in CheckBool::pointerArithBool() - Use AST and SymbolDatabase - Removed redundant skipping over template arguments
1 parent 86a34db commit 6e0302f

2 files changed

Lines changed: 60 additions & 39 deletions

File tree

lib/checkbool.cpp

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -130,41 +130,42 @@ void CheckBool::checkComparisonOfBoolWithInt()
130130
for (std::size_t i = 0; i < functions; ++i) {
131131
const Scope * scope = symbolDatabase->functionScopes[i];
132132
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
133-
if ((!Token::Match(tok->previous(), "%cop%")) && Token::Match(tok->next(), "%comp%") && (!Token::Match(tok->tokAt(3), "%cop%"))) {
134-
const Token* const right = tok->tokAt(2);
135-
if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
136-
const Token* varTok = tok;
133+
const Token* const left = tok->astOperand1();
134+
const Token* const right = tok->astOperand2();
135+
if (left && right && tok->isComparisonOp()) {
136+
if ((left->varId() && right->isNumber()) || (left->isNumber() && right->varId())) { // Comparing variable with number
137+
const Token* varTok = left;
137138
const Token* numTok = right;
138-
if (tok->isNumber() && right->varId()) // num with var
139+
if (left->isNumber() && right->varId()) // num with var
139140
std::swap(varTok, numTok);
140141
if (isBool(varTok->variable()) && // Variable has to be a boolean
141-
((tok->strAt(1) != "==" && tok->strAt(1) != "!=") ||
142+
((tok->str() != "==" && tok->str() != "!=") ||
142143
(MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1
143-
comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
144+
comparisonOfBoolWithIntError(varTok, numTok->str(), tok->str() == "==" || tok->str() == "!=");
144145
}
145-
} else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable
146+
} else if (left->isBoolean() && right->varId()) { // Comparing boolean constant with variable
146147
if (isNonBoolStdType(right->variable())) { // Variable has to be of non-boolean standard type
147-
comparisonOfBoolWithIntError(right, tok->str(), false);
148-
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
149-
comparisonOfBoolWithInvalidComparator(right, tok->str());
148+
comparisonOfBoolWithIntError(right, left->str(), false);
149+
} else if (tok->str() != "==" && tok->str() != "!=") {
150+
comparisonOfBoolWithInvalidComparator(right, left->str());
150151
}
151-
} else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant
152-
if (isNonBoolStdType(tok->variable())) { // Variable has to be of non-boolean standard type
153-
comparisonOfBoolWithIntError(tok, right->str(), false);
154-
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
155-
comparisonOfBoolWithInvalidComparator(right, tok->str());
152+
} else if (left->varId() && right->isBoolean()) { // Comparing variable with boolean constant
153+
if (isNonBoolStdType(left->variable())) { // Variable has to be of non-boolean standard type
154+
comparisonOfBoolWithIntError(left, right->str(), false);
155+
} else if (tok->str() != "==" && tok->str() != "!=") {
156+
comparisonOfBoolWithInvalidComparator(right, left->str());
156157
}
157-
} else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
158-
comparisonOfBoolWithIntError(tok, right->str(), false);
159-
} else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
160-
comparisonOfBoolWithIntError(tok, tok->str(), false);
161-
} else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
158+
} else if (left->isNumber() && right->isBoolean()) { // number constant with boolean constant
159+
comparisonOfBoolWithIntError(left, right->str(), false);
160+
} else if (left->isBoolean() && right->isNumber()) { // number constant with boolean constant
161+
comparisonOfBoolWithIntError(left, left->str(), false);
162+
} else if (left->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
162163
const Variable* var1 = right->variable();
163-
const Variable* var2 = tok->variable();
164+
const Variable* var2 = left->variable();
164165
if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
165-
comparisonOfBoolWithIntError(tok, var1->name(), false);
166+
comparisonOfBoolWithIntError(left, var1->name(), false);
166167
else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
167-
comparisonOfBoolWithIntError(tok, var2->name(), false);
168+
comparisonOfBoolWithIntError(left, var2->name(), false);
168169
}
169170
}
170171
}
@@ -368,12 +369,6 @@ void CheckBool::checkComparisonOfBoolExpressionWithInt()
368369
if (!tok->isComparisonOp())
369370
continue;
370371

371-
// Skip template parameters
372-
if (tok->link() && tok->str() == "<") {
373-
tok = tok->link();
374-
continue;
375-
}
376-
377372
const Token* numTok = 0;
378373
const Token* boolExpr = 0;
379374
bool numInRhs;
@@ -432,14 +427,20 @@ void CheckBool::pointerArithBool()
432427
{
433428
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
434429

435-
const std::size_t functions = symbolDatabase->functionScopes.size();
436-
for (std::size_t i = 0; i < functions; ++i) {
437-
const Scope * scope = symbolDatabase->functionScopes[i];
438-
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
439-
if (Token::Match(tok, "if|while (")) {
440-
pointerArithBoolCond(tok->next()->astOperand2());
441-
}
442-
}
430+
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
431+
if (scope->type != Scope::eIf && scope->type != Scope::eWhile && scope->type != Scope::eDo && scope->type != Scope::eFor)
432+
continue;
433+
const Token* tok = scope->classDef->next()->astOperand2();
434+
if (scope->type == Scope::eFor) {
435+
tok = Token::findsimplematch(scope->classDef->tokAt(2), ";");
436+
if (tok)
437+
tok = tok->astOperand2();
438+
if (tok)
439+
tok = tok->astOperand1();
440+
} else if (scope->type == Scope::eDo)
441+
tok = scope->classEnd->tokAt(2)->astOperand2();
442+
443+
pointerArithBoolCond(tok);
443444
}
444445
}
445446

@@ -452,7 +453,7 @@ void CheckBool::pointerArithBoolCond(const Token *tok)
452453
pointerArithBoolCond(tok->astOperand2());
453454
return;
454455
}
455-
if (tok->str() != "+")
456+
if (tok->str() != "+" && tok->str() != "-")
456457
return;
457458

458459
if (tok->astOperand1() &&

test/testbool.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,10 +922,30 @@ class TestBool : public TestFixture {
922922
"}");
923923
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n", errout.str());
924924

925+
check("void f(char *p) {\n"
926+
" do {} while (p+1);\n"
927+
"}");
928+
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n", errout.str());
929+
930+
check("void f(char *p) {\n"
931+
" while (p-1) {}\n"
932+
"}");
933+
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n", errout.str());
934+
935+
check("void f(char *p) {\n"
936+
" for (int i = 0; p+1; i++) {}\n"
937+
"}");
938+
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n", errout.str());
939+
925940
check("void f(char *p) {\n"
926941
" if (p && p+1){}\n"
927942
"}");
928943
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n", errout.str());
944+
945+
check("void f(char *p) {\n"
946+
" if (p+2 || p) {}\n"
947+
"}");
948+
ASSERT_EQUALS("[test.cpp:2]: (error) Converting pointer arithmetic result to bool. The bool is always true unless there is undefined behaviour.\n", errout.str());
929949
}
930950
};
931951

0 commit comments

Comments
 (0)