Skip to content

Commit bc9bb17

Browse files
committed
Refactor CheckOther::oppositeInnerCondition() using AST and isSameExpression()
1 parent e9411e0 commit bc9bb17

File tree

2 files changed

+38
-42
lines changed

2 files changed

+38
-42
lines changed

lib/checkother.cpp

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3398,7 +3398,7 @@ void CheckOther::incompleteArrayFillError(const Token* tok, const std::string& b
33983398

33993399
void CheckOther::oppositeInnerCondition()
34003400
{
3401-
if (!_settings->isEnabled("warning") || !_settings->inconclusive)
3401+
if (!_settings->isEnabled("warning"))
34023402
return;
34033403

34043404
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
@@ -3407,50 +3407,46 @@ void CheckOther::oppositeInnerCondition()
34073407
if (scope->type != Scope::eIf && scope->type != Scope::eElseIf)
34083408
continue;
34093409

3410-
const Token *op1Tok, *op2Tok;
3411-
op1Tok = scope->classDef->tokAt(2);
3412-
op2Tok = scope->classDef->tokAt(4);
3410+
// Condition..
3411+
const Token *cond1 = scope->classDef->next()->astOperand2();
3412+
if (!cond1 || !cond1->isComparisonOp())
3413+
continue;
34133414

3414-
if (scope->classDef->strAt(6) == "{") {
3415+
const std::string comp1 = cond1->str();
34153416

3416-
const char *oppositeCondition = nullptr;
3417+
if (!Token::simpleMatch(scope->classDef->linkAt(1), ") { if"))
3418+
continue;
34173419

3418-
if (scope->classDef->strAt(3) == "==")
3419-
oppositeCondition = "if|while ( %any% !=|<|>|<=|>= %any% )";
3420-
else if (scope->classDef->strAt(3) == "!=")
3421-
oppositeCondition = "if|while ( %any% ==|>=|<= %any% )";
3422-
else if (scope->classDef->strAt(3) == "<")
3423-
oppositeCondition = "if|while ( %any% >|>=|== %any% )";
3424-
else if (scope->classDef->strAt(3) == "<=")
3425-
oppositeCondition = "if|while ( %any% > %any% )";
3426-
else if (scope->classDef->strAt(3) == ">")
3427-
oppositeCondition = "if|while ( %any% <|<=|== %any% )";
3428-
else if (scope->classDef->strAt(3) == ">=")
3429-
oppositeCondition = "if|while ( %any% < %any% )";
3420+
const Token * const tok = scope->classDef->linkAt(1)->tokAt(2);
34303421

3431-
if (oppositeCondition) {
3432-
int flag = 0;
3422+
const Token *cond2 = tok->next()->astOperand2();
3423+
if (!cond2 || !cond2->isComparisonOp())
3424+
continue;
34333425

3434-
for (const Token* tok = scope->classStart; tok != scope->classEnd && flag == 0; tok = tok->next()) {
3435-
if ((tok->str() == op1Tok->str() || tok->str() == op2Tok->str()) && (tok->next()->isAssignmentOp() || tok->next()->type() == Token::eIncDecOp))
3436-
break;
3426+
// condition found .. get comparator
3427+
std::string comp2;
3428+
if (isSameExpression(cond1->astOperand1(), cond2->astOperand1(), _settings->library.functionpure) &&
3429+
isSameExpression(cond1->astOperand2(), cond2->astOperand2(), _settings->library.functionpure)) {
3430+
comp2 = cond2->str();
3431+
} else if (isSameExpression(cond1->astOperand1(), cond2->astOperand1(), _settings->library.functionpure) &&
3432+
isSameExpression(cond1->astOperand2(), cond2->astOperand2(), _settings->library.functionpure)) {
3433+
comp2 = cond2->str();
3434+
if (comp2[0] == '>')
3435+
comp2[0] = '<';
3436+
else if (comp2[0] == '<')
3437+
comp2[0] = '>';
3438+
}
34373439

3438-
if (Token::Match(tok, oppositeCondition)) {
3439-
if ((tok->strAt(2) == op1Tok->str() && tok->strAt(4) == op2Tok->str()) || (tok->strAt(2) == op2Tok->str() && tok->strAt(4) == op1Tok->str()))
3440-
oppositeInnerConditionError(scope->classDef, tok);
3441-
} else if (Token::Match(tok, "%any% (")) {
3442-
if (tok->function()) { // Check if it is a member function. If yes: bailout (TODO: this causes false negatives, since we do not check of which function this is a member
3443-
const Function* func = tok->function();
3444-
if (!func->isConst && (func->access == Private || func->access == Protected || func->access == Public))
3445-
break;
3446-
}
3447-
if (op1Tok->varId() && Token::findmatch(tok->next(), "%varid%", tok->linkAt(1), op1Tok->varId()) != nullptr)
3448-
break;
3449-
if (op2Tok->varId() && Token::findmatch(tok->next(), "%varid%", tok->linkAt(1), op2Tok->varId()) != nullptr)
3450-
break;
3451-
}
3452-
}
3453-
}
3440+
// is condition opposite?
3441+
if ((comp1 == "==" && comp2 == "!=") ||
3442+
(comp1 == "!=" && comp2 == "==") ||
3443+
(comp1 == "<" && comp2 == ">=") ||
3444+
(comp1 == "<=" && comp2 == ">") ||
3445+
(comp1 == "<=" && comp2 == ">=") ||
3446+
(comp1 == ">" && comp2 == "<=") ||
3447+
(comp1 == ">=" && comp2 == "<") ||
3448+
(comp1 == ">=" && comp2 == "<=")) {
3449+
oppositeInnerConditionError(scope->classDef, tok);
34543450
}
34553451
}
34563452
}
@@ -3460,7 +3456,7 @@ void CheckOther::oppositeInnerConditionError(const Token *tok1, const Token* tok
34603456
std::list<const Token*> callstack;
34613457
callstack.push_back(tok1);
34623458
callstack.push_back(tok2);
3463-
reportError(callstack, Severity::warning, "oppositeInnerCondition", "Opposite conditions in nested 'if' blocks lead to a dead code block.", true);
3459+
reportError(callstack, Severity::warning, "oppositeInnerCondition", "Opposite conditions in nested 'if' blocks lead to a dead code block.");
34643460
}
34653461

34663462

test/testother.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class TestOther : public TestFixture {
302302
" if(a!=b)\n"
303303
" cout << a;\n"
304304
"}");
305-
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Opposite conditions in nested 'if' blocks lead to a dead code block.\n", errout.str());
305+
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n", errout.str());
306306

307307
check("void foo(int a) {\n"
308308
" if(a >= 50) {\n"
@@ -312,7 +312,7 @@ class TestOther : public TestFixture {
312312
" cout << 100;\n"
313313
" }\n"
314314
"}");
315-
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Opposite conditions in nested 'if' blocks lead to a dead code block.\n", errout.str());
315+
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Opposite conditions in nested 'if' blocks lead to a dead code block.\n", errout.str());
316316

317317
// #4186
318318
check("void foo(int a) {\n"

0 commit comments

Comments
 (0)