valueFlowContainerSize: forward analysis inside conditional code
This commit is contained in:
parent
4a502a7f6b
commit
10461e5429
|
@ -3499,11 +3499,26 @@ static void valueFlowContainerSize(TokenList * /*tokenlist*/, SymbolDatabase* sy
|
|||
|
||||
ValueFlow::Value value(conditionToken, intval);
|
||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||
|
||||
// possible value before condition
|
||||
valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings);
|
||||
|
||||
// possible value after condition
|
||||
const Token *after = scope.bodyEnd;
|
||||
if (Token::simpleMatch(after, "} else {"))
|
||||
after = after->linkAt(2);
|
||||
valueFlowContainerForward(after, tok->varId(), value, settings);
|
||||
|
||||
// known value in conditional code
|
||||
if (conditionToken->str() == "==" || conditionToken->str() == "(") {
|
||||
const Token *parent = conditionToken;
|
||||
while (parent && parent->str() != "!")
|
||||
parent = parent->astParent();
|
||||
if (!parent) {
|
||||
value.setKnown();
|
||||
valueFlowContainerForward(scope.bodyStart, tok->varId(), value, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3245,17 +3245,33 @@ private:
|
|||
ASSERT_EQUALS(true, values.front().intvalue == 0 || values.back().intvalue == 0);
|
||||
}
|
||||
|
||||
static bool isPossibleContainerSizeValue(const std::list<ValueFlow::Value> &values, MathLib::bigint i) {
|
||||
return values.size() == 1 &&
|
||||
values.front().isContainerSizeValue() &&
|
||||
values.front().isPossible() &&
|
||||
values.front().intvalue == i;
|
||||
static std::string isPossibleContainerSizeValue(const std::list<ValueFlow::Value> &values, MathLib::bigint i) {
|
||||
if (values.size() != 1)
|
||||
return "values.size():" + std::to_string(values.size());
|
||||
if (!values.front().isContainerSizeValue())
|
||||
return "ContainerSizeValue";
|
||||
if (!values.front().isPossible())
|
||||
return "Possible";
|
||||
if (values.front().intvalue != i)
|
||||
return "intvalue:" + std::to_string(values.front().intvalue);
|
||||
return "";
|
||||
}
|
||||
|
||||
static std::string isKnownContainerSizeValue(const std::list<ValueFlow::Value> &values, MathLib::bigint i) {
|
||||
if (values.size() != 1)
|
||||
return "values.size():" + std::to_string(values.size());
|
||||
if (!values.front().isContainerSizeValue())
|
||||
return "ContainerSizeValue";
|
||||
if (!values.front().isKnown())
|
||||
return "Known";
|
||||
if (values.front().intvalue != i)
|
||||
return "intvalue:" + std::to_string(values.front().intvalue);
|
||||
return "";
|
||||
}
|
||||
|
||||
void valueFlowContainerSize() {
|
||||
const char *code;
|
||||
|
||||
|
||||
LOAD_LIB_2(settings.library, "std.cfg");
|
||||
|
||||
// valueFlowContainerReverse
|
||||
|
@ -3263,13 +3279,13 @@ private:
|
|||
" ints.front();\n"
|
||||
" if (ints.empty()) {}\n"
|
||||
"}";
|
||||
ASSERT(isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
|
||||
code = "void f(const std::list<int> &ints) {\n"
|
||||
" ints.front();\n"
|
||||
" if (ints.size()==0) {}\n"
|
||||
"}";
|
||||
ASSERT(isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
|
||||
code = "void f(std::list<int> ints) {\n"
|
||||
" ints.front();\n"
|
||||
|
@ -3282,14 +3298,21 @@ private:
|
|||
" v[10] = 0;\n"
|
||||
" if (v.size() == 10) {}\n"
|
||||
"}";
|
||||
ASSERT(isPossibleContainerSizeValue(tokenValues(code, "v ["), 10));
|
||||
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "v ["), 10));
|
||||
|
||||
// valueFlowContainerForward
|
||||
code = "void f(const std::list<int> &ints) {\n"
|
||||
" if (ints.empty()) {}\n"
|
||||
" ints.front();\n"
|
||||
"}";
|
||||
ASSERT(isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
|
||||
code = "void f(const std::list<int> &ints) {\n"
|
||||
" if (ints.empty()) {\n"
|
||||
" ints.front();\n"
|
||||
" }\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "ints . front"), 0));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue