Fix issue 8369: False negative: Condition 'condition' is always true (#1325)
* Fix issue 8369: False negative: Condition 'condition' is always true * Use simpleMatch * Add iterator header * Cleanup * Remove unused variable
This commit is contained in:
parent
576418e17d
commit
3947c23290
|
@ -92,6 +92,8 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <functional>
|
||||||
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -1829,6 +1831,22 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Forward known values in the else branch
|
||||||
|
if(Token::simpleMatch(end, "} else {")) {
|
||||||
|
std::list<ValueFlow::Value> knownValues;
|
||||||
|
std::copy_if(values.begin(), values.end(), std::back_inserter(knownValues), std::mem_fn(&ValueFlow::Value::isKnown));
|
||||||
|
valueFlowForward(end->tokAt(2),
|
||||||
|
end->linkAt(2),
|
||||||
|
var,
|
||||||
|
varid,
|
||||||
|
knownValues,
|
||||||
|
constValue,
|
||||||
|
subFunction,
|
||||||
|
tokenlist,
|
||||||
|
errorLogger,
|
||||||
|
settings);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove conditional values
|
// Remove conditional values
|
||||||
std::list<ValueFlow::Value>::iterator it;
|
std::list<ValueFlow::Value>::iterator it;
|
||||||
for (it = values.begin(); it != values.end();) {
|
for (it = values.begin(); it != values.end();) {
|
||||||
|
|
|
@ -2462,6 +2462,15 @@ private:
|
||||||
|
|
||||||
check("void f() { if(1) {} }");
|
check("void f() { if(1) {} }");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f(int i) {\n"
|
||||||
|
" bool b = false;\n"
|
||||||
|
" if (i == 0) b = true;\n"
|
||||||
|
" else if (!b && i == 1) {}\n"
|
||||||
|
" if (b)\n"
|
||||||
|
" {}\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (style) Condition '!b' is always true\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkInvalidTestForOverflow() {
|
void checkInvalidTestForOverflow() {
|
||||||
|
|
|
@ -80,6 +80,7 @@ private:
|
||||||
TEST_CASE(valueFlowAfterCondition);
|
TEST_CASE(valueFlowAfterCondition);
|
||||||
TEST_CASE(valueFlowForwardCompoundAssign);
|
TEST_CASE(valueFlowForwardCompoundAssign);
|
||||||
TEST_CASE(valueFlowForwardCorrelatedVariables);
|
TEST_CASE(valueFlowForwardCorrelatedVariables);
|
||||||
|
TEST_CASE(valueFlowForwardModifiedVariables);
|
||||||
TEST_CASE(valueFlowForwardFunction);
|
TEST_CASE(valueFlowForwardFunction);
|
||||||
TEST_CASE(valueFlowForwardTernary);
|
TEST_CASE(valueFlowForwardTernary);
|
||||||
TEST_CASE(valueFlowForwardLambda);
|
TEST_CASE(valueFlowForwardLambda);
|
||||||
|
@ -107,6 +108,24 @@ private:
|
||||||
TEST_CASE(valueFlowContainerSize);
|
TEST_CASE(valueFlowContainerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool testValueOfXKnown(const char code[], unsigned int linenr, int value) {
|
||||||
|
// Tokenize..
|
||||||
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
|
||||||
|
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||||
|
if (tok->str() == "x" && tok->linenr() == linenr) {
|
||||||
|
for(const ValueFlow::Value& val:tok->values()) {
|
||||||
|
if(val.isKnown() && val.intvalue == value)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool testValueOfX(const char code[], unsigned int linenr, int value) {
|
bool testValueOfX(const char code[], unsigned int linenr, int value) {
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
@ -2135,6 +2154,27 @@ private:
|
||||||
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
|
ASSERT_EQUALS(false, testValueOfX(code, 4U, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void valueFlowForwardModifiedVariables() {
|
||||||
|
const char *code;
|
||||||
|
|
||||||
|
code = "void f(bool b) {\n"
|
||||||
|
" int x = 0;\n"
|
||||||
|
" if (b) x = 1;\n"
|
||||||
|
" else b = x;\n"
|
||||||
|
"}";
|
||||||
|
ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 0));
|
||||||
|
|
||||||
|
code = "void f(int i) {\n"
|
||||||
|
" int x = 0;\n"
|
||||||
|
" if (i == 0) \n"
|
||||||
|
" x = 1;\n"
|
||||||
|
" else if (!x && i == 1) \n"
|
||||||
|
" int b = x;\n"
|
||||||
|
"}\n";
|
||||||
|
ASSERT_EQUALS(true, testValueOfXKnown(code, 5U, 0));
|
||||||
|
ASSERT_EQUALS(true, testValueOfXKnown(code, 6U, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void valueFlowForwardFunction() {
|
void valueFlowForwardFunction() {
|
||||||
const char *code;
|
const char *code;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue