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 <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
@ -1829,6 +1831,22 @@ static bool valueFlowForward(Token * const startToken,
|
|||
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
|
||||
std::list<ValueFlow::Value>::iterator it;
|
||||
for (it = values.begin(); it != values.end();) {
|
||||
|
|
|
@ -2462,6 +2462,15 @@ private:
|
|||
|
||||
check("void f() { if(1) {} }");
|
||||
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() {
|
||||
|
|
|
@ -80,6 +80,7 @@ private:
|
|||
TEST_CASE(valueFlowAfterCondition);
|
||||
TEST_CASE(valueFlowForwardCompoundAssign);
|
||||
TEST_CASE(valueFlowForwardCorrelatedVariables);
|
||||
TEST_CASE(valueFlowForwardModifiedVariables);
|
||||
TEST_CASE(valueFlowForwardFunction);
|
||||
TEST_CASE(valueFlowForwardTernary);
|
||||
TEST_CASE(valueFlowForwardLambda);
|
||||
|
@ -107,6 +108,24 @@ private:
|
|||
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) {
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
|
@ -2135,6 +2154,27 @@ private:
|
|||
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() {
|
||||
const char *code;
|
||||
|
||||
|
|
Loading…
Reference in New Issue