New warning: warn about redundant code in condition.

This commit is contained in:
Dmitry-Me 2015-06-10 18:53:55 +02:00 committed by Daniel Marjamäki
parent 6ba2534f32
commit cae605b1ec
3 changed files with 61 additions and 1 deletions

View File

@ -607,6 +607,12 @@ void CheckCondition::checkIncorrectLogicOperator()
} }
else if (Token::Match(tok, "&&|%oror%")) { else if (Token::Match(tok, "&&|%oror%")) {
if (tok->str() == "||" && tok->astOperand1() && tok->astOperand2() && tok->astOperand2()->str() == "&&") {
const Token* tok2 = tok->astOperand2()->astOperand1();
if (isOppositeCond(tok->astOperand1(), tok2, _settings->library.functionpure)) {
redundantConditionError(tok, tok2->expressionString() + ". 'A && (!A || B)' is equivalent to 'A || B'");
}
}
// Comparison #1 (LHS) // Comparison #1 (LHS)
const Token *comp1 = tok->astOperand1(); const Token *comp1 = tok->astOperand1();
if (comp1 && comp1->str() == tok->str()) if (comp1 && comp1->str() == tok->str())

View File

@ -1178,7 +1178,7 @@ std::string Token::expressionString() const
{ {
const Token * const top = this; const Token * const top = this;
const Token *start = top; const Token *start = top;
while (start->astOperand1() && start->astOperand2()) while (start->astOperand1() && (start->astOperand2() || Token::simpleMatch(start, "( )")))
start = start->astOperand1(); start = start->astOperand1();
const Token *end = top; const Token *end = top;
while (end->astOperand1() && (end->astOperand2() || end->isUnaryPreOp())) { while (end->astOperand1() && (end->astOperand2() || end->isUnaryPreOp())) {

View File

@ -1281,6 +1281,60 @@ private:
" if (x = b < 0 ? 1 : 2) {}\n" // don't simplify and verify this code " if (x = b < 0 ? 1 : 2) {}\n" // don't simplify and verify this code
"}", false); "}", false);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" int y = rand(), z = rand();\n"
" if (y || (!y && z));\n"
"}", false);
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition: !y. 'A && (!A || B)' is equivalent to 'A || B'\n", errout.str());
check("void f() {\n"
" int y = rand(), z = rand();\n"
" if (y || !y && z);\n"
"}", false);
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition: !y. 'A && (!A || B)' is equivalent to 'A || B'\n", errout.str());
check("void f() {\n"
" if (!a || a && b) {}\n"
"}", false);
ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: a. 'A && (!A || B)' is equivalent to 'A || B'\n", errout.str());
check("void f() {\n"
" if (!tok->next()->function() || \n"
" (tok->next()->function() && tok->next()->function()->isConstructor()));\n"
"}", false);
ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: tok.next().function(). 'A && (!A || B)' is equivalent to 'A || B'\n", errout.str());
check("void f() {\n"
" if (!tok->next()->function() || \n"
" (!tok->next()->function() && tok->next()->function()->isConstructor()));\n"
"}", false);
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" if (!tok->next()->function() || \n"
" (!tok2->next()->function() && tok->next()->function()->isConstructor()));\n"
"}", false);
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" if (!tok->next(1)->function(1) || \n"
" (tok->next(1)->function(1) && tok->next(1)->function(1)->isConstructor()));\n"
"}", false);
ASSERT_EQUALS("[test.cpp:2]: (style) Redundant condition: tok.next(1).function(1). 'A && (!A || B)' is equivalent to 'A || B'\n", errout.str());
check("void f() {\n"
" if (!tok->next()->function(1) || \n"
" (tok->next()->function(2) && tok->next()->function()->isConstructor()));\n"
"}", false);
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" int y = rand(), z = rand();\n"
" if (y==0 || y!=0 && z);\n"
"}", false);
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant condition: y. 'A && (!A || B)' is equivalent to 'A || B'\n", errout.str());
} }
// clarify conditions with bitwise operator and comparison // clarify conditions with bitwise operator and comparison