Fix issue 10088: ValueFlow: Array size, wrong known value (#3204)

This commit is contained in:
Paul Fultz II 2021-04-09 00:43:54 -05:00 committed by GitHub
parent 1e9687aa8b
commit 255f273c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 7 deletions

View File

@ -4476,7 +4476,6 @@ struct ConditionHandler {
// start token of conditional code
Token* startTokens[] = {nullptr, nullptr};
bool inverted = false;
// if astParent is "!" we need to invert codeblock
{
const Token* tok2 = tok;
@ -4484,10 +4483,8 @@ struct ConditionHandler {
const Token* parent = tok2->astParent();
while (parent && parent->str() == "&&")
parent = parent->astParent();
if (parent && (parent->str() == "!" || Token::simpleMatch(parent, "== false"))) {
inverted = true;
if (parent && (parent->str() == "!" || Token::simpleMatch(parent, "== false")))
std::swap(thenValues, elseValues);
}
tok2 = parent;
}
}
@ -4569,8 +4566,25 @@ struct ConditionHandler {
std::mem_fn(&ValueFlow::Value::isPossible));
}
if (values.empty())
return;
if (dead_if || dead_else) {
if (!inverted && Token::Match(tok->astParent(), "&&|&")) {
const Token* parent = tok->astParent();
// Skip the not operator
while (Token::simpleMatch(parent, "!"))
parent = parent->astParent();
bool possible = false;
if (Token::Match(parent, "&&|%oror%")) {
std::string op = parent->str();
while (parent && parent->str() == op)
parent = parent->astParent();
if (Token::simpleMatch(parent, "!") || Token::simpleMatch(parent, "== false"))
possible = op == "||";
else
possible = op == "&&";
}
if (possible) {
values.remove_if(std::mem_fn(&ValueFlow::Value::isImpossible));
changeKnownToPossible(values);
} else {
@ -4578,8 +4592,9 @@ struct ConditionHandler {
valueFlowSetConditionToKnown(tok, values, false);
}
}
if (!values.empty())
forward(after, scope->bodyEnd, cond.vartok, values, tokenlist, settings);
if (values.empty())
return;
forward(after, scope->bodyEnd, cond.vartok, values, tokenlist, settings);
}
}
});

View File

@ -5063,6 +5063,22 @@ private:
ASSERT_EQUALS("",
isKnownContainerSizeValue(tokenValues(code, "a . front", ValueFlow::Value::ValueType::CONTAINER_SIZE), 10));
code = "int f(const std::vector<int>& x) {\n"
" if (!x.empty() && x[0] == 0)\n"
" return 2;\n"
" return x.front();\n"
"}\n";
ASSERT_EQUALS("",
isPossibleContainerSizeValue(tokenValues(code, "x . front", ValueFlow::Value::ValueType::CONTAINER_SIZE), 0));
code = "int f(const std::vector<int>& x) {\n"
" if (!(x.empty() || x[0] != 0))\n"
" return 2;\n"
" return x.front();\n"
"}\n";
ASSERT_EQUALS("",
isPossibleContainerSizeValue(tokenValues(code, "x . front", ValueFlow::Value::ValueType::CONTAINER_SIZE), 0));
code = "void f(std::string str) {\n"
" if (str == \"123\") {\n"
" bool x = (str == \"\");\n"