Skip to content

Commit 830ef47

Browse files
Fix #14660 Handle reverse conditions in isOppositeCond function (#8408)
1 parent ff9ac4b commit 830ef47

2 files changed

Lines changed: 52 additions & 12 deletions

File tree

lib/astutils.cpp

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,21 +1807,31 @@ bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Se
18071807
return commutativeEquals;
18081808
}
18091809

1810-
static bool isZeroBoundCond(const Token * const cond)
1810+
static bool isZeroBoundCond(const Token * const cond, bool reverse)
18111811
{
1812-
if (cond == nullptr)
1812+
if (cond == nullptr || !cond->isBinaryOp())
18131813
return false;
1814+
1815+
const Token* op = reverse ? cond->astOperand1() : cond->astOperand2();
1816+
if (!op->hasKnownIntValue())
1817+
return false;
1818+
18141819
// Assume unsigned
1815-
// TODO: Handle reverse conditions
1816-
const bool isZero = cond->astOperand2()->getValue(0);
1817-
if (cond->str() == "==" || cond->str() == ">=")
1820+
const bool isZero = op->getKnownIntValue() == 0;
1821+
std::string cmp = cond->str();
1822+
if (reverse) {
1823+
if (cmp[0] == '>')
1824+
cmp[0] = '<';
1825+
else if (cmp[0] == '<')
1826+
cmp[0] = '>';
1827+
}
1828+
1829+
if (cmp == "==" || cmp == ">=")
18181830
return isZero;
1819-
if (cond->str() == "<=")
1831+
if (cmp == "<=")
18201832
return true;
1821-
if (cond->str() == "<")
1833+
if (cmp == "<")
18221834
return !isZero;
1823-
if (cond->str() == ">")
1824-
return false;
18251835
return false;
18261836
}
18271837

@@ -1885,7 +1895,7 @@ bool isOppositeCond(bool isNot, const Token * const cond1, const Token * const c
18851895
if (isSameExpression(true, cond1->astOperand2(), cond2->astOperand2(), settings, pure, followVar, errors))
18861896
return isDifferentKnownValues(cond1->astOperand1(), cond2->astOperand1());
18871897
}
1888-
// TODO: Handle reverse conditions
1898+
18891899
if (Library::isContainerYield(cond1, Library::Container::Yield::EMPTY, "empty") &&
18901900
Library::isContainerYield(cond2->astOperand1(), Library::Container::Yield::SIZE, "size") &&
18911901
isSameExpression(true,
@@ -1895,7 +1905,19 @@ bool isOppositeCond(bool isNot, const Token * const cond1, const Token * const c
18951905
pure,
18961906
followVar,
18971907
errors)) {
1898-
return !isZeroBoundCond(cond2);
1908+
return !isZeroBoundCond(cond2, false);
1909+
}
1910+
1911+
if (Library::isContainerYield(cond1, Library::Container::Yield::EMPTY, "empty") &&
1912+
Library::isContainerYield(cond2->astOperand2(), Library::Container::Yield::SIZE, "size") &&
1913+
isSameExpression(true,
1914+
cond1->astOperand1()->astOperand1(),
1915+
cond2->astOperand2()->astOperand1()->astOperand1(),
1916+
settings,
1917+
pure,
1918+
followVar,
1919+
errors)) {
1920+
return !isZeroBoundCond(cond2, true);
18991921
}
19001922

19011923
if (Library::isContainerYield(cond2, Library::Container::Yield::EMPTY, "empty") &&
@@ -1907,7 +1929,19 @@ bool isOppositeCond(bool isNot, const Token * const cond1, const Token * const c
19071929
pure,
19081930
followVar,
19091931
errors)) {
1910-
return !isZeroBoundCond(cond1);
1932+
return !isZeroBoundCond(cond1, false);
1933+
}
1934+
1935+
if (Library::isContainerYield(cond2, Library::Container::Yield::EMPTY, "empty") &&
1936+
Library::isContainerYield(cond1->astOperand2(), Library::Container::Yield::SIZE, "size") &&
1937+
isSameExpression(true,
1938+
cond2->astOperand1()->astOperand1(),
1939+
cond1->astOperand2()->astOperand1()->astOperand1(),
1940+
settings,
1941+
pure,
1942+
followVar,
1943+
errors)) {
1944+
return !isZeroBoundCond(cond1, true);
19111945
}
19121946
}
19131947

test/testcondition.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,12 @@ class TestCondition : public TestFixture {
26742674
check("void f1(const std::string &s) { if(s.size() >= 0) if(s.empty()) {}} "); // CheckOther says: Unsigned expression 's.size()' can't be negative so it is unnecessary to test it. [unsignedPositive]
26752675
ASSERT_EQUALS("", errout_str());
26762676

2677+
check("void f1(const std::string &s) { if(42 < s.size()) if(s.empty()) {}}");
2678+
ASSERT_EQUALS("[test.cpp:1:39] -> [test.cpp:1:61]: (warning) Opposite inner 'if' condition leads to a dead code block. [oppositeInnerCondition]\n", errout_str());
2679+
2680+
check("void f1(const std::string &s) { if(s.empty()) if(42 < s.size()) {}}");
2681+
ASSERT_EQUALS("[test.cpp:1:43] -> [test.cpp:1:53]: (warning) Opposite inner 'if' condition leads to a dead code block. [oppositeInnerCondition]\n", errout_str());
2682+
26772683
// TODO: These are identical condition since size cannot be negative
26782684
check("void f1(const std::string &s) { if(s.size() <= 0) if(s.empty()) {}}");
26792685
ASSERT_EQUALS("", errout_str());

0 commit comments

Comments
 (0)