Fixed #8863 (false positive: (warning) Accessing an item in container 's'. Either the condition 's.empty()' is redundant or 's' can be empty.)

This commit is contained in:
Daniel Marjamäki 2019-01-06 12:21:47 +01:00
parent dd62da02e4
commit 5636497c0b
2 changed files with 28 additions and 7 deletions

View File

@ -376,6 +376,19 @@ static void combineValueProperties(const ValueFlow::Value &value1, const ValueFl
result->errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath; result->errorPath = (value1.errorPath.empty() ? value2 : value1).errorPath;
} }
static const Token *getCastTypeStartToken(const Token *parent)
{
// TODO: This might be a generic utility function?
if (!parent || parent->str() != "(")
return nullptr;
if (!parent->astOperand2() && Token::Match(parent,"( %name%"))
return parent->next();
if (parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
return parent->astOperand1()->tokAt(2);
return nullptr;
}
/** Set token value for cast */ /** Set token value for cast */
static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings); static void setTokenValueCast(Token *parent, const ValueType &valueType, const ValueFlow::Value &value, const Settings *settings);
@ -446,13 +459,8 @@ static void setTokenValue(Token* tok, const ValueFlow::Value &value, const Setti
} }
// cast.. // cast..
if (parent->str() == "(" && !parent->astOperand2() && Token::Match(parent,"( %name%")) { if (const Token *castType = getCastTypeStartToken(parent)) {
const ValueType &valueType = ValueType::parseDecl(parent->next(), settings); const ValueType &valueType = ValueType::parseDecl(castType, settings);
setTokenValueCast(parent, valueType, value, settings);
}
else if (parent->str() == "(" && parent->astOperand2() && Token::Match(parent->astOperand1(), "const_cast|dynamic_cast|reinterpret_cast|static_cast <")) {
const ValueType &valueType = ValueType::parseDecl(parent->astOperand1()->tokAt(2), settings);
setTokenValueCast(parent, valueType, value, settings); setTokenValueCast(parent, valueType, value, settings);
} }
@ -4644,6 +4652,12 @@ static void valueFlowContainerAfterCondition(TokenList *tokenlist,
// TODO: Handle .size() // TODO: Handle .size()
if (!isContainerEmpty(vartok)) if (!isContainerEmpty(vartok))
return cond; return cond;
const Token *parent = tok->astParent();
while (parent) {
if (Token::Match(parent, "%comp%|!"))
return cond;
parent = parent->astParent();
}
ValueFlow::Value value(tok, 0LL); ValueFlow::Value value(tok, 0LL);
value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; value.valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
cond.true_values.emplace_back(value); cond.true_values.emplace_back(value);

View File

@ -3629,6 +3629,13 @@ private:
LOAD_LIB_2(settings.library, "std.cfg"); LOAD_LIB_2(settings.library, "std.cfg");
// condition
code = "void f(const std::list<int> &ints) {\n"
" if (!static_cast<bool>(ints.empty()))\n"
" ints.front();\n"
"}";
ASSERT(tokenValues(code, "ints . front").empty());
// valueFlowContainerReverse // valueFlowContainerReverse
code = "void f(const std::list<int> &ints) {\n" code = "void f(const std::list<int> &ints) {\n"
" ints.front();\n" // <- container can be empty " ints.front();\n" // <- container can be empty