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:
parent
dd62da02e4
commit
5636497c0b
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue