Skip to content

Commit e735376

Browse files
authored
Refactor to use AST for isContainerSizeChanged (#4222)
1 parent e6fdcb9 commit e735376

3 files changed

Lines changed: 51 additions & 33 deletions

File tree

lib/astutils.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,23 @@ static const Token* getContainerFunction(const Token* tok)
271271
return nullptr;
272272
}
273273

274-
Library::Container::Action astContainerAction(const Token* tok)
274+
Library::Container::Action astContainerAction(const Token* tok, const Token** ftok)
275275
{
276-
const Token* ftok = getContainerFunction(tok);
277-
if (!ftok)
276+
const Token* ftok2 = getContainerFunction(tok);
277+
if (ftok)
278+
*ftok = ftok2;
279+
if (!ftok2)
278280
return Library::Container::Action::NO_ACTION;
279-
return tok->valueType()->container->getAction(ftok->str());
281+
return tok->valueType()->container->getAction(ftok2->str());
282+
}
283+
Library::Container::Yield astContainerYield(const Token* tok, const Token** ftok)
284+
{
285+
const Token* ftok2 = getContainerFunction(tok);
286+
if (ftok)
287+
*ftok = ftok2;
288+
if (!ftok2)
289+
return Library::Container::Yield::NO_YIELD;
290+
return tok->valueType()->container->getYield(ftok2->str());
280291
}
281292

282293
bool astIsRangeBasedForDecl(const Token* tok)

lib/astutils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ bool astIsContainer(const Token *tok);
139139
bool astIsContainerView(const Token* tok);
140140
bool astIsContainerOwned(const Token* tok);
141141

142-
Library::Container::Action astContainerAction(const Token* tok);
142+
Library::Container::Action astContainerAction(const Token* tok, const Token** ftok = nullptr);
143+
Library::Container::Yield astContainerYield(const Token* tok, const Token** ftok = nullptr);
143144

144145
/** Is given token a range-declaration in a range-based for loop */
145146
bool astIsRangeBasedForDecl(const Token* tok);

lib/valueflow.cpp

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7498,8 +7498,8 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
74987498
}))
74997499
return Action::Read | Action::Write | Action::Incremental;
75007500
}
7501-
} else if (Token::Match(tok, "%name% . %name% (")) {
7502-
Library::Container::Action action = container->getAction(tok->strAt(2));
7501+
} else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
7502+
Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
75037503
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) {
75047504
std::vector<const Token*> args = getArguments(tok->tokAt(3));
75057505
if (args.size() < 2)
@@ -7535,8 +7535,8 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
75357535
}
75367536
}
75377537
}
7538-
} else if (Token::Match(tok, "%name% . %name% (")) {
7539-
Library::Container::Action action = container->getAction(tok->strAt(2));
7538+
} else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
7539+
Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
75407540
if (action == Library::Container::Action::PUSH)
75417541
val->intvalue++;
75427542
if (action == Library::Container::Action::POP)
@@ -7661,29 +7661,34 @@ bool isContainerSizeChanged(const Token* tok, const Settings* settings, int dept
76617661
return false;
76627662
if (!tok->valueType() || !tok->valueType()->container)
76637663
return true;
7664-
if (Token::Match(tok, "%name% %assign%|<<"))
7664+
if (astIsLHS(tok) && Token::Match(tok->astParent(), "%assign%|<<"))
76657665
return true;
7666-
if (Token::Match(tok, "%var% [") && tok->valueType()->container->stdAssociativeLike)
7666+
const Library::Container* container = tok->valueType()->container;
7667+
// Views cannot change container size
7668+
if (container->view)
7669+
return false;
7670+
if (astIsLHS(tok) && Token::simpleMatch(tok->astParent(), "["))
7671+
return container->stdAssociativeLike;
7672+
Library::Container::Action action = astContainerAction(tok);
7673+
Library::Container::Yield yield = astContainerYield(tok);
7674+
switch (action) {
7675+
case Library::Container::Action::RESIZE:
7676+
case Library::Container::Action::CLEAR:
7677+
case Library::Container::Action::PUSH:
7678+
case Library::Container::Action::POP:
7679+
case Library::Container::Action::CHANGE:
7680+
case Library::Container::Action::INSERT:
7681+
case Library::Container::Action::ERASE:
76677682
return true;
7668-
if (Token::Match(tok, "%name% . %name% (")) {
7669-
Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2));
7670-
Library::Container::Yield yield = tok->valueType()->container->getYield(tok->strAt(2));
7671-
switch (action) {
7672-
case Library::Container::Action::RESIZE:
7673-
case Library::Container::Action::CLEAR:
7674-
case Library::Container::Action::PUSH:
7675-
case Library::Container::Action::POP:
7676-
case Library::Container::Action::CHANGE:
7677-
case Library::Container::Action::INSERT:
7678-
case Library::Container::Action::ERASE:
7679-
return true;
7680-
case Library::Container::Action::NO_ACTION: // might be unknown action
7683+
case Library::Container::Action::NO_ACTION:
7684+
// Is this an unknown member function call?
7685+
if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% ("))
76817686
return yield == Library::Container::Yield::NO_YIELD;
7682-
case Library::Container::Action::FIND:
7683-
case Library::Container::Action::CHANGE_CONTENT:
7684-
case Library::Container::Action::CHANGE_INTERNAL:
7685-
break;
7686-
}
7687+
break;
7688+
case Library::Container::Action::FIND:
7689+
case Library::Container::Action::CHANGE_CONTENT:
7690+
case Library::Container::Action::CHANGE_INTERNAL:
7691+
break;
76877692
}
76887693
if (isContainerSizeChangedByFunction(tok, settings, depth))
76897694
return true;
@@ -7795,16 +7800,17 @@ static void valueFlowIterators(TokenList *tokenlist, const Settings *settings)
77957800
continue;
77967801
if (!astIsContainer(tok))
77977802
continue;
7798-
if (Token::Match(tok->astParent(), ". %name% (")) {
7799-
Library::Container::Yield yield = getLibraryContainer(tok)->getYield(tok->astParent()->strAt(1));
7803+
const Token* ftok = nullptr;
7804+
Library::Container::Yield yield = astContainerYield(tok, &ftok);
7805+
if (ftok) {
78007806
ValueFlow::Value v(0);
78017807
v.setKnown();
78027808
if (yield == Library::Container::Yield::START_ITERATOR) {
78037809
v.valueType = ValueFlow::Value::ValueType::ITERATOR_START;
7804-
setTokenValue(tok->astParent()->tokAt(2), v, settings);
7810+
setTokenValue(ftok->next(), v, settings);
78057811
} else if (yield == Library::Container::Yield::END_ITERATOR) {
78067812
v.valueType = ValueFlow::Value::ValueType::ITERATOR_END;
7807-
setTokenValue(tok->astParent()->tokAt(2), v, settings);
7813+
setTokenValue(ftok->next(), v, settings);
78087814
}
78097815
}
78107816
}

0 commit comments

Comments
 (0)