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);
|
ValueFlow::Value value(conditionToken, intval);
|
||||||
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
|
||||||
|
|
||||||
|
// possible value before condition
|
||||||
valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings);
|
valueFlowContainerReverse(scope.classDef, tok->varId(), value, settings);
|
||||||
|
|
||||||
|
// possible value after condition
|
||||||
const Token *after = scope.bodyEnd;
|
const Token *after = scope.bodyEnd;
|
||||||
if (Token::simpleMatch(after, "} else {"))
|
if (Token::simpleMatch(after, "} else {"))
|
||||||
after = after->linkAt(2);
|
after = after->linkAt(2);
|
||||||
valueFlowContainerForward(after, tok->varId(), value, settings);
|
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);
|
ASSERT_EQUALS(true, values.front().intvalue == 0 || values.back().intvalue == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isPossibleContainerSizeValue(const std::list<ValueFlow::Value> &values, MathLib::bigint i) {
|
static std::string isPossibleContainerSizeValue(const std::list<ValueFlow::Value> &values, MathLib::bigint i) {
|
||||||
return values.size() == 1 &&
|
if (values.size() != 1)
|
||||||
values.front().isContainerSizeValue() &&
|
return "values.size():" + std::to_string(values.size());
|
||||||
values.front().isPossible() &&
|
if (!values.front().isContainerSizeValue())
|
||||||
values.front().intvalue == i;
|
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() {
|
void valueFlowContainerSize() {
|
||||||
const char *code;
|
const char *code;
|
||||||
|
|
||||||
|
|
||||||
LOAD_LIB_2(settings.library, "std.cfg");
|
LOAD_LIB_2(settings.library, "std.cfg");
|
||||||
|
|
||||||
// valueFlowContainerReverse
|
// valueFlowContainerReverse
|
||||||
|
@ -3263,13 +3279,13 @@ private:
|
||||||
" ints.front();\n"
|
" ints.front();\n"
|
||||||
" if (ints.empty()) {}\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"
|
code = "void f(const std::list<int> &ints) {\n"
|
||||||
" ints.front();\n"
|
" ints.front();\n"
|
||||||
" if (ints.size()==0) {}\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"
|
code = "void f(std::list<int> ints) {\n"
|
||||||
" ints.front();\n"
|
" ints.front();\n"
|
||||||
|
@ -3282,14 +3298,21 @@ private:
|
||||||
" v[10] = 0;\n"
|
" v[10] = 0;\n"
|
||||||
" if (v.size() == 10) {}\n"
|
" if (v.size() == 10) {}\n"
|
||||||
"}";
|
"}";
|
||||||
ASSERT(isPossibleContainerSizeValue(tokenValues(code, "v ["), 10));
|
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "v ["), 10));
|
||||||
|
|
||||||
// valueFlowContainerForward
|
// valueFlowContainerForward
|
||||||
code = "void f(const std::list<int> &ints) {\n"
|
code = "void f(const std::list<int> &ints) {\n"
|
||||||
" if (ints.empty()) {}\n"
|
" if (ints.empty()) {}\n"
|
||||||
" ints.front();\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