Add a check for identical inner conditions (#1156)
This commit is contained in:
parent
541e255159
commit
b85dda77da
|
@ -585,6 +585,8 @@ void CheckCondition::multiCondition2()
|
||||||
} else if (isOppositeCond(false, _tokenizer->isCPP(), firstCondition, cond2, _settings->library, true)) {
|
} else if (isOppositeCond(false, _tokenizer->isCPP(), firstCondition, cond2, _settings->library, true)) {
|
||||||
if (!isAliased(vars))
|
if (!isAliased(vars))
|
||||||
oppositeInnerConditionError(firstCondition, cond2);
|
oppositeInnerConditionError(firstCondition, cond2);
|
||||||
|
} else if(isSameExpression(_tokenizer->isCPP(), true, firstCondition, cond2, _settings->library, true)) {
|
||||||
|
identicalInnerConditionError(firstCondition, cond2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -693,6 +695,18 @@ void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token*
|
||||||
reportError(errorPath, Severity::warning, "oppositeInnerCondition", msg, CWE398, false);
|
reportError(errorPath, Severity::warning, "oppositeInnerCondition", msg, CWE398, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token* tok2)
|
||||||
|
{
|
||||||
|
const std::string s1(tok1 ? tok1->expressionString() : "x");
|
||||||
|
const std::string s2(tok2 ? tok2->expressionString() : "x");
|
||||||
|
ErrorPath errorPath;
|
||||||
|
errorPath.push_back(ErrorPathItem(tok1, "outer condition: " + s1));
|
||||||
|
errorPath.push_back(ErrorPathItem(tok2, "identical inner condition: " + s2));
|
||||||
|
const std::string msg("Identical inner 'if' condition is always true.\n"
|
||||||
|
"Identical inner 'if' condition is always true (outer condition is '" + s1 + "' and inner condition is '" + s2 + "').");
|
||||||
|
reportError(errorPath, Severity::warning, "identicalInnerCondition", msg, CWE398, false);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckCondition::identicalConditionAfterEarlyExitError(const Token *cond1, const Token* cond2)
|
void CheckCondition::identicalConditionAfterEarlyExitError(const Token *cond1, const Token* cond2)
|
||||||
{
|
{
|
||||||
const std::string cond(cond1 ? cond1->expressionString() : "x");
|
const std::string cond(cond1 ? cond1->expressionString() : "x");
|
||||||
|
|
|
@ -133,6 +133,8 @@ private:
|
||||||
|
|
||||||
void oppositeInnerConditionError(const Token *tok1, const Token* tok2);
|
void oppositeInnerConditionError(const Token *tok1, const Token* tok2);
|
||||||
|
|
||||||
|
void identicalInnerConditionError(const Token *tok1, const Token* tok2);
|
||||||
|
|
||||||
void identicalConditionAfterEarlyExitError(const Token *cond1, const Token *cond2);
|
void identicalConditionAfterEarlyExitError(const Token *cond1, const Token *cond2);
|
||||||
|
|
||||||
void incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always, bool inconclusive);
|
void incorrectLogicOperatorError(const Token *tok, const std::string &condition, bool always, bool inconclusive);
|
||||||
|
@ -156,6 +158,7 @@ private:
|
||||||
c.multiConditionError(nullptr,1);
|
c.multiConditionError(nullptr,1);
|
||||||
c.mismatchingBitAndError(nullptr, 0xf0, nullptr, 1);
|
c.mismatchingBitAndError(nullptr, 0xf0, nullptr, 1);
|
||||||
c.oppositeInnerConditionError(nullptr, nullptr);
|
c.oppositeInnerConditionError(nullptr, nullptr);
|
||||||
|
c.identicalInnerConditionError(nullptr, nullptr);
|
||||||
c.identicalConditionAfterEarlyExitError(nullptr, nullptr);
|
c.identicalConditionAfterEarlyExitError(nullptr, nullptr);
|
||||||
c.incorrectLogicOperatorError(nullptr, "foo > 3 && foo < 4", true, false);
|
c.incorrectLogicOperatorError(nullptr, "foo > 3 && foo < 4", true, false);
|
||||||
c.redundantConditionError(nullptr, "If x > 11 the condition x > 10 is always true.", false);
|
c.redundantConditionError(nullptr, "If x > 11 the condition x > 10 is always true.", false);
|
||||||
|
|
|
@ -87,6 +87,8 @@ private:
|
||||||
TEST_CASE(oppositeInnerConditionAnd);
|
TEST_CASE(oppositeInnerConditionAnd);
|
||||||
TEST_CASE(oppositeInnerConditionEmpty);
|
TEST_CASE(oppositeInnerConditionEmpty);
|
||||||
|
|
||||||
|
TEST_CASE(identicalInnerCondition);
|
||||||
|
|
||||||
TEST_CASE(identicalConditionAfterEarlyExit);
|
TEST_CASE(identicalConditionAfterEarlyExit);
|
||||||
|
|
||||||
TEST_CASE(clarifyCondition1); // if (a = b() < 0)
|
TEST_CASE(clarifyCondition1); // if (a = b() < 0)
|
||||||
|
@ -1876,6 +1878,14 @@ private:
|
||||||
check("void f1(const std::string v[10]) { if(v[0].size() > 42) if(v[1].empty()) {}} ");
|
check("void f1(const std::string v[10]) { if(v[0].size() > 42) if(v[1].empty()) {}} ");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void identicalInnerCondition() {
|
||||||
|
check("void f1(int a, int b) { if(a==b) if(a==b) {}}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Identical inner 'if' condition is always true.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f2(int a, int b) { if(a!=b) if(a!=b) {}}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:1]: (warning) Identical inner 'if' condition is always true.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void identicalConditionAfterEarlyExit() {
|
void identicalConditionAfterEarlyExit() {
|
||||||
check("void f(int x) {\n"
|
check("void f(int x) {\n"
|
||||||
|
|
Loading…
Reference in New Issue