@@ -96,6 +96,21 @@ const ValueFlow::Value* ProgramMemory::getValue(nonneg int exprid, bool impossib
96
96
return nullptr ;
97
97
}
98
98
99
+ ValueFlow::Value* ProgramMemory::getValue (nonneg int exprid)
100
+ {
101
+ if (mValues ->empty ())
102
+ return nullptr ;
103
+
104
+ // TODO: avoid copy if no value is found
105
+ copyOnWrite ();
106
+
107
+ const auto it = find (exprid);
108
+ const bool found = it != mValues ->cend ();
109
+ if (found)
110
+ return &it->second ;
111
+ return nullptr ;
112
+ }
113
+
99
114
// cppcheck-suppress unusedFunction
100
115
bool ProgramMemory::getIntValue (nonneg int exprid, MathLib::bigint& result) const
101
116
{
@@ -172,24 +187,6 @@ bool ProgramMemory::hasValue(nonneg int exprid) const
172
187
return it != mValues ->cend ();
173
188
}
174
189
175
- const ValueFlow::Value& ProgramMemory::at (nonneg int exprid) const {
176
- const auto it = find (exprid);
177
- if (it == mValues ->cend ()) {
178
- throw std::out_of_range (" ProgramMemory::at" );
179
- }
180
- return it->second ;
181
- }
182
-
183
- ValueFlow::Value& ProgramMemory::at (nonneg int exprid) {
184
- copyOnWrite ();
185
-
186
- const auto it = find (exprid);
187
- if (it == mValues ->end ()) {
188
- throw std::out_of_range (" ProgramMemory::at" );
189
- }
190
- return it->second ;
191
- }
192
-
193
190
void ProgramMemory::erase_if (const std::function<bool (const ExprIdToken&)>& pred)
194
191
{
195
192
if (mValues ->empty ())
@@ -253,6 +250,7 @@ ProgramMemory::Map::const_iterator ProgramMemory::find(nonneg int exprid) const
253
250
return cvalues.find (ExprIdToken::create (exprid));
254
251
}
255
252
253
+ // need to call copyOnWrite() before calling this
256
254
ProgramMemory::Map::iterator ProgramMemory::find (nonneg int exprid)
257
255
{
258
256
return mValues ->find (ExprIdToken::create (exprid));
@@ -1350,10 +1348,9 @@ namespace {
1350
1348
1351
1349
ValueFlow::Value executeMultiCondition (bool b, const Token* expr)
1352
1350
{
1353
- if (pm->hasValue (expr->exprId ())) {
1354
- const ValueFlow::Value& v = utils::as_const (*pm).at (expr->exprId ());
1355
- if (v.isIntValue ())
1356
- return v;
1351
+ if (const ValueFlow::Value* v = utils::as_const (*pm).getValue (expr->exprId ())) {
1352
+ if (v->isIntValue ())
1353
+ return *v;
1357
1354
}
1358
1355
1359
1356
// Evaluate recursively if there are no exprids
@@ -1482,18 +1479,18 @@ namespace {
1482
1479
if (rhs.isUninitValue ())
1483
1480
return unknown ();
1484
1481
if (expr->str () != " =" ) {
1485
- if (!pm->hasValue (expr->astOperand1 ()->exprId ()))
1482
+ ValueFlow::Value* lhs = pm->getValue (expr->astOperand1 ()->exprId ());
1483
+ if (!lhs)
1486
1484
return unknown ();
1487
- ValueFlow::Value& lhs = pm->at (expr->astOperand1 ()->exprId ());
1488
- rhs = evaluate (removeAssign (expr->str ()), lhs, rhs);
1489
- if (lhs.isIntValue ())
1490
- ValueFlow::Value::visitValue (rhs, std::bind (assign{}, std::ref (lhs.intvalue ), std::placeholders::_1));
1491
- else if (lhs.isFloatValue ())
1485
+ rhs = evaluate (removeAssign (expr->str ()), *lhs, rhs);
1486
+ if (lhs->isIntValue ())
1487
+ ValueFlow::Value::visitValue (rhs, std::bind (assign{}, std::ref (lhs->intvalue ), std::placeholders::_1));
1488
+ else if (lhs->isFloatValue ())
1492
1489
ValueFlow::Value::visitValue (rhs,
1493
- std::bind (assign{}, std::ref (lhs. floatValue ), std::placeholders::_1));
1490
+ std::bind (assign{}, std::ref (lhs-> floatValue ), std::placeholders::_1));
1494
1491
else
1495
1492
return unknown ();
1496
- return lhs;
1493
+ return * lhs;
1497
1494
}
1498
1495
pm->setValue (expr->astOperand1 (), rhs);
1499
1496
return rhs;
@@ -1505,20 +1502,20 @@ namespace {
1505
1502
execute (expr->astOperand1 ());
1506
1503
return execute (expr->astOperand2 ());
1507
1504
} else if (expr->tokType () == Token::eIncDecOp && expr->astOperand1 () && expr->astOperand1 ()->exprId () != 0 ) {
1508
- if (!pm->hasValue (expr->astOperand1 ()->exprId ()))
1505
+ ValueFlow::Value* lhs = pm->getValue (expr->astOperand1 ()->exprId ());
1506
+ if (!lhs)
1509
1507
return ValueFlow::Value::unknown ();
1510
- ValueFlow::Value& lhs = pm->at (expr->astOperand1 ()->exprId ());
1511
- if (!lhs.isIntValue ())
1508
+ if (!lhs->isIntValue ())
1512
1509
return unknown ();
1513
1510
// overflow
1514
- if (!lhs. isImpossible () && lhs. intvalue == 0 && expr->str () == " --" && astIsUnsigned (expr->astOperand1 ()))
1511
+ if (!lhs-> isImpossible () && lhs-> intvalue == 0 && expr->str () == " --" && astIsUnsigned (expr->astOperand1 ()))
1515
1512
return unknown ();
1516
1513
1517
1514
if (expr->str () == " ++" )
1518
- lhs. intvalue ++;
1515
+ lhs-> intvalue ++;
1519
1516
else
1520
- lhs. intvalue --;
1521
- return lhs;
1517
+ lhs-> intvalue --;
1518
+ return * lhs;
1522
1519
} else if (expr->str () == " [" && expr->astOperand1 () && expr->astOperand2 ()) {
1523
1520
const Token* tokvalue = nullptr ;
1524
1521
if (!pm->getTokValue (expr->astOperand1 ()->exprId (), tokvalue)) {
@@ -1609,13 +1606,16 @@ namespace {
1609
1606
}
1610
1607
return execute (expr->astOperand1 ());
1611
1608
}
1612
- if (expr->exprId () > 0 && pm->hasValue (expr->exprId ())) {
1613
- ValueFlow::Value result = utils::as_const (*pm).at (expr->exprId ());
1614
- if (result.isImpossible () && result.isIntValue () && result.intvalue == 0 && isUsedAsBool (expr, settings)) {
1615
- result.intvalue = !result.intvalue ;
1616
- result.setKnown ();
1609
+ if (expr->exprId () > 0 ) {
1610
+ if (const ValueFlow::Value* v = utils::as_const (*pm).getValue (expr->exprId ()))
1611
+ {
1612
+ ValueFlow::Value result = *v;
1613
+ if (result.isImpossible () && result.isIntValue () && result.intvalue == 0 && isUsedAsBool (expr, settings)) {
1614
+ result.intvalue = !result.intvalue ;
1615
+ result.setKnown ();
1616
+ }
1617
+ return result;
1617
1618
}
1618
- return result;
1619
1619
}
1620
1620
1621
1621
if (Token::Match (expr->previous (), " >|%name% {|(" )) {
@@ -1665,14 +1665,16 @@ namespace {
1665
1665
}
1666
1666
// Check if function modifies argument
1667
1667
visitAstNodes (expr->astOperand2 (), [&](const Token* child) {
1668
- if (child->exprId () > 0 && pm->hasValue (child->exprId ())) {
1669
- ValueFlow::Value& v = pm->at (child->exprId ());
1670
- if (v.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) {
1671
- if (ValueFlow::isContainerSizeChanged (child, v.indirect , settings))
1672
- v = unknown ();
1673
- } else if (v.valueType != ValueFlow::Value::ValueType::UNINIT) {
1674
- if (isVariableChanged (child, v.indirect , settings))
1675
- v = unknown ();
1668
+ if (child->exprId () > 0 ) {
1669
+ if (ValueFlow::Value* v = pm->getValue (child->exprId ()))
1670
+ {
1671
+ if (v->valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) {
1672
+ if (ValueFlow::isContainerSizeChanged (child, v->indirect , settings))
1673
+ *v = unknown ();
1674
+ } else if (v->valueType != ValueFlow::Value::ValueType::UNINIT) {
1675
+ if (isVariableChanged (child, v->indirect , settings))
1676
+ *v = unknown ();
1677
+ }
1676
1678
}
1677
1679
}
1678
1680
return ChildrenToVisit::op1_and_op2;
@@ -1724,22 +1726,27 @@ namespace {
1724
1726
return v;
1725
1727
if (!expr)
1726
1728
return v;
1727
- if (expr->exprId () > 0 && pm->hasValue (expr->exprId ())) {
1728
- if (updateValue (v, utils::as_const (*pm).at (expr->exprId ())))
1729
- return v;
1729
+ if (expr->exprId () > 0 ) {
1730
+ if (const ValueFlow::Value* val = utils::as_const (*pm).getValue (expr->exprId ()))
1731
+ {
1732
+ if (updateValue (v, *val))
1733
+ return v;
1734
+ }
1730
1735
}
1731
1736
// Find symbolic values
1732
1737
for (const ValueFlow::Value& value : expr->values ()) {
1733
1738
if (!value.isSymbolicValue ())
1734
1739
continue ;
1735
1740
if (!value.isKnown ())
1736
1741
continue ;
1737
- if (value.tokvalue ->exprId () > 0 && !pm->hasValue (value.tokvalue ->exprId ()))
1742
+ if (value.tokvalue ->exprId () == 0 )
1743
+ continue ;
1744
+ const ValueFlow::Value* v_p = utils::as_const (*pm).getValue (value.tokvalue ->exprId ());
1745
+ if (!v_p)
1738
1746
continue ;
1739
- const ValueFlow::Value& v_ref = utils::as_const (*pm).at (value.tokvalue ->exprId ());
1740
- if (!v_ref.isIntValue () && value.intvalue != 0 )
1747
+ if (!v_p->isIntValue () && value.intvalue != 0 )
1741
1748
continue ;
1742
- ValueFlow::Value v2 = v_ref ;
1749
+ ValueFlow::Value v2 = *v_p ;
1743
1750
v2.intvalue += value.intvalue ;
1744
1751
return v2;
1745
1752
}
0 commit comments