Skip to content

Commit e22a740

Browse files
authored
Fix 11647: FN knownConditionTrueFalse with strings of same length (#4936)
* Fix 11647: FN knownConditionTrueFalse with strings of same length * Format * Remove extra size * Use simpleMatch
1 parent 47fdd1e commit e22a740

2 files changed

Lines changed: 83 additions & 1 deletion

File tree

lib/valueflow.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ static bool isComputableValue(const Token* parent, const ValueFlow::Value& value
503503
return false;
504504
if (value.isIteratorValue() && !Token::Match(parent, "+|-"))
505505
return false;
506-
if (value.isTokValue() && (!parent->isComparisonOp() || value.tokvalue->tokType() != Token::eString))
506+
if (value.isTokValue() && (!parent->isComparisonOp() || !Token::Match(value.tokvalue, "{|%str%")))
507507
return false;
508508
return true;
509509
}
@@ -886,6 +886,35 @@ static void setTokenValue(Token* tok,
886886
result.intvalue = calculate(parent->str(), intValue1(), intValue2(), &error);
887887
if (error)
888888
continue;
889+
} else if (value1.isTokValue() && value2.isTokValue() &&
890+
(astIsContainer(parent->astOperand1()) || astIsContainer(parent->astOperand2()))) {
891+
const Token* tok1 = value1.tokvalue;
892+
const Token* tok2 = value2.tokvalue;
893+
bool equal = false;
894+
if (Token::Match(tok1, "%str%") && Token::Match(tok2, "%str%")) {
895+
equal = tok1->str() == tok2->str();
896+
} else if (Token::simpleMatch(tok1, "{") && Token::simpleMatch(tok2, "{")) {
897+
std::vector<const Token*> args1 = getArguments(tok1);
898+
std::vector<const Token*> args2 = getArguments(tok2);
899+
if (args1.size() == args2.size()) {
900+
if (!std::all_of(args1.begin(), args1.end(), std::mem_fn(&Token::hasKnownIntValue)))
901+
continue;
902+
if (!std::all_of(args2.begin(), args2.end(), std::mem_fn(&Token::hasKnownIntValue)))
903+
continue;
904+
equal = std::equal(args1.begin(),
905+
args1.end(),
906+
args2.begin(),
907+
[&](const Token* atok, const Token* btok) {
908+
return atok->values().front().intvalue ==
909+
btok->values().front().intvalue;
910+
});
911+
} else {
912+
equal = false;
913+
}
914+
} else {
915+
continue;
916+
}
917+
result.intvalue = parent->str() == "==" ? equal : !equal;
889918
} else {
890919
continue;
891920
}

test/testvalueflow.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ class TestValueFlow : public TestFixture {
163163
TEST_CASE(valueFlowSmartPointer);
164164
TEST_CASE(valueFlowImpossibleMinMax);
165165
TEST_CASE(valueFlowImpossibleUnknownConstant);
166+
TEST_CASE(valueFlowContainerEqual);
166167
}
167168

168169
static bool isNotTokValue(const ValueFlow::Value &val) {
@@ -7889,6 +7890,58 @@ class TestValueFlow : public TestFixture {
78897890
"}\n";
78907891
ASSERT_EQUALS(true, testValueOfXImpossible(code, 4U, 0));
78917892
}
7893+
7894+
void valueFlowContainerEqual()
7895+
{
7896+
const char* code;
7897+
7898+
code = "bool f() {\n"
7899+
" std::string s = \"abc\";\n"
7900+
" bool x = (s == \"def\");\n"
7901+
" return x;\n"
7902+
"}\n";
7903+
ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0));
7904+
7905+
code = "bool f() {\n"
7906+
" std::string s = \"abc\";\n"
7907+
" bool x = (s != \"def\");\n"
7908+
" return x;\n"
7909+
"}\n";
7910+
ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 1));
7911+
7912+
code = "bool f() {\n"
7913+
" std::vector<int> v1 = {1, 2};\n"
7914+
" std::vector<int> v2 = {1, 2};\n"
7915+
" bool x = (v1 == v2);\n"
7916+
" return x;\n"
7917+
"}\n";
7918+
ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 1));
7919+
7920+
code = "bool f() {\n"
7921+
" std::vector<int> v1 = {1, 2};\n"
7922+
" std::vector<int> v2 = {1, 2};\n"
7923+
" bool x = (v1 != v2);\n"
7924+
" return x;\n"
7925+
"}\n";
7926+
ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 0));
7927+
7928+
code = "bool f(int i) {\n"
7929+
" std::vector<int> v1 = {i, i+1};\n"
7930+
" std::vector<int> v2 = {i};\n"
7931+
" bool x = (v1 == v2);\n"
7932+
" return x;\n"
7933+
"}\n";
7934+
ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 0));
7935+
7936+
code = "bool f(int i, int j) {\n"
7937+
" std::vector<int> v1 = {i, i};\n"
7938+
" std::vector<int> v2 = {i, j};\n"
7939+
" bool x = (v1 == v2);\n"
7940+
" return x;\n"
7941+
"}\n";
7942+
ASSERT_EQUALS(false, testValueOfX(code, 5U, 1));
7943+
ASSERT_EQUALS(false, testValueOfX(code, 5U, 0));
7944+
}
78927945
};
78937946

78947947
REGISTER_TEST(TestValueFlow)

0 commit comments

Comments
 (0)