| 1511 | } |
| 1512 | |
| 1513 | void writeValue(ValueFlow::Value* val, const Token* tok, Direction d) const override { |
| 1514 | if (!val) |
| 1515 | return; |
| 1516 | if (!tok->astParent()) |
| 1517 | return; |
| 1518 | if (!tok->valueType()) |
| 1519 | return; |
| 1520 | if (!astIsContainer(tok)) |
| 1521 | return; |
| 1522 | const Token* parent = tok->astParent(); |
| 1523 | const Library::Container* container = getLibraryContainer(tok); |
| 1524 | MathLib::bigint n = 0; |
| 1525 | |
| 1526 | if (container->stdStringLike && Token::simpleMatch(parent, "+=") && parent->astOperand2()) { |
| 1527 | const Token* rhs = parent->astOperand2(); |
| 1528 | const Library::Container* rhsContainer = getLibraryContainer(rhs); |
| 1529 | if (rhs->tokType() == Token::eString) |
| 1530 | n = Token::getStrLength(rhs); |
| 1531 | else if (rhsContainer && rhsContainer->stdStringLike) { |
| 1532 | auto it = std::find_if(rhs->values().begin(), rhs->values().end(), [&](const ValueFlow::Value& rhsval) { |
| 1533 | return rhsval.isKnown() && rhsval.isContainerSizeValue(); |
| 1534 | }); |
| 1535 | if (it != rhs->values().end()) |
| 1536 | n = it->intvalue; |
| 1537 | } |
| 1538 | } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) { |
| 1539 | const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1)); |
| 1540 | switch (action) { |
| 1541 | case Library::Container::Action::PUSH: |
| 1542 | n = 1; |
| 1543 | break; |
| 1544 | case Library::Container::Action::POP: |
| 1545 | n = -1; |
| 1546 | break; |
| 1547 | case Library::Container::Action::APPEND: { |
| 1548 | std::vector<const Token*> args = getArguments(tok->astParent()->tokAt(2)); |
| 1549 | if (args.size() == 1) // TODO: handle overloads |
| 1550 | n = ValueFlow::valueFlowGetStrLength(tok->astParent()->tokAt(3), settings); |
| 1551 | if (n == 0) // TODO: handle known empty append |
| 1552 | val->setPossible(); |
| 1553 | break; |
| 1554 | } |
| 1555 | default: |
| 1556 | break; |
| 1557 | } |
| 1558 | } |
| 1559 | if (d == Direction::Reverse) |
| 1560 | val->intvalue -= n; |
| 1561 | else |
| 1562 | val->intvalue += n; |
| 1563 | } |
| 1564 | |
| 1565 | int getIndirect(const Token* tok) const override |
| 1566 | { |
nothing calls this directly
no test coverage detected