@@ -85,6 +85,21 @@ const ValueFlow::Value* ProgramMemory::getValue(nonneg int exprid, bool impossib
8585 return nullptr ;
8686}
8787
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+
88103// cppcheck-suppress unusedFunction
89104bool ProgramMemory::getIntValue (nonneg int exprid, MathLib::bigint& result) const
90105{
@@ -161,24 +176,6 @@ bool ProgramMemory::hasValue(nonneg int exprid) const
161176 return it != mValues ->cend ();
162177}
163178
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-
182179void ProgramMemory::erase_if (const std::function<bool (const ExprIdToken&)>& pred)
183180{
184181 if (mValues ->empty ())
@@ -244,6 +241,7 @@ ProgramMemory::Map::const_iterator ProgramMemory::find(nonneg int exprid) const
244241 });
245242}
246243
244+ // need to call copyOnWrite() before calling this
247245ProgramMemory::Map::iterator ProgramMemory::find (nonneg int exprid)
248246{
249247 return std::find_if (mValues ->begin (), mValues ->end (), [&exprid](const Map::value_type& entry) {
@@ -1343,10 +1341,9 @@ namespace {
13431341
13441342 ValueFlow::Value executeMultiCondition (bool b, const Token* expr)
13451343 {
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;
13501347 }
13511348
13521349 // Evaluate recursively if there are no exprids
@@ -1475,18 +1472,18 @@ namespace {
14751472 if (rhs.isUninitValue ())
14761473 return unknown ();
14771474 if (expr->str () != " =" ) {
1478- if (!pm->hasValue (expr->astOperand1 ()->exprId ()))
1475+ ValueFlow::Value* lhs = pm->getValue (expr->astOperand1 ()->exprId ());
1476+ if (!lhs)
14791477 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 ())
14851482 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));
14871484 else
14881485 return unknown ();
1489- return lhs;
1486+ return * lhs;
14901487 }
14911488 pm->setValue (expr->astOperand1 (), rhs);
14921489 return rhs;
@@ -1498,20 +1495,20 @@ namespace {
14981495 execute (expr->astOperand1 ());
14991496 return execute (expr->astOperand2 ());
15001497 } 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)
15021500 return ValueFlow::Value::unknown ();
1503- ValueFlow::Value& lhs = pm->at (expr->astOperand1 ()->exprId ());
1504- if (!lhs.isIntValue ())
1501+ if (!lhs->isIntValue ())
15051502 return unknown ();
15061503 // 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 ()))
15081505 return unknown ();
15091506
15101507 if (expr->str () == " ++" )
1511- lhs. intvalue ++;
1508+ lhs-> intvalue ++;
15121509 else
1513- lhs. intvalue --;
1514- return lhs;
1510+ lhs-> intvalue --;
1511+ return * lhs;
15151512 } else if (expr->str () == " [" && expr->astOperand1 () && expr->astOperand2 ()) {
15161513 const Token* tokvalue = nullptr ;
15171514 if (!pm->getTokValue (expr->astOperand1 ()->exprId (), tokvalue)) {
@@ -1602,13 +1599,16 @@ namespace {
16021599 }
16031600 return execute (expr->astOperand1 ());
16041601 }
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;
16101611 }
1611- return result;
16121612 }
16131613
16141614 if (Token::Match (expr->previous (), " >|%name% {|(" )) {
@@ -1658,14 +1658,16 @@ namespace {
16581658 }
16591659 // Check if function modifies argument
16601660 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+ }
16691671 }
16701672 }
16711673 return ChildrenToVisit::op1_and_op2;
@@ -1717,22 +1719,27 @@ namespace {
17171719 return v;
17181720 if (!expr)
17191721 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+ }
17231728 }
17241729 // Find symbolic values
17251730 for (const ValueFlow::Value& value : expr->values ()) {
17261731 if (!value.isSymbolicValue ())
17271732 continue ;
17281733 if (!value.isKnown ())
17291734 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)
17311739 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 )
17341741 continue ;
1735- ValueFlow::Value v2 = v_ref ;
1742+ ValueFlow::Value v2 = *v_p ;
17361743 v2.intvalue += value.intvalue ;
17371744 return v2;
17381745 }
0 commit comments