11
22#include " programmemory.h"
3- #include " mathlib.h"
4- #include " token.h"
53#include " astutils.h"
4+ #include " mathlib.h"
65#include " symboldatabase.h"
6+ #include " token.h"
77#include < algorithm>
88#include < cassert>
9+ #include < cstdio>
910#include < limits>
1011#include < memory>
1112
12- void ProgramMemory::setValue (nonneg int varid, const ValueFlow::Value &value)
13- {
14- values[varid] = value;
15- }
16- const ValueFlow::Value* ProgramMemory::getValue (nonneg int varid) const
13+ void ProgramMemory::setValue (MathLib::bigint exprid, const ValueFlow::Value& value) { values[exprid] = value; }
14+ const ValueFlow::Value* ProgramMemory::getValue (MathLib::bigint exprid) const
1715{
18- const ProgramMemory::Map::const_iterator it = values.find (varid );
16+ const ProgramMemory::Map::const_iterator it = values.find (exprid );
1917 const bool found = it != values.end () && !it->second .isImpossible ();
2018 if (found)
2119 return &it->second ;
2220 else
2321 return nullptr ;
2422}
2523
26- bool ProgramMemory::getIntValue (nonneg int varid , MathLib::bigint* result) const
24+ bool ProgramMemory::getIntValue (MathLib::bigint exprid , MathLib::bigint* result) const
2725{
28- const ValueFlow::Value* value = getValue (varid );
26+ const ValueFlow::Value* value = getValue (exprid );
2927 if (value && value->isIntValue ()) {
3028 *result = value->intvalue ;
3129 return true ;
3230 }
3331 return false ;
3432}
3533
36- void ProgramMemory::setIntValue (nonneg int varid , MathLib::bigint value)
34+ void ProgramMemory::setIntValue (MathLib::bigint exprid , MathLib::bigint value)
3735{
38- values[varid ] = ValueFlow::Value (value);
36+ values[exprid ] = ValueFlow::Value (value);
3937}
4038
41- bool ProgramMemory::getTokValue (nonneg int varid , const Token** result) const
39+ bool ProgramMemory::getTokValue (MathLib::bigint exprid , const Token** result) const
4240{
43- const ValueFlow::Value* value = getValue (varid );
41+ const ValueFlow::Value* value = getValue (exprid );
4442 if (value && value->isTokValue ()) {
4543 *result = value->tokvalue ;
4644 return true ;
4745 }
4846 return false ;
4947}
5048
51- bool ProgramMemory::getContainerSizeValue (nonneg int varid , MathLib::bigint* result) const
49+ bool ProgramMemory::getContainerSizeValue (MathLib::bigint exprid , MathLib::bigint* result) const
5250{
53- const ValueFlow::Value* value = getValue (varid );
51+ const ValueFlow::Value* value = getValue (exprid );
5452 if (value && value->isContainerSizeValue ()) {
5553 *result = value->intvalue ;
5654 return true ;
5755 }
5856 return false ;
5957}
6058
61- void ProgramMemory::setUnknown (nonneg int varid )
59+ void ProgramMemory::setUnknown (MathLib::bigint exprid )
6260{
63- values[varid ].valueType = ValueFlow::Value::ValueType::UNINIT ;
61+ values[exprid ].valueType = ValueFlow::Value::ValueType::UNINIT ;
6462}
6563
66- bool ProgramMemory::hasValue (nonneg int varid)
67- {
68- return values.find (varid) != values.end ();
69- }
64+ bool ProgramMemory::hasValue (MathLib::bigint exprid) { return values.find (exprid) != values.end (); }
7065
7166void ProgramMemory::swap (ProgramMemory &pm)
7267{
@@ -85,8 +80,9 @@ bool ProgramMemory::empty() const
8580
8681void ProgramMemory::replace (const ProgramMemory &pm)
8782{
88- for (auto && p: pm.values )
83+ for (auto && p : pm.values ) {
8984 values[p.first ] = p.second ;
85+ }
9086}
9187
9288void ProgramMemory::insert (const ProgramMemory &pm)
@@ -146,21 +142,13 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
146142 });
147143 if (!vartok)
148144 return ;
149- if (vartok->varId () == 0 )
145+ if (vartok->exprId () == 0 )
150146 return ;
151147 if (!truevalue.isIntValue ())
152148 return ;
153- if (endTok && isVariableChanged (tok->next (), endTok, vartok->varId (), false , settings, true ))
154- return ;
155- pm.setIntValue (vartok->varId (), then ? truevalue.intvalue : falsevalue.intvalue );
156- } else if (Token::Match (tok, " %var%" )) {
157- if (tok->varId () == 0 )
149+ if (endTok && isExpressionChanged (vartok, tok->next (), endTok, settings, true ))
158150 return ;
159- if (then && !astIsPointer (tok) && !astIsBool (tok))
160- return ;
161- if (endTok && isVariableChanged (tok->next (), endTok, tok->varId (), false , settings, true ))
162- return ;
163- pm.setIntValue (tok->varId (), then);
151+ pm.setIntValue (vartok->exprId (), then ? truevalue.intvalue : falsevalue.intvalue );
164152 } else if (Token::simpleMatch (tok, " !" )) {
165153 programMemoryParseCondition (pm, tok->astOperand1 (), endTok, settings, !then);
166154 } else if (then && Token::simpleMatch (tok, " &&" )) {
@@ -169,6 +157,12 @@ void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Toke
169157 } else if (!then && Token::simpleMatch (tok, " ||" )) {
170158 programMemoryParseCondition (pm, tok->astOperand1 (), endTok, settings, then);
171159 programMemoryParseCondition (pm, tok->astOperand2 (), endTok, settings, then);
160+ } else if (tok->exprId () > 0 ) {
161+ if (then && !astIsPointer (tok) && !astIsBool (tok))
162+ return ;
163+ if (endTok && isExpressionChanged (tok, tok->next (), endTok, settings, true ))
164+ return ;
165+ pm.setIntValue (tok->exprId (), then);
172166 }
173167}
174168
@@ -197,36 +191,33 @@ static void fillProgramMemoryFromAssignments(ProgramMemory& pm, const Token* tok
197191{
198192 int indentlevel = 0 ;
199193 for (const Token *tok2 = tok; tok2; tok2 = tok2->previous ()) {
200- bool setvar = false ;
201- if (Token::Match (tok2, " [;{}] %var% = %var% ;" )) {
194+ if ((Token::simpleMatch (tok2, " =" ) || Token::Match (tok2->previous (), " %var% (|{" )) && tok2->astOperand1 () &&
195+ tok2->astOperand2 ()) {
196+ bool setvar = false ;
197+ const Token* vartok = tok2->astOperand1 ();
198+ const Token* valuetok = tok2->astOperand2 ();
202199 for (const auto & p:vars) {
203- if (p.first != tok2-> next ()-> varId ())
200+ if (p.first != vartok-> exprId ())
204201 continue ;
205- const Token *vartok = tok2->tokAt (3 );
206202 if (vartok == tok)
207203 continue ;
208- pm.setValue (vartok->varId (), p.second );
204+ pm.setValue (vartok->exprId (), p.second );
209205 setvar = true ;
210206 }
211- }
212- if (!setvar && (Token::Match (tok2, " ;|{|}|%type% %var% =" ) || Token::Match (tok2, " [;{}] const| %type% %var% (" ) ||
213- Token::Match (tok2->previous (), " for ( %var% =" ))) {
214- const Token *vartok = tok2->next ();
215- while (vartok->next ()->isName ())
216- vartok = vartok->next ();
217- if (!pm.hasValue (vartok->varId ())) {
218- MathLib::bigint result = 0 ;
219- bool error = false ;
220- execute (vartok->next ()->astOperand2 (), &pm, &result, &error);
221- if (!error)
222- pm.setIntValue (vartok->varId (), result);
223- else
224- pm.setUnknown (vartok->varId ());
207+ if (!setvar) {
208+ if (!pm.hasValue (vartok->exprId ())) {
209+ MathLib::bigint result = 0 ;
210+ bool error = false ;
211+ execute (valuetok, &pm, &result, &error);
212+ if (!error)
213+ pm.setIntValue (vartok->exprId (), result);
214+ else
215+ pm.setUnknown (vartok->exprId ());
216+ }
225217 }
226- } else if (!setvar && Token::Match (tok2, " %var% !!=" ) && isVariableChanged (tok2, 0 , nullptr , true )) {
227- const Token *vartok = tok2;
228- if (!pm.hasValue (vartok->varId ()))
229- pm.setUnknown (vartok->varId ());
218+ } else if (tok2->exprId () > 0 && Token::Match (tok2, " .|(|[|*|%var%" ) && !pm.hasValue (tok2->exprId ()) &&
219+ isVariableChanged (tok2, 0 , nullptr , true )) {
220+ pm.setUnknown (tok2->exprId ());
230221 }
231222
232223 if (tok2->str () == " {" ) {
@@ -291,12 +282,12 @@ void ProgramMemoryState::replace(const ProgramMemory &pm, const Token* origin)
291282
292283void ProgramMemoryState::addState (const Token* tok, const ProgramMemory::Map& vars)
293284{
294- ProgramMemory pm;
285+ ProgramMemory pm = state ;
295286 fillProgramMemoryFromConditions (pm, tok, nullptr );
296287 for (const auto & p:vars) {
297- nonneg int varid = p.first ;
288+ MathLib::bigint exprid = p.first ;
298289 const ValueFlow::Value &value = p.second ;
299- pm.setValue (varid , value);
290+ pm.setValue (exprid , value);
300291 if (value.varId )
301292 pm.setIntValue (value.varId , value.varvalue );
302293 }
@@ -343,9 +334,9 @@ ProgramMemory getProgramMemory(const Token *tok, const ProgramMemory::Map& vars)
343334 fillProgramMemoryFromConditions (programMemory, tok, nullptr );
344335 ProgramMemory state;
345336 for (const auto & p:vars) {
346- nonneg int varid = p.first ;
337+ MathLib::bigint exprid = p.first ;
347338 const ValueFlow::Value &value = p.second ;
348- programMemory.setValue (varid , value);
339+ programMemory.setValue (exprid , value);
349340 if (value.varId )
350341 programMemory.setIntValue (value.varId , value.varvalue );
351342 }
@@ -354,17 +345,17 @@ ProgramMemory getProgramMemory(const Token *tok, const ProgramMemory::Map& vars)
354345 return programMemory;
355346}
356347
357- ProgramMemory getProgramMemory (const Token * tok, nonneg int varid , const ValueFlow::Value & value)
348+ ProgramMemory getProgramMemory (const Token* tok, MathLib::bigint exprid , const ValueFlow::Value& value)
358349{
359350 ProgramMemory programMemory;
360351 programMemory.replace (getInitialProgramState (tok, value.tokvalue ));
361352 programMemory.replace (getInitialProgramState (tok, value.condition ));
362353 fillProgramMemoryFromConditions (programMemory, tok, nullptr );
363- programMemory.setValue (varid , value);
354+ programMemory.setValue (exprid , value);
364355 if (value.varId )
365356 programMemory.setIntValue (value.varId , value.varvalue );
366357 const ProgramMemory state = programMemory;
367- fillProgramMemoryFromAssignments (programMemory, tok, state, {{varid , value}});
358+ fillProgramMemoryFromAssignments (programMemory, tok, state, {{exprid , value}});
368359 return programMemory;
369360}
370361
@@ -391,6 +382,11 @@ void execute(const Token *expr,
391382 *error = true ;
392383 }
393384
385+ else if (expr->exprId () > 0 && programMemory->hasValue (expr->exprId ())) {
386+ if (!programMemory->getIntValue (expr->exprId (), result))
387+ *error = true ;
388+ }
389+
394390 else if (expr->isComparisonOp ()) {
395391 MathLib::bigint result1 (0 ), result2 (0 );
396392 execute (expr->astOperand1 (), programMemory, &result1, error);
@@ -411,45 +407,45 @@ void execute(const Token *expr,
411407
412408 else if (expr->isAssignmentOp ()) {
413409 execute (expr->astOperand2 (), programMemory, result, error);
414- if (!expr->astOperand1 () || !expr->astOperand1 ()->varId ())
410+ if (!expr->astOperand1 () || !expr->astOperand1 ()->exprId ())
415411 *error = true ;
416412 if (*error)
417413 return ;
418414
419415 if (expr->str () == " =" ) {
420- programMemory->setIntValue (expr->astOperand1 ()->varId (), *result);
416+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), *result);
421417 return ;
422418 }
423419
424420 long long intValue;
425- if (!programMemory->getIntValue (expr->astOperand1 ()->varId (), &intValue)) {
421+ if (!programMemory->getIntValue (expr->astOperand1 ()->exprId (), &intValue)) {
426422 *error = true ;
427423 return ;
428424 }
429425 if (expr->str () == " +=" )
430- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue + *result);
426+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue + *result);
431427 else if (expr->str () == " -=" )
432- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue - *result);
428+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue - *result);
433429 else if (expr->str () == " *=" )
434- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue * *result);
430+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue * *result);
435431 else if (expr->str () == " /=" && *result != 0 )
436- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue / *result);
432+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue / *result);
437433 else if (expr->str () == " %=" && *result != 0 )
438- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue % *result);
434+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue % *result);
439435 else if (expr->str () == " &=" )
440- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue & *result);
436+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue & *result);
441437 else if (expr->str () == " |=" )
442- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue | *result);
438+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue | *result);
443439 else if (expr->str () == " ^=" )
444- programMemory->setIntValue (expr->astOperand1 ()->varId (), intValue ^ *result);
440+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), intValue ^ *result);
445441 }
446442
447443 else if (Token::Match (expr, " ++|--" )) {
448- if (!expr->astOperand1 () || expr->astOperand1 ()->varId () == 0U )
444+ if (!expr->astOperand1 () || expr->astOperand1 ()->exprId () == 0U )
449445 *error = true ;
450446 else {
451447 long long intValue;
452- if (!programMemory->getIntValue (expr->astOperand1 ()->varId (), &intValue))
448+ if (!programMemory->getIntValue (expr->astOperand1 ()->exprId (), &intValue))
453449 *error = true ;
454450 else {
455451 if (intValue == 0 &&
@@ -458,7 +454,7 @@ void execute(const Token *expr,
458454 expr->astOperand1 ()->variable ()->isUnsigned ())
459455 *error = true ; // overflow
460456 *result = intValue + (expr->str () == " ++" ? 1 : -1 );
461- programMemory->setIntValue (expr->astOperand1 ()->varId (), *result);
457+ programMemory->setIntValue (expr->astOperand1 ()->exprId (), *result);
462458 }
463459 }
464460 }
@@ -530,7 +526,7 @@ void execute(const Token *expr,
530526
531527 else if (expr->str () == " [" && expr->astOperand1 () && expr->astOperand2 ()) {
532528 const Token *tokvalue = nullptr ;
533- if (!programMemory->getTokValue (expr->astOperand1 ()->varId (), &tokvalue)) {
529+ if (!programMemory->getTokValue (expr->astOperand1 ()->exprId (), &tokvalue)) {
534530 auto tokvalue_it = std::find_if (expr->astOperand1 ()->values ().begin (),
535531 expr->astOperand1 ()->values ().end (),
536532 std::mem_fn (&ValueFlow::Value::isTokValue));
@@ -558,11 +554,11 @@ void execute(const Token *expr,
558554 if (astIsContainer (containerTok)) {
559555 Library::Container::Yield yield = containerTok->valueType ()->container ->getYield (expr->strAt (-1 ));
560556 if (yield == Library::Container::Yield::SIZE ) {
561- if (!programMemory->getContainerSizeValue (containerTok->varId (), result))
557+ if (!programMemory->getContainerSizeValue (containerTok->exprId (), result))
562558 *error = true ;
563559 } else if (yield == Library::Container::Yield::EMPTY ) {
564560 MathLib::bigint size = 0 ;
565- if (!programMemory->getContainerSizeValue (containerTok->varId (), &size))
561+ if (!programMemory->getContainerSizeValue (containerTok->exprId (), &size))
566562 *error = true ;
567563 *result = (size == 0 );
568564 } else {
0 commit comments