Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions lib/programmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ void ProgramMemory::setValue(const Token* expr, const ValueFlow::Value& value) {
if (subexpr)
(*mValues)[subexpr] = std::move(subvalue);
}

const ValueFlow::Value* ProgramMemory::getValue(nonneg int exprid, bool impossible) const
{
const auto it = utils::as_const(*mValues).find(exprid);
const auto it = find(exprid);
const bool found = it != mValues->cend() && (impossible || !it->second.isImpossible());
if (found)
return &it->second;
Expand Down Expand Up @@ -154,18 +155,28 @@ void ProgramMemory::setUnknown(const Token* expr) {
(*mValues)[expr].valueType = ValueFlow::Value::ValueType::UNINIT;
}

bool ProgramMemory::hasValue(nonneg int exprid)
bool ProgramMemory::hasValue(nonneg int exprid) const
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detecting this is tracked in https://trac.cppcheck.net/ticket/12162.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually. With my changes this might have been caught now.

{
return mValues->find(exprid) != mValues->end();
const auto it = find(exprid);
return it != mValues->cend();
}

const ValueFlow::Value& ProgramMemory::at(nonneg int exprid) const {
return mValues->at(exprid);
const auto it = find(exprid);
if (it == mValues->cend()) {
throw std::out_of_range("ProgramMemory::at");
}
return it->second;
}

ValueFlow::Value& ProgramMemory::at(nonneg int exprid) {
copyOnWrite();

return mValues->at(exprid);
const auto it = find(exprid);
if (it == mValues->end()) {
throw std::out_of_range("ProgramMemory::at");
}
return it->second;
}

void ProgramMemory::erase_if(const std::function<bool(const ExprIdToken&)>& pred)
Expand Down Expand Up @@ -225,6 +236,21 @@ void ProgramMemory::copyOnWrite()
mValues = std::make_shared<Map>(*mValues);
}

ProgramMemory::Map::const_iterator ProgramMemory::find(nonneg int exprid) const
{
const auto& cvalues = utils::as_const(*mValues);
return std::find_if(cvalues.cbegin(), cvalues.cend(), [&exprid](const Map::value_type& entry) {
return entry.first.getExpressionId() == exprid;
});
}

ProgramMemory::Map::iterator ProgramMemory::find(nonneg int exprid)
{
return std::find_if(mValues->begin(), mValues->end(), [&exprid](const Map::value_type& entry) {
return entry.first.getExpressionId() == exprid;
});
}

static ValueFlow::Value execute(const Token* expr, ProgramMemory& pm, const Settings& settings);

static bool evaluateCondition(MathLib::bigint r, const Token* condition, ProgramMemory& pm, const Settings& settings)
Expand Down Expand Up @@ -395,7 +421,7 @@ static void fillProgramMemoryFromAssignments(ProgramMemory& pm, const Token* tok
bool setvar = false;
const Token* vartok = tok2->astOperand1();
for (const auto& p:vars) {
if (p.first != vartok->exprId())
if (p.first.getExpressionId() != vartok->exprId())
continue;
if (vartok == tok)
continue;
Expand Down
9 changes: 3 additions & 6 deletions lib/programmemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,9 @@ struct ExprIdToken {
const Token* tok = nullptr;
nonneg int exprid = 0;

ExprIdToken() = default;
// cppcheck-suppress noExplicitConstructor
// NOLINTNEXTLINE(google-explicit-constructor)
ExprIdToken(const Token* tok);
// TODO: Make this constructor only available from ProgramMemory
// cppcheck-suppress noExplicitConstructor
// NOLINTNEXTLINE(google-explicit-constructor)
ExprIdToken(nonneg int exprid) : exprid(exprid) {}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was only used for lookups/comparisons.


nonneg int getExpressionId() const;

Expand Down Expand Up @@ -117,7 +112,7 @@ struct CPPCHECKLIB ProgramMemory {
void setUnknown(const Token* expr);

bool getTokValue(nonneg int exprid, const Token*& result) const;
bool hasValue(nonneg int exprid);
bool hasValue(nonneg int exprid) const;

const ValueFlow::Value& at(nonneg int exprid) const;
ValueFlow::Value& at(nonneg int exprid);
Expand Down Expand Up @@ -150,6 +145,8 @@ struct CPPCHECKLIB ProgramMemory {

private:
void copyOnWrite();
Map::const_iterator find(nonneg int exprid) const;
Map::iterator find(nonneg int exprid);

std::shared_ptr<Map> mValues;
};
Expand Down
19 changes: 19 additions & 0 deletions test/testprogrammemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class TestProgramMemory : public TestFixture {
private:
void run() override {
TEST_CASE(copyOnWrite);
TEST_CASE(hasValue);
TEST_CASE(getValue);
TEST_CASE(at);
}

void copyOnWrite() const {
Expand Down Expand Up @@ -79,6 +82,22 @@ class TestProgramMemory : public TestFixture {
ASSERT(v);
ASSERT_EQUALS(41, v->intvalue);
}

void hasValue() const {
ProgramMemory pm;
ASSERT(!pm.hasValue(123));
}

void getValue() const {
ProgramMemory pm;
ASSERT(!pm.getValue(123));
}

void at() const {
ProgramMemory pm;
ASSERT_THROW_EQUALS_2(pm.at(123), std::out_of_range, "ProgramMemory::at");
ASSERT_THROW_EQUALS_2(utils::as_const(pm).at(123), std::out_of_range, "ProgramMemory::at");
}
};

REGISTER_TEST(TestProgramMemory)
Loading