Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,23 @@ static const Token* getContainerFunction(const Token* tok)
return nullptr;
}

Library::Container::Action astContainerAction(const Token* tok)
Library::Container::Action astContainerAction(const Token* tok, const Token** ftok)
{
const Token* ftok = getContainerFunction(tok);
if (!ftok)
const Token* ftok2 = getContainerFunction(tok);
if (ftok)
*ftok = ftok2;
if (!ftok2)
return Library::Container::Action::NO_ACTION;
return tok->valueType()->container->getAction(ftok->str());
return tok->valueType()->container->getAction(ftok2->str());
}
Library::Container::Yield astContainerYield(const Token* tok, const Token** ftok)
{
const Token* ftok2 = getContainerFunction(tok);
if (ftok)
*ftok = ftok2;
if (!ftok2)
return Library::Container::Yield::NO_YIELD;
return tok->valueType()->container->getYield(ftok2->str());
}

bool astIsRangeBasedForDecl(const Token* tok)
Expand Down
3 changes: 2 additions & 1 deletion lib/astutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ bool astIsContainer(const Token *tok);
bool astIsContainerView(const Token* tok);
bool astIsContainerOwned(const Token* tok);

Library::Container::Action astContainerAction(const Token* tok);
Library::Container::Action astContainerAction(const Token* tok, const Token** ftok = nullptr);
Library::Container::Yield astContainerYield(const Token* tok, const Token** ftok = nullptr);

/** Is given token a range-declaration in a range-based for loop */
bool astIsRangeBasedForDecl(const Token* tok);
Expand Down
62 changes: 34 additions & 28 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7499,8 +7499,8 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
}))
return Action::Read | Action::Write | Action::Incremental;
}
} else if (Token::Match(tok, "%name% . %name% (")) {
Library::Container::Action action = container->getAction(tok->strAt(2));
} else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) {
std::vector<const Token*> args = getArguments(tok->tokAt(3));
if (args.size() < 2)
Expand Down Expand Up @@ -7536,8 +7536,8 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
}
}
}
} else if (Token::Match(tok, "%name% . %name% (")) {
Library::Container::Action action = container->getAction(tok->strAt(2));
} else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
if (action == Library::Container::Action::PUSH)
val->intvalue++;
if (action == Library::Container::Action::POP)
Expand Down Expand Up @@ -7662,29 +7662,34 @@ bool isContainerSizeChanged(const Token* tok, const Settings* settings, int dept
return false;
if (!tok->valueType() || !tok->valueType()->container)
return true;
if (Token::Match(tok, "%name% %assign%|<<"))
if (astIsLHS(tok) && Token::Match(tok->astParent(), "%assign%|<<"))
return true;
if (Token::Match(tok, "%var% [") && tok->valueType()->container->stdAssociativeLike)
const Library::Container* container = tok->valueType()->container;
// Views cannot change container size
if (container->view)
return false;
if (astIsLHS(tok) && Token::simpleMatch(tok->astParent(), "["))
return container->stdAssociativeLike;
Library::Container::Action action = astContainerAction(tok);
Library::Container::Yield yield = astContainerYield(tok);
switch (action) {
case Library::Container::Action::RESIZE:
case Library::Container::Action::CLEAR:
case Library::Container::Action::PUSH:
case Library::Container::Action::POP:
case Library::Container::Action::CHANGE:
case Library::Container::Action::INSERT:
case Library::Container::Action::ERASE:
return true;
if (Token::Match(tok, "%name% . %name% (")) {
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
Library::Container::Yield yield = tok->valueType()->container->getYield(tok->strAt(2));
switch (action) {
case Library::Container::Action::RESIZE:
case Library::Container::Action::CLEAR:
case Library::Container::Action::PUSH:
case Library::Container::Action::POP:
case Library::Container::Action::CHANGE:
case Library::Container::Action::INSERT:
case Library::Container::Action::ERASE:
return true;
case Library::Container::Action::NO_ACTION: // might be unknown action
case Library::Container::Action::NO_ACTION:
// Is this an unknown member function call?
if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% ("))
return yield == Library::Container::Yield::NO_YIELD;
case Library::Container::Action::FIND:
case Library::Container::Action::CHANGE_CONTENT:
case Library::Container::Action::CHANGE_INTERNAL:
break;
}
break;
case Library::Container::Action::FIND:
case Library::Container::Action::CHANGE_CONTENT:
case Library::Container::Action::CHANGE_INTERNAL:
break;
}
if (isContainerSizeChangedByFunction(tok, settings, depth))
return true;
Expand Down Expand Up @@ -7796,16 +7801,17 @@ static void valueFlowIterators(TokenList *tokenlist, const Settings *settings)
continue;
if (!astIsContainer(tok))
continue;
if (Token::Match(tok->astParent(), ". %name% (")) {
Library::Container::Yield yield = getLibraryContainer(tok)->getYield(tok->astParent()->strAt(1));
const Token* ftok = nullptr;
Library::Container::Yield yield = astContainerYield(tok, &ftok);
if (ftok) {
ValueFlow::Value v(0);
v.setKnown();
if (yield == Library::Container::Yield::START_ITERATOR) {
v.valueType = ValueFlow::Value::ValueType::ITERATOR_START;
setTokenValue(tok->astParent()->tokAt(2), v, settings);
setTokenValue(ftok->next(), v, settings);
} else if (yield == Library::Container::Yield::END_ITERATOR) {
v.valueType = ValueFlow::Value::ValueType::ITERATOR_END;
setTokenValue(tok->astParent()->tokAt(2), v, settings);
setTokenValue(ftok->next(), v, settings);
}
}
}
Expand Down