Evaluate container size in program memory
This commit is contained in:
parent
fec2914700
commit
a5b0a1c9e2
|
@ -34,6 +34,15 @@ bool ProgramMemory::getTokValue(nonneg int varid, const Token** result) const
|
|||
return found;
|
||||
}
|
||||
|
||||
bool ProgramMemory::getContainerSizeValue(nonneg int varid, MathLib::bigint* result) const
|
||||
{
|
||||
const ProgramMemory::Map::const_iterator it = values.find(varid);
|
||||
const bool found = it != values.end() && it->second.isContainerSizeValue();
|
||||
if (found)
|
||||
*result = it->second.intvalue;
|
||||
return found;
|
||||
}
|
||||
|
||||
void ProgramMemory::setUnknown(nonneg int varid)
|
||||
{
|
||||
values[varid].valueType = ValueFlow::Value::ValueType::UNINIT;
|
||||
|
@ -534,6 +543,25 @@ void execute(const Token *expr,
|
|||
else
|
||||
*error = true;
|
||||
}
|
||||
else if (Token::Match(expr->tokAt(-3), "%var% . %name% (")) {
|
||||
const Token* containerTok = expr->tokAt(-3);
|
||||
if (astIsContainer(containerTok) && containerTok->varId() > 0) {
|
||||
Library::Container::Yield yield = containerTok->valueType()->container->getYield(expr->strAt(-1));
|
||||
if (yield == Library::Container::Yield::SIZE) {
|
||||
if (!programMemory->getContainerSizeValue(containerTok->varId(), result))
|
||||
*error = true;
|
||||
} else if (yield == Library::Container::Yield::EMPTY) {
|
||||
MathLib::bigint size = 0;
|
||||
if (!programMemory->getContainerSizeValue(containerTok->varId(), &size))
|
||||
*error = true;
|
||||
*result = (size == 0);
|
||||
} else {
|
||||
*error = true;
|
||||
}
|
||||
} else {
|
||||
*error = true;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
*error = true;
|
||||
|
|
|
@ -19,6 +19,8 @@ struct ProgramMemory {
|
|||
bool getIntValue(nonneg int varid, MathLib::bigint* result) const;
|
||||
void setIntValue(nonneg int varid, MathLib::bigint value);
|
||||
|
||||
bool getContainerSizeValue(nonneg int varid, MathLib::bigint* result) const;
|
||||
|
||||
void setUnknown(nonneg int varid);
|
||||
|
||||
bool getTokValue(nonneg int varid, const Token** result) const;
|
||||
|
|
|
@ -5773,6 +5773,8 @@ static bool isContainerSizeChanged(const Token *tok, int depth)
|
|||
return true;
|
||||
if (Token::Match(tok, "%name% %assign%|<<"))
|
||||
return true;
|
||||
if (Token::Match(tok, "%var% [") && tok->valueType()->container->stdAssociativeLike)
|
||||
return true;
|
||||
if (Token::Match(tok, "%name% . %name% (")) {
|
||||
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
|
||||
Library::Container::Yield yield = tok->valueType()->container->getYield(tok->strAt(2));
|
||||
|
|
|
@ -335,6 +335,16 @@ private:
|
|||
" x[0] = 0;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkNormal("void f(bool b) {\n"
|
||||
" std::vector<int> x;\n"
|
||||
" if (b)\n"
|
||||
" x.push_back(1);\n"
|
||||
" if (x.size() < 2)\n"
|
||||
" return;\n"
|
||||
" x[0] = 2;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void outOfBoundsIndexExpression() {
|
||||
|
|
Loading…
Reference in New Issue