| 6633 | } |
| 6634 | |
| 6635 | static void valueFlowContainerSize(const TokenList& tokenlist, |
| 6636 | const SymbolDatabase& symboldatabase, |
| 6637 | ErrorLogger& errorLogger, |
| 6638 | const Settings& settings, |
| 6639 | const std::set<const Scope*>& skippedFunctions) |
| 6640 | { |
| 6641 | // declaration |
| 6642 | for (const Variable *var : symboldatabase.variableList()) { |
| 6643 | if (!var) |
| 6644 | continue; |
| 6645 | if (!var->scope() || !var->scope()->bodyEnd || !var->scope()->bodyStart) |
| 6646 | continue; |
| 6647 | if (!var->valueType() || !var->valueType()->container) |
| 6648 | continue; |
| 6649 | if (!astIsContainer(var->nameToken())) |
| 6650 | continue; |
| 6651 | if (skippedFunctions.count(getFunctionScope(var->scope()))) |
| 6652 | continue; |
| 6653 | |
| 6654 | bool known = true; |
| 6655 | MathLib::bigint size = 0; |
| 6656 | const bool nonLocal = !var->isLocal() || var->isPointer() || var->isReference() || var->isStatic(); |
| 6657 | bool constSize = var->isConst() && !nonLocal; |
| 6658 | bool staticSize = false; |
| 6659 | if (var->valueType()->container->size_templateArgNo >= 0) { |
| 6660 | staticSize = true; |
| 6661 | constSize = true; |
| 6662 | size = -1; |
| 6663 | if (var->dimensions().size() == 1) { |
| 6664 | const Dimension& dim = var->dimensions().front(); |
| 6665 | if (dim.known) { |
| 6666 | size = dim.num; |
| 6667 | } else if (dim.tok && dim.tok->hasKnownIntValue() && dim.tok->strAt(1) == ">") { |
| 6668 | size = dim.tok->getKnownIntValue(); |
| 6669 | } |
| 6670 | } |
| 6671 | if (size < 0) |
| 6672 | continue; |
| 6673 | } |
| 6674 | if (!staticSize && nonLocal) |
| 6675 | continue; |
| 6676 | auto* nameToken = const_cast<Token*>(var->nameToken()); |
| 6677 | if (nameToken->hasKnownValue(ValueFlow::Value::ValueType::CONTAINER_SIZE)) |
| 6678 | continue; |
| 6679 | if (!staticSize) { |
| 6680 | if (!Token::Match(nameToken, "%name% ;") && |
| 6681 | !(Token::Match(nameToken, "%name% {") && Token::simpleMatch(nameToken->linkAt(1), "} ;")) && |
| 6682 | !Token::Match(nameToken, "%name% (")) |
| 6683 | continue; |
| 6684 | } |
| 6685 | if (Token::Match(nameToken->astTop()->previous(), "for|while")) |
| 6686 | known = !isVariableChanged(var, settings); |
| 6687 | std::vector<ValueFlow::Value> values{ValueFlow::Value{size}}; |
| 6688 | values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE; |
| 6689 | if (known) |
| 6690 | values.back().setKnown(); |
| 6691 | if (!staticSize) { |
| 6692 | if (Token::simpleMatch(nameToken->next(), "{")) { |
no test coverage detected