Refactor to use AST for isContainerSizeChanged (#4222)

This commit is contained in:
Paul Fultz II 2022-06-19 01:17:05 -05:00 committed by GitHub
parent e6fdcb9de2
commit e735376f7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 33 deletions

View File

@ -271,12 +271,23 @@ static const Token* getContainerFunction(const Token* tok)
return nullptr; return nullptr;
} }
Library::Container::Action astContainerAction(const Token* tok) Library::Container::Action astContainerAction(const Token* tok, const Token** ftok)
{ {
const Token* ftok = getContainerFunction(tok); const Token* ftok2 = getContainerFunction(tok);
if (!ftok) if (ftok)
*ftok = ftok2;
if (!ftok2)
return Library::Container::Action::NO_ACTION; 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) bool astIsRangeBasedForDecl(const Token* tok)

View File

@ -139,7 +139,8 @@ bool astIsContainer(const Token *tok);
bool astIsContainerView(const Token* tok); bool astIsContainerView(const Token* tok);
bool astIsContainerOwned(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 */ /** Is given token a range-declaration in a range-based for loop */
bool astIsRangeBasedForDecl(const Token* tok); bool astIsRangeBasedForDecl(const Token* tok);

View File

@ -7498,8 +7498,8 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
})) }))
return Action::Read | Action::Write | Action::Incremental; return Action::Read | Action::Write | Action::Incremental;
} }
} else if (Token::Match(tok, "%name% . %name% (")) { } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
Library::Container::Action action = container->getAction(tok->strAt(2)); Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) { if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) {
std::vector<const Token*> args = getArguments(tok->tokAt(3)); std::vector<const Token*> args = getArguments(tok->tokAt(3));
if (args.size() < 2) if (args.size() < 2)
@ -7535,8 +7535,8 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
} }
} }
} }
} else if (Token::Match(tok, "%name% . %name% (")) { } else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
Library::Container::Action action = container->getAction(tok->strAt(2)); Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
if (action == Library::Container::Action::PUSH) if (action == Library::Container::Action::PUSH)
val->intvalue++; val->intvalue++;
if (action == Library::Container::Action::POP) if (action == Library::Container::Action::POP)
@ -7661,29 +7661,34 @@ bool isContainerSizeChanged(const Token* tok, const Settings* settings, int dept
return false; return false;
if (!tok->valueType() || !tok->valueType()->container) if (!tok->valueType() || !tok->valueType()->container)
return true; return true;
if (Token::Match(tok, "%name% %assign%|<<")) if (astIsLHS(tok) && Token::Match(tok->astParent(), "%assign%|<<"))
return true; 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; return true;
if (Token::Match(tok, "%name% . %name% (")) { case Library::Container::Action::NO_ACTION:
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2)); // Is this an unknown member function call?
Library::Container::Yield yield = tok->valueType()->container->getYield(tok->strAt(2)); if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% ("))
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
return yield == Library::Container::Yield::NO_YIELD; return yield == Library::Container::Yield::NO_YIELD;
case Library::Container::Action::FIND: break;
case Library::Container::Action::CHANGE_CONTENT: case Library::Container::Action::FIND:
case Library::Container::Action::CHANGE_INTERNAL: case Library::Container::Action::CHANGE_CONTENT:
break; case Library::Container::Action::CHANGE_INTERNAL:
} break;
} }
if (isContainerSizeChangedByFunction(tok, settings, depth)) if (isContainerSizeChangedByFunction(tok, settings, depth))
return true; return true;
@ -7795,16 +7800,17 @@ static void valueFlowIterators(TokenList *tokenlist, const Settings *settings)
continue; continue;
if (!astIsContainer(tok)) if (!astIsContainer(tok))
continue; continue;
if (Token::Match(tok->astParent(), ". %name% (")) { const Token* ftok = nullptr;
Library::Container::Yield yield = getLibraryContainer(tok)->getYield(tok->astParent()->strAt(1)); Library::Container::Yield yield = astContainerYield(tok, &ftok);
if (ftok) {
ValueFlow::Value v(0); ValueFlow::Value v(0);
v.setKnown(); v.setKnown();
if (yield == Library::Container::Yield::START_ITERATOR) { if (yield == Library::Container::Yield::START_ITERATOR) {
v.valueType = ValueFlow::Value::ValueType::ITERATOR_START; 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) { } else if (yield == Library::Container::Yield::END_ITERATOR) {
v.valueType = ValueFlow::Value::ValueType::ITERATOR_END; v.valueType = ValueFlow::Value::ValueType::ITERATOR_END;
setTokenValue(tok->astParent()->tokAt(2), v, settings); setTokenValue(ftok->next(), v, settings);
} }
} }
} }