@@ -88,6 +88,21 @@ const ValueFlow::Value* ProgramMemory::getValue(nonneg int exprid, bool impossib
88
88
return nullptr ;
89
89
}
90
90
91
+ ValueFlow::Value* ProgramMemory::getValue (nonneg int exprid)
92
+ {
93
+ if (mValues ->empty ())
94
+ return nullptr ;
95
+
96
+ // TODO: avoid copy if no value is found
97
+ copyOnWrite ();
98
+
99
+ const auto it = find (exprid);
100
+ const bool found = it != mValues ->cend ();
101
+ if (found)
102
+ return &it->second ;
103
+ return nullptr ;
104
+ }
105
+
91
106
// cppcheck-suppress unusedFunction
92
107
bool ProgramMemory::getIntValue (nonneg int exprid, MathLib::bigint& result) const
93
108
{
@@ -164,24 +179,6 @@ bool ProgramMemory::hasValue(nonneg int exprid) const
164
179
return it != mValues ->cend ();
165
180
}
166
181
167
- const ValueFlow::Value& ProgramMemory::at (nonneg int exprid) const {
168
- const auto it = find (exprid);
169
- if (it == mValues ->cend ()) {
170
- throw std::out_of_range (" ProgramMemory::at" );
171
- }
172
- return it->second ;
173
- }
174
-
175
- ValueFlow::Value& ProgramMemory::at (nonneg int exprid) {
176
- copyOnWrite ();
177
-
178
- const auto it = find (exprid);
179
- if (it == mValues ->end ()) {
180
- throw std::out_of_range (" ProgramMemory::at" );
181
- }
182
- return it->second ;
183
- }
184
-
185
182
void ProgramMemory::erase_if (const std::function<bool (const ExprIdToken&)>& pred)
186
183
{
187
184
if (mValues ->empty ())
@@ -245,6 +242,7 @@ ProgramMemory::Map::const_iterator ProgramMemory::find(nonneg int exprid) const
245
242
return cvalues.find (ExprIdToken::create (exprid));
246
243
}
247
244
245
+ // need to call copyOnWrite() before calling this
248
246
ProgramMemory::Map::iterator ProgramMemory::find (nonneg int exprid)
249
247
{
250
248
return mValues ->find (ExprIdToken::create (exprid));
@@ -1342,10 +1340,9 @@ namespace {
1342
1340
1343
1341
ValueFlow::Value executeMultiCondition (bool b, const Token* expr)
1344
1342
{
1345
- if (pm->hasValue (expr->exprId ())) {
1346
- const ValueFlow::Value& v = utils::as_const (*pm).at (expr->exprId ());
1347
- if (v.isIntValue ())
1348
- return v;
1343
+ if (const ValueFlow::Value* v = utils::as_const (*pm).getValue (expr->exprId ())) {
1344
+ if (v->isIntValue ())
1345
+ return *v;
1349
1346
}
1350
1347
1351
1348
// Evaluate recursively if there are no exprids
@@ -1474,18 +1471,18 @@ namespace {
1474
1471
if (rhs.isUninitValue ())
1475
1472
return unknown ();
1476
1473
if (expr->str () != " =" ) {
1477
- if (!pm->hasValue (expr->astOperand1 ()->exprId ()))
1474
+ ValueFlow::Value* lhs = pm->getValue (expr->astOperand1 ()->exprId ());
1475
+ if (!lhs)
1478
1476
return unknown ();
1479
- ValueFlow::Value& lhs = pm->at (expr->astOperand1 ()->exprId ());
1480
- rhs = evaluate (removeAssign (expr->str ()), lhs, rhs);
1481
- if (lhs.isIntValue ())
1482
- ValueFlow::Value::visitValue (rhs, std::bind (assign{}, std::ref (lhs.intvalue ), std::placeholders::_1));
1483
- else if (lhs.isFloatValue ())
1477
+ rhs = evaluate (removeAssign (expr->str ()), *lhs, rhs);
1478
+ if (lhs->isIntValue ())
1479
+ ValueFlow::Value::visitValue (rhs, std::bind (assign{}, std::ref (lhs->intvalue ), std::placeholders::_1));
1480
+ else if (lhs->isFloatValue ())
1484
1481
ValueFlow::Value::visitValue (rhs,
1485
- std::bind (assign{}, std::ref (lhs. floatValue ), std::placeholders::_1));
1482
+ std::bind (assign{}, std::ref (lhs-> floatValue ), std::placeholders::_1));
1486
1483
else
1487
1484
return unknown ();
1488
- return lhs;
1485
+ return * lhs;
1489
1486
}
1490
1487
pm->setValue (expr->astOperand1 (), rhs);
1491
1488
return rhs;
@@ -1497,20 +1494,20 @@ namespace {
1497
1494
execute (expr->astOperand1 ());
1498
1495
return execute (expr->astOperand2 ());
1499
1496
} else if (expr->tokType () == Token::eIncDecOp && expr->astOperand1 () && expr->astOperand1 ()->exprId () != 0 ) {
1500
- if (!pm->hasValue (expr->astOperand1 ()->exprId ()))
1497
+ ValueFlow::Value* lhs = pm->getValue (expr->astOperand1 ()->exprId ());
1498
+ if (!lhs)
1501
1499
return ValueFlow::Value::unknown ();
1502
- ValueFlow::Value& lhs = pm->at (expr->astOperand1 ()->exprId ());
1503
- if (!lhs.isIntValue ())
1500
+ if (!lhs->isIntValue ())
1504
1501
return unknown ();
1505
1502
// overflow
1506
- if (!lhs. isImpossible () && lhs. intvalue == 0 && expr->str () == " --" && astIsUnsigned (expr->astOperand1 ()))
1503
+ if (!lhs-> isImpossible () && lhs-> intvalue == 0 && expr->str () == " --" && astIsUnsigned (expr->astOperand1 ()))
1507
1504
return unknown ();
1508
1505
1509
1506
if (expr->str () == " ++" )
1510
- lhs. intvalue ++;
1507
+ lhs-> intvalue ++;
1511
1508
else
1512
- lhs. intvalue --;
1513
- return lhs;
1509
+ lhs-> intvalue --;
1510
+ return * lhs;
1514
1511
} else if (expr->str () == " [" && expr->astOperand1 () && expr->astOperand2 ()) {
1515
1512
const Token* tokvalue = nullptr ;
1516
1513
if (!pm->getTokValue (expr->astOperand1 ()->exprId (), tokvalue)) {
@@ -1601,13 +1598,16 @@ namespace {
1601
1598
}
1602
1599
return execute (expr->astOperand1 ());
1603
1600
}
1604
- if (expr->exprId () > 0 && pm->hasValue (expr->exprId ())) {
1605
- ValueFlow::Value result = utils::as_const (*pm).at (expr->exprId ());
1606
- if (result.isImpossible () && result.isIntValue () && result.intvalue == 0 && isUsedAsBool (expr, settings)) {
1607
- result.intvalue = !result.intvalue ;
1608
- result.setKnown ();
1601
+ if (expr->exprId () > 0 ) {
1602
+ if (const ValueFlow::Value* v = utils::as_const (*pm).getValue (expr->exprId ()))
1603
+ {
1604
+ ValueFlow::Value result = *v;
1605
+ if (result.isImpossible () && result.isIntValue () && result.intvalue == 0 && isUsedAsBool (expr, settings)) {
1606
+ result.intvalue = !result.intvalue ;
1607
+ result.setKnown ();
1608
+ }
1609
+ return result;
1609
1610
}
1610
- return result;
1611
1611
}
1612
1612
1613
1613
if (Token::Match (expr->previous (), " >|%name% {|(" )) {
@@ -1657,14 +1657,16 @@ namespace {
1657
1657
}
1658
1658
// Check if function modifies argument
1659
1659
visitAstNodes (expr->astOperand2 (), [&](const Token* child) {
1660
- if (child->exprId () > 0 && pm->hasValue (child->exprId ())) {
1661
- ValueFlow::Value& v = pm->at (child->exprId ());
1662
- if (v.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) {
1663
- if (ValueFlow::isContainerSizeChanged (child, v.indirect , settings))
1664
- v = unknown ();
1665
- } else if (v.valueType != ValueFlow::Value::ValueType::UNINIT) {
1666
- if (isVariableChanged (child, v.indirect , settings))
1667
- v = unknown ();
1660
+ if (child->exprId () > 0 ) {
1661
+ if (ValueFlow::Value* v = pm->getValue (child->exprId ()))
1662
+ {
1663
+ if (v->valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) {
1664
+ if (ValueFlow::isContainerSizeChanged (child, v->indirect , settings))
1665
+ *v = unknown ();
1666
+ } else if (v->valueType != ValueFlow::Value::ValueType::UNINIT) {
1667
+ if (isVariableChanged (child, v->indirect , settings))
1668
+ *v = unknown ();
1669
+ }
1668
1670
}
1669
1671
}
1670
1672
return ChildrenToVisit::op1_and_op2;
@@ -1716,22 +1718,27 @@ namespace {
1716
1718
return v;
1717
1719
if (!expr)
1718
1720
return v;
1719
- if (expr->exprId () > 0 && pm->hasValue (expr->exprId ())) {
1720
- if (updateValue (v, utils::as_const (*pm).at (expr->exprId ())))
1721
- return v;
1721
+ if (expr->exprId () > 0 ) {
1722
+ if (const ValueFlow::Value* val = utils::as_const (*pm).getValue (expr->exprId ()))
1723
+ {
1724
+ if (updateValue (v, *val))
1725
+ return v;
1726
+ }
1722
1727
}
1723
1728
// Find symbolic values
1724
1729
for (const ValueFlow::Value& value : expr->values ()) {
1725
1730
if (!value.isSymbolicValue ())
1726
1731
continue ;
1727
1732
if (!value.isKnown ())
1728
1733
continue ;
1729
- if (value.tokvalue ->exprId () > 0 && !pm->hasValue (value.tokvalue ->exprId ()))
1734
+ if (value.tokvalue ->exprId () == 0 )
1735
+ continue ;
1736
+ const ValueFlow::Value* v_p = utils::as_const (*pm).getValue (value.tokvalue ->exprId ());
1737
+ if (!v_p)
1730
1738
continue ;
1731
- const ValueFlow::Value& v_ref = utils::as_const (*pm).at (value.tokvalue ->exprId ());
1732
- if (!v_ref.isIntValue () && value.intvalue != 0 )
1739
+ if (!v_p->isIntValue () && value.intvalue != 0 )
1733
1740
continue ;
1734
- ValueFlow::Value v2 = v_ref ;
1741
+ ValueFlow::Value v2 = *v_p ;
1735
1742
v2.intvalue += value.intvalue ;
1736
1743
return v2;
1737
1744
}
0 commit comments