| 322 | } |
| 323 | |
| 324 | virtual void writeValue(ValueFlow::Value* value, const Token* tok, Direction d) const { |
| 325 | if (!value) |
| 326 | return; |
| 327 | if (!tok->astParent()) |
| 328 | return; |
| 329 | // Lifetime value doesn't change |
| 330 | if (value->isLifetimeValue()) |
| 331 | return; |
| 332 | if (tok->astParent()->isAssignmentOp()) { |
| 333 | const Token* rhs = tok->astParent()->astOperand2(); |
| 334 | std::vector<MathLib::bigint> result = evaluateInt(rhs); |
| 335 | assert(!result.empty()); |
| 336 | ValueFlow::Value rhsValue{result.front()}; |
| 337 | if (evalAssignment(*value, getAssign(tok->astParent(), d), rhsValue)) { |
| 338 | std::string info("Compound assignment '" + tok->astParent()->str() + "', assigned value is " + |
| 339 | value->infoString()); |
| 340 | if (tok->astParent()->str() == "=") |
| 341 | value->errorPath.clear(); |
| 342 | value->errorPath.emplace_back(tok, std::move(info)); |
| 343 | } else { |
| 344 | assert(false && "Writable value cannot be evaluated"); |
| 345 | // TODO: Don't set to zero |
| 346 | value->intvalue = 0; |
| 347 | } |
| 348 | } else if (tok->astParent()->tokType() == Token::eIncDecOp) { |
| 349 | bool inc = tok->astParent()->str() == "++"; |
| 350 | const std::string opName(inc ? "incremented" : "decremented"); |
| 351 | if (d == Direction::Reverse) |
| 352 | inc = !inc; |
| 353 | value->intvalue += (inc ? 1 : -1); |
| 354 | |
| 355 | /* Truncate value */ |
| 356 | const ValueType *dst = tok->valueType(); |
| 357 | if (dst) { |
| 358 | const size_t sz = dst->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer); |
| 359 | if (sz > 0 && sz < sizeof(MathLib::biguint)) { |
| 360 | MathLib::bigint newvalue = ValueFlow::truncateIntValue(value->intvalue, sz, dst->sign); |
| 361 | |
| 362 | /* Handle overflow/underflow for value bounds */ |
| 363 | if (value->bound != ValueFlow::Value::Bound::Point) { |
| 364 | if ((newvalue > value->intvalue && !inc) || (newvalue < value->intvalue && inc)) |
| 365 | value->invertBound(); |
| 366 | } |
| 367 | |
| 368 | value->intvalue = newvalue; |
| 369 | } |
| 370 | |
| 371 | value->errorPath.emplace_back(tok, tok->str() + " is " + opName + "', new value is " + value->infoString()); |
| 372 | } |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | virtual bool useSymbolicValues() const { |
| 377 | return true; |
no test coverage detected