MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / ContainerExpressionAnalyzer

Class ContainerExpressionAnalyzer

lib/vf_analyzers.cpp:1464–1585  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1462}
1463
1464struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
1465 ContainerExpressionAnalyzer(const Token* expr, ValueFlow::Value val, const Settings& s)
1466 : ExpressionAnalyzer(expr, std::move(val), s)
1467 {}
1468
1469 bool match(const Token* tok) const override {
1470 return tok->exprId() == expr->exprId() || (astIsIterator(tok) && isAliasOf(tok, expr->exprId()));
1471 }
1472
1473 Action isWritable(const Token* tok, Direction /*d*/) const override
1474 {
1475 if (astIsIterator(tok))
1476 return Action::None;
1477 if (!getValue(tok))
1478 return Action::None;
1479 if (!tok->valueType())
1480 return Action::None;
1481 if (!astIsContainer(tok))
1482 return Action::None;
1483 const Token* parent = tok->astParent();
1484 const Library::Container* container = getLibraryContainer(tok);
1485
1486 if (container->stdStringLike && Token::simpleMatch(parent, "+=") && astIsLHS(tok) && parent->astOperand2()) {
1487 const Token* rhs = parent->astOperand2();
1488 if (rhs->tokType() == Token::eString)
1489 return Action::Read | Action::Write | Action::Incremental;
1490 const Library::Container* rhsContainer = getLibraryContainer(rhs);
1491 if (rhsContainer && rhsContainer->stdStringLike) {
1492 if (std::any_of(rhs->values().cbegin(), rhs->values().cend(), [&](const ValueFlow::Value &rhsval) {
1493 return rhsval.isKnown() && rhsval.isContainerSizeValue();
1494 }))
1495 return Action::Read | Action::Write | Action::Incremental;
1496 }
1497 } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
1498 const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
1499 if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP || action == Library::Container::Action::APPEND) { // TODO: handle more actions?
1500 std::vector<const Token*> args = getArguments(tok->tokAt(3));
1501 bool isVariadic = false;
1502 if (const Library::Function* libFunc = settings.library.getFunction(tok->tokAt(2))) {
1503 const auto& argChecks = libFunc->argumentChecks;
1504 isVariadic = argChecks.find(-1) != argChecks.end() && argChecks.at(-1).variadic;
1505 }
1506 if (args.size() < 2 || action == Library::Container::Action::APPEND || isVariadic)
1507 return Action::Read | Action::Write | Action::Incremental;
1508 }
1509 }
1510 return Action::None;
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;

Callers 2

makeAnalyzerFunction · 0.85
makeReverseAnalyzerFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected