| 6501 | } |
| 6502 | |
| 6503 | static std::vector<ValueFlow::Value> getContainerSizeFromConstructorArgs(const std::vector<const Token*>& args, |
| 6504 | const Library::Container* container, |
| 6505 | bool known) |
| 6506 | { |
| 6507 | if (astIsIntegral(args[0], false)) { // { count, i } or { count } |
| 6508 | if (args.size() == 1 || (args.size() > 1 && !astIsIntegral(args[1], false))) |
| 6509 | return {makeContainerSizeValue(args[0], known)}; |
| 6510 | } else if (astIsContainer(args[0]) && args.size() == 1) { // copy constructor |
| 6511 | return getContainerValues(args[0]); |
| 6512 | } else if (isIteratorPair(args)) { |
| 6513 | std::vector<ValueFlow::Value> result = getContainerValues(args[0]); |
| 6514 | if (!result.empty()) |
| 6515 | return result; |
| 6516 | // (ptr, ptr + size) |
| 6517 | if (astIsPointer(args[0]) && args[0]->exprId() != 0) { |
| 6518 | // (ptr, ptr) is empty |
| 6519 | // TODO: Use lifetime values to check if it points to the same address |
| 6520 | if (args[0]->exprId() == args[1]->exprId()) |
| 6521 | return {makeContainerSizeValue(MathLib::bigint{0}, known)}; |
| 6522 | // TODO: Insert iterator positions for pointers |
| 6523 | if (Token::simpleMatch(args[1], "+")) { |
| 6524 | nonneg int const eid = args[0]->exprId(); |
| 6525 | const Token* vartok = args[1]->astOperand1(); |
| 6526 | const Token* sizetok = args[1]->astOperand2(); |
| 6527 | if (sizetok->exprId() == eid) |
| 6528 | std::swap(vartok, sizetok); |
| 6529 | if (vartok->exprId() == eid && sizetok->hasKnownIntValue()) |
| 6530 | return {makeContainerSizeValue(sizetok, known)}; |
| 6531 | } |
| 6532 | } |
| 6533 | } else if (container->stdStringLike) { |
| 6534 | if (astIsPointer(args[0])) { |
| 6535 | if (args.size() == 1 && args[0]->tokType() == Token::Type::eString) |
| 6536 | return {makeContainerSizeValue(Token::getStrLength(args[0]), known)}; |
| 6537 | if (args.size() == 1 && args[0]->variable() && args[0]->variable()->isArray() && |
| 6538 | args[0]->variable()->isConst() && args[0]->variable()->dimensions().size() == 1 && args[0]->variable()->dimensions()[0].known) |
| 6539 | return {makeContainerSizeValue(args[0]->variable()->dimensions()[0].num, known)}; |
| 6540 | if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count } |
| 6541 | return {makeContainerSizeValue(args[1], known)}; |
| 6542 | } else if (astIsContainer(args[0])) { |
| 6543 | if (args.size() == 1) // copy constructor { str } |
| 6544 | return getContainerValues(args[0]); |
| 6545 | if (args.size() == 3) // { str, pos, count } |
| 6546 | return {makeContainerSizeValue(args[2], known)}; |
| 6547 | // TODO: { str, pos }, { ..., alloc } |
| 6548 | } |
| 6549 | } |
| 6550 | return {}; |
| 6551 | } |
| 6552 | |
| 6553 | static bool valueFlowIsSameContainerType(const ValueType& contType, const Token* tok, bool isView, const Settings& settings) |
| 6554 | { |
no test coverage detected