Skip to content
Open
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
12 changes: 7 additions & 5 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,9 @@ static const Token * getVariableInitExpression(const Variable * var)

const Token* isInLoopCondition(const Token* tok)
{
const Token* top = tok->astTop();
if (!tok)
return nullptr;
const Token* top = tok->astTop(true);
return Token::Match(top->previous(), "for|while (") ? top : nullptr;
}

Expand Down Expand Up @@ -2243,12 +2245,12 @@ bool isReturnScope(const Token* const endToken, const Library& library, const To
!Token::findsimplematch(prev->link(), "break", prev)) {
return isReturnScope(prev, library, unknownFunc, functionScope);
}
if (isEscaped(prev->link()->astTop(), functionScope, library))
if (isEscaped(prev->link()->astTop(true), functionScope, library))
return true;
if (Token::Match(prev->link()->previous(), "[;{}] {"))
return isReturnScope(prev, library, unknownFunc, functionScope);
} else if (Token::simpleMatch(prev, ";")) {
if (prev->tokAt(-2) && hasNoreturnFunction(prev->tokAt(-2)->astTop(), library, unknownFunc))
if (prev->tokAt(-2) && hasNoreturnFunction(prev->tokAt(-2)->astTop(true), library, unknownFunc))
return true;
// Unknown symbol
if (Token::Match(prev->tokAt(-2), ";|}|{ %name% ;") && prev->previous()->isIncompleteVar()) {
Expand All @@ -2257,9 +2259,9 @@ bool isReturnScope(const Token* const endToken, const Library& library, const To
return false;
}
if (Token::simpleMatch(prev->previous(), ") ;") && prev->linkAt(-1) &&
isEscaped(prev->linkAt(-1)->astTop(), functionScope, library))
isEscaped(prev->linkAt(-1)->astTop(true), functionScope, library))
return true;
if (isEscaped(prev->previous()->astTop(), functionScope, library))
if (isEscaped(prev->previous()->astTop(true), functionScope, library))
return true;
// return/goto statement
prev = prev->previous();
Expand Down
4 changes: 2 additions & 2 deletions lib/checkautovariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ static bool isDeadTemporary(const Token* tok, const Token* expr, const Library&
if (!isTemporary(tok, &library))
return false;
if (expr) {
if (!precedes(nextAfterAstRightmostLeaf(tok->astTop()), nextAfterAstRightmostLeaf(expr->astTop())))
if (!precedes(nextAfterAstRightmostLeaf(tok->astTop(true)), nextAfterAstRightmostLeaf(expr->astTop(true))))
return false;
const Token* parent = tok->astParent();
if (Token::simpleMatch(parent, "{") && Token::simpleMatch(parent->astParent(), ":"))
Expand Down Expand Up @@ -642,7 +642,7 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
}
if (!ValueFlow::isLifetimeBorrowed(tok, *mSettings))
continue;
const Token* nextTok = nextAfterAstRightmostLeaf(tok->astTop());
const Token* nextTok = nextAfterAstRightmostLeaf(tok->astTop(true));
if (!nextTok)
nextTok = tok->next();
if (var && (!var->isLocal() || var->isStatic()) && !var->isArgument() && !(val.tokvalue && val.tokvalue->variable() && val.tokvalue->variable()->isStatic()) &&
Expand Down
4 changes: 2 additions & 2 deletions lib/checkclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1877,7 +1877,7 @@ CheckClass::Bool CheckClass::isInverted(const Token *tok, const Token *rhs)

const Token * CheckClass::getIfStmtBodyStart(const Token *tok, const Token *rhs)
{
const Token *top = tok->astTop();
const Token *top = tok->astTop(true);
if (Token::simpleMatch(top->link(), ") {")) {
switch (isInverted(tok->astParent(), rhs)) {
case Bool::BAILOUT:
Expand Down Expand Up @@ -2522,7 +2522,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member
return false;
parent = parent->astParent();
}
const Token* const top = lhs->astTop();
const Token* const top = lhs->astTop(true);
if (top->isAssignmentOp()) {
if (Token::simpleMatch(top->astOperand2(), "{") && !top->astOperand2()->previous()->function()) // TODO: check usage in init list
return false;
Expand Down
6 changes: 3 additions & 3 deletions lib/checkcondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ static std::string innerSmtString(const Token * tok)
{
if (!tok)
return "if";
const Token * top = tok->astTop();
const Token * top = tok->astTop(true);
if (top->str() == "(" && top->astOperand1())
return top->astOperand1()->str();
return top->str();
Expand Down Expand Up @@ -1138,7 +1138,7 @@ static std::string conditionString(const Token * tok)
}

static bool isIfConstexpr(const Token* tok) {
const Token* const top = tok->astTop();
const Token* const top = tok->astTop(true);
return Token::simpleMatch(top->astOperand1(), "if") && top->astOperand1()->isConstexpr();
}

Expand Down Expand Up @@ -1835,7 +1835,7 @@ void CheckCondition::checkDuplicateConditionalAssign()
continue;
if (!blockTok->next())
continue;
const Token *assignTok = blockTok->next()->astTop();
const Token *assignTok = blockTok->next()->astTop(true);
if (!Token::simpleMatch(assignTok, "="))
continue;
if (nextAfterAstRightmostLeaf(assignTok) != blockTok->link()->previous())
Expand Down
2 changes: 1 addition & 1 deletion lib/checkfunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ void CheckFunctions::checkLibraryMatchFunctions()
if (tok->function())
continue;

if (Token::simpleMatch(tok->astTop(), "throw"))
if (Token::simpleMatch(tok->astTop(true), "throw"))
continue;

if (Token::simpleMatch(tok->astParent(), ".")) {
Expand Down
2 changes: 1 addition & 1 deletion lib/checkleakautovar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI
var->second.type = allocation.type;
var->second.allocTok = allocation.allocTok;
}
} else if (allocation.status != VarInfo::NOALLOC && allocation.status != VarInfo::OWNED && !Token::simpleMatch(tok->astTop(), "return")) {
} else if (allocation.status != VarInfo::NOALLOC && allocation.status != VarInfo::OWNED && !Token::simpleMatch(tok->astTop(true), "return")) {
auto& allocInfo = alloctype[arg->varId()];
allocInfo.status = VarInfo::DEALLOC;
allocInfo.allocTok = tok;
Expand Down
2 changes: 1 addition & 1 deletion lib/checkmemoryleak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
tok2 = tok2->astParent();
if (Token::Match(tok2, "%assign%")) // TODO: check if function returns allocated resource
continue;
if (Token::simpleMatch(tok->astTop(), "return"))
if (Token::simpleMatch(tok->astTop(true), "return"))
continue;

const std::string& functionName = tok->str();
Expand Down
6 changes: 3 additions & 3 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2241,7 +2241,7 @@ static bool isConstTop(const Token *tok)
if (!tok->astParent())
return true;
if (Token::simpleMatch(tok->astParent(), ";") &&
Token::Match(tok->astTop()->previous(), "for|if (") && Token::simpleMatch(tok->astTop()->astOperand2(), ";")) {
Token::Match(tok->astTop(true)->previous(), "for|if (") && Token::simpleMatch(tok->astTop(true)->astOperand2(), ";")) {
if (Token::simpleMatch(tok->astParent()->astParent(), ";"))
return tok->astParent()->astOperand2() == tok;
return tok->astParent()->astOperand1() == tok;
Expand Down Expand Up @@ -2272,7 +2272,7 @@ void CheckOther::checkIncompleteStatement()
continue;
if (!isConstTop(tok))
continue;
if (tok->str() == "," && Token::simpleMatch(tok->astTop()->previous(), "for ("))
if (tok->str() == "," && Token::simpleMatch(tok->astTop(true)->previous(), "for ("))
continue;

// Do not warn for statement when both lhs and rhs has side effects:
Expand Down Expand Up @@ -2540,7 +2540,7 @@ static const Token * getSingleExpressionInBlock(const Token * tok)
{
if (!tok)
return nullptr;
const Token * top = tok->astTop();
const Token * top = tok->astTop(true);
const Token * nextExpression = nextAfterAstRightmostLeaf(top);
if (!Token::simpleMatch(nextExpression, "; }"))
return nullptr;
Expand Down
4 changes: 2 additions & 2 deletions lib/checkstl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1649,7 +1649,7 @@ static const Token* skipLocalVars(const Token* const tok)
return skipLocalVars(tok->next());

if (tok->isAssignmentOp()) {
const Token *top = tok->astTop();
const Token *top = tok->astTop(true);
const Token *varTok = top->astOperand1();
const Variable *var = varTok->variable();
if (!var)
Expand All @@ -1667,7 +1667,7 @@ static const Token* skipLocalVars(const Token* const tok)
static const Token *findInsertValue(const Token *tok, const Token *containerTok, const Token *keyTok, const Settings &settings)
{
const Token *startTok = skipLocalVars(tok);
const Token *top = startTok->astTop();
const Token *top = startTok->astTop(true);

const Token *icontainerTok = nullptr;
const Token *ikeyTok = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion lib/forwardanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ namespace {
// In the middle of a loop structure so bail
return Break(Analyzer::Terminate::Bail);
} else if (tok->str() == ";" && tok->astParent()) {
Token* top = tok->astTop();
Token* top = tok->astTop(true);
if (Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) {
Token* endCond = top->link();
Token* endBlock = endCond->linkAt(1);
Expand Down
4 changes: 2 additions & 2 deletions lib/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,7 @@ bool Library::isScopeNoReturn(const Token *end, std::string *unknownFunc) const
unknownFunc->clear();

if (Token::Match(end->tokAt(-2), "!!{ ; }")) {
const Token *lastTop = end->tokAt(-2)->astTop();
const Token *lastTop = end->tokAt(-2)->astTop(true);
if (Token::simpleMatch(lastTop, "<<") &&
Token::simpleMatch(lastTop->astOperand1(), "(") &&
Token::Match(lastTop->astOperand1()->previous(), "%name% ("))
Expand All @@ -1349,7 +1349,7 @@ bool Library::isScopeNoReturn(const Token *end, std::string *unknownFunc) const
return false;

const Token *funcname = end->linkAt(-2)->previous();
if (funcname->isCpp() && funcname->astTop()->str() == "throw")
if (funcname->isCpp() && funcname->astTop(true)->str() == "throw")
return true;
const Token *start = funcname;
if (Token::Match(funcname->tokAt(-3),"( * %name% )")) {
Expand Down
6 changes: 4 additions & 2 deletions lib/programmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,13 +524,15 @@ void ProgramMemoryState::addState(const Token* tok, const ProgramMemory::Map& va

void ProgramMemoryState::assume(const Token* tok, bool b, bool isEmpty)
{
if (!tok)
return;
ProgramMemory pm = state;
if (isEmpty)
pm.setContainerSizeValue(tok, 0, b);
else
programMemoryParseCondition(pm, tok, nullptr, settings, b);
const Token* origin = tok;
const Token* top = tok->astTop();
const Token* top = tok->astTop(true);
if (Token::Match(top->previous(), "for|while|if (") && !Token::simpleMatch(tok->astParent(), "?")) {
origin = top->link()->next();
if (!b && origin->link()) {
Expand Down Expand Up @@ -1748,7 +1750,7 @@ namespace {
if (!scope->bodyStart)
return {unknown()};
for (const Token* tok = scope->bodyStart->next(); precedes(tok, scope->bodyEnd); tok = tok->next()) {
const Token* top = tok->astTop();
const Token* top = tok->astTop(true);

if (Token::simpleMatch(top, "return") && top->astOperand1())
return {execute(top->astOperand1())};
Expand Down
2 changes: 1 addition & 1 deletion lib/reverseanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ namespace {
if (!condTok)
break;
Analyzer::Action condAction = analyzeRecursive(condTok);
const bool inLoop = Token::Match(condTok->astTop()->previous(), "for|while (");
const bool inLoop = Token::Match(condTok->astTop(true)->previous(), "for|while (");
// Evaluate condition of for and while loops first
if (inLoop) {
if (Token::findmatch(tok->link(), "goto|break", tok))
Expand Down
2 changes: 1 addition & 1 deletion lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5369,7 +5369,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::set<st
return nullptr;

if (tok->scope()->type == ScopeType::eGlobal) {
const Token* astTop = tok->astTop();
const Token* astTop = tok->astTop(true);
if (Token::simpleMatch(astTop, ":") && Token::simpleMatch(astTop->astOperand1(), "(")) { // ctor init list
const Token* ctor = astTop->astOperand1()->previous();
if (ctor && ctor->function() && ctor->function()->nestedIn)
Expand Down
4 changes: 2 additions & 2 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ void Token::astOperand1(Token *tok)
mImpl->mAstOperand1->astParent(nullptr);
// goto parent operator
if (tok) {
tok = tok->astTop();
tok = tok->astTop(false);
tok->astParent(this);
}
mImpl->mAstOperand1 = tok;
Expand All @@ -1449,7 +1449,7 @@ void Token::astOperand2(Token *tok)
mImpl->mAstOperand2->astParent(nullptr);
// goto parent operator
if (tok) {
tok = tok->astTop();
tok = tok->astTop(false);
tok->astParent(this);
}
mImpl->mAstOperand2 = tok;
Expand Down
19 changes: 17 additions & 2 deletions lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct TokenImpl {
Token* mAstOperand1{};
Token* mAstOperand2{};
Token* mAstParent{};
Token* mAstTop{};

// symbol database information
const Scope* mScope{};
Expand Down Expand Up @@ -1531,17 +1532,31 @@ class CPPCHECKLIB Token {
return nullptr;

}
RET_NONNULL Token *astTop() {
/** If the ast tree has not been created, pls make sure to use cache=false,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the "pls" :-)

as the real top has not been identified finally. */
RET_NONNULL Token *astTop(bool cache) {
Token *ret = this;
if (cache && mImpl->mAstTop) {
return mImpl->mAstTop;
}
while (ret->mImpl->mAstParent)
ret = ret->mImpl->mAstParent;
if (cache) {
mImpl->mAstTop = ret;
}
return ret;
}

RET_NONNULL const Token *astTop() const {
RET_NONNULL const Token *astTop(bool cache) const {
const Token *ret = this;
if (cache && mImpl->mAstTop) {
return mImpl->mAstTop;
}
while (ret->mImpl->mAstParent)
ret = ret->mImpl->mAstParent;
if (cache) {
mImpl->mAstTop = const_cast<Token *>(ret);
}
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/tokenlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1728,7 +1728,7 @@ static Token * createAstAtToken(Token *tok)
}

if (init != semicolon1)
semicolon1->astOperand1(init->astTop());
semicolon1->astOperand1(init->astTop(false));
tok->next()->astOperand1(tok);
tok->next()->astOperand2(semicolon1);

Expand Down
18 changes: 9 additions & 9 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,7 +1575,7 @@ static bool isConditionKnown(const Token* tok, bool then)
const Token* parent = tok->astParent();
while (parent && (parent->str() == op || parent->str() == "!" || parent->isCast()))
parent = parent->astParent();
const Token* top = tok->astTop();
const Token* top = tok->astTop(true);
if (Token::Match(top->previous(), "if|while|for ("))
return parent == top || Token::simpleMatch(parent, ";");
return parent && parent->str() != op;
Expand Down Expand Up @@ -2105,7 +2105,7 @@ const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* default
if (!end || (smallest ? precedes(varEnd, end) : succeeds(varEnd, end)))
end = varEnd;

const Token* top = var->nameToken()->astTop();
const Token* top = var->nameToken()->astTop(true);
if (Token::simpleMatch(top->tokAt(-1), "if (")) { // variable declared in if (...)
const Token* elseTok = top->link()->linkAt(1);
if (Token::simpleMatch(elseTok, "} else {") && tok->scope()->isNestedIn(elseTok->tokAt(2)->scope()))
Expand Down Expand Up @@ -4599,7 +4599,7 @@ struct ConditionHandler {
if (Token::Match(tok, ":|;|,"))
continue;

const Token* top = tok->astTop();
const Token* top = tok->astTop(true);

if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?|!"))
continue;
Expand Down Expand Up @@ -4633,7 +4633,7 @@ struct ConditionHandler {
if (tok->hasKnownIntValue())
return;

Token* top = tok->astTop();
Token* top = tok->astTop(true);

if (Token::Match(top, "%assign%"))
return;
Expand Down Expand Up @@ -4852,7 +4852,7 @@ struct ConditionHandler {
}
}

Token* top = condTok->astTop();
Token* top = condTok->astTop(true);

if (top->previous()->isExpandedMacro()) {
for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
Expand Down Expand Up @@ -5414,7 +5414,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
}

if (Token::Match(tok2, "%oror%|&&")) {
const ProgramMemory programMemory(getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings));
const ProgramMemory programMemory(getProgramMemory(tok2->astTop(true), expr, ValueFlow::Value(value), settings));
if ((tok2->str() == "&&" && !conditionIsTrue(tok2->astOperand1(), programMemory, settings)) ||
(tok2->str() == "||" && !conditionIsFalse(tok2->astOperand1(), programMemory, settings))) {
// Skip second expression..
Expand All @@ -5439,11 +5439,11 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,

if ((tok2->str() == "&&" &&
conditionIsFalse(tok2->astOperand1(),
getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings),
getProgramMemory(tok2->astTop(true), expr, ValueFlow::Value(value), settings),
settings)) ||
(tok2->str() == "||" &&
conditionIsTrue(tok2->astOperand1(),
getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings),
getProgramMemory(tok2->astTop(true), expr, ValueFlow::Value(value), settings),
settings)))
break;

Expand Down Expand Up @@ -6799,7 +6799,7 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
!Token::Match(nameToken, "%name% ("))
continue;
}
if (Token::Match(nameToken->astTop()->previous(), "for|while"))
if (Token::Match(nameToken->astTop(true)->previous(), "for|while"))
known = !isVariableChanged(var, settings);
std::vector<ValueFlow::Value> values{ValueFlow::Value{size}};
values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
Expand Down
Loading