Fix issue 9320: False positive knownConditionTrueFalse related to truncation (#2144)

This commit is contained in:
Paul Fultz II 2019-09-05 08:15:58 -05:00 committed by Daniel Marjamäki
parent e7ea748805
commit e657cf4073
3 changed files with 54 additions and 11 deletions

View File

@ -445,6 +445,36 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2,
errors->push_back(item);
}
template<class Predicate, class F>
static void findTokenValue(const Token* const tok, Predicate pred, F f)
{
auto x = std::find_if(tok->values().begin(), tok->values().end(), pred);
if (x != tok->values().end())
f(*x);
}
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2)
{
bool result = false;
findTokenValue(tok1, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v1) {
findTokenValue(tok2, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v2) {
result = v1.equalValue(v2);
});
});
return result;
}
bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2)
{
bool result = false;
findTokenValue(tok1, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v1) {
findTokenValue(tok2, std::mem_fn(&ValueFlow::Value::isKnown), [&](const ValueFlow::Value& v2) {
result = !v1.equalValue(v2);
});
});
return result;
}
bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors)
{
if (tok1 == nullptr && tok2 == nullptr)
@ -464,6 +494,8 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
if (Token::simpleMatch(tok2, "!") && Token::simpleMatch(tok2->astOperand1(), "!") && !Token::simpleMatch(tok2->astParent(), "=")) {
return isSameExpression(cpp, macro, tok1, tok2->astOperand1()->astOperand1(), library, pure, followVar, errors);
}
if (tok1->str() != tok2->str() && isDifferentKnownValues(tok1, tok2))
return false;
// Follow variable
if (followVar && tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) {
const Token * varTok1 = followVariableExpression(tok1, cpp, tok2);
@ -596,16 +628,6 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
return commutativeEquals;
}
bool isEqualKnownValue(const Token * const tok1, const Token * const tok2)
{
return tok1->hasKnownValue() && tok2->hasKnownValue() && tok1->values() == tok2->values();
}
bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2)
{
return tok1->hasKnownValue() && tok2->hasKnownValue() && tok1->values() != tok2->values();
}
static bool isZeroBoundCond(const Token * const cond)
{
if (cond == nullptr)

View File

@ -60,7 +60,7 @@ namespace ValueFlow {
{}
Value(const Token *c, long long val);
bool operator==(const Value &rhs) const {
bool equalValue(const ValueFlow::Value& rhs) const {
if (valueType != rhs.valueType)
return false;
switch (valueType) {
@ -95,6 +95,12 @@ namespace ValueFlow {
if (tokvalue != rhs.tokvalue)
return false;
}
return true;
}
bool operator==(const Value &rhs) const {
if (!equalValue(rhs))
return false;
return varvalue == rhs.varvalue &&
condition == rhs.condition &&
@ -105,6 +111,10 @@ namespace ValueFlow {
valueKind == rhs.valueKind;
}
bool operator!=(const Value &rhs) const {
return !(*this == rhs);
}
std::string infoString() const;
enum ValueType { INT, TOK, FLOAT, MOVED, UNINIT, CONTAINER_SIZE, LIFETIME, BUFFER_SIZE } valueType;

View File

@ -137,6 +137,7 @@ private:
TEST_CASE(duplicateExpression6); // ticket #4639
TEST_CASE(duplicateExpression7);
TEST_CASE(duplicateExpression8);
TEST_CASE(duplicateExpression9); // #9320
TEST_CASE(duplicateExpressionLoop);
TEST_CASE(duplicateValueTernary);
TEST_CASE(duplicateExpressionTernary); // #6391
@ -4584,6 +4585,16 @@ private:
ASSERT_EQUALS("", errout.str());
}
void duplicateExpression9() {
// #9320
check("void f() {\n"
" uint16_t x = 1000;\n"
" uint8_t y = x;\n"
" if (x != y) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void duplicateExpressionLoop() {
check("void f() {\n"
" int a = 1;\n"