Skip to content

Commit b0eed57

Browse files
Report overlappingInnerCondition errors (#8448)
Signed-off-by: Francois Berder <fberder@outlook.fr>
1 parent 7f43d0b commit b0eed57

3 files changed

Lines changed: 39 additions & 2 deletions

File tree

lib/checkcondition.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ void CheckCondition::oppositeElseIfConditionError(const Token *ifCond, const Tok
602602

603603
//---------------------------------------------------------------------------
604604
// - Opposite inner conditions => always false
605-
// - (TODO) Same/Overlapping inner condition => always true
605+
// - Same/Overlapping inner condition => always true
606606
// - same condition after early exit => always false
607607
//---------------------------------------------------------------------------
608608

@@ -759,6 +759,8 @@ void CheckCondition::multiCondition2()
759759
oppositeInnerConditionError(firstCondition, cond2, errorPath);
760760
} else if (!isReturnVar && isSameExpression(true, firstCondition, cond2, *mSettings, true, true, &errorPath)) {
761761
identicalInnerConditionError(firstCondition, cond2, errorPath);
762+
} else if (!isReturnVar && isOverlappingCond(cond2, firstCondition, true)) {
763+
overlappingInnerConditionError(firstCondition, cond2, errorPath);
762764
}
763765
}
764766
return ChildrenToVisit::none;
@@ -879,6 +881,21 @@ void CheckCondition::oppositeInnerConditionError(const Token *tok1, const Token*
879881
reportError(std::move(errorPath), Severity::warning, "oppositeInnerCondition", msg, CWE398, Certainty::normal);
880882
}
881883

884+
void CheckCondition::overlappingInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath)
885+
{
886+
if (diag(tok1, tok2))
887+
return;
888+
const std::string s1(tok1 ? tok1->expressionString() : "x");
889+
const std::string s2(tok2 ? tok2->expressionString() : "x");
890+
const std::string innerSmt = innerSmtString(tok2);
891+
errorPath.emplace_back(tok1, "outer condition: " + s1);
892+
errorPath.emplace_back(tok2, "overlapping inner condition: " + s2);
893+
894+
const std::string msg("Overlapping inner '" + innerSmt + "' condition is always true.\n"
895+
"Overlapping inner '" + innerSmt + "' condition is always true (outer condition is '" + s1 + "' and inner condition is '" + s2 + "').");
896+
reportError(std::move(errorPath), Severity::warning, "overlappingInnerCondition", msg, CWE398, Certainty::normal);
897+
}
898+
882899
void CheckCondition::identicalInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath)
883900
{
884901
if (diag(tok1, tok2))
@@ -2106,6 +2123,7 @@ void CheckCondition::getErrorMessages(ErrorLogger *errorLogger, const Settings *
21062123
c.comparisonError(nullptr, "&", 6, "==", 1, false);
21072124
c.duplicateConditionError(nullptr, nullptr, ErrorPath{});
21082125
c.overlappingElseIfConditionError(nullptr, 1);
2126+
c.overlappingInnerConditionError(nullptr, nullptr, ErrorPath());
21092127
c.mismatchingBitAndError(nullptr, 0xf0, nullptr, 1);
21102128
c.oppositeInnerConditionError(nullptr, nullptr, ErrorPath{});
21112129
c.identicalInnerConditionError(nullptr, nullptr, ErrorPath{});

lib/checkcondition.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class CPPCHECKLIB CheckCondition : public Check {
8484
/**
8585
* multiconditions #2
8686
* - Opposite inner conditions => always false
87-
* - (TODO) Same/Overlapping inner condition => always true
87+
* - Same/Overlapping inner condition => always true
8888
* - same condition after early exit => always false
8989
**/
9090
void multiCondition2();
@@ -130,6 +130,7 @@ class CPPCHECKLIB CheckCondition : public Check {
130130
bool result);
131131
void duplicateConditionError(const Token *tok1, const Token *tok2, ErrorPath errorPath);
132132
void overlappingElseIfConditionError(const Token *tok, nonneg int line1);
133+
void overlappingInnerConditionError(const Token *tok1, const Token *tok2, ErrorPath errorPath);
133134
void oppositeElseIfConditionError(const Token *ifCond, const Token *elseIfCond, ErrorPath errorPath);
134135

135136
void oppositeInnerConditionError(const Token *tok1, const Token* tok2, ErrorPath errorPath);

test/testcondition.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class TestCondition : public TestFixture {
9494
TEST_CASE(identicalConditionAfterEarlyExit);
9595
TEST_CASE(innerConditionModified);
9696

97+
TEST_CASE(overlappingInnerCondition);
98+
9799
TEST_CASE(clarifyCondition1); // if (a = b() < 0)
98100
TEST_CASE(clarifyCondition2); // if (a & b == c)
99101
TEST_CASE(clarifyCondition3); // if (! a & b)
@@ -3022,6 +3024,22 @@ class TestCondition : public TestFixture {
30223024
ASSERT_EQUALS("", errout_str());
30233025
}
30243026

3027+
void overlappingInnerCondition() {
3028+
check("void f(int x) {\n"
3029+
" if (x == 1) {\n"
3030+
" if (x & 7) {}\n"
3031+
" }\n"
3032+
"}");
3033+
ASSERT_EQUALS("[test.cpp:2:11] -> [test.cpp:3:15]: (warning) Overlapping inner 'if' condition is always true. [overlappingInnerCondition]\n", errout_str());
3034+
3035+
check("void f(int x) {\n"
3036+
" if (x & 7) {\n"
3037+
" if (x == 1) {}\n"
3038+
" }\n"
3039+
"}");
3040+
ASSERT_EQUALS("", errout_str());
3041+
}
3042+
30253043
// clarify conditions with = and comparison
30263044
void clarifyCondition1() {
30273045
check("void f() {\n"

0 commit comments

Comments
 (0)