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