Evaluate container size in program memory

This commit is contained in:
Paul 2020-08-10 20:08:49 -05:00
parent fec2914700
commit a5b0a1c9e2
4 changed files with 42 additions and 0 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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() {