From c1c10f1dc7e5699e1ce4a33c88b09a083758b8d6 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 1 Jun 2024 21:59:19 +0200 Subject: [PATCH 1/6] CheckInternal::checkRedundantNextPrevious(): Fix FN, simplify --- lib/astutils.cpp | 10 ++--- lib/checkassert.cpp | 2 +- lib/checkboost.cpp | 2 +- lib/checkbufferoverrun.cpp | 2 +- lib/checkclass.cpp | 12 ++--- lib/checkcondition.cpp | 12 ++--- lib/checkexceptionsafety.cpp | 10 ++--- lib/checkinternal.cpp | 10 +---- lib/checkleakautovar.cpp | 2 +- lib/checkmemoryleak.cpp | 16 +++---- lib/checknullpointer.cpp | 6 +-- lib/checkother.cpp | 8 ++-- lib/checkstl.cpp | 18 ++++---- lib/checkstring.cpp | 4 +- lib/checkuninitvar.cpp | 8 ++-- lib/checkunusedvar.cpp | 4 +- lib/findtoken.h | 2 +- lib/forwardanalyzer.cpp | 10 ++--- lib/pathanalysis.cpp | 8 ++-- lib/symboldatabase.cpp | 70 ++++++++++++++--------------- lib/templatesimplifier.cpp | 12 ++--- lib/tokenize.cpp | 86 ++++++++++++++++++------------------ lib/tokenlist.cpp | 8 ++-- lib/valueflow.cpp | 12 ++--- test/testinternal.cpp | 22 +++++---- 25 files changed, 177 insertions(+), 179 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index efe879e180d..a6ffa107878 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -484,7 +484,7 @@ static bool isFunctionCall(const Token* tok) { if (Token::Match(tok, "%name% (")) return true; - if (Token::Match(tok, "%name% <") && Token::simpleMatch(tok->next()->link(), "> (")) + if (Token::Match(tok, "%name% <") && Token::simpleMatch(tok->linkAt(1), "> (")) return true; if (Token::Match(tok, "%name% ::")) return isFunctionCall(tok->tokAt(2)); @@ -538,7 +538,7 @@ static T* nextAfterAstRightmostLeafGeneric(T* tok) else break; } while (rightmostLeaf->astOperand1() || rightmostLeaf->astOperand2()); - while (Token::Match(rightmostLeaf->next(), "]|)") && !hasToken(rightmostLeaf->next()->link(), rightmostLeaf->next(), tok)) + while (Token::Match(rightmostLeaf->next(), "]|)") && !hasToken(rightmostLeaf->linkAt(1), rightmostLeaf->next(), tok)) rightmostLeaf = rightmostLeaf->next(); if (Token::Match(rightmostLeaf, "{|(|[") && rightmostLeaf->link()) rightmostLeaf = rightmostLeaf->link(); @@ -1694,11 +1694,11 @@ bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Se } } // templates/casts - if ((tok1->next() && tok1->next()->link() && Token::Match(tok1, "%name% <")) || - (tok2->next() && tok2->next()->link() && Token::Match(tok2, "%name% <"))) { + if ((tok1->next() && tok1->linkAt(1) && Token::Match(tok1, "%name% <")) || + (tok2->next() && tok2->linkAt(1) && Token::Match(tok2, "%name% <"))) { // non-const template function that is not a dynamic_cast => return false - if (pure && Token::simpleMatch(tok1->next()->link(), "> (") && + if (pure && Token::simpleMatch(tok1->linkAt(1), "> (") && !(tok1->function() && tok1->function()->isConst()) && tok1->str() != "dynamic_cast") return false; diff --git a/lib/checkassert.cpp b/lib/checkassert.cpp index 26d0c93b8cc..7bdff94a119 100644 --- a/lib/checkassert.cpp +++ b/lib/checkassert.cpp @@ -55,7 +55,7 @@ void CheckAssert::assertWithSideEffects() if (!Token::simpleMatch(tok, "assert (")) continue; - const Token *endTok = tok->next()->link(); + const Token *endTok = tok->linkAt(1); for (const Token* tmp = tok->next(); tmp != endTok; tmp = tmp->next()) { if (Token::simpleMatch(tmp, "sizeof (")) tmp = tmp->linkAt(1); diff --git a/lib/checkboost.cpp b/lib/checkboost.cpp index 4913a691fba..b5c3612b78a 100644 --- a/lib/checkboost.cpp +++ b/lib/checkboost.cpp @@ -40,7 +40,7 @@ void CheckBoost::checkBoostForeachModification() if (!Token::simpleMatch(tok, "BOOST_FOREACH (")) continue; - const Token *containerTok = tok->next()->link()->previous(); + const Token *containerTok = tok->linkAt(1)->previous(); if (!Token::Match(containerTok, "%var% ) {")) continue; diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index 45820f02de4..144ae310919 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -787,7 +787,7 @@ void CheckBufferOverrun::stringNotZeroTerminated() } // Is the buffer zero terminated after the call? bool isZeroTerminated = false; - for (const Token *tok2 = tok->next()->link(); tok2 != scope->bodyEnd; tok2 = tok2->next()) { + for (const Token *tok2 = tok->linkAt(1); tok2 != scope->bodyEnd; tok2 = tok2->next()) { if (!Token::simpleMatch(tok2, "] =")) continue; const Token *rhs = tok2->next()->astOperand2(); diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c05d60478ca..5253824e45b 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -949,7 +949,7 @@ void CheckClass::initializeVarList(const Function &func, std::listnext(); // Passing "this" => assume that everything is initialized - for (const Token *tok2 = ftok->next()->link(); tok2 && tok2 != ftok; tok2 = tok2->previous()) { + for (const Token *tok2 = ftok->linkAt(1); tok2 && tok2 != ftok; tok2 = tok2->previous()) { if (tok2->str() == "this") { assignAllVar(usage); return; @@ -1020,7 +1020,7 @@ void CheckClass::initializeVarList(const Function &func, std::listtokAt(2); tok && tok != ftok->next()->link(); tok = tok->next()) { + for (const Token *tok = ftok->tokAt(2); tok && tok != ftok->linkAt(1); tok = tok->next()) { if (tok->isName()) { assignVar(usage, tok->varId()); } @@ -1047,7 +1047,7 @@ void CheckClass::initializeVarList(const Function &func, std::liststrAt(1) == "[") - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); else if (Token::Match(tok2->next(), ". %name%")) tok2 = tok2->tokAt(2); else @@ -1637,7 +1637,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co // avoid endless recursions if (analyzedFunctions.find(&*it) == analyzedFunctions.end()) { analyzedFunctions.insert(&*it); - checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->next()->link(), + checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->linkAt(1), analyzedFunctions); } // just bail for now @@ -1853,7 +1853,7 @@ const Token * CheckClass::getIfStmtBodyStart(const Token *tok, const Token *rhs) case Bool::TRUE: return top->link()->next(); case Bool::FALSE: - return top->link()->next()->link(); + return top->link()->linkAt(1); } } return nullptr; @@ -2407,7 +2407,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member const Token *lpar = funcTok->next(); if (Token::simpleMatch(lpar, "( ) (")) lpar = lpar->tokAt(2); - for (const Token* tok = lpar->next(); tok && tok != funcTok->next()->link(); tok = tok->next()) { + for (const Token* tok = lpar->next(); tok && tok != funcTok->linkAt(1); tok = tok->next()) { if (tok->str() == "(") tok = tok->link(); else if ((tok->isName() && isMemberVar(scope, tok)) || (tok->isUnaryOp("&") && (tok = tok->astOperand1()) && isMemberVar(scope, tok))) { diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index bc1df36aacc..6ecf3330509 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -191,7 +191,7 @@ bool CheckCondition::assignIfParseScope(const Token * const assignTok, ret = true; if (ret && tok2->str() == ";") return false; - if (!islocal && Token::Match(tok2, "%name% (") && !Token::simpleMatch(tok2->next()->link(), ") {")) + if (!islocal && Token::Match(tok2, "%name% (") && !Token::simpleMatch(tok2->linkAt(1), ") {")) return true; if (Token::Match(tok2, "if|while (")) { if (!islocal && tok2->str() == "while") @@ -205,7 +205,7 @@ bool CheckCondition::assignIfParseScope(const Token * const assignTok, } // parse condition - const Token * const end = tok2->next()->link(); + const Token * const end = tok2->linkAt(1); for (; tok2 != end; tok2 = tok2->next()) { if (Token::Match(tok2, "[(,] &| %varid% [,)]", varid)) { return true; @@ -227,8 +227,8 @@ bool CheckCondition::assignIfParseScope(const Token * const assignTok, const bool ret1 = assignIfParseScope(assignTok, end->tokAt(2), varid, islocal, bitop, num); bool ret2 = false; - if (Token::simpleMatch(end->next()->link(), "} else {")) - ret2 = assignIfParseScope(assignTok, end->next()->link()->tokAt(3), varid, islocal, bitop, num); + if (Token::simpleMatch(end->linkAt(1), "} else {")) + ret2 = assignIfParseScope(assignTok, end->linkAt(1)->tokAt(3), varid, islocal, bitop, num); if (ret1 || ret2) return true; } @@ -1803,9 +1803,9 @@ void CheckCondition::checkDuplicateConditionalAssign() for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { if (!Token::simpleMatch(tok, "if (")) continue; - if (!Token::simpleMatch(tok->next()->link(), ") {")) + if (!Token::simpleMatch(tok->linkAt(1), ") {")) continue; - const Token *blockTok = tok->next()->link()->next(); + const Token *blockTok = tok->linkAt(1)->next(); const Token *condTok = tok->next()->astOperand2(); const bool isBoolVar = Token::Match(condTok, "!| %var%"); if (!isBoolVar && !Token::Match(condTok, "==|!=")) diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index c4e1e5c0c94..12aa3f1dac5 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -63,13 +63,13 @@ void CheckExceptionSafety::destructors() for (const Token *tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { // Skip try blocks if (Token::simpleMatch(tok, "try {")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); } // Skip uncaught exceptions else if (Token::simpleMatch(tok, "if ( ! std :: uncaught_exception ( ) ) {")) { - tok = tok->next()->link(); // end of if ( ... ) - tok = tok->next()->link(); // end of { ... } + tok = tok->linkAt(1); // end of if ( ... ) + tok = tok->linkAt(1); // end of { ... } } // throw found within a destructor @@ -183,8 +183,8 @@ void CheckExceptionSafety::checkRethrowCopy() const unsigned int varid = scope.bodyStart->tokAt(-2)->varId(); if (varid) { for (const Token* tok = scope.bodyStart->next(); tok && tok != scope.bodyEnd; tok = tok->next()) { - if (Token::simpleMatch(tok, "catch (") && tok->next()->link() && tok->next()->link()->next()) { // Don't check inner catch - it is handled in another iteration of outer loop. - tok = tok->next()->link()->next()->link(); + if (Token::simpleMatch(tok, "catch (") && tok->linkAt(1) && tok->linkAt(1)->next()) { // Don't check inner catch - it is handled in another iteration of outer loop. + tok = tok->linkAt(1)->linkAt(1); if (!tok) break; } else if (Token::Match(tok, "%varid% .", varid)) { diff --git a/lib/checkinternal.cpp b/lib/checkinternal.cpp index b152389bad5..d34e07e6615 100644 --- a/lib/checkinternal.cpp +++ b/lib/checkinternal.cpp @@ -296,7 +296,7 @@ void CheckInternal::checkRedundantNextPrevious() continue; tok = tok->next(); - if (Token::Match(tok, "previous ( ) . next|tokAt|strAt|linkAt (") || Token::Match(tok, "next ( ) . previous|tokAt|strAt|linkAt (") || + if (Token::Match(tok, "previous ( ) . previous|next|tokAt|str|strAt|link|linkAt (") || Token::Match(tok, "next ( ) . previous|next|tokAt|str|strAt|link|linkAt (") || (Token::simpleMatch(tok, "tokAt (") && Token::Match(tok->linkAt(1), ") . previous|next|tokAt|strAt|linkAt|str|link ("))) { const std::string& func1 = tok->str(); const std::string& func2 = tok->linkAt(1)->strAt(2); @@ -304,14 +304,6 @@ void CheckInternal::checkRedundantNextPrevious() if ((func2 == "previous" || func2 == "next" || func2 == "str" || func2 == "link") && tok->linkAt(1)->strAt(4) != ")") continue; - redundantNextPreviousError(tok, func1, func2); - } else if (Token::Match(tok, "next|previous ( ) . next|previous ( ) . next|previous|linkAt|strAt|link|str (")) { - const std::string& func1 = tok->str(); - const std::string& func2 = tok->strAt(8); - - if ((func2 == "previous" || func2 == "next" || func2 == "str" || func2 == "link") && tok->strAt(10) != ")") - continue; - redundantNextPreviousError(tok, func1, func2); } } diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 2f3a26a58f5..d71865c3312 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -701,7 +701,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, continue; functionCall(ftok, openingPar, varInfo, allocation, af); - tok = ftok->next()->link(); + tok = ftok->linkAt(1); // Handle scopes that might be noreturn if (allocation.status == VarInfo::NOALLOC && Token::simpleMatch(tok, ") ; }")) { diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index e9f7d4100aa..76aea729a55 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -860,20 +860,20 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const vari else if (Token::simpleMatch(tok3, "if (") && notvar(tok3->next()->astOperand2(), structmemberid)) { // Goto the ")" - tok3 = tok3->next()->link(); + tok3 = tok3->linkAt(1); // make sure we have ") {".. it should be if (!Token::simpleMatch(tok3, ") {")) break; // Goto the "}" - tok3 = tok3->next()->link(); + tok3 = tok3->linkAt(1); } // succeeded allocation else if (ifvar(tok3, structmemberid, "!=", "0")) { // goto the ")" - tok3 = tok3->next()->link(); + tok3 = tok3->linkAt(1); // check if the variable is deallocated or returned.. int indentlevel4 = 0; @@ -1103,7 +1103,7 @@ void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope) for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { if (Token::Match(tok, "%name% (")) { - const Token *endParamToken = tok->next()->link(); + const Token *endParamToken = tok->linkAt(1); const Token* pointerType = nullptr; const Token* functionCalled = nullptr; @@ -1112,12 +1112,12 @@ void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope) const Function *func = tok2->function(); const bool isNothrow = func && (func->isAttributeNothrow() || func->isThrow()); - if (Token::Match(tok2, "shared_ptr|unique_ptr <") && Token::Match(tok2->next()->link(), "> ( new %name%")) { + if (Token::Match(tok2, "shared_ptr|unique_ptr <") && Token::Match(tok2->linkAt(1), "> ( new %name%")) { pointerType = tok2; } else if (!isNothrow) { if (Token::Match(tok2, "%name% (")) functionCalled = tok2; - else if (tok2->isName() && Token::simpleMatch(tok2->next()->link(), "> (")) + else if (tok2->isName() && Token::simpleMatch(tok2->linkAt(1), "> (")) functionCalled = tok2; } } @@ -1126,12 +1126,12 @@ void CheckMemoryLeakNoVar::checkForUnsafeArgAlloc(const Scope *scope) std::string functionName = functionCalled->str(); if (functionCalled->strAt(1) == "<") { functionName += '<'; - for (const Token* tok2 = functionCalled->tokAt(2); tok2 != functionCalled->next()->link(); tok2 = tok2->next()) + for (const Token* tok2 = functionCalled->tokAt(2); tok2 != functionCalled->linkAt(1); tok2 = tok2->next()) functionName += tok2->str(); functionName += '>'; } std::string objectTypeName; - for (const Token* tok2 = pointerType->tokAt(2); tok2 != pointerType->next()->link(); tok2 = tok2->next()) + for (const Token* tok2 = pointerType->tokAt(2); tok2 != pointerType->linkAt(1); tok2 = tok2->next()) objectTypeName += tok2->str(); unsafeArgAllocError(tok, functionName, pointerType->str(), objectTypeName); diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 35a0219276b..6e034738260 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -285,7 +285,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (isUnevaluated(tok)) { - tok = tok->next()->link(); + tok = tok->linkAt(1); continue; } @@ -347,7 +347,7 @@ void CheckNullPointer::nullConstantDereference() for (; tok != scope->bodyEnd; tok = tok->next()) { if (isUnevaluated(tok)) - tok = tok->next()->link(); + tok = tok->linkAt(1); else if (Token::simpleMatch(tok, "* 0")) { if (Token::Match(tok->previous(), "return|throw|;|{|}|:|[|(|,") || tok->previous()->isOp()) { @@ -355,7 +355,7 @@ void CheckNullPointer::nullConstantDereference() } } - else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->next()->link()->next(), "[.(]"))) + else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->linkAt(1)->next(), "[.(]"))) nullPointerError(tok); else if (Token::Match(tok->previous(), "!!. %name% (|{") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 13fc6359078..711360e7aaa 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2529,7 +2529,7 @@ void CheckOther::checkDuplicateExpression() if (isWithoutSideEffects(tok->astOperand1())) { const Token* loopTok = isInLoopCondition(tok); if (!loopTok || - !findExpressionChanged(tok, tok, loopTok->link()->next()->link(), *mSettings)) { + !findExpressionChanged(tok, tok, loopTok->link()->linkAt(1), *mSettings)) { const bool isEnum = tok->scope()->type == Scope::eEnum; const bool assignment = !isEnum && tok->str() == "="; if (assignment) @@ -3215,11 +3215,11 @@ void CheckOther::checkInterlockedDecrement() raceAfterInterlockedDecrementError(checkStartTok); } } else if (Token::Match(tok, "if ( ::| InterlockedDecrement ( & %name%")) { - const Token* condEnd = tok->next()->link(); + const Token* condEnd = tok->linkAt(1); const Token* funcTok = tok->tokAt(2); const Token* firstAccessTok = funcTok->str() == "::" ? funcTok->tokAt(4) : funcTok->tokAt(3); - if (condEnd && condEnd->next() && condEnd->next()->link()) { - const Token* ifEndTok = condEnd->next()->link(); + if (condEnd && condEnd->next() && condEnd->linkAt(1)) { + const Token* ifEndTok = condEnd->linkAt(1); if (Token::Match(ifEndTok, "} return %name%")) { const Token* secondAccessTok = ifEndTok->tokAt(2); if (secondAccessTok->str() == firstAccessTok->str()) { diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 07453a26f49..61deb6d0d57 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1110,7 +1110,7 @@ void CheckStl::invalidContainer() for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (const Token* contTok = getLoopContainer(tok)) { - const Token* blockStart = tok->next()->link()->next(); + const Token* blockStart = tok->linkAt(1)->next(); const Token* blockEnd = blockStart->link(); if (contTok->exprId() == 0) continue; @@ -1688,7 +1688,7 @@ void CheckStl::checkFindInsert() for (const Token *tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (!Token::simpleMatch(tok, "if (")) continue; - if (!Token::simpleMatch(tok->next()->link(), ") {")) + if (!Token::simpleMatch(tok->linkAt(1), ") {")) continue; if (!Token::Match(tok->next()->astOperand2(), "%comp%")) continue; @@ -1702,7 +1702,7 @@ void CheckStl::checkFindInsert() if (mSettings->standards.cpp < Standards::CPP17 && !(keyTok && keyTok->valueType() && (keyTok->valueType()->isIntegral() || keyTok->valueType()->pointer > 0))) continue; - const Token *thenTok = tok->next()->link()->next(); + const Token *thenTok = tok->linkAt(1)->next(); const Token *valueTok = findInsertValue(thenTok, containerTok, keyTok, *mSettings); if (!valueTok) continue; @@ -2040,7 +2040,7 @@ void CheckStl::string_c_str() else break; if (!tok2 && j == i->second.n - 1) - tok2 = tok->next()->link(); + tok2 = tok->linkAt(1); else if (tok2) tok2 = tok2->previous(); else @@ -2420,7 +2420,7 @@ void CheckStl::checkDereferenceInvalidIterator2() for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "sizeof|decltype|typeid|typeof (")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); continue; } @@ -2742,7 +2742,7 @@ namespace { std::set varsChanged; explicit LoopAnalyzer(const Token* tok, const Settings* psettings) - : bodyTok(tok->next()->link()->next()), settings(psettings) + : bodyTok(tok->linkAt(1)->next()), settings(psettings) { const Token* splitTok = tok->next()->astOperand2(); if (Token::simpleMatch(splitTok, ":") && splitTok->previous()->varId() != 0) { @@ -2893,7 +2893,7 @@ void CheckStl::useStlAlgorithm() // Parse range-based for loop if (!Token::simpleMatch(tok, "for (")) continue; - if (!Token::simpleMatch(tok->next()->link(), ") {")) + if (!Token::simpleMatch(tok->linkAt(1), ") {")) continue; LoopAnalyzer a{tok, mSettings}; std::string algoName = a.findAlgo(); @@ -2902,7 +2902,7 @@ void CheckStl::useStlAlgorithm() continue; } - const Token *bodyTok = tok->next()->link()->next(); + const Token *bodyTok = tok->linkAt(1)->next(); const Token *splitTok = tok->next()->astOperand2(); const Token* loopVar{}; bool isIteratorLoop = false; @@ -3114,7 +3114,7 @@ void CheckStl::knownEmptyContainer() // Parse range-based for loop if (tok->str() == "for") { - if (!Token::simpleMatch(tok->next()->link(), ") {")) + if (!Token::simpleMatch(tok->linkAt(1), ") {")) continue; const Token *splitTok = tok->next()->astOperand2(); if (!Token::simpleMatch(splitTok, ":")) diff --git a/lib/checkstring.cpp b/lib/checkstring.cpp index 5024b4a5155..43b2ffe922b 100644 --- a/lib/checkstring.cpp +++ b/lib/checkstring.cpp @@ -287,8 +287,8 @@ void CheckString::checkIncorrectStringCompare() // skip "assert(str && ..)" and "assert(.. && str)" if ((endsWith(tok->str(), "assert") || endsWith(tok->str(), "ASSERT")) && Token::Match(tok, "%name% (") && - (Token::Match(tok->tokAt(2), "%str% &&") || Token::Match(tok->next()->link()->tokAt(-2), "&& %str% )"))) - tok = tok->next()->link(); + (Token::Match(tok->tokAt(2), "%str% &&") || Token::Match(tok->linkAt(1)->tokAt(-2), "&& %str% )"))) + tok = tok->linkAt(1); if (Token::simpleMatch(tok, ". substr (") && Token::Match(tok->tokAt(3)->nextArgument(), "%num% )")) { const MathLib::biguint clen = MathLib::toBigUNumber(tok->linkAt(2)->strAt(-1)); diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 90a6b252394..a053c811a75 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -503,7 +503,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var } // goto the { - tok = tok->next()->link()->next(); + tok = tok->linkAt(1)->next(); if (!tok) break; @@ -583,7 +583,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var // = { .. } else if (Token::simpleMatch(tok, "= {") || (Token::Match(tok, "%name% {") && tok->variable() && tok == tok->variable()->nameToken())) { // end token - const Token *end = tok->next()->link(); + const Token *end = tok->linkAt(1); // If address of variable is taken in the block then bail out if (var.isPointer() || var.isArray()) { @@ -630,7 +630,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var return true; // goto the { - const Token *tok2 = forwhile ? tok->next()->link()->next() : tok->next(); + const Token *tok2 = forwhile ? tok->linkAt(1)->next() : tok->next(); if (tok2 && tok2->str() == "{") { const bool init = checkLoopBody(tok2, var, *alloc, membervar, (number_of_if > 0) || suppressErrors); @@ -642,7 +642,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var // is variable used in for-head? bool initcond = false; if (!suppressErrors) { - const Token *startCond = forwhile ? tok->next() : tok->next()->link()->tokAt(2); + const Token *startCond = forwhile ? tok->next() : tok->linkAt(1)->tokAt(2); initcond = checkIfForWhileHead(startCond, var, false, bool(number_of_if == 0), *alloc, membervar); } diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 58c016272bb..ebc2e213ed3 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1069,8 +1069,8 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const } else if (Token::Match(tok, "[(,] & %var% [,)]")) { variables.eraseAll(tok->tokAt(2)->varId()); } else if (Token::Match(tok, "[(,] (") && - Token::Match(tok->next()->link(), ") %var% [,)[]")) { - variables.use(tok->next()->link()->next()->varId(), tok); // use = read + write + Token::Match(tok->linkAt(1), ") %var% [,)[]")) { + variables.use(tok->linkAt(1)->next()->varId(), tok); // use = read + write } else if (Token::Match(tok, "[(,] *| *| %var%")) { const Token* vartok = tok->next(); while (vartok->str() == "*") diff --git a/lib/findtoken.h b/lib/findtoken.h index 647cbda7746..73b4f0894f1 100644 --- a/lib/findtoken.h +++ b/lib/findtoken.h @@ -91,7 +91,7 @@ bool findTokensSkipDeadCodeImpl(const Library& library, if (found(tok)) return true; } - if (Token::Match(tok, "if|for|while (") && Token::simpleMatch(tok->next()->link(), ") {")) { + if (Token::Match(tok, "if|for|while (") && Token::simpleMatch(tok->linkAt(1), ") {")) { const Token* condTok = getCondTok(tok); if (!condTok) continue; diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index d299624cc2b..d36e38407c5 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -656,14 +656,14 @@ namespace { return Break(); } } else if (tok->isControlFlowKeyword() && Token::Match(tok, "if|while|for (") && - Token::simpleMatch(tok->next()->link(), ") {")) { + Token::simpleMatch(tok->linkAt(1), ") {")) { if ((settings.vfOptions.maxForwardBranches > 0) && (++branchCount > settings.vfOptions.maxForwardBranches)) { // TODO: should be logged on function-level instead of file-level reportError(Severity::information, "normalCheckLevelMaxBranches", "Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches."); return Break(Analyzer::Terminate::Bail); } - Token* endCond = tok->next()->link(); - Token* endBlock = endCond->next()->link(); + Token* endCond = tok->linkAt(1); + Token* endBlock = endCond->linkAt(1); Token* condTok = getCondTok(tok); Token* initTok = getInitTok(tok); if (initTok && updateRecursive(initTok) == Progress::Break) @@ -769,7 +769,7 @@ namespace { } } } else if (Token::simpleMatch(tok, "try {")) { - Token* endBlock = tok->next()->link(); + Token* endBlock = tok->linkAt(1); ForwardTraversal tryTraversal = fork(); tryTraversal.updateScope(endBlock, depth - 1); bool bail = tryTraversal.actions.isModified(); @@ -792,7 +792,7 @@ namespace { return Break(); tok = endBlock; } else if (Token::simpleMatch(tok, "do {")) { - Token* endBlock = tok->next()->link(); + Token* endBlock = tok->linkAt(1); Token* condTok = Token::simpleMatch(endBlock, "} while (") ? endBlock->tokAt(2)->astOperand2() : nullptr; if (updateLoop(end, endBlock, condTok) == Progress::Break) return Break(); diff --git a/lib/pathanalysis.cpp b/lib/pathanalysis.cpp index 1ad6a941a72..a50f7d4fd3c 100644 --- a/lib/pathanalysis.cpp +++ b/lib/pathanalysis.cpp @@ -123,14 +123,14 @@ PathAnalysis::Progress PathAnalysis::forwardRange(const Token* startToken, const if (Token::simpleMatch(tok, "} else {")) { tok = tok->linkAt(2); } - } else if (Token::Match(tok, "if|while|for (") && Token::simpleMatch(tok->next()->link(), ") {")) { - const Token * endCond = tok->next()->link(); - const Token * endBlock = endCond->next()->link(); + } else if (Token::Match(tok, "if|while|for (") && Token::simpleMatch(tok->linkAt(1), ") {")) { + const Token * endCond = tok->linkAt(1); + const Token * endBlock = endCond->linkAt(1); const Token * condTok = getCondTok(tok); if (!condTok) continue; // Traverse condition - if (forwardRange(tok->next(), tok->next()->link(), info, f) == Progress::Break) + if (forwardRange(tok->next(), tok->linkAt(1), info, f) == Progress::Break) return Progress::Break; Info i = info; i.known = false; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 7d900e6a44c..3f5c826a6a8 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -211,8 +211,8 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() Token::simpleMatch(tok2->linkAt(2), "} ;")) tok = tok2->linkAt(2)->next(); else if (Token::Match(tok2->next(), "(|{") && - tok2->next()->link()->strAt(1) == ";") - tok = tok2->next()->link()->next(); + tok2->linkAt(1)->strAt(1) == ";") + tok = tok2->linkAt(1)->next(); // skip variable declaration else if (Token::Match(tok2, "*|&|>")) continue; @@ -423,13 +423,13 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // unnamed struct and union else if (tok->isKeyword() && Token::Match(tok, "struct|union {") && - Token::Match(tok->next()->link(), "} *|&| %name% ;|[|=")) { + Token::Match(tok->linkAt(1), "} *|&| %name% ;|[|=")) { scopeList.emplace_back(this, tok, scope); Scope *new_scope = &scopeList.back(); access[new_scope] = AccessControl::Public; - const Token* varNameTok = tok->next()->link()->next(); + const Token* varNameTok = tok->linkAt(1)->next(); if (varNameTok->str() == "*") { varNameTok = varNameTok->next(); } else if (varNameTok->str() == "&") { @@ -464,7 +464,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // anonymous struct, union and namespace else if (tok->isKeyword() && ((Token::Match(tok, "struct|union {") && - Token::simpleMatch(tok->next()->link(), "} ;")) || + Token::simpleMatch(tok->linkAt(1), "} ;")) || Token::simpleMatch(tok, "namespace {"))) { scopeList.emplace_back(this, tok, scope); @@ -713,8 +713,8 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() tok = tok1; scope->nestedList.push_back(&scopeList.back()); scope = &scopeList.back(); - } else if (tok->isKeyword() && Token::Match(tok, "if|for|while|catch|switch (") && Token::simpleMatch(tok->next()->link(), ") {")) { - const Token *scopeStartTok = tok->next()->link()->next(); + } else if (tok->isKeyword() && Token::Match(tok, "if|for|while|catch|switch (") && Token::simpleMatch(tok->linkAt(1), ") {")) { + const Token *scopeStartTok = tok->linkAt(1)->next(); if (tok->str() == "if") scopeList.emplace_back(this, tok, scope, Scope::eIf, scopeStartTok); else if (tok->str() == "for") { @@ -734,7 +734,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() scope->checkVariable(tok->tokAt(2), AccessControl::Throw, mSettings); // check for variable declaration and add it to new scope if found tok = scopeStartTok; } else if (Token::Match(tok, "%var% {")) { - endInitList.emplace(tok->next()->link(), scope); + endInitList.emplace(tok->linkAt(1), scope); tok = tok->next(); } else if (const Token *lambdaEndToken = findLambdaEndToken(tok)) { tok = addLambda(tok, lambdaEndToken); @@ -1153,7 +1153,7 @@ void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass) if (inTemplateArg == tok) inTemplateArg = nullptr; if (tok->isName() && !tok->function() && tok->varId() == 0 && ((tok->astParent() && tok->astParent()->isComparisonOp()) || Token::Match(tok, "%name% [{(,)>;]")) && !isReservedName(tok)) { - if (tok->next()->str() == ">" && !tok->next()->link()) + if (tok->next()->str() == ">" && !tok->linkAt(1)) continue; const Function *function = findFunction(tok); @@ -1348,14 +1348,14 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() // func(...).var // func(...)[...].var else if (tok->function() && tok->next()->str() == "(" && - (Token::Match(tok->next()->link(), ") . %name% !!(") || - (Token::Match(tok->next()->link(), ") [") && Token::Match(tok->next()->link()->next()->link(), "] . %name% !!(")))) { + (Token::Match(tok->linkAt(1), ") . %name% !!(") || + (Token::Match(tok->linkAt(1), ") [") && Token::Match(tok->linkAt(1)->linkAt(1), "] . %name% !!(")))) { const Type *type = tok->function()->retType; Token* membertok; - if (tok->next()->link()->next()->str() == ".") - membertok = tok->next()->link()->next()->next(); + if (tok->linkAt(1)->next()->str() == ".") + membertok = tok->linkAt(1)->next()->next(); else - membertok = tok->next()->link()->next()->link()->next()->next(); + membertok = tok->linkAt(1)->linkAt(1)->next()->next(); if (type) { const Variable *membervar = membertok->variable(); if (!membervar) { @@ -1376,12 +1376,12 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() } } else if (Token::simpleMatch(tok->astParent(), ".") && tok->next()->str() == "(" && - astIsContainer(tok->astParent()->astOperand1()) && Token::Match(tok->next()->link(), ") . %name% !!(")) { + astIsContainer(tok->astParent()->astOperand1()) && Token::Match(tok->linkAt(1), ") . %name% !!(")) { const ValueType* vt = tok->astParent()->astOperand1()->valueType(); const Library::Container* cont = vt->container; auto it = cont->functions.find(tok->str()); if (it != cont->functions.end() && isContainerYieldElement(it->second.yield) && vt->containerTypeToken) { - Token* memberTok = tok->next()->link()->tokAt(2); + Token* memberTok = tok->linkAt(1)->tokAt(2); const Scope* scope = vt->containerTypeToken->scope(); const Type* contType{}; const std::string& typeStr = vt->containerTypeToken->str(); // TODO: handle complex type expressions @@ -1657,8 +1657,8 @@ void SymbolDatabase::createSymbolDatabaseExprIds() std::unordered_map unknownConstantIds; const Token* inConstExpr = nullptr; for (const Token* tok = mTokenizer.list.front(); tok != mTokenizer.list.back(); tok = tok->next()) { - if (Token::Match(tok, "decltype|sizeof|typeof (") && tok->next()->link()) { - tok = tok->next()->link()->previous(); + if (Token::Match(tok, "decltype|sizeof|typeof (") && tok->linkAt(1)) { + tok = tok->linkAt(1)->previous(); } else if (tok == inConstExpr) { inConstExpr = nullptr; } else if (inConstExpr) { @@ -1673,7 +1673,7 @@ void SymbolDatabase::createSymbolDatabaseExprIds() } else if (tok->link() && tok->str() == "<") { inConstExpr = tok->link(); } else if (Token::Match(tok, "%var% [") && tok->variable() && tok->variable()->nameToken() == tok) { - inConstExpr = tok->next()->link(); + inConstExpr = tok->linkAt(1); } } @@ -1724,7 +1724,7 @@ void SymbolDatabase::createSymbolDatabaseExprIds() if (tok->isControlFlowKeyword()) continue; - if (Token::Match(tok, "%name% <") && tok->next()->link()) { + if (Token::Match(tok, "%name% <") && tok->linkAt(1)) { tok->exprId(id); ++id; } else { @@ -1923,7 +1923,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const } } - else if (!tok->isName() || !tok->next() || !tok->next()->link()) + else if (!tok->isName() || !tok->next() || !tok->linkAt(1)) return false; // regular function? @@ -1931,7 +1931,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const (Token::Match(tok->previous(), "%name%|>|&|&&|*|::|~") || // Either a return type or scope qualifier in front of tok outerScope->isClassOrStructOrUnion())) { // or a ctor/dtor const Token* tok1 = tok->previous(); - const Token* tok2 = tok->next()->link()->next(); + const Token* tok2 = tok->linkAt(1)->next(); if (!Tokenizer::isFunctionHead(tok->next(), ";:{")) return false; @@ -2027,7 +2027,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const if (tok2 && (Token::Match(tok2, ";|{|=") || (tok2->isUpperCaseName() && Token::Match(tok2, "%name% ;|{")) || - (tok2->isUpperCaseName() && Token::Match(tok2, "%name% (") && tok2->next()->link()->strAt(1) == "{") || + (tok2->isUpperCaseName() && Token::Match(tok2, "%name% (") && tok2->linkAt(1)->strAt(1) == "{") || Token::Match(tok2, ": ::| %name% (|::|<|{") || Token::Match(tok2, "&|&&| ;|{") || Token::Match(tok2, "= delete|default ;") || @@ -2052,10 +2052,10 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const } // template constructor? - else if (Token::Match(tok, "%name% <") && Token::simpleMatch(tok->next()->link(), "> (")) { + else if (Token::Match(tok, "%name% <") && Token::simpleMatch(tok->linkAt(1), "> (")) { if (tok->isKeyword() || tok->isStandardType() || !outerScope->isClassOrStructOrUnion()) return false; - const Token* tok2 = tok->next()->link()->next()->link(); + const Token* tok2 = tok->linkAt(1)->linkAt(1); if (Token::Match(tok2, ") const| ;|{|=") || Token::Match(tok2, ") : ::| %name% (|::|<|{") || Token::Match(tok2, ") const| noexcept {|;|(")) { @@ -2473,8 +2473,8 @@ std::string Variable::getTypeName() const // TODO: For known types, generate the full type name for (const Token *typeTok = mTypeStartToken; Token::Match(typeTok, "%name%|::") && typeTok->varId() == 0; typeTok = typeTok->next()) { ret += typeTok->str(); - if (Token::simpleMatch(typeTok->next(), "<") && typeTok->next()->link()) // skip template arguments - typeTok = typeTok->next()->link(); + if (Token::simpleMatch(typeTok->next(), "<") && typeTok->linkAt(1)) // skip template arguments + typeTok = typeTok->linkAt(1); } return ret; } @@ -3299,7 +3299,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To Function * func = findFunctionInScope(tok1, it2->scope, path, path_length); if (func) { if (!func->hasBody()) { - const Token *closeParen = tok->next()->link(); + const Token *closeParen = tok->linkAt(1); if (closeParen) { const Token *eq = Tokenizer::isFunctionHead(closeParen, ";"); if (eq && Token::simpleMatch(eq->tokAt(-2), "= default ;")) { @@ -3372,7 +3372,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To auto * func = const_cast(it->second); if (!func->hasBody()) { if (func->argsMatch(scope1, func->argDef, tok->next(), path, path_length)) { - const Token *closeParen = tok->next()->link(); + const Token *closeParen = tok->linkAt(1); if (closeParen) { const Token *eq = Tokenizer::isFunctionHead(closeParen, ";"); if (eq && Token::simpleMatch(eq->tokAt(-2), "= default ;")) { @@ -4451,7 +4451,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s // skip array dimension(s) tok = tok->link(); while (tok->next()->str() == "[") - tok = tok->next()->link(); + tok = tok->linkAt(1); } else if (tok->str() == "<") { tok = tok->link(); if (!tok) // something is wrong so just bail out @@ -4815,11 +4815,11 @@ void Scope::getVariableList(const Settings& settings, const Token* start, const break; } if (tok->isKeyword() && Token::Match(tok, "struct|union {")) { - if (Token::Match(tok->next()->link(), "} %name% ;|[")) { - tok = tok->next()->link()->tokAt(2); + if (Token::Match(tok->linkAt(1), "} %name% ;|[")) { + tok = tok->linkAt(1)->tokAt(2); continue; } - if (Token::simpleMatch(tok->next()->link(), "} ;")) { + if (Token::simpleMatch(tok->linkAt(1), "} ;")) { tok = tok->next(); continue; } @@ -5040,7 +5040,7 @@ bool Scope::isVariableDeclaration(const Token* const tok, const Token*& vartok, if (Token::Match(tok, "const_cast|dynamic_cast|reinterpret_cast|static_cast <")) return false; - const Token* closeTok = localTypeTok->next()->link(); + const Token* closeTok = localTypeTok->linkAt(1); if (closeTok) { localVarTok = skipPointers(closeTok->next()); @@ -5076,7 +5076,7 @@ bool Scope::isVariableDeclaration(const Token* const tok, const Token*& vartok, vartok = localVarTok; typetok = localTypeTok; } else if (localVarTok && localVarTok->varId() && Token::Match(localVarTok, "%name% (|{") && - Token::Match(localVarTok->next()->link(), ")|} ;")) { + Token::Match(localVarTok->linkAt(1), ")|} ;")) { vartok = localVarTok; typetok = localTypeTok; } else if (type == eCatch && diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index c2785187449..e2cdbfa6e7d 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -296,11 +296,11 @@ void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() // skip executing scopes (ticket #1985).. else if (Token::simpleMatch(tok, "try {")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); while (Token::simpleMatch(tok, "} catch (")) { tok = tok->linkAt(2); if (Token::simpleMatch(tok, ") {")) - tok = tok->next()->link(); + tok = tok->linkAt(1); } } @@ -2801,7 +2801,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba validTokenEnd(bounded, tok, backToken, 2))))) { tok->deleteNext(); if (tok->next()->str() == "(") - eraseTokens(tok, tok->next()->link()); + eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; } else if (validTokenEnd(bounded, tok, backToken, 4) && @@ -2810,7 +2810,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba tok->deleteNext(); tok->deleteNext(); if (tok->next()->str() == "(") - eraseTokens(tok, tok->next()->link()); + eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; } @@ -2822,7 +2822,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba Token::Match(tok->previous(), "return|case 1 %oror% %any% ,|:|;|=|%cop%"))) { tok->deleteNext(); if (tok->next()->str() == "(") - eraseTokens(tok, tok->next()->link()); + eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; } else if (validTokenEnd(bounded, tok, backToken, 4) && @@ -2831,7 +2831,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba tok->deleteNext(); tok->deleteNext(); if (tok->next()->str() == "(") - eraseTokens(tok, tok->next()->link()); + eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 17c768795c5..2093b364e3b 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -282,7 +282,7 @@ bool Tokenizer::duplicateTypedef(Token *&tokPtr, const Token *name, const Token if (Token::Match(tok->previous(), "%type%") && !Token::Match(tok->previous(), "return|new|const|struct")) { // duplicate definition so skip entire function - tokPtr = end->next()->link(); + tokPtr = end->linkAt(1); return true; } } else if (end->str() == ">") { // template parameter ? @@ -512,7 +512,7 @@ const Token *Tokenizer::processFunc(const Token *tok2, bool inOperator) const tok2 = tok2->next(); else { if (tok2->next()->str() == "(") - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); else if (!inOperator && !Token::Match(tok2->next(), "[|>|;")) { tok2 = tok2->next(); @@ -533,17 +533,17 @@ const Token *Tokenizer::processFunc(const Token *tok2, bool inOperator) const tok2 = tok2->link(); if (tok2->next()->str() == "(") - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); } // skip over typedef parameter if (tok2->next() && tok2->next()->str() == "(") { - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); if (!tok2->next()) syntaxError(tok2); if (tok2->next()->str() == "(") - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); } } } @@ -1466,13 +1466,13 @@ void Tokenizer::simplifyTypedefCpp() // typedef ... ( * ( ... type )( ... )); else if (tokOffset->str() == "(" && ( (tokOffset->link() && Token::Match(tokOffset->link()->previous(), "%type% ) (") && - Token::Match(tokOffset->link()->next()->link(), ") const|volatile|;")) || + Token::Match(tokOffset->link()->linkAt(1), ") const|volatile|;")) || (Token::simpleMatch(tokOffset, "( (") && - tokOffset->next() && Token::Match(tokOffset->next()->link()->previous(), "%type% ) (") && - Token::Match(tokOffset->next()->link()->next()->link(), ") const|volatile| ) ;|,")) || + tokOffset->next() && Token::Match(tokOffset->linkAt(1)->previous(), "%type% ) (") && + Token::Match(tokOffset->linkAt(1)->linkAt(1), ") const|volatile| ) ;|,")) || (Token::simpleMatch(tokOffset, "( * (") && tokOffset->linkAt(2) && Token::Match(tokOffset->linkAt(2)->previous(), "%type% ) (") && - Token::Match(tokOffset->linkAt(2)->next()->link(), ") const|volatile| ) ;|,")))) { + Token::Match(tokOffset->linkAt(2)->linkAt(1), ") const|volatile| ) ;|,")))) { if (tokOffset->next()->str() == "(") tokOffset = tokOffset->next(); else if (Token::simpleMatch(tokOffset, "( * (")) { @@ -1489,7 +1489,7 @@ void Tokenizer::simplifyTypedefCpp() funcEnd = tokOffset->tokAt(-2); typeName = tokOffset->previous(); argStart = tokOffset->next(); - argEnd = tokOffset->next()->link(); + argEnd = tokOffset->linkAt(1); if (!argEnd) syntaxError(argStart); @@ -2184,11 +2184,11 @@ void Tokenizer::simplifyTypedefCpp() // check for function and skip over args if (tok2 && tok2->next() && tok2->next()->str() == "(") - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); // check for array if (tok2 && tok2->next() && tok2->next()->str() == "[") - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); } tok2->insertToken(")"); @@ -2311,7 +2311,7 @@ void Tokenizer::simplifyTypedefCpp() if (tok2->str() == "=") { if (tok2->next()->str() == "{") - tok2 = tok2->next()->link()->next(); + tok2 = tok2->linkAt(1)->next(); else if (tok2->next()->str().at(0) == '\"') tok2 = tok2->tokAt(2); } @@ -3718,9 +3718,9 @@ void Tokenizer::simplifyRedundantConsecutiveBraces() for (Token *tok = list.front(); tok;) { if (Token::simpleMatch(tok, "= {")) { tok = tok->linkAt(1); - } else if (Token::simpleMatch(tok, "{ {") && Token::simpleMatch(tok->next()->link(), "} }")) { + } else if (Token::simpleMatch(tok, "{ {") && Token::simpleMatch(tok->linkAt(1), "} }")) { //remove internal parentheses - tok->next()->link()->deleteThis(); + tok->linkAt(1)->deleteThis(); tok->deleteNext(); } else tok = tok->next(); @@ -5245,13 +5245,13 @@ void Tokenizer::setVarIdPass2() // goto end of var if (tok3->strAt(1) == "<") { tok3 = tok3->next()->findClosingBracket(); - if (tok3 && tok3->next() && tok3->next()->link()) - tok3 = tok3->next()->link(); + if (tok3 && tok3->next() && tok3->linkAt(1)) + tok3 = tok3->linkAt(1); } else tok3 = tok3->linkAt(1); } if (Token::Match(tok3, ")|} {")) { - setVarIdClassFunction(classname, tok2, tok3->next()->link(), thisClassVars, structMembers, mVarId); + setVarIdClassFunction(classname, tok2, tok3->linkAt(1), thisClassVars, structMembers, mVarId); } } } @@ -5554,7 +5554,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) // if (x) MACRO() .. for (const Token *tok = list.front(); tok; tok = tok->next()) { if (Token::simpleMatch(tok, "if (")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); if (Token::Match(tok, ") %name% (") && tok->next()->isUpperCaseName() && Token::Match(tok->linkAt(2), ") {|else")) { @@ -6901,7 +6901,7 @@ void Tokenizer::simplifyFunctionParameters() tok->linenr(tok->previous()->linenr()); } //goto forward and continue - tok = tok->next()->link(); + tok = tok->linkAt(1); } } } @@ -6934,7 +6934,7 @@ void Tokenizer::simplifyFunctionPointers() // #2873 - do not simplify function pointer usage here: // (void)(xy(*p)(0)); if (Token::simpleMatch(tok, ") (")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); continue; } @@ -7002,7 +7002,7 @@ void Tokenizer::simplifyFunctionPointers() if (!tok || !tok->link() || !tok->link()->next()) { syntaxError(nullptr); } - Token *endTok = tok->link()->next()->link(); + Token *endTok = tok->link()->linkAt(1); if (Token::simpleMatch(endTok, ") throw (")) endTok = endTok->linkAt(2); if (!Token::Match(endTok, ") const|volatile| const|volatile| ;|,|)|=|[|{")) @@ -7069,14 +7069,14 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co if (Token::Match(tok, "class|struct|namespace|union")) scopeDecl = true; if (Token::Match(tok, "decltype|noexcept (")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); // skip decltype(...){...} if (tok && Token::simpleMatch(tok->previous(), ") {")) tok = tok->link(); } else if (Token::simpleMatch(tok, "= {") || (!scopeDecl && Token::Match(tok, "%name%|> {") && !Token::Match(tok, "else|try|do|const|constexpr|override|volatile|noexcept"))) { - if (!tok->next()->link()) + if (!tok->linkAt(1)) syntaxError(tokBegin); // Check for lambdas before skipping if (Token::Match(tok->tokAt(-2), ") . %name%")) { // trailing return type @@ -7088,18 +7088,18 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co if (lambdaEnd) simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar); } else { - for (Token* tok2 = tok->next(); tok2 != tok->next()->link(); tok2 = tok2->next()) { + for (Token* tok2 = tok->next(); tok2 != tok->linkAt(1); tok2 = tok2->next()) { Token* lambdaEnd = findLambdaEndScope(tok2); if (!lambdaEnd) continue; simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar); } } - tok = tok->next()->link(); + tok = tok->linkAt(1); } } else if (Token::simpleMatch(tok, "= {")) { - tok = tok->next()->link(); + tok = tok->linkAt(1); } if (!tok) { syntaxError(tokBegin); @@ -7843,7 +7843,7 @@ bool Tokenizer::simplifyRedundantParentheses() } while (Token::simpleMatch(tok, "( (") && - tok->link() && tok->link()->previous() == tok->next()->link()) { + tok->link() && tok->link()->previous() == tok->linkAt(1)) { // We have "(( *something* ))", remove the inner // parentheses tok->deleteNext(); @@ -8002,7 +8002,7 @@ void Tokenizer::simplifyTypeIntrinsics() auto p = intrinsics.find(tok->str()); if (p == intrinsics.end()) continue; - Token * end = tok->next()->link(); + Token * end = tok->linkAt(1); Token * prev = tok->previous(); tok->str(p->second); prev->insertToken("::"); @@ -8263,7 +8263,7 @@ static bool isCPPAttribute(const Token * tok) static bool isAlignAttribute(const Token * tok) { - return Token::simpleMatch(tok, "alignas (") && tok->next()->link(); + return Token::simpleMatch(tok, "alignas (") && tok->linkAt(1); } template @@ -8272,7 +8272,7 @@ static T* skipCPPOrAlignAttribute(T * tok) if (isCPPAttribute(tok)) return tok->link(); if (isAlignAttribute(tok)) { - return tok->next()->link(); + return tok->linkAt(1); } return tok; } @@ -8599,7 +8599,7 @@ void Tokenizer::findGarbageCode() const // count number of semicolons int semicolons = 0, colons = 0; const Token* const startTok = tok; - tok = tok->next()->link()->previous(); // find ")" of the for-loop + tok = tok->linkAt(1)->previous(); // find ")" of the for-loop // walk backwards until we find the beginning (startTok) of the for() again for (; tok != startTok; tok = tok->previous()) { if (tok->str() == ";") { // do the counting @@ -8935,7 +8935,7 @@ void Tokenizer::simplifyStructDecl() continue; // check for anonymous struct/union if (Token::Match(tok, "struct|union {")) { - if (Token::Match(tok->next()->link(), "} const| *|&| const| %type% ,|;|[|(|{|=")) { + if (Token::Match(tok->linkAt(1), "} const| *|&| const| %type% ,|;|[|(|{|=")) { tok->insertToken("Anonymous" + std::to_string(count++)); } } @@ -8950,7 +8950,7 @@ void Tokenizer::simplifyStructDecl() else if (isAnonymousEnum(tok)) { Token *start = tok->strAt(1) == ":" ? tok->linkAt(3) : tok->linkAt(1); if (start && Token::Match(start->next(), "( %type% )")) { - start->next()->link()->deleteThis(); + start->linkAt(1)->deleteThis(); start->next()->deleteThis(); } tok->insertToken("Anonymous" + std::to_string(count++)); @@ -9146,9 +9146,9 @@ void Tokenizer::simplifyDeclspec() functok->isAttributeExport(true); } } else if (tok->strAt(2) == "property") - tok->next()->link()->insertToken("__property"); + tok->linkAt(1)->insertToken("__property"); - Token::eraseTokens(tok, tok->next()->link()->next()); + Token::eraseTokens(tok, tok->linkAt(1)->next()); tok->deleteThis(); } } @@ -9569,9 +9569,9 @@ void Tokenizer::simplifyAsm() std::string instruction; for (Token *tok = list.front(); tok; tok = tok->next()) { if (Token::Match(tok, "__asm|_asm|asm {") && - tok->next()->link()->next()) { - instruction = tok->tokAt(2)->stringifyList(tok->next()->link()); - Token::eraseTokens(tok, tok->next()->link()->next()); + tok->linkAt(1)->next()) { + instruction = tok->tokAt(2)->stringifyList(tok->linkAt(1)); + Token::eraseTokens(tok, tok->linkAt(1)->next()); } else if (Token::Match(tok, "asm|__asm|__asm__ volatile|__volatile|__volatile__| (")) { @@ -9664,7 +9664,7 @@ void Tokenizer::simplifyAsm2() start = start->previous(); } - const Token *last = tok->next()->link(); + const Token *last = tok->linkAt(1); if (Token::simpleMatch(last, ") {")) last = last->linkAt(1); last = last->next(); @@ -9779,7 +9779,7 @@ void Tokenizer::simplifyBitfields() !Token::Match(tok1->tokAt(2), "public|protected|private| %type% ::|<|,|{|;"))) { while (tok1->next() && !Token::Match(tok1->next(), "[;,)]{}=]")) { if (Token::Match(tok1->next(), "[([]")) - Token::eraseTokens(tok1, tok1->next()->link()); + Token::eraseTokens(tok1, tok1->linkAt(1)); tok1->deleteNext(); } @@ -9906,7 +9906,7 @@ void Tokenizer::simplifyMicrosoftMemoryFunctions() Token *tok2 = tok1->nextArgument(); // Third argument if (tok2) - Token::move(tok1->previous(), tok2->tokAt(-2), tok->next()->link()->previous()); // Swap third with second argument + Token::move(tok1->previous(), tok2->tokAt(-2), tok->linkAt(1)->previous()); // Swap third with second argument } } else if (Token::Match(tok, "ZeroMemory|RtlZeroMemory|RtlZeroBytes|RtlSecureZeroMemory")) { // ZeroMemory(dst, len) -> memset(dst, 0, len) @@ -10086,7 +10086,7 @@ bool Tokenizer::operatorEnd(const Token * tok) tok = tok->link()->next(); } } else if (tok->str() == "throw" && tok->next() && tok->next()->str() == "(") { - tok = tok->next()->link()->next(); + tok = tok->linkAt(1)->next(); } // unknown macros ") MACRO {" and ") MACRO(...) {" else if (tok->isUpperCaseName()) { diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 71ad1fadf76..8c11db0c73b 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -804,7 +804,7 @@ static void compileTerm(Token *&tok, AST_state& state) repeat = true; } if (Token::simpleMatch(tok->next(), "<") && Token::Match(tok->linkAt(1), "> %name%")) { - tok = tok->next()->link()->next(); + tok = tok->linkAt(1)->next(); repeat = true; } } @@ -980,9 +980,9 @@ static void compilePrecedence2(Token *&tok, AST_state& state) } const bool hasTemplateArg = Token::simpleMatch(squareBracket->link(), "] <") && - Token::simpleMatch(squareBracket->link()->next()->link(), "> ("); + Token::simpleMatch(squareBracket->link()->linkAt(1), "> ("); if (Token::simpleMatch(squareBracket->link(), "] (") || hasTemplateArg) { - Token* const roundBracket = hasTemplateArg ? squareBracket->link()->next()->link()->next() : squareBracket->link()->next(); + Token* const roundBracket = hasTemplateArg ? squareBracket->link()->linkAt(1)->next() : squareBracket->link()->next(); Token* curlyBracket = roundBracket->link()->next(); while (Token::Match(curlyBracket, "mutable|const|constexpr|consteval")) curlyBracket = curlyBracket->next(); @@ -1597,7 +1597,7 @@ static Token * createAstAtToken(Token *tok) compileExpression(tok3, state1); } Token *init1 = nullptr; - Token * const endPar = tok->next()->link(); + Token * const endPar = tok->linkAt(1); if (tok2 == tok->tokAt(2) && Token::Match(tok2, "%op%|(")) { init1 = tok2; AST_state state1(cpp); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 8b72c91d502..35ba611b563 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -583,7 +583,7 @@ static void valueFlowArray(TokenList &tokenlist, const Settings &settings) // const array decl else if (tok->variable() && tok->variable()->isArray() && tok->variable()->isConst() && tok->variable()->nameToken() == tok && Token::Match(tok, "%var% [ %num%| ] = {")) { - Token* rhstok = tok->next()->link()->tokAt(2); + Token* rhstok = tok->linkAt(1)->tokAt(2); constantArrays[tok->varId()] = rhstok; tok = rhstok->link(); } @@ -604,7 +604,7 @@ static void valueFlowArray(TokenList &tokenlist, const Settings &settings) if (Token::Match(tok, "const %type% %var% [ %num%| ] = {")) { Token *vartok = tok->tokAt(2); - Token *rhstok = vartok->next()->link()->tokAt(2); + Token *rhstok = vartok->linkAt(1)->tokAt(2); constantArrays[vartok->varId()] = rhstok; tok = rhstok->link(); continue; @@ -612,7 +612,7 @@ static void valueFlowArray(TokenList &tokenlist, const Settings &settings) if (Token::Match(tok, "const char %var% [ %num%| ] = %str% ;")) { Token *vartok = tok->tokAt(2); - Token *strtok = vartok->next()->link()->tokAt(2); + Token *strtok = vartok->linkAt(1)->tokAt(2); constantArrays[vartok->varId()] = strtok; tok = strtok->next(); continue; @@ -4191,7 +4191,7 @@ static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, co valueFlowLifetimeConstructor(tok->next(), tokenlist, errorLogger, settings); } // Check function calls - else if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->next()->link(), ") {")) { + else if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) { valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings); } // Unique pointer lifetimes @@ -6344,7 +6344,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart, } if (settings.debugwarnings) bailout(tokenlist, errorLogger, tok2, "For loop variable skipping conditional scope"); - tok2 = tok2->next()->link(); + tok2 = tok2->linkAt(1); if (Token::simpleMatch(tok2, "} else {")) { if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(2), vartok->varId())) { if (settings.debugwarnings) @@ -7965,7 +7965,7 @@ static void valueFlowContainerSize(const TokenList& tokenlist, continue; if (!staticSize) { if (!Token::Match(nameToken, "%name% ;") && - !(Token::Match(nameToken, "%name% {") && Token::simpleMatch(nameToken->next()->link(), "} ;")) && + !(Token::Match(nameToken, "%name% {") && Token::simpleMatch(nameToken->linkAt(1), "} ;")) && !Token::Match(nameToken, "%name% (")) continue; } diff --git a/test/testinternal.cpp b/test/testinternal.cpp index 5dc59aad9f4..13cade82957 100644 --- a/test/testinternal.cpp +++ b/test/testinternal.cpp @@ -279,14 +279,14 @@ class TestInternal : public TestFixture { ASSERT_EQUALS("", errout_str()); check("void f() {\n" - " return tok->next()->next();\n" // Simplification won't make code much shorter/readable + " return tok->next()->next();\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::next()' can be simplified.\n", errout_str()); check("void f() {\n" - " return tok->previous()->previous();\n" // Simplification won't make code much shorter/readable + " return tok->previous()->previous();\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::previous()' followed by 'Token::previous()' can be simplified.\n", errout_str()); check("void f() {\n" " return tok->tokAt(foo+bar)->tokAt();\n" @@ -306,12 +306,16 @@ class TestInternal : public TestFixture { check("void f() {\n" " return tok->next()->next()->str();\n" "}"); - ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::str()' can be simplified.\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::next()' can be simplified.\n" + "[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::str()' can be simplified.\n", + errout_str()); check("void f() {\n" " return tok->previous()->next()->str();\n" "}"); - ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::previous()' followed by 'Token::next()' can be simplified.\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::previous()' followed by 'Token::next()' can be simplified.\n" + "[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::str()' can be simplified.\n", + errout_str()); } @@ -487,7 +491,7 @@ class TestInternal : public TestFixture { " const Token *tok;\n" " if(tok->previous() && Token::Match(tok->previous()->previous(), \"5str% foobar\")) {};\n" "}"); - ASSERT_EQUALS("", errout_str()); + ASSERT_EQUALS("[test.cpp:3]: (style) Call to 'Token::previous()' followed by 'Token::previous()' can be simplified.\n", errout_str()); // if a && fn(a) triggers, make sure !a || !fn(a) triggers as well! check("void f() {\n" @@ -521,7 +525,9 @@ class TestInternal : public TestFixture { " const Token *tok;\n" " if(!tok->previous()->previous() || !Token::simpleMatch(tok->previous()->previous(), \"foobar\")) {};\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok->previous()->previous()\", match-function already checks if it is null.\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3]: (style) Call to 'Token::previous()' followed by 'Token::previous()' can be simplified.\n" + "[test.cpp:3]: (style) Call to 'Token::previous()' followed by 'Token::previous()' can be simplified.\n" + "[test.cpp:3]: (style) Unnecessary check of \"tok->previous()->previous()\", match-function already checks if it is null.\n", errout_str()); } }; From 58c7279a2b45725f56d5cf543bad52bd92602607 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 1 Jun 2024 22:32:39 +0200 Subject: [PATCH 2/6] Fix --- lib/astutils.cpp | 26 ++-- lib/checkclass.cpp | 14 +- lib/checkcondition.cpp | 4 +- lib/checkfunctions.cpp | 2 +- lib/checkio.cpp | 14 +- lib/checkleakautovar.cpp | 2 +- lib/checknullpointer.cpp | 6 +- lib/checkother.cpp | 4 +- lib/checksizeof.cpp | 4 +- lib/checkstl.cpp | 6 +- lib/checkuninitvar.cpp | 2 +- lib/checkunusedfunctions.cpp | 2 +- lib/checkunusedvar.cpp | 18 +-- lib/fwdanalysis.cpp | 2 +- lib/library.cpp | 10 +- lib/programmemory.cpp | 2 +- lib/reverseanalyzer.cpp | 2 +- lib/symboldatabase.cpp | 104 ++++++------- lib/symboldatabase.h | 2 +- lib/templatesimplifier.cpp | 32 ++-- lib/tokenize.cpp | 280 +++++++++++++++++------------------ lib/tokenlist.cpp | 14 +- lib/valueflow.cpp | 16 +- lib/vf_common.cpp | 2 +- lib/vf_settokenvalue.cpp | 2 +- test/testsymboldatabase.cpp | 2 +- test/testtoken.cpp | 4 +- 27 files changed, 289 insertions(+), 289 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index a6ffa107878..3f45dea5cfc 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -453,8 +453,8 @@ bool isTemporary(const Token* tok, const Library* library, bool unknown) return tok->valueType()->reference == Reference::None && tok->valueType()->pointer == 0; } const Token* ftok = nullptr; - if (Token::simpleMatch(tok->previous(), ">") && tok->previous()->link()) - ftok = tok->previous()->link()->previous(); + if (Token::simpleMatch(tok->previous(), ">") && tok->linkAt(-1)) + ftok = tok->linkAt(-1)->previous(); else ftok = tok->previous(); if (!ftok) @@ -568,7 +568,7 @@ Token* astParentSkipParens(Token* tok) if (parent->link() != nextAfterAstRightmostLeaf(tok)) return parent; if (Token::Match(parent->previous(), "%name% (") || - (Token::simpleMatch(parent->previous(), "> (") && parent->previous()->link())) + (Token::simpleMatch(parent->previous(), "> (") && parent->linkAt(-1))) return parent; return astParentSkipParens(parent); } @@ -839,7 +839,7 @@ static T* getCondTokFromEndImpl(T* endBlock) if (Token::simpleMatch(startBlock->previous(), "do")) return getCondTok(startBlock->previous()); if (Token::simpleMatch(startBlock->previous(), ")")) - return getCondTok(startBlock->previous()->link()); + return getCondTok(startBlock->linkAt(-1)); if (Token::simpleMatch(startBlock->tokAt(-2), "} else {")) return getCondTokFromEnd(startBlock->tokAt(-2)); return nullptr; @@ -1669,7 +1669,7 @@ bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Se if (!compareTokenFlags(tok1, tok2, macro)) return false; - if (pure && tok1->isName() && tok1->next()->str() == "(" && tok1->str() != "sizeof" && !(tok1->variable() && tok1 == tok1->variable()->nameToken())) { + if (pure && tok1->isName() && tok1->strAt(1) == "(" && tok1->str() != "sizeof" && !(tok1->variable() && tok1 == tok1->variable()->nameToken())) { if (!tok1->function()) { if (Token::simpleMatch(tok1->previous(), ".")) { const Token *lhs = tok1->previous(); @@ -1725,7 +1725,7 @@ bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Se // cast => assert that the casts are equal if (tok1->str() == "(" && tok1->previous() && !tok1->previous()->isName() && - !(tok1->previous()->str() == ">" && tok1->previous()->link())) { + !(tok1->strAt(-1) == ">" && tok1->linkAt(-1))) { const Token *t1 = tok1->next(); const Token *t2 = tok2->next(); while (t1 && t2 && @@ -2052,7 +2052,7 @@ bool isConstExpression(const Token *tok, const Library& library) return true; if (tok->variable() && tok->variable()->isVolatile()) return false; - if (tok->isName() && tok->next()->str() == "(") { + if (tok->isName() && tok->strAt(1) == "(") { if (!isConstFunctionCall(tok, library)) return false; } @@ -2233,8 +2233,8 @@ bool isReturnScope(const Token* const endToken, const Library& library, const To *unknownFunc = prev->previous(); return false; } - if (Token::simpleMatch(prev->previous(), ") ;") && prev->previous()->link() && - isEscaped(prev->previous()->link()->astTop(), functionScope, library)) + if (Token::simpleMatch(prev->previous(), ") ;") && prev->linkAt(-1) && + isEscaped(prev->linkAt(-1)->astTop(), functionScope, library)) return true; if (isEscaped(prev->previous()->astTop(), functionScope, library)) return true; @@ -2740,7 +2740,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, // structured binding, nonconst reference variable in lhs if (Token::Match(tok2->astParent(), ":|=") && tok2 == tok2->astParent()->astOperand2() && Token::simpleMatch(tok2->astParent()->previous(), "]")) { - const Token *typeStart = tok2->astParent()->previous()->link()->previous(); + const Token *typeStart = tok2->astParent()->linkAt(-1)->previous(); if (Token::simpleMatch(typeStart, "&")) typeStart = typeStart->previous(); if (typeStart && Token::Match(typeStart->previous(), "[;{}(] auto &| [")) { @@ -3095,7 +3095,7 @@ int numberOfArgumentsWithoutAst(const Token* start) const Token* openBracket = start->next(); while (Token::simpleMatch(openBracket, ")")) openBracket = openBracket->next(); - if (openBracket && openBracket->str()=="(" && openBracket->next() && openBracket->next()->str()!=")") { + if (openBracket && openBracket->str()=="(" && openBracket->next() && openBracket->strAt(1)!=")") { const Token* argument=openBracket->next(); while (argument) { ++arguments; @@ -3595,7 +3595,7 @@ bool isGlobalData(const Token *expr) return ChildrenToVisit::none; } } - if (tok->varId() == 0 && tok->isName() && tok->previous()->str() != ".") { + if (tok->varId() == 0 && tok->isName() && tok->strAt(-1) != ".") { globalData = true; return ChildrenToVisit::none; } @@ -3609,7 +3609,7 @@ bool isGlobalData(const Token *expr) globalData = true; return ChildrenToVisit::none; } - if (tok->previous()->str() != "." && !tok->variable()->isLocal() && !tok->variable()->isArgument()) { + if (tok->strAt(-1) != "." && !tok->variable()->isLocal() && !tok->variable()->isArgument()) { globalData = true; return ChildrenToVisit::none; } diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 5253824e45b..f471809ec99 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -983,7 +983,7 @@ void CheckClass::initializeVarList(const Function &func, std::listnext(); if (tok2->str() == "&") tok2 = tok2->next(); - if (isVariableChangedByFunctionCall(tok2, tok2->previous()->str() == "&", tok2->varId(), *mSettings, nullptr)) + if (isVariableChangedByFunctionCall(tok2, tok2->strAt(-1) == "&", tok2->varId(), *mSettings, nullptr)) assignVar(usage, tok2->varId()); } } @@ -1622,14 +1622,14 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co // check if a function is called if (tok->strAt(2) == "(" && - tok->linkAt(2)->next()->str() == ";") { + tok->linkAt(2)->strAt(1) == ";") { // check if it is a member function for (std::list::const_iterator it = scope->functionList.cbegin(); it != scope->functionList.cend(); ++it) { // check for a regular function with the same name and a body if (it->type == Function::eFunction && it->hasBody() && - it->token->str() == tok->next()->str()) { + it->token->str() == tok->strAt(1)) { // check for the proper return type - if (it->tokenDef->previous()->str() == "&" && + if (it->tokenDef->strAt(-1) == "&" && it->tokenDef->strAt(-2) == scope->className) { // make sure it's not a const function if (!it->isConst()) { @@ -1653,7 +1653,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co else if (!(Token::simpleMatch(tok->next(), "operator= (") || Token::simpleMatch(tok->next(), "this . operator= (") || (Token::Match(tok->next(), "%type% :: operator= (") && - tok->next()->str() == scope->className))) + tok->strAt(1) == scope->className))) operatorEqRetRefThisError(func->token); } if (foundReturn) { @@ -2848,11 +2848,11 @@ const std::list & CheckClass::getVirtualFunctionCalls(const Funct continue; if (tok->previous() && - tok->previous()->str() == "(") { + tok->strAt(-1) == "(") { const Token * prev = tok->previous(); if (prev->previous() && (mSettings->library.ignorefunction(tok->str()) - || mSettings->library.ignorefunction(prev->previous()->str()))) + || mSettings->library.ignorefunction(prev->strAt(-1)))) continue; } diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 6ecf3330509..f124ae3b4fc 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -106,7 +106,7 @@ void CheckCondition::assignIf() if (Token::Match(tok->next(), "%num% [&|]")) { bitop = tok->strAt(2).at(0); - num = MathLib::toBigNumber(tok->next()->str()); + num = MathLib::toBigNumber(tok->strAt(1)); } else { const Token *endToken = Token::findsimplematch(tok, ";"); @@ -116,7 +116,7 @@ void CheckCondition::assignIf() if (endToken && Token::Match(endToken->tokAt(-2), "[&|] %num% ;")) { bitop = endToken->strAt(-2).at(0); - num = MathLib::toBigNumber(endToken->previous()->str()); + num = MathLib::toBigNumber(endToken->strAt(-1)); } } diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index eb811d957de..0b876738d23 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -335,7 +335,7 @@ static bool isForwardJump(const Token *gotoToken) if (!Token::Match(gotoToken, "goto %name% ;")) return false; for (const Token *prev = gotoToken; gotoToken; gotoToken = gotoToken->previous()) { - if (Token::Match(prev, "%name% :") && prev->str() == gotoToken->next()->str()) + if (Token::Match(prev, "%name% :") && prev->str() == gotoToken->strAt(1)) return true; if (prev->str() == "{" && prev->scope()->type == Scope::eFunction) return false; diff --git a/lib/checkio.cpp b/lib/checkio.cpp index de4e6e15c44..a6134428f23 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -1434,7 +1434,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, const Token *tok1 = arg->next(); for (; tok1; tok1 = tok1->next()) { if (tok1->str() == "," || tok1->str() == ")") { - if (tok1->previous()->str() == "]") { + if (tok1->strAt(-1) == "]") { varTok = tok1->linkAt(-1)->previous(); if (varTok->str() == ")" && varTok->link()->previous()->tokType() == Token::eFunction) { const Function * function = varTok->link()->previous()->function(); @@ -1455,7 +1455,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, } return; } - } else if (tok1->previous()->str() == ")" && tok1->linkAt(-1)->previous()->tokType() == Token::eFunction) { + } else if (tok1->strAt(-1) == ")" && tok1->linkAt(-1)->previous()->tokType() == Token::eFunction) { const Function * function = tok1->linkAt(-1)->previous()->function(); if (function && function->retType && function->retType->isEnumType()) { if (function->retType->classScope->enumType) @@ -1484,9 +1484,9 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, // check for some common well known functions else if (isCPP && ((Token::Match(tok1->previous(), "%var% . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous())) || - (Token::Match(tok1->previous(), "] . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous()->link()->previous())))) { + (Token::Match(tok1->previous(), "] . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->linkAt(-1)->previous())))) { tempToken = new Token(tok1); - if (tok1->next()->str() == "size") { + if (tok1->strAt(1) == "size") { // size_t is platform dependent if (settings.platform.sizeof_size_t == 8) { tempToken->str("long"); @@ -1502,9 +1502,9 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, tempToken->originalName("size_t"); tempToken->isUnsigned(true); - } else if (tok1->next()->str() == "empty") { + } else if (tok1->strAt(1) == "empty") { tempToken->str("bool"); - } else if (tok1->next()->str() == "c_str") { + } else if (tok1->strAt(1) == "c_str") { tempToken->str("const"); tempToken->insertToken("*"); if (typeToken->strAt(2) == "string") @@ -1534,7 +1534,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings &settings, if (varTok) { variableInfo = varTok->variable(); - element = tok1->previous()->str() == "]"; + element = tok1->strAt(-1) == "]"; // look for std::vector operator [] and use template type as return type if (variableInfo) { diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index d71865c3312..cf4aca0264a 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -923,7 +923,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI if (allocation.status == VarInfo::NOALLOC) { // possible usage varInfo.possibleUsage[arg->varId()] = { tok, VarInfo::USED }; - if (var->second.status == VarInfo::DEALLOC && arg->previous()->str() == "&") + if (var->second.status == VarInfo::DEALLOC && arg->strAt(-1) == "&") varInfo.erase(arg->varId()); } else if (var->second.managed()) { doubleFreeError(tok, var->second.allocTok, arg->str(), allocation.type); diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 6e034738260..8c9cc1eb160 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -355,10 +355,10 @@ void CheckNullPointer::nullConstantDereference() } } - else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->linkAt(1)->next(), "[.(]"))) + else if (Token::Match(tok, "0 [") && (tok->strAt(-1) != "&" || !Token::Match(tok->linkAt(1)->next(), "[.(]"))) nullPointerError(tok); - else if (Token::Match(tok->previous(), "!!. %name% (|{") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { + else if (Token::Match(tok->previous(), "!!. %name% (|{") && (tok->strAt(-1) != "::" || tok->strAt(-2) == "std")) { if (Token::Match(tok->tokAt(2), "0|NULL|nullptr )|}") && tok->varId()) { // constructor call const Variable *var = tok->variable(); if (var && !var->isPointer() && !var->isArray() && var->isStlStringType()) @@ -395,7 +395,7 @@ void CheckNullPointer::nullConstantDereference() if (Token::Match(tok2->previous(), ";|{|}|:|(")) break; } - if (tok2 && tok2->previous() && tok2->previous()->str()=="(") + if (tok2 && tok2->previous() && tok2->strAt(-1)=="(") continue; if (Token::simpleMatch(tok2, "std :: cin")) nullPointerError(tok); diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 711360e7aaa..03e1aa7575e 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1886,7 +1886,7 @@ static bool isVoidStmt(const Token *tok) const Token *tok2 = tok; while (tok2->astOperand1()) tok2 = tok2->astOperand1(); - if (Token::simpleMatch(tok2->previous(), ")") && Token::simpleMatch(tok2->previous()->link(), "( void")) + if (Token::simpleMatch(tok2->previous(), ")") && Token::simpleMatch(tok2->linkAt(-1), "( void")) return true; if (Token::simpleMatch(tok2, "( void")) return true; @@ -2540,7 +2540,7 @@ void CheckOther::checkDuplicateExpression() while (parent && parent->astParent()) { parent = parent->astParent(); } - if (parent && parent->previous() && parent->previous()->str() == "static_assert") { + if (parent && parent->previous() && parent->strAt(-1) == "static_assert") { continue; } } diff --git a/lib/checksizeof.cpp b/lib/checksizeof.cpp index ffd9622bdc0..c14de0a78db 100644 --- a/lib/checksizeof.cpp +++ b/lib/checksizeof.cpp @@ -326,7 +326,7 @@ void CheckSizeof::sizeofCalculation() // ignore if the `sizeof` result is cast to void inside a macro, i.e. the calculation is // expected to be parsed but skipped, such as in a disabled custom ASSERT() macro if (tok->isExpandedMacro() && tok->previous()) { - const Token *cast_end = (tok->previous()->str() == "(") ? tok->previous() : tok; + const Token *cast_end = (tok->strAt(-1) == "(") ? tok->previous() : tok; if (Token::simpleMatch(cast_end->tokAt(-3), "( void )") || Token::simpleMatch(cast_end->tokAt(-4), "static_cast < void >")) { continue; @@ -369,7 +369,7 @@ void CheckSizeof::sizeofFunction() // ignore if the `sizeof` result is cast to void inside a macro, i.e. the calculation is // expected to be parsed but skipped, such as in a disabled custom ASSERT() macro if (tok->isExpandedMacro() && tok->previous()) { - const Token *cast_end = (tok->previous()->str() == "(") ? tok->previous() : tok; + const Token *cast_end = (tok->strAt(-1) == "(") ? tok->previous() : tok; if (Token::simpleMatch(cast_end->tokAt(-3), "( void )") || Token::simpleMatch(cast_end->tokAt(-4), "static_cast < void >")) { continue; diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 61deb6d0d57..09d7c77e28b 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -284,7 +284,7 @@ bool CheckStl::isContainerSize(const Token *containerToken, const Token *expr) c return false; if (!isSameExpression(false, containerToken, expr->astOperand1()->astOperand1(), *mSettings, false, false)) return false; - return containerToken->valueType()->container->getYield(expr->previous()->str()) == Library::Container::Yield::SIZE; + return containerToken->valueType()->container->getYield(expr->strAt(-1)) == Library::Container::Yield::SIZE; } bool CheckStl::isContainerSizeGE(const Token * containerToken, const Token *expr) const @@ -537,7 +537,7 @@ void CheckStl::iterators() continue; // No warning // skip error message if the iterator is erased/inserted by value - if (itTok->previous()->str() == "*") + if (itTok->strAt(-1) == "*") continue; // inserting iterator range.. @@ -2885,7 +2885,7 @@ void CheckStl::useStlAlgorithm() auto isConditionWithoutSideEffects = [this](const Token* tok) -> bool { if (!Token::simpleMatch(tok, "{") || !Token::simpleMatch(tok->previous(), ")")) return false; - return isConstExpression(tok->previous()->link()->astOperand2(), mSettings->library); + return isConstExpression(tok->linkAt(-1)->astOperand2(), mSettings->library); }; for (const Scope *function : mTokenizer->getSymbolDatabase()->functionScopes) { diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index a053c811a75..7fd9a063d64 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1373,7 +1373,7 @@ int CheckUninitVar::isFunctionParUsage(const Token *vartok, const Library& libra // is this a function call? if (Token::Match(start->previous(), "%name% (")) { - const bool address(vartok->previous()->str() == "&"); + const bool address(vartok->strAt(-1) == "&"); const bool array(vartok->variable() && vartok->variable()->isArray()); // check how function handle uninitialized data arguments.. const Function *func = start->previous()->function(); diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index 67f0f0c56f4..f538b3a3544 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -131,7 +131,7 @@ void CheckUnusedFunctions::parseTokens(const Tokenizer &tokenizer, const Setting mFunctionCalls.insert(markupVarToken->str()); if (mFunctions.find(markupVarToken->str()) != mFunctions.end()) mFunctions[markupVarToken->str()].usedOtherFile = true; - else if (markupVarToken->next()->str() == "(") { + else if (markupVarToken->strAt(1) == "(") { FunctionUsage &func = mFunctions[markupVarToken->str()]; func.filename = tokenizer.list.getFiles()[markupVarToken->fileIndex()]; if (func.filename.empty() || func.filename == "+") diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index ebc2e213ed3..6c457c58584 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -697,15 +697,15 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const if (i->isThrow() || i->isExtern()) continue; Variables::VariableType type = Variables::none; - if (i->isArray() && (i->nameToken()->previous()->str() == "*" || i->nameToken()->strAt(-2) == "*")) + if (i->isArray() && (i->nameToken()->strAt(-1) == "*" || i->nameToken()->strAt(-2) == "*")) type = Variables::pointerArray; - else if (i->isArray() && i->nameToken()->previous()->str() == "&") + else if (i->isArray() && i->nameToken()->strAt(-1) == "&") type = Variables::referenceArray; else if (i->isArray()) type = Variables::array; else if (i->isReference() && !(i->valueType() && i->valueType()->type == ValueType::UNKNOWN_TYPE && Token::simpleMatch(i->typeStartToken(), "auto"))) type = Variables::reference; - else if (i->nameToken()->previous()->str() == "*" && i->nameToken()->strAt(-2) == "*") + else if (i->nameToken()->strAt(-1) == "*" && i->nameToken()->strAt(-2) == "*") type = Variables::pointerPointer; else if (i->isPointerToArray()) type = Variables::pointerPointer; @@ -743,7 +743,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const if (defValTok && defValTok->next()) { // simple assignment "var = 123" - if (defValTok->str() == "=" && defValTok->next()->str() != "{") { + if (defValTok->str() == "=" && defValTok->strAt(1) != "{") { doAssignment(variables, i->nameToken(), false, scope); } else { // could be "var = {...}" OR "var{...}" (since C++11) @@ -1064,7 +1064,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const // function parameter else if (Token::Match(tok, "[(,] %var% [")) { variables.use(tok->next()->varId(), tok); // use = read + write - } else if (Token::Match(tok, "[(,] %var% [,)]") && tok->previous()->str() != "*") { + } else if (Token::Match(tok, "[(,] %var% [,)]") && tok->strAt(-1) != "*") { variables.use(tok->next()->varId(), tok); // use = read + write } else if (Token::Match(tok, "[(,] & %var% [,)]")) { variables.eraseAll(tok->tokAt(2)->varId()); @@ -1110,7 +1110,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const variables.readAll(tok->next()->varId(), tok); } - else if (tok->varId() && !isVarDecl(tok) && tok->next() && (tok->next()->str() == ")" || tok->next()->isExtendedOp())) { + else if (tok->varId() && !isVarDecl(tok) && tok->next() && (tok->strAt(1) == ")" || tok->next()->isExtendedOp())) { if (Token::Match(tok->tokAt(-2), "%name% ( %var% [,)]") && !(tok->tokAt(-2)->variable() && tok->tokAt(-2)->variable()->isReference())) variables.use(tok->varId(), tok); @@ -1143,7 +1143,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const } } else if (tok->variable() && tok->variable()->isClass() && tok->variable()->type() && (tok->variable()->type()->needInitialization == Type::NeedInitialization::False) && - tok->next()->str() == ";") { + tok->strAt(1) == ";") { variables.write(tok->varId(), tok); } } @@ -1369,7 +1369,7 @@ void CheckUnusedVar::checkFunctionVariableUsage() else if (!usage._var->isMaybeUnused() && !usage._modified && !usage._read && var) { const Token* vnt = var->nameToken(); bool error = false; - if (vnt->next()->isSplittedVarDeclEq() || (!var->isReference() && vnt->next()->str() == "=")) { + if (vnt->next()->isSplittedVarDeclEq() || (!var->isReference() && vnt->strAt(1) == "=")) { const Token* nextStmt = vnt->tokAt(2); if (nextStmt->isExpandedMacro()) { const Token* parent = nextStmt; @@ -1524,7 +1524,7 @@ void CheckUnusedVar::checkStructMemberUsage() // Check if the struct member variable is used anywhere in the file bool use = false; for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { - if (Token::Match(tok, ". %name%") && !tok->next()->variable() && !tok->next()->function() && tok->next()->str() == var.name()) { + if (Token::Match(tok, ". %name%") && !tok->next()->variable() && !tok->next()->function() && tok->strAt(1) == var.name()) { // not known => assume variable is used use = true; break; diff --git a/lib/fwdanalysis.cpp b/lib/fwdanalysis.cpp index 9b6feff7fea..d735e6771e9 100644 --- a/lib/fwdanalysis.cpp +++ b/lib/fwdanalysis.cpp @@ -406,7 +406,7 @@ std::set FwdAnalysis::getExprVarIds(const Token* expr, bool* localOu [&](const Token *tok) { if (tok->str() == "[" && mWhat == What::UnusedValue) return ChildrenToVisit::op1; - if (tok->varId() == 0 && tok->isName() && tok->previous()->str() != ".") { + if (tok->varId() == 0 && tok->isName() && tok->strAt(-1) != ".") { // unknown variable unknownVarId = true; return ChildrenToVisit::none; diff --git a/lib/library.cpp b/lib/library.cpp index 239ec0062e5..0c2df2145b2 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -938,7 +938,7 @@ bool Library::isIntArgValid(const Token *ftok, int argnr, const MathLib::bigint return true; if (Token::Match(tok, "%num% : ,") && argvalue >= MathLib::toBigNumber(tok->str())) return true; - if ((!tok->previous() || tok->previous()->str() == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toBigNumber(tok->strAt(1))) + if ((!tok->previous() || tok->strAt(-1) == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toBigNumber(tok->strAt(1))) return true; } return false; @@ -956,12 +956,12 @@ bool Library::isFloatArgValid(const Token *ftok, int argnr, double argvalue) con return true; if (Token::Match(tok, "%num% : ,") && argvalue >= MathLib::toDoubleNumber(tok->str())) return true; - if ((!tok->previous() || tok->previous()->str() == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toDoubleNumber(tok->strAt(1))) + if ((!tok->previous() || tok->strAt(-1) == ",") && Token::Match(tok,": %num%") && argvalue <= MathLib::toDoubleNumber(tok->strAt(1))) return true; if (Token::Match(tok, "%num%") && MathLib::isFloat(tok->str()) && MathLib::isEqual(tok->str(), MathLib::toString(argvalue))) return true; - if (Token::Match(tok, "! %num%") && MathLib::isFloat(tok->next()->str())) - return MathLib::isNotEqual(tok->next()->str(), MathLib::toString(argvalue)); + if (Token::Match(tok, "! %num%") && MathLib::isFloat(tok->strAt(1))) + return MathLib::isNotEqual(tok->strAt(1), MathLib::toString(argvalue)); } return false; } @@ -1265,7 +1265,7 @@ bool Library::isContainerYield(const Token * const cond, Library::Container::Yie return tok->astOperand2() && y == container->getYield(tok->astOperand2()->str()); } } else if (!fallback.empty()) { - return Token::simpleMatch(cond, "( )") && cond->previous()->str() == fallback; + return Token::simpleMatch(cond, "( )") && cond->strAt(-1) == fallback; } } } diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index dab952aa9a3..e8609cdae9c 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -1549,7 +1549,7 @@ namespace { return unknown(); } else if (expr->str() == "(" && expr->isCast()) { - if (Token::simpleMatch(expr->previous(), ">") && expr->previous()->link()) + if (Token::simpleMatch(expr->previous(), ">") && expr->linkAt(-1)) return execute(expr->astOperand2()); return execute(expr->astOperand1()); } diff --git a/lib/reverseanalyzer.cpp b/lib/reverseanalyzer.cpp index 22a7fda933a..04aba5bc203 100644 --- a/lib/reverseanalyzer.cpp +++ b/lib/reverseanalyzer.cpp @@ -111,7 +111,7 @@ namespace { if (Token::simpleMatch(tok->tokAt(-2), "} else {")) tok = tok->linkAt(-2); if (Token::simpleMatch(tok->previous(), ") {")) - return tok->previous()->link(); + return tok->linkAt(-1); if (Token::simpleMatch(tok->previous(), "do {")) return tok->previous(); return tok; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3f5c826a6a8..0ed2154c591 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -205,7 +205,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() if (!Token::Match(tok2, "{|:")) { // check for qualified variable if (tok2 && tok2->next()) { - if (tok2->next()->str() == ";") + if (tok2->strAt(1) == ";") tok = tok2->next(); else if (Token::simpleMatch(tok2->next(), "= {") && Token::simpleMatch(tok2->linkAt(2), "} ;")) @@ -543,7 +543,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // class function? else if (isFunction(tok, scope, funcStart, argStart, declEnd)) { - if (tok->previous()->str() != "::" || tok->strAt(-2) == scope->className) { + if (tok->strAt(-1) != "::" || tok->strAt(-2) == scope->className) { Function function(tok, scope, funcStart, argStart); // save the access type @@ -651,12 +651,12 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() tok = funcStart; // class function - if (tok->previous() && tok->previous()->str() == "::") + if (tok->previous() && tok->strAt(-1) == "::") addClassFunction(scope, tok, argStart); // class destructor else if (tok->previous() && - tok->previous()->str() == "~" && + tok->strAt(-1) == "~" && tok->strAt(-2) == "::") addClassFunction(scope, tok, argStart); @@ -1153,7 +1153,7 @@ void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass) if (inTemplateArg == tok) inTemplateArg = nullptr; if (tok->isName() && !tok->function() && tok->varId() == 0 && ((tok->astParent() && tok->astParent()->isComparisonOp()) || Token::Match(tok, "%name% [{(,)>;]")) && !isReservedName(tok)) { - if (tok->next()->str() == ">" && !tok->linkAt(1)) + if (tok->strAt(1) == ">" && !tok->linkAt(1)) continue; const Function *function = findFunction(tok); @@ -1162,7 +1162,7 @@ void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass) tok->function(function); - if (tok->next()->str() != "(") + if (tok->strAt(1) != "(") const_cast(function)->functionPointerUsage = tok; } } @@ -1347,12 +1347,12 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() // check for function returning record type // func(...).var // func(...)[...].var - else if (tok->function() && tok->next()->str() == "(" && + else if (tok->function() && tok->strAt(1) == "(" && (Token::Match(tok->linkAt(1), ") . %name% !!(") || (Token::Match(tok->linkAt(1), ") [") && Token::Match(tok->linkAt(1)->linkAt(1), "] . %name% !!(")))) { const Type *type = tok->function()->retType; Token* membertok; - if (tok->linkAt(1)->next()->str() == ".") + if (tok->linkAt(1)->strAt(1) == ".") membertok = tok->linkAt(1)->next()->next(); else membertok = tok->linkAt(1)->linkAt(1)->next()->next(); @@ -1375,7 +1375,7 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() } } } - else if (Token::simpleMatch(tok->astParent(), ".") && tok->next()->str() == "(" && + else if (Token::simpleMatch(tok->astParent(), ".") && tok->strAt(1) == "(" && astIsContainer(tok->astParent()->astOperand1()) && Token::Match(tok->linkAt(1), ") . %name% !!(")) { const ValueType* vt = tok->astParent()->astOperand1()->valueType(); const Library::Container* cont = vt->container; @@ -1491,7 +1491,7 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars() while (Token::simpleMatch(ftok, "::")) { if (!Token::Match(ftok->previous(), "%name%")) break; - fstr.insert(0, ftok->previous()->str() + "::"); + fstr.insert(0, ftok->strAt(-1) + "::"); ftok = ftok->tokAt(-2); } if (mSettings.library.functions().find(fstr) != mSettings.library.functions().end()) @@ -1822,7 +1822,7 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow() if (Token::Match(tokenList.front(), "; %num% ;")) { dimension.known = true; - dimension.num = MathLib::toBigNumber(tokenList.front()->next()->str()); + dimension.num = MathLib::toBigNumber(tokenList.front()->strAt(1)); } continue; @@ -1893,11 +1893,11 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const // function returning reference to array '... ( & %name% ( ... ))[ ... ] {' // TODO: Activate this again if ((false) && tok->str() == "(" && tok->strAt(1) != "*" && // NOLINT(readability-simplify-boolean-expr) - (tok->link()->previous()->str() == ")" || Token::simpleMatch(tok->link()->tokAt(-2), ") const"))) { + (tok->link()->strAt(-1) == ")" || Token::simpleMatch(tok->link()->tokAt(-2), ") const"))) { const Token* tok2 = tok->link()->next(); if (tok2 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "{|;|const|=")) { const Token* argStartTok; - if (tok->link()->previous()->str() == "const") + if (tok->link()->strAt(-1) == "const") argStartTok = tok->link()->linkAt(-2); else argStartTok = tok->link()->linkAt(-1); @@ -1911,7 +1911,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const tok2 = tok2->link()->next(); if (Token::Match(tok2, "{|;|const|=")) { const Token* argStartTok; - if (tok->link()->previous()->str() == "const") + if (tok->link()->strAt(-1) == "const") argStartTok = tok->link()->linkAt(-2); else argStartTok = tok->link()->linkAt(-1); @@ -2275,7 +2275,7 @@ bool Variable::isMember() const { bool Variable::isPointerArray() const { - return isArray() && nameToken() && nameToken()->previous() && (nameToken()->previous()->str() == "*"); + return isArray() && nameToken() && nameToken()->previous() && (nameToken()->strAt(-1) == "*"); } bool Variable::isUnsigned() const @@ -2381,7 +2381,7 @@ void Variable::evaluate(const Settings& settings) while (tok && tok->str() == "]") tok = tok->link()->previous(); // add array dimensions if present - if (tok && tok->next()->str() == "[") + if (tok && tok->strAt(1) == "[") setFlag(fIsArray, arrayDimensions(settings, isContainer)); } if (!tok) @@ -2443,7 +2443,7 @@ const Type* Variable::smartPointerType() const const Scope* scope = typeTok->scope(); const Type* ptrType{}; while (scope && !ptrType) { - ptrType = scope->findType(typeTok->next()->str()); + ptrType = scope->findType(typeTok->strAt(1)); scope = scope->nestedIn; } return ptrType; @@ -2517,7 +2517,7 @@ Function::Function(const Token *tok, tokenDef->str().size() > scope->className.size() + 1 && tokenDef->str()[scope->className.size() + 1] == '<'))) { // destructor - if (tokenDef->previous()->str() == "~") + if (tokenDef->strAt(-1) == "~") type = Function::eDestructor; // constructor of any kind else @@ -2568,7 +2568,7 @@ Function::Function(const Token *tok, isVolatile(true); else if (tok->str() == "noexcept") { isNoExcept(!Token::simpleMatch(tok->next(), "( false )")); - if (tok->next()->str() == "(") + if (tok->strAt(1) == "(") tok = tok->linkAt(1); } else if (Token::simpleMatch(tok, "throw (")) { isThrow(true); @@ -2841,11 +2841,11 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se second = skipTopLevelConst(second); // skip default value assignment - if (oldSecond == second && first->next()->str() == "=") { + if (oldSecond == second && first->strAt(1) == "=") { first = first->nextArgument(); if (first) first = first->tokAt(-2); - if (second->next()->str() == "=") { + if (second->strAt(1) == "=") { second = second->nextArgument(); if (second) second = second->tokAt(-2); @@ -2855,7 +2855,7 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se } else if (!first) { // End of argument list (first) return !second->nextArgument(); // End of argument list (second) } - } else if (oldSecond == second && second->next()->str() == "=") { + } else if (oldSecond == second && second->strAt(1) == "=") { second = second->nextArgument(); if (second) second = second->tokAt(-2); @@ -2865,29 +2865,29 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se } // definition missing variable name - else if ((first->next()->str() == "," && second->next()->str() != ",") || - (Token::Match(first, "!!( )") && second->next()->str() != ")")) { + else if ((first->strAt(1) == "," && second->strAt(1) != ",") || + (Token::Match(first, "!!( )") && second->strAt(1) != ")")) { second = second->next(); // skip default value assignment - if (second->next()->str() == "=") { + if (second->strAt(1) == "=") { do { second = second->next(); } while (!Token::Match(second->next(), ",|)")); } - } else if (first->next()->str() == "[" && second->next()->str() != "[") + } else if (first->strAt(1) == "[" && second->strAt(1) != "[") second = second->next(); // function missing variable name - else if ((second->next()->str() == "," && first->next()->str() != ",") || - (Token::Match(second, "!!( )") && first->next()->str() != ")")) { + else if ((second->strAt(1) == "," && first->strAt(1) != ",") || + (Token::Match(second, "!!( )") && first->strAt(1) != ")")) { first = first->next(); // skip default value assignment - if (first->next()->str() == "=") { + if (first->strAt(1) == "=") { do { first = first->next(); } while (!Token::Match(first->next(), ",|)")); } - } else if (second->next()->str() == "[" && first->next()->str() != "[") + } else if (second->strAt(1) == "[" && first->strAt(1) != "[") first = first->next(); // unnamed parameters @@ -2915,7 +2915,7 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se } // const after * - else if (first->next()->str() == "*" && second->next()->str() == "*" && + else if (first->strAt(1) == "*" && second->strAt(1) == "*" && ((first->strAt(2) != "const" && second->strAt(2) == "const") || (first->strAt(2) == "const" && second->strAt(2) != "const"))) { if (first->strAt(2) != "const") { @@ -2940,13 +2940,13 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se // variable names are different else if ((Token::Match(first->next(), "%name% ,|)|=|[") && Token::Match(second->next(), "%name% ,|)|[")) && - (first->next()->str() != second->next()->str())) { + (first->strAt(1) != second->strAt(1))) { // skip variable names first = first->next(); second = second->next(); // skip default value assignment - if (first->next()->str() == "=") { + if (first->strAt(1) == "=") { do { first = first->next(); } while (!Token::Match(first->next(), ",|)")); @@ -2978,10 +2978,10 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se (Token::Match(second->next(), "%name% :: %name%") || (Token::Match(second->next(), "%name% <") && Token::Match(second->linkAt(1), "> :: %name%"))) && - ((second->next()->str() == scope->className) || - (scope->nestedIn && second->next()->str() == scope->nestedIn->className) || - (scope->definedType && scope->definedType->isDerivedFrom(second->next()->str()))) && - (first->next()->str() == second->strAt(3))) { + ((second->strAt(1) == scope->className) || + (scope->nestedIn && second->strAt(1) == scope->nestedIn->className) || + (scope->definedType && scope->definedType->isDerivedFrom(second->strAt(1)))) && + (first->strAt(1) == second->strAt(3))) { if (Token::Match(second->next(), "%name% <")) second = second->linkAt(1)->next(); else @@ -3244,7 +3244,7 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok, void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const Token *argStart) { - const bool destructor(tok->previous()->str() == "~"); + const bool destructor(tok->strAt(-1) == "~"); const bool has_const(argStart->link()->strAt(1) == "const"); const bool lval(argStart->link()->strAt(has_const ? 2 : 1) == "&"); const bool rval(argStart->link()->strAt(has_const ? 2 : 1) == "&&"); @@ -3257,7 +3257,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To tok1 = tok1->previous(); // back up to head of path - while (tok1 && tok1->previous() && tok1->previous()->str() == "::" && tok1->tokAt(-2) && + while (tok1 && tok1->previous() && tok1->strAt(-1) == "::" && tok1->tokAt(-2) && ((tok1->tokAt(-2)->isName() && !tok1->tokAt(-2)->isStandardType()) || (tok1->strAt(-2) == ">" && tok1->linkAt(-2) && Token::Match(tok1->linkAt(-2)->previous(), "%name%")))) { count++; @@ -3267,7 +3267,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To if (tok2) { do { - path = tok1->previous()->str() + " " + path; + path = tok1->strAt(-1) + " " + path; tok1 = tok1->previous(); path_length++; } while (tok1 != tok2); @@ -3383,7 +3383,7 @@ void SymbolDatabase::addClassFunction(Scope *&scope, const Token *&tok, const To func->hasBody(true); } else if (func->type != Function::eDestructor && !destructor) { // normal function? - const bool hasConstKeyword = closeParen->next()->str() == "const"; + const bool hasConstKeyword = closeParen->strAt(1) == "const"; if ((func->isConst() == hasConstKeyword) && (func->hasLvalRefQualifier() == lval) && (func->hasRvalRefQualifier() == rval)) { @@ -3709,7 +3709,7 @@ bool Variable::arrayDimensions(const Settings& settings, bool& isContainer) Dimension dimension_; dimension_.known = false; // check for empty array dimension [] - if (dim->next()->str() != "]") { + if (dim->strAt(1) != "]") { dimension_.tok = dim->astOperand2(); // TODO: only perform when ValueFlow is enabled // TODO: collect timing information for this call? @@ -4042,7 +4042,7 @@ void SymbolDatabase::printOut(const char *title) const std::cout << (enumerator.value_known ? " " : "") << "[" << tok->str(); while (tok && tok != enumerator.end) { if (tok->next()) - std::cout << " " << tok->next()->str(); + std::cout << " " << tok->strAt(1); tok = tok->next(); } @@ -4450,7 +4450,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s } else if (tok->str() == "[") { // skip array dimension(s) tok = tok->link(); - while (tok->next()->str() == "[") + while (tok->strAt(1) == "[") tok = tok->linkAt(1); } else if (tok->str() == "<") { tok = tok->link(); @@ -4864,8 +4864,8 @@ void Scope::getVariableList(const Settings& settings, const Token* start, const // skip return, goto and delete else if (tok->isKeyword() && Token::Match(tok, "return|delete|goto")) { while (tok->next() && - tok->next()->str() != ";" && - tok->next()->str() != "}" /* ticket #4994 */) { + tok->strAt(1) != ";" && + tok->strAt(1) != "}" /* ticket #4994 */) { tok = tok->next(); } continue; @@ -6571,14 +6571,14 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, const } if (vt1 && vt1->container && vt1->containerTypeToken && Token::Match(parent, ". %name% (") && - isContainerYieldElement(vt1->container->getYield(parent->next()->str()))) { + isContainerYieldElement(vt1->container->getYield(parent->strAt(1)))) { ValueType item; if (parsedecl(vt1->containerTypeToken, &item, mDefaultSignedness, mSettings)) { if (item.constness == 0) item.constness = vt1->constness; if (item.volatileness == 0) item.volatileness = vt1->volatileness; - if (isContainerYieldPointer(vt1->container->getYield(parent->next()->str()))) + if (isContainerYieldPointer(vt1->container->getYield(parent->strAt(1)))) item.pointer += 1; else item.reference = Reference::LValue; @@ -6845,13 +6845,13 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, const autovt.reference = Reference::LValue; else if (Token::simpleMatch(autoToken->next(), "&&")) autovt.reference = Reference::RValue; - if (autoToken->previous()->str() == "const") { + if (autoToken->strAt(-1) == "const") { if (autovt.pointer && autovt.reference != Reference::None) autovt.constness |= 2; else autovt.constness |= 1; } - if (autoToken->previous()->str() == "volatile") { + if (autoToken->strAt(-1) == "volatile") { if (autovt.pointer && autovt.reference != Reference::None) autovt.volatileness |= 2; else @@ -7071,7 +7071,7 @@ static const Token* parsedecl(const Token* type, valuetype->setDebugPath(type, loc); const Token * const previousType = type; const unsigned int pointer0 = valuetype->pointer; - while (Token::Match(type->previous(), "%name%") && !endsWith(type->previous()->str(), ':')) + while (Token::Match(type->previous(), "%name%") && !endsWith(type->strAt(-1), ':')) type = type->previous(); valuetype->sign = ValueType::Sign::UNKNOWN_SIGN; if (!valuetype->typeScope && !valuetype->smartPointerType) @@ -7479,7 +7479,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to continue; } - valuetype.type = ValueType::typeFromString(tok->previous()->str(), tok->previous()->isLong()); + valuetype.type = ValueType::typeFromString(tok->strAt(-1), tok->previous()->isLong()); if (tok->previous()->isUnsigned()) valuetype.sign = ValueType::Sign::UNSIGNED; else if (tok->previous()->isSigned()) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 72dff5c99bf..2057c407fc4 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -106,7 +106,7 @@ class CPPCHECKLIB Type { else if (classDef_ && classDef_->str() == "using") { typeStart = classDef->tokAt(3); typeEnd = typeStart; - while (typeEnd->next() && typeEnd->next()->str() != ";") { + while (typeEnd->next() && typeEnd->strAt(1) != ";") { if (Token::simpleMatch(typeEnd, "decltype (")) typeEnd = typeEnd->linkAt(1); else diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index e2cdbfa6e7d..bf21d51c5e0 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -347,9 +347,9 @@ void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() inclevel = true; else if (Token::simpleMatch(tok2, "< typename")) inclevel = true; - else if (Token::Match(tok2->tokAt(-2), "<|, %type% <") && usedtypes.find(tok2->previous()->str()) != usedtypes.end()) + else if (Token::Match(tok2->tokAt(-2), "<|, %type% <") && usedtypes.find(tok2->strAt(-1)) != usedtypes.end()) inclevel = true; - else if (Token::Match(tok2, "< %type%") && usedtypes.find(tok2->next()->str()) != usedtypes.end()) + else if (Token::Match(tok2, "< %type%") && usedtypes.find(tok2->strAt(1)) != usedtypes.end()) inclevel = true; else if (Token::Match(tok2, "< %type%")) { // is the next token a type and not a variable/constant? @@ -365,7 +365,7 @@ void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() if (inclevel) { ++level; if (Token::Match(tok2->tokAt(-2), "<|, %type% <")) - usedtypes.insert(tok2->previous()->str()); + usedtypes.insert(tok2->strAt(-1)); } } else if (tok2->str() == ">") { if (level > 0) @@ -1902,7 +1902,7 @@ void TemplateSimplifier::expandTemplate( } if (tok3->str()=="template") { - if (tok3->next() && tok3->next()->str()=="<") { + if (tok3->next() && tok3->strAt(1)=="<") { std::vector localTypeParametersInDeclaration; getTemplateParametersInDeclaration(tok3->tokAt(2), localTypeParametersInDeclaration); inTemplateDefinition = localTypeParametersInDeclaration.size() == typeParametersInDeclaration.size(); // Partial specialization @@ -2336,8 +2336,8 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok, bool isTemplate break; const Token* op = tok->next(); const Token* after = tok->tokAt(3); - const std::string &num1 = op->previous()->str(); - const std::string &num2 = op->next()->str(); + const std::string &num1 = op->strAt(-1); + const std::string &num2 = op->strAt(1); if (Token::Match(before, "* %num% /") && (num2 != "0") && num1 == MathLib::multiply(num2, MathLib::divide(num1, num2))) { // Division where result is a whole number } else if (!((op->str() == "*" && (isLowerThanMulDiv(before) || before->str() == "*") && isLowerEqualThanMulDiv(after)) || // associative @@ -2508,7 +2508,7 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end, st if ((Token::Match(tok->previous(), "(|&&|%oror%|,") || tok == start) && (Token::Match(tok->tokAt(3), ")|&&|%oror%|?") || tok->tokAt(3) == end)) { const MathLib::bigint op1(MathLib::toBigNumber(tok->str())); - const std::string &cmp(tok->next()->str()); + const std::string &cmp(tok->strAt(1)); const MathLib::bigint op2(MathLib::toBigNumber(tok->strAt(2))); std::string result; @@ -2541,11 +2541,11 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end, st if (tok->str() == "?" && ((tok->previous()->isNumber() || tok->previous()->isBoolean()) || Token::Match(tok->tokAt(-3), "( %bool%|%num% )"))) { - const int offset = (tok->previous()->str() == ")") ? 2 : 1; + const int offset = (tok->strAt(-1) == ")") ? 2 : 1; // Find the token ":" then go to the next token Token *colon = skipTernaryOp(tok, end); - if (!colon || colon->previous()->str() != ":" || !colon->next()) + if (!colon || colon->strAt(-1) != ":" || !colon->next()) continue; //handle the GNU extension: "x ? : y" <-> "x ? x : y" @@ -2755,7 +2755,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba Token::Match(tok->previous(), "[(=,] 1 %oror%"))) { unsigned int par = 0; const Token *tok2 = tok; - const bool andAnd = (tok->next()->str() == "&&"); + const bool andAnd = (tok->strAt(1) == "&&"); for (; tok2; tok2 = tok2->next()) { if (tok2->str() == "(" || tok2->str() == "[") ++par; @@ -2779,7 +2779,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba (Token::Match(tok->previous(), "%or% 0 %cop%|;") && isLowerThanXor(tok->next())))) { tok = tok->previous(); if (Token::Match(tok->tokAt(-4), "[;{}] %name% = %name% [+-|] 0 ;") && - tok->strAt(-3) == tok->previous()->str()) { + tok->strAt(-3) == tok->strAt(-1)) { tok = tok->tokAt(-4); tok->deleteNext(5); } else { @@ -2800,7 +2800,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba Token::Match(tok->previous(), "return|case 0 *|&& (")) && validTokenEnd(bounded, tok, backToken, 2))))) { tok->deleteNext(); - if (tok->next()->str() == "(") + if (tok->strAt(1) == "(") eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; @@ -2809,7 +2809,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba Token::Match(tok->previous(), "return|case 0 && *|& %any% ,|:|;|=|%cop%"))) { tok->deleteNext(); tok->deleteNext(); - if (tok->next()->str() == "(") + if (tok->strAt(1) == "(") eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; @@ -2821,7 +2821,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba (Token::Match(tok->previous(), "[=[(,] 1 %oror% %any% ,|]|)|;|=|%cop%") || Token::Match(tok->previous(), "return|case 1 %oror% %any% ,|:|;|=|%cop%"))) { tok->deleteNext(); - if (tok->next()->str() == "(") + if (tok->strAt(1) == "(") eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; @@ -2830,7 +2830,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba Token::Match(tok->previous(), "return|case 1 %oror% *|& %any% ,|:|;|=|%cop%"))) { tok->deleteNext(); tok->deleteNext(); - if (tok->next()->str() == "(") + if (tok->strAt(1) == "(") eraseTokens(tok, tok->linkAt(1)); tok->deleteNext(); ret = true; @@ -2877,7 +2877,7 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *ba Token::Match(tok->previous(), "(|&&|%oror%") && Token::Match(tok->tokAt(3), ")|&&|%oror%|?")) { const MathLib::bigint op1(MathLib::toBigNumber(tok->str())); - const std::string &cmp(tok->next()->str()); + const std::string &cmp(tok->strAt(1)); const MathLib::bigint op2(MathLib::toBigNumber(tok->strAt(2))); std::string result; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 2093b364e3b..b56df5df959 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -248,7 +248,7 @@ bool Tokenizer::duplicateTypedef(Token *&tokPtr, const Token *name, const Token // find end of definition while (end && end->next() && !Token::Match(end->next(), ";|)|>")) { - if (end->next()->str() == "(") + if (end->strAt(1) == "(") end = end->linkAt(1); end = (end)?end->next():nullptr; @@ -256,15 +256,15 @@ bool Tokenizer::duplicateTypedef(Token *&tokPtr, const Token *name, const Token if (end) end = end->next(); } else if (end->str() == "(") { - if (startsWith(tok->previous()->str(), "operator")) + if (startsWith(tok->strAt(-1), "operator")) // conversion operator return false; - if (tok->previous()->str() == "typedef") + if (tok->strAt(-1) == "typedef") // typedef of function returning this type return false; if (Token::Match(tok->previous(), "public:|private:|protected:")) return false; - if (tok->previous()->str() == ">") { + if (tok->strAt(-1) == ">") { if (!Token::Match(tok->tokAt(-2), "%type%")) return false; @@ -300,39 +300,39 @@ bool Tokenizer::duplicateTypedef(Token *&tokPtr, const Token *name, const Token } else { // look backwards if (Token::Match(tok->previous(), "typedef|}|>") || - (end->str() == ";" && tok->previous()->str() == ",") || - (tok->previous()->str() == "*" && tok->next()->str() != "(") || + (end->str() == ";" && tok->strAt(-1) == ",") || + (tok->strAt(-1) == "*" && tok->strAt(1) != "(") || (Token::Match(tok->previous(), "%type%") && (!Token::Match(tok->previous(), "return|new|const|friend|public|private|protected|throw|extern") && !Token::simpleMatch(tok->tokAt(-2), "friend class")))) { // scan backwards for the end of the previous statement while (tok && tok->previous() && !Token::Match(tok->previous(), ";|{")) { - if (tok->previous()->str() == "}") { - tok = tok->previous()->link(); - } else if (tok->previous()->str() == "typedef") { + if (tok->strAt(-1) == "}") { + tok = tok->linkAt(-1); + } else if (tok->strAt(-1) == "typedef") { return true; - } else if (tok->previous()->str() == "enum") { + } else if (tok->strAt(-1) == "enum") { return true; - } else if (tok->previous()->str() == "struct") { + } else if (tok->strAt(-1) == "struct") { if (tok->strAt(-2) == "typedef" && - tok->next()->str() == "{" && + tok->strAt(1) == "{" && typeDef->strAt(3) != "{") { // declaration after forward declaration return true; } - if (tok->next()->str() == "{") + if (tok->strAt(1) == "{") return true; if (Token::Match(tok->next(), ")|*")) return true; - if (tok->next()->str() == name->str()) + if (tok->strAt(1) == name->str()) return true; - if (tok->next()->str() != ";") + if (tok->strAt(1) != ";") return true; return false; - } else if (tok->previous()->str() == "union") { - return tok->next()->str() != ";"; - } else if (tok->isCpp() && tok->previous()->str() == "class") { - return tok->next()->str() != ";"; + } else if (tok->strAt(-1) == "union") { + return tok->strAt(1) != ";"; + } else if (tok->isCpp() && tok->strAt(-1) == "class") { + return tok->strAt(1) != ";"; } if (tok) tok = tok->previous(); @@ -385,13 +385,13 @@ Token * Tokenizer::deleteInvalidTypedef(Token *typeDef) // remove typedef but leave ; while (typeDef->next()) { - if (typeDef->next()->str() == ";") { + if (typeDef->strAt(1) == ";") { typeDef->deleteNext(); break; } - if (typeDef->next()->str() == "{") + if (typeDef->strAt(1) == "{") Token::eraseTokens(typeDef, typeDef->linkAt(1)); - else if (typeDef->next()->str() == "}") + else if (typeDef->strAt(1) == "}") break; typeDef->deleteNext(); } @@ -423,7 +423,7 @@ static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount) std::set qualifiers; while (Token::Match(tok->next(), "const|volatile")) { - qualifiers.insert(tok->next()->str()); + qualifiers.insert(tok->strAt(1)); tok->deleteNext(); } @@ -454,7 +454,7 @@ static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount) if (tok1->next()) { // use typedef name if available if (Token::Match(tok1->next(), "%type%")) - name = tok1->next()->str(); + name = tok1->strAt(1); else // create a unique name name = "Unnamed" + std::to_string((*unnamedCount)++); tok->next()->insertToken(name); @@ -465,7 +465,7 @@ static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount) tok1->insertToken(";"); tok1 = tok1->next(); - if (tok1->next() && tok1->next()->str() == ";" && tok1->previous()->str() == "}") { + if (tok1->next() && tok1->strAt(1) == ";" && tok1->strAt(-1) == "}") { tok->deleteThis(); tok1->deleteThis(); return nullptr; @@ -477,7 +477,7 @@ static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount) tok1->insertToken(qualifier); tok1 = tok1->next(); } - tok1->insertToken(tok->next()->str()); // struct, union or enum + tok1->insertToken(tok->strAt(1)); // struct, union or enum tok1 = tok1->next(); tok1->insertToken(name); tok->deleteThis(); @@ -493,8 +493,8 @@ static Token *splitDefinitionFromTypedef(Token *tok, nonneg int *unnamedCount) * related pattern */ const Token *Tokenizer::processFunc(const Token *tok2, bool inOperator) const { - if (tok2->next() && tok2->next()->str() != ")" && - tok2->next()->str() != ",") { + if (tok2->next() && tok2->strAt(1) != ")" && + tok2->strAt(1) != ",") { // skip over tokens for some types of canonicalization if (Token::Match(tok2->next(), "( * %type% ) (")) tok2 = tok2->linkAt(5); @@ -511,7 +511,7 @@ const Token *Tokenizer::processFunc(const Token *tok2, bool inOperator) const Token::simpleMatch(tok2->linkAt(2), "] ;")) tok2 = tok2->next(); else { - if (tok2->next()->str() == "(") + if (tok2->strAt(1) == "(") tok2 = tok2->linkAt(1); else if (!inOperator && !Token::Match(tok2->next(), "[|>|;")) { tok2 = tok2->next(); @@ -529,20 +529,20 @@ const Token *Tokenizer::processFunc(const Token *tok2, bool inOperator) const if (tok2->str() == "(" && tok2->link()->next() && - tok2->link()->next()->str() == "(") { + tok2->link()->strAt(1) == "(") { tok2 = tok2->link(); - if (tok2->next()->str() == "(") + if (tok2->strAt(1) == "(") tok2 = tok2->linkAt(1); } // skip over typedef parameter - if (tok2->next() && tok2->next()->str() == "(") { + if (tok2->next() && tok2->strAt(1) == "(") { tok2 = tok2->linkAt(1); if (!tok2->next()) syntaxError(tok2); - if (tok2->next()->str() == "(") + if (tok2->strAt(1) == "(") tok2 = tok2->linkAt(1); } } @@ -787,14 +787,14 @@ namespace { // Inherited type => skip "struct" / "class" if (Token::Match(mRangeType.first, "const| struct|class %name% {") && Token::Match(tok->previous(), "public|protected|private|<")) { tok->originalName(tok->str()); - tok->str(mRangeType.second->previous()->str()); + tok->str(mRangeType.second->strAt(-1)); return; } if (Token::Match(tok, "%name% ::")) { if (Token::Match(mRangeType.first, "const| struct|class %name% %name% ;")) { tok->originalName(tok->str()); - tok->str(mRangeType.second->previous()->str()); + tok->str(mRangeType.second->strAt(-1)); } else { mReplaceFailed = true; } @@ -821,7 +821,7 @@ namespace { // Do not duplicate class/struct/enum/union if (Token::Match(tok->previous(), "enum|union|struct|class")) { bool found = false; - const std::string &kw = tok->previous()->str(); + const std::string &kw = tok->strAt(-1); for (const Token* type = mRangeType.first; type != mRangeType.second; type = type->next()) { if (type->str() == kw) { found = true; @@ -994,7 +994,7 @@ namespace { return false; if (Token::Match(tok->previous(), "struct|union|class|enum %name% %name%") && Token::simpleMatch(mRangeType.second, "{") && - tok->str() != mRangeType.second->previous()->str()) + tok->str() != mRangeType.second->strAt(-1)) return true; if (Token::Match(tok->previous(), "; %name% ;")) return false; @@ -1033,7 +1033,7 @@ namespace { static bool isCast(const Token* tok) { if (Token::Match(tok, "( %name% ) (|%name%")) return !tok->tokAt(2)->isKeyword(); - if (Token::Match(tok, "< %name% > (") && tok->previous() && endsWith(tok->previous()->str(), "_cast", 5)) + if (Token::Match(tok, "< %name% > (") && tok->previous() && endsWith(tok->strAt(-1), "_cast", 5)) return true; return false; } @@ -1192,10 +1192,10 @@ void Tokenizer::simplifyTypedefCpp() // Skip typedefs inside parentheses (#2453 and #4002) tok = tok->next(); } else if (Token::Match(tok, "class|struct|namespace %any%") && - (!tok->previous() || tok->previous()->str() != "enum")) { + (!tok->previous() || tok->strAt(-1) != "enum")) { isNamespace = (tok->str() == "namespace"); hasClass = true; - className = tok->next()->str(); + className = tok->strAt(1); const Token *tok1 = tok->next(); fullClassName = className; while (Token::Match(tok1, "%name% :: %name%")) { @@ -1424,7 +1424,7 @@ void Tokenizer::simplifyTypedefCpp() // function else if (isFunctionHead(tokOffset->link(), ";,")) { function = true; - if (tokOffset->link()->next()->str() == "const") { + if (tokOffset->link()->strAt(1) == "const") { specStart = tokOffset->link()->next(); specEnd = specStart; } @@ -1473,7 +1473,7 @@ void Tokenizer::simplifyTypedefCpp() (Token::simpleMatch(tokOffset, "( * (") && tokOffset->linkAt(2) && Token::Match(tokOffset->linkAt(2)->previous(), "%type% ) (") && Token::Match(tokOffset->linkAt(2)->linkAt(1), ") const|volatile| ) ;|,")))) { - if (tokOffset->next()->str() == "(") + if (tokOffset->strAt(1) == "(") tokOffset = tokOffset->next(); else if (Token::simpleMatch(tokOffset, "( * (")) { pointers.emplace_back("*"); @@ -1589,7 +1589,7 @@ void Tokenizer::simplifyTypedefCpp() // pointer/reference to array else if (Token::Match(tokOffset, "( *|& %type% ) [")) { - ptrToArray = (tokOffset->next()->str() == "*"); + ptrToArray = (tokOffset->strAt(1) == "*"); refToArray = !ptrToArray; tokOffset = tokOffset->tokAt(2); typeName = tokOffset; @@ -1718,7 +1718,7 @@ void Tokenizer::simplifyTypedefCpp() const Token *func = tok2->previous(); /** @todo add support for multi-token operators */ - if (func->previous()->str() == "operator") + if (func->strAt(-1) == "operator") func = func->previous(); if (!func->previous()) @@ -1745,7 +1745,7 @@ void Tokenizer::simplifyTypedefCpp() if (tok2->strAt(-2) == "namespace") { if (classLevel < spaceInfo.size() && spaceInfo[classLevel].isNamespace && - spaceInfo[classLevel].className == tok2->previous()->str()) { + spaceInfo[classLevel].className == tok2->strAt(-1)) { spaceInfo[classLevel].bodyEnd2 = tok2->link(); ++classLevel; pattern.clear(); @@ -1773,12 +1773,12 @@ void Tokenizer::simplifyTypedefCpp() else if (tok2->isCpp() && tok2->str() == "operator" && tok2->next() && - tok2->next()->str() == typeName->str() && + tok2->strAt(1) == typeName->str() && tok2->linkAt(2) && tok2->strAt(2) == "(" && Token::Match(tok2->linkAt(2), ") const| {")) { // check for qualifier - if (tok2->previous()->str() == "::") { + if (tok2->strAt(-1) == "::") { // check for available and matching class name if (spaceInfo.size() > 1 && classLevel < spaceInfo.size() && tok2->strAt(-2) == spaceInfo[classLevel].className) { @@ -1867,9 +1867,9 @@ void Tokenizer::simplifyTypedefCpp() // skip to end of scope if not already there if (tok2->str() != "}") { while (tok2->next()) { - if (tok2->next()->str() == "{") + if (tok2->strAt(1) == "{") tok2 = tok2->linkAt(1)->previous(); - else if (tok2->next()->str() == "}") + else if (tok2->strAt(1) == "}") break; tok2 = tok2->next(); @@ -1877,7 +1877,7 @@ void Tokenizer::simplifyTypedefCpp() } } else if (Token::Match(tok2->tokAt(-2), "%type% *|&")) { // Ticket #5868: Don't substitute variable names - } else if (tok2->previous()->str() != ".") { + } else if (tok2->strAt(-1) != ".") { simplifyType = (TypedefSimplifier::canReplaceStatic(tok2) != 0); } } @@ -1890,8 +1890,8 @@ void Tokenizer::simplifyTypedefCpp() mTypedefInfo.back().used = true; // can't simplify 'operator functionPtr ()' and 'functionPtr operator ... ()' - if (functionPtr && (tok2->previous()->str() == "operator" || - (tok2->next() && tok2->next()->str() == "operator"))) { + if (functionPtr && (tok2->strAt(-1) == "operator" || + (tok2->next() && tok2->strAt(1) == "operator"))) { simplifyType = false; tok2 = tok2->next(); continue; @@ -1916,8 +1916,8 @@ void Tokenizer::simplifyTypedefCpp() // check for cast: (some_typedef) A or static_cast(A) // todo: check for more complicated casts like: (const some_typedef *)A - if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")" && tok2->strAt(-2) != "sizeof") || - (tok2->previous()->str() == "<" && Token::simpleMatch(tok2->next(), "> (")) || + if ((tok2->strAt(-1) == "(" && tok2->strAt(1) == ")" && tok2->strAt(-2) != "sizeof") || + (tok2->strAt(-1) == "<" && Token::simpleMatch(tok2->next(), "> (")) || Token::Match(tok2->tokAt(-2), "( const %name% )")) inCast = true; @@ -2070,7 +2070,7 @@ void Tokenizer::simplifyTypedefCpp() // don't add parentheses around function names because it // confuses other simplifications bool needParen = true; - if (!inTemplate && function && tok2->next() && tok2->next()->str() != "*") + if (!inTemplate && function && tok2->next() && tok2->strAt(1) != "*") needParen = false; if (needParen) { tok2->insertToken("("); @@ -2146,7 +2146,7 @@ void Tokenizer::simplifyTypedefCpp() if (!tok2 || !tok2->next()) syntaxError(nullptr); - if (tok2->next()->str() != ")") + if (tok2->strAt(1) != ")") tok2 = tok2->next(); } @@ -2176,18 +2176,18 @@ void Tokenizer::simplifyTypedefCpp() bool hasName = false; // skip over name - if (tok2->next() && tok2->next()->str() != ")" && tok2->next()->str() != "," && - tok2->next()->str() != ">") { + if (tok2->next() && tok2->strAt(1) != ")" && tok2->strAt(1) != "," && + tok2->strAt(1) != ">") { hasName = true; - if (tok2->next()->str() != "(") + if (tok2->strAt(1) != "(") tok2 = tok2->next(); // check for function and skip over args - if (tok2 && tok2->next() && tok2->next()->str() == "(") + if (tok2 && tok2->next() && tok2->strAt(1) == "(") tok2 = tok2->linkAt(1); // check for array - if (tok2 && tok2->next() && tok2->next()->str() == "[") + if (tok2 && tok2->next() && tok2->strAt(1) == "[") tok2 = tok2->linkAt(1); } @@ -2302,7 +2302,7 @@ void Tokenizer::simplifyTypedefCpp() syntaxError(tok2); // can't recover so quit // skip over array dimensions - while (tok2->next()->str() == "[") + while (tok2->strAt(1) == "[") tok2 = tok2->linkAt(1); tok2 = TokenList::copyTokens(tok2, arrayStart, arrayEnd); @@ -2310,9 +2310,9 @@ void Tokenizer::simplifyTypedefCpp() syntaxError(tok2); if (tok2->str() == "=") { - if (tok2->next()->str() == "{") + if (tok2->strAt(1) == "{") tok2 = tok2->linkAt(1)->next(); - else if (tok2->next()->str().at(0) == '\"') + else if (tok2->strAt(1).at(0) == '\"') tok2 = tok2->tokAt(2); } } while (Token::Match(tok2, ", %name% ;|=|,")); @@ -2353,7 +2353,7 @@ void Tokenizer::simplifyTypedefCpp() if (!tokOffset->next()) return; // invalid input - if (tokOffset->next()->str() == ";") + if (tokOffset->strAt(1) == ";") break; if (tokOffset->str() == "]") break; @@ -3255,7 +3255,7 @@ bool Tokenizer::simplifyUsing() if (!type->next()) syntaxError(type); // invalid input - else if (type->next()->str() == ";") + else if (type->strAt(1) == ";") atEnd = true; else if (type->str() == "]") atEnd = true; @@ -3507,8 +3507,8 @@ void Tokenizer::combineOperators() for (Token *tok = list.front(); tok && tok->next(); tok = tok->next()) { const char c1 = tok->str()[0]; - if (tok->str().length() == 1 && tok->next()->str().length() == 1) { - const char c2 = tok->next()->str()[0]; + if (tok->str().length() == 1 && tok->strAt(1).length() == 1) { + const char c2 = tok->strAt(1)[0]; // combine +-*/ and = if (c2 == '=' && (std::strchr("+-*/%|^=!<>", c1)) && !Token::Match(tok->previous(), "%type% *")) { @@ -3523,7 +3523,7 @@ void Tokenizer::combineOperators() tok->deleteNext(); continue; } - } else if (tok->next()->str() == "=") { + } else if (tok->strAt(1) == "=") { if (tok->str() == ">>") { tok->str(">>="); tok->deleteNext(); @@ -3592,7 +3592,7 @@ void Tokenizer::combineStringAndCharLiterals() tok->next()->deleteNext(); } // Two strings after each other, combine them - tok->concatStr(simplifyString(tok->next()->str())); + tok->concatStr(simplifyString(tok->strAt(1))); tok->deleteNext(); } } @@ -3604,12 +3604,12 @@ void Tokenizer::concatenateNegativeNumberAndAnyPositive() if (!Token::Match(tok, "?|:|,|(|[|{|return|case|sizeof|%op% +|-") || tok->tokType() == Token::eIncDecOp) continue; - while (tok->str() != ">" && tok->next() && tok->next()->str() == "+" && (!Token::Match(tok->tokAt(2), "%name% (|;") || Token::Match(tok, "%op%"))) + while (tok->str() != ">" && tok->next() && tok->strAt(1) == "+" && (!Token::Match(tok->tokAt(2), "%name% (|;") || Token::Match(tok, "%op%"))) tok->deleteNext(); if (Token::Match(tok->next(), "- %num%")) { tok->deleteNext(); - tok->next()->str("-" + tok->next()->str()); + tok->next()->str("-" + tok->strAt(1)); } } } @@ -3623,7 +3623,7 @@ void Tokenizer::simplifyExternC() for (Token *tok = list.front(); tok; tok = tok->next()) { if (Token::Match(tok, "extern \"C\"|\"C++\"")) { Token *tok2 = tok->next(); - const bool isExtC = tok->next()->str().size() == 3; + const bool isExtC = tok->strAt(1).size() == 3; if (tok->strAt(2) == "{") { tok2 = tok2->next(); // skip { while ((tok2 = tok2->next()) && tok2 != tok->linkAt(2)) @@ -3733,7 +3733,7 @@ void Tokenizer::simplifyDoublePlusAndDoubleMinus() for (Token *tok = list.front(); tok; tok = tok->next()) { while (tok->next()) { if (tok->str() == "+") { - if (tok->next()->str()[0] == '-') { + if (tok->strAt(1)[0] == '-') { tok = tok->next(); if (tok->str().size() == 1) { tok = tok->previous(); @@ -3747,7 +3747,7 @@ void Tokenizer::simplifyDoublePlusAndDoubleMinus() continue; } } else if (tok->str() == "-") { - if (tok->next()->str()[0] == '-') { + if (tok->strAt(1)[0] == '-') { tok = tok->next(); if (tok->str().size() == 1) { tok = tok->previous(); @@ -3960,7 +3960,7 @@ void Tokenizer::simplifyLabelsCaseDefault() continue; if (tok->str() == "{") { - if (tok->previous()->str() == "=") + if (tok->strAt(-1) == "=") tok = tok->link(); else ++indentLevel; @@ -3979,7 +3979,7 @@ void Tokenizer::simplifyLabelsCaseDefault() break; if (tok->str() != ":" || tok->strAt(-1) == "case" || !tok->next()) syntaxError(tok); - if (tok->next()->str() != ";" && tok->next()->str() != "case") + if (tok->strAt(1) != ";" && tok->strAt(1) != "case") tok->insertToken(";"); else tok = tok->previous(); @@ -4215,7 +4215,7 @@ static bool setVarIdParseDeclaration(Token*& tok, const VariableMap& variableMap singleNameCount = 0; } else if (Token::Match(tok2, "const|extern")) { // just skip "const", "extern" - } else if (!hasstruct && variableMap.map(false).count(tok2->str()) && tok2->previous()->str() != "::") { + } else if (!hasstruct && variableMap.map(false).count(tok2->str()) && tok2->strAt(-1) != "::") { ++typeCount; tok2 = tok2->next(); if (!tok2 || tok2->str() != "::") @@ -4405,7 +4405,7 @@ static bool setVarIdClassDeclaration(Token* const startToken, if (!tok->isName() && tok->str() != ":") break; if (Token::Match(tok, "class|struct|enum %type% [:{]")) { - className = tok->next()->str(); + className = tok->strAt(1); break; } } @@ -4445,7 +4445,7 @@ static bool setVarIdClassDeclaration(Token* const startToken, continue; if (!tok->next()) return false; - if (tok->next()->str() == "::") { + if (tok->strAt(1) == "::") { if (tok->str() == className) tok = tok->tokAt(2); else @@ -4731,7 +4731,7 @@ void Tokenizer::setVarIdPass1() } const Token* prev2 = tok2->previous(); - if (Token::Match(prev2, "%type% [;[=,)]") && tok2->previous()->str() != "const") + if (Token::Match(prev2, "%type% [;[=,)]") && tok2->strAt(-1) != "const") ; else if (Token::Match(prev2, "%type% :") && tok->strAt(-1) == "for") ; @@ -4791,7 +4791,7 @@ void Tokenizer::setVarIdPass1() if (Token::Match(tok3, "[([]")) tok3 = tok3->link(); if (Token::Match(tok3, ", %name% [,=;]")) - variableMap.addVariable(tok3->next()->str(), false); + variableMap.addVariable(tok3->strAt(1), false); } } @@ -4824,12 +4824,12 @@ void Tokenizer::setVarIdPass1() bool globalNamespace = false; if (!isC()) { - if (tok->previous() && tok->previous()->str() == "::") { + if (tok->previous() && tok->strAt(-1) == "::") { if (Token::Match(tok->tokAt(-2), ")|]|%name%")) continue; globalNamespace = true; } - if (tok->next() && tok->next()->str() == "::") + if (tok->next() && tok->strAt(1) == "::") continue; if (Token::simpleMatch(tok->tokAt(-2), ":: template")) continue; @@ -4860,7 +4860,7 @@ void Tokenizer::setVarIdPass1() for (end = tok->next(); Token::Match(end, "%name%|*|&|,|[|]|%num%"); end = end->next()) {} // there are tokens which can't appear at the begin of a function declaration such as "return" - const bool isNotstartKeyword = start->next() && notstart.find(start->next()->str()) != notstart.end(); + const bool isNotstartKeyword = start->next() && notstart.find(start->strAt(1)) != notstart.end(); // now check if it is a function declaration if (Token::Match(start, "[;{}] %type% %name%|*") && par && Token::simpleMatch(end, ") ;") && !isNotstartKeyword) { @@ -4945,7 +4945,7 @@ static Token * matchMemberName(const std::list &scope, const Token return nullptr; if (memberToken->str() != scopeIt->name) return nullptr; - if (memberToken->next()->str() == "<") { + if (memberToken->strAt(1) == "<") { memberToken = memberToken->next()->findClosingBracket(); if (!Token::simpleMatch(memberToken, "> ::")) return nullptr; @@ -5387,7 +5387,7 @@ void Tokenizer::createLinks2() (token->strAt(-1) == ")" && token->linkAt(-1)->strAt(-1) == "operator"))) || Token::Match(token->next(), ">|>>"))) { type.push(token); - if (token->previous()->str() == "template") + if (token->strAt(-1) == "template") templateTokens.push(token); } else if (token->str() == ">" || token->str() == ">>") { if (type.empty() || type.top()->str() != "<") // < and > don't match. @@ -6359,7 +6359,7 @@ void Tokenizer::splitTemplateRightAngleBrackets(bool check) // Ticket #6181: normalize C++11 template parameter list closing syntax if (tok->previous() && tok->str() == "<" && TemplateSimplifier::templateParameters(tok) && std::none_of(vars.begin(), vars.end(), [&](const std::pair& v) { - return v.first == tok->previous()->str(); + return v.first == tok->strAt(-1); })) { Token *endTok = tok->findClosingBracket(); if (check) { @@ -6376,7 +6376,7 @@ void Tokenizer::splitTemplateRightAngleBrackets(bool check) endTok->insertToken(">"); } } else if (Token::Match(tok, "class|struct|union|=|:|public|protected|private %name% <") && std::none_of(vars.begin(), vars.end(), [&](const std::pair& v) { - return v.first == tok->next()->str(); + return v.first == tok->strAt(1); })) { Token *endTok = tok->tokAt(2)->findClosingBracket(); if (check) { @@ -6406,7 +6406,7 @@ void Tokenizer::removeMacrosInGlobalScope() } if (Token::Match(tok, "%type%") && tok->isUpperCaseName() && - (!tok->previous() || Token::Match(tok->previous(), "[;{}]") || (tok->previous()->isName() && endsWith(tok->previous()->str(), ':')))) { + (!tok->previous() || Token::Match(tok->previous(), "[;{}]") || (tok->previous()->isName() && endsWith(tok->strAt(-1), ':')))) { const Token *tok2 = tok->next(); if (tok2 && tok2->str() == "(") tok2 = tok2->link()->next(); @@ -6769,8 +6769,8 @@ void Tokenizer::simplifyFunctionParameters() else if (tok1->str() != funcName) argumentNames[tok1->str()] = tok1; else { - if (tok1->next()->str() == ")") { - if (tok1->previous()->str() == ",") { + if (tok1->strAt(1) == ")") { + if (tok1->strAt(-1) == ",") { tok1 = tok1->tokAt(-2); tok1->deleteNext(2); } else { @@ -6785,7 +6785,7 @@ void Tokenizer::simplifyFunctionParameters() } } - if (tok1->next()->str() == ")") { + if (tok1->strAt(1) == ")") { tok1 = tok1->tokAt(2); //expect at least a type name after round brace.. if (!tok1 || !tok1->isName()) @@ -6880,11 +6880,11 @@ void Tokenizer::simplifyFunctionParameters() while (tok->str() != ")") { //initialize start and end tokens to be moved - Token *declStart = argumentNames2[tok->next()->str()]; + Token *declStart = argumentNames2[tok->strAt(1)]; Token *declEnd = declStart; - while (declStart->previous()->str() != ";" && declStart->previous()->str() != ")") + while (declStart->strAt(-1) != ";" && declStart->strAt(-1) != ")") declStart = declStart->previous(); - while (declEnd->next()->str() != ";" && declEnd->next()->str() != "{") + while (declEnd->strAt(1) != ";" && declEnd->strAt(1) != "{") declEnd = declEnd->next(); //remove ';' after declaration @@ -6951,7 +6951,7 @@ void Tokenizer::simplifyFunctionPointers() if (Token::Match(tok1->next(), "%type%")) tok1 = tok1->next(); - while (tok1->next()->str() == "*") + while (tok1->strAt(1) == "*") tok1 = tok1->next(); // check that the cast ends @@ -7205,13 +7205,13 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co //skip combinations of templates and namespaces while (!isC() && (Token::Match(tok2, "%type% <") || Token::Match(tok2, "%type% ::"))) { - if (tok2->next()->str() == "<" && !TemplateSimplifier::templateParameters(tok2->next())) { + if (tok2->strAt(1) == "<" && !TemplateSimplifier::templateParameters(tok2->next())) { tok2 = nullptr; break; } typelen += 2; tok2 = tok2->tokAt(2); - if (tok2 && tok2->previous()->str() == "::") + if (tok2 && tok2->strAt(-1) == "::") continue; int indentlevel = 0; int parens = 0; @@ -7258,9 +7258,9 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co //pattern: "%type% *| ... *| const| %name% ,|=" if (Token::Match(tok2, "%type%") || - (tok2 && tok2->previous() && tok2->previous()->str() == ">")) { + (tok2 && tok2->previous() && tok2->strAt(-1) == ">")) { Token *varName = tok2; - if (!tok2->previous() || tok2->previous()->str() != ">") + if (!tok2->previous() || tok2->strAt(-1) != ">") varName = varName->next(); else --typelen; @@ -7426,7 +7426,7 @@ void Tokenizer::simplifyStaticConst() for (int i = 0; i < sizeof(qualifiers)/sizeof(qualifiers[0]); i++) { // Keep searching for a qualifier - if (!tok->next() || tok->next()->str() != qualifiers[i]) + if (!tok->next() || tok->strAt(1) != qualifiers[i]) continue; // Look backwards to find the beginning of the declaration @@ -7666,7 +7666,7 @@ Token * Tokenizer::initVar(Token * tok) return tok; tok = tok->next(); - } else if (!tok->isStandardType() && tok->str() != "auto" && tok->next()->str() != "*") + } else if (!tok->isStandardType() && tok->str() != "auto" && tok->strAt(1) != "*") return tok; // goto variable name.. @@ -7723,7 +7723,7 @@ void Tokenizer::elseif() tok2 = tok2->link(); if (Token::Match(tok2, "}|;")) { - if (tok2->next() && tok2->next()->str() != "else") { + if (tok2->next() && tok2->strAt(1) != "else") { tok->insertToken("{"); tok2->insertToken("}"); Token::createMutualLinks(tok->next(), tok2->next()); @@ -7804,7 +7804,7 @@ bool Tokenizer::simplifyRedundantParentheses() continue; if (tok->isCpp() && Token::simpleMatch(tok->previous(), "} (")) { - const Token* plp = tok->previous()->link()->previous(); + const Token* plp = tok->linkAt(-1)->previous(); if (Token::Match(plp, "%name%|>|] {") || (Token::simpleMatch(plp, ")") && Token::simpleMatch(plp->link()->previous(), "]"))) continue; } @@ -7834,8 +7834,8 @@ bool Tokenizer::simplifyRedundantParentheses() // !!operator = ( x ) ; if (tok->strAt(-2) != "operator" && - tok->previous() && tok->previous()->str() == "=" && - tok->next() && tok->next()->str() != "{" && + tok->previous() && tok->strAt(-1) == "=" && + tok->next() && tok->strAt(1) != "{" && Token::simpleMatch(tok->link(), ") ;")) { tok->link()->deleteThis(); tok->deleteThis(); @@ -7891,7 +7891,7 @@ bool Tokenizer::simplifyRedundantParentheses() if (!Token::simpleMatch(tok->tokAt(-2), "operator delete") && Token::Match(tok->previous(), "delete|; (") && - (tok->previous()->str() != "delete" || tok->next()->varId() > 0) && + (tok->strAt(-1) != "delete" || tok->next()->varId() > 0) && Token::Match(tok->link(), ") ;|,")) { tok->link()->deleteThis(); tok->deleteThis(); @@ -8394,9 +8394,9 @@ void Tokenizer::reportUnknownMacros() const if (Token::Match(tok, "[(,] %name% (") && Token::Match(tok->linkAt(2), ") %name% %name%|,|)")) { if (tok->next()->isKeyword() || tok->linkAt(2)->next()->isKeyword()) continue; - if (cAlternativeTokens.count(tok->linkAt(2)->next()->str()) > 0) + if (cAlternativeTokens.count(tok->linkAt(2)->strAt(1)) > 0) continue; - if (startsWith(tok->next()->str(), "__")) // attribute/annotation + if (startsWith(tok->strAt(1), "__")) // attribute/annotation continue; unknownMacroError(tok->next()); } @@ -8417,7 +8417,7 @@ void Tokenizer::reportUnknownMacros() const if (isNonMacro(tok2)) continue; - if (tok2->next()->str() == "(") { + if (tok2->strAt(1) == "(") { if (Token::Match(tok->previous(), "%name%|::|>")) continue; } @@ -8477,7 +8477,7 @@ void Tokenizer::findGarbageCode() const // Assign/increment/decrement literal else if (Token::Match(tok, "!!) %num%|%str%|%char% %assign%|++|--")) { if (!isCPP() || mSettings.standards.cpp < Standards::CPP20 || !Token::Match(tok->previous(), "%name% : %num% =")) - syntaxError(tok, tok->next()->str() + " " + tok->strAt(2)); + syntaxError(tok, tok->strAt(1) + " " + tok->strAt(2)); } else if (Token::simpleMatch(tok, ") return") && !Token::Match(tok->link()->previous(), "if|while|for (")) { if (tok->link()->previous() && tok->link()->previous()->isUpperCaseName()) @@ -8511,7 +8511,7 @@ void Tokenizer::findGarbageCode() const // keyword keyword if (tok->isKeyword() && nonConsecutiveKeywords.count(tok->str()) != 0) { - if (Token::Match(tok, "%name% %name%") && nonConsecutiveKeywords.count(tok->next()->str()) == 1) + if (Token::Match(tok, "%name% %name%") && nonConsecutiveKeywords.count(tok->strAt(1)) == 1) syntaxError(tok); const Token* prev = tok; while (prev && prev->isName()) @@ -8652,7 +8652,7 @@ void Tokenizer::findGarbageCode() const if (Token::Match(tok, "%or%|%oror%|~|^|!|%comp%|+|-|/|%")) { std::string code; if (Token::Match(tok->next(), ")|]|}")) - code = tok->str() + tok->next()->str(); + code = tok->str() + tok->strAt(1); if (Token::simpleMatch(tok->next(), "( )")) code = tok->str() + "()"; if (!code.empty()) { @@ -9200,7 +9200,7 @@ void Tokenizer::simplifyAttribute() vartok = after; if (vartok) { - const std::string &attribute(attr->next()->str()); + const std::string &attribute(attr->strAt(1)); if (attribute.find("unused") != std::string::npos) vartok->isAttributeUnused(true); else @@ -9212,7 +9212,7 @@ void Tokenizer::simplifyAttribute() if (!functok) syntaxError(tok); - const std::string &attribute(attr->next()->str()); + const std::string &attribute(attr->strAt(1)); if (attribute.find("pure") != std::string::npos) functok->isAttributePure(true); else if (attribute.find("const") != std::string::npos) @@ -9245,7 +9245,7 @@ void Tokenizer::simplifyCppcheckAttribute() continue; if (!tok->previous()) continue; - const std::string &attr = tok->previous()->str(); + const std::string &attr = tok->strAt(-1); if (!startsWith(attr, "__cppcheck_")) continue; if (attr.compare(attr.size()-2, 2, "__") != 0) // TODO: ends_with("__") @@ -9261,10 +9261,10 @@ void Tokenizer::simplifyCppcheckAttribute() if (vartok->isName()) { if (Token::Match(tok->previous(), "__cppcheck_low__ ( %num% )")) vartok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, - MathLib::toBigNumber(tok->next()->str())); + MathLib::toBigNumber(tok->strAt(1))); else if (Token::Match(tok->previous(), "__cppcheck_high__ ( %num% )")) vartok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, - MathLib::toBigNumber(tok->next()->str())); + MathLib::toBigNumber(tok->strAt(1))); } // Delete cppcheck attribute.. @@ -9326,16 +9326,16 @@ void Tokenizer::simplifyCPPAttribute() argtok = argtok->previous(); } if (argtok && argtok->str() == vartok->str()) { - if (vartok->next()->str() == ">=") + if (vartok->strAt(1) == ">=") argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, MathLib::toBigNumber(vartok->strAt(2))); - else if (vartok->next()->str() == ">") + else if (vartok->strAt(1) == ">") argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, MathLib::toBigNumber(vartok->strAt(2)) + 1); - else if (vartok->next()->str() == "<=") + else if (vartok->strAt(1) == "<=") argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, MathLib::toBigNumber(vartok->strAt(2))); - else if (vartok->next()->str() == "<") + else if (vartok->strAt(1) == "<") argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, MathLib::toBigNumber(vartok->strAt(2)) - 1); } @@ -9533,7 +9533,7 @@ void Tokenizer::simplifyAssignmentBlock() { for (Token *tok = list.front(); tok; tok = tok->next()) { if (Token::Match(tok, "[;{}] %name% = ( {")) { - const std::string &varname = tok->next()->str(); + const std::string &varname = tok->strAt(1); // goto the "} )" int indentlevel = 0; @@ -9553,7 +9553,7 @@ void Tokenizer::simplifyAssignmentBlock() tok2 = tok2->tokAt(-3); if (Token::Match(tok2, "[;{}] %num%|%name% ;")) { tok2->insertToken("="); - tok2->insertToken(tok->next()->str()); + tok2->insertToken(tok->strAt(1)); tok2->next()->varId(tok->next()->varId()); tok->deleteNext(3); tok2->tokAt(5)->deleteNext(); @@ -9634,7 +9634,7 @@ void Tokenizer::simplifyAsm() //move the new tokens in the same line as ";" if available tok = tok->tokAt(2); - if (tok->next() && tok->next()->str() == ";" && + if (tok->next() && tok->strAt(1) == ";" && tok->next()->linenr() != tok->linenr()) { const int endposition = tok->next()->linenr(); tok = tok->tokAt(-3); @@ -9677,7 +9677,7 @@ void Tokenizer::simplifyAsm2() if (start && last) { std::string asmcode; while (start->next() != last) { - asmcode += start->next()->str(); + asmcode += start->strAt(1); start->deleteNext(); } if (last->str() == "}") @@ -9733,7 +9733,7 @@ void Tokenizer::simplifyAt() // keywords in compiler from cosmic software for STM8 // TODO: Should use platform configuration. if (Token::Match(tok, "@ builtin|eeprom|far|inline|interrupt|near|noprd|nostack|nosvf|packed|stack|svlreg|tiny|vector")) { - tok->str(tok->next()->str() + "@"); + tok->str(tok->strAt(1) + "@"); tok->deleteNext(); } } @@ -9771,7 +9771,7 @@ void Tokenizer::simplifyBitfields() if (Token::Match(tok->next(), "const| %type% %name% :") && !Token::Match(tok->next(), "case|public|protected|private|class|struct") && !Token::simpleMatch(tok->tokAt(2), "default :")) { - Token *tok1 = (tok->next()->str() == "const") ? tok->tokAt(3) : tok->tokAt(2); + Token *tok1 = (tok->strAt(1) == "const") ? tok->tokAt(3) : tok->tokAt(2); if (Token::Match(tok1, "%name% : %num% [;=]")) tok1->setBits(MathLib::toBigNumber(tok1->strAt(2))); if (tok1 && tok1->tokAt(2) && @@ -9786,15 +9786,15 @@ void Tokenizer::simplifyBitfields() last = tok1->next(); } } else if (isEnum && Token::Match(tok, "} %name%| : %num% ;")) { - if (tok->next()->str() == ":") { + if (tok->strAt(1) == ":") { tok->deleteNext(2); tok->insertToken("Anonymous"); } else { tok->next()->deleteNext(2); } } else if (Token::Match(tok->next(), "const| %type% : %num%|%bool% ;") && - tok->next()->str() != "default") { - const int offset = (tok->next()->str() == "const") ? 1 : 0; + tok->strAt(1) != "default") { + const int offset = (tok->strAt(1) == "const") ? 1 : 0; if (!Token::Match(tok->tokAt(3 + offset), "[{};()]")) { tok->deleteNext(4 + offset); goback = true; @@ -10004,7 +10004,7 @@ void Tokenizer::simplifyMicrosoftStringFunctions() tok->next()->deleteNext(); tok->next()->deleteThis(); tok->next()->deleteNext(); - tok->concatStr(tok->next()->str()); + tok->concatStr(tok->strAt(1)); tok->deleteNext(); } } @@ -10085,7 +10085,7 @@ bool Tokenizer::operatorEnd(const Token * tok) if (tok && tok->str() == "(") { tok = tok->link()->next(); } - } else if (tok->str() == "throw" && tok->next() && tok->next()->str() == "(") { + } else if (tok->str() == "throw" && tok->next() && tok->strAt(1) == "(") { tok = tok->linkAt(1)->next(); } // unknown macros ") MACRO {" and ") MACRO(...) {" @@ -10123,7 +10123,7 @@ void Tokenizer::simplifyOperatorName() continue; // operator op if (Token::Match(tok, "operator %op% (") && !operatorEnd(tok->linkAt(2))) { - tok->str(tok->str() + tok->next()->str()); + tok->str(tok->str() + tok->strAt(1)); tok->deleteNext(); continue; } @@ -10320,7 +10320,7 @@ void Tokenizer::removeUnnecessaryQualification() std::vector classInfo; for (Token *tok = list.front(); tok; tok = tok->next()) { if (Token::Match(tok, "class|struct|namespace %type% :|{") && - (!tok->previous() || tok->previous()->str() != "enum")) { + (!tok->previous() || tok->strAt(-1) != "enum")) { Space info; info.isNamespace = tok->str() == "namespace"; tok = tok->next(); @@ -10336,7 +10336,7 @@ void Tokenizer::removeUnnecessaryQualification() if (tok == classInfo.back().bodyEnd) classInfo.pop_back(); else if (tok->str() == classInfo.back().className && - !classInfo.back().isNamespace && tok->previous()->str() != ":" && + !classInfo.back().isNamespace && tok->strAt(-1) != ":" && (Token::Match(tok, "%type% :: ~| %type% (") || Token::Match(tok, "%type% :: operator"))) { const Token *tok1 = tok->tokAt(3); @@ -10664,11 +10664,11 @@ void Tokenizer::simplifyNamespaceAliases() tok = tok->previous(); if (tok->tokAt(-1) && !Token::Match(tok->tokAt(-1), "[;{}]")) syntaxError(tok->tokAt(-1)); - const std::string name(tok->next()->str()); + const std::string name(tok->strAt(1)); Token * tokNameStart = tok->tokAt(3); Token * tokNameEnd = tokNameStart; - while (tokNameEnd && tokNameEnd->next() && tokNameEnd->next()->str() != ";") { + while (tokNameEnd && tokNameEnd->next() && tokNameEnd->strAt(1) != ";") { if (tokNameEnd->str() == "(") { if (tokNameEnd->previous()->isName()) unknownMacroError(tokNameEnd->previous()); @@ -10722,7 +10722,7 @@ void Tokenizer::simplifyNamespaceAliases() tok2->str(tokNameStart->str()); Token * tok3 = tokNameStart; while (tok3 != tokNameEnd) { - tok2->insertToken(tok3->next()->str()); + tok2->insertToken(tok3->strAt(1)); tok2 = tok2->next(); tok3 = tok3->next(); } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 8c11db0c73b..f5063c6f535 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -497,11 +497,11 @@ static bool iscast(const Token *tok, bool cpp) if (Token::Match(tok->link(), ") %assign%|,|...")) return false; - if (tok->previous() && tok->previous()->isName() && tok->previous()->str() != "return" && + if (tok->previous() && tok->previous()->isName() && tok->strAt(-1) != "return" && (!cpp || !Token::Match(tok->previous(), "delete|throw"))) return false; - if (Token::simpleMatch(tok->previous(), ">") && tok->previous()->link()) + if (Token::simpleMatch(tok->previous(), ">") && tok->linkAt(-1)) return false; if (Token::Match(tok, "( (| typeof (") && Token::Match(tok->link(), ") %num%")) @@ -548,7 +548,7 @@ static bool iscast(const Token *tok, bool cpp) if (!Token::Match(tok2, "%name%|*|::")) return false; - if (tok2->isStandardType() && (tok2->next()->str() != "(" || Token::Match(tok2->next(), "( * *| )"))) + if (tok2->isStandardType() && (tok2->strAt(1) != "(" || Token::Match(tok2->next(), "( * *| )"))) type = true; } @@ -913,7 +913,7 @@ static bool isPrefixUnary(const Token* tok, bool cpp) && (tok->previous()->tokType() != Token::eIncDecOp || tok->tokType() == Token::eIncDecOp))) return true; - if (tok->previous()->str() == "}") { + if (tok->strAt(-1) == "}") { const Token* parent = tok->linkAt(-1)->tokAt(-1); return !Token::Match(parent, "%type%") || parent->isKeyword(); } @@ -1882,7 +1882,7 @@ void TokenList::validateAst(bool print) const if (Token::Match(tok->previous(), "if|while|for|switch|assert|ASSERT (")) { if (!tok->astOperand1() || !tok->astOperand2()) throw InternalError(tok, - "Syntax Error: AST broken, '" + tok->previous()->str() + + "Syntax Error: AST broken, '" + tok->strAt(-1) + "' doesn't have two operands.", InternalError::AST); } @@ -1895,7 +1895,7 @@ void TokenList::validateAst(bool print) const } if (!tok->next()->astOperand1() || !tok->next()->astOperand2()) { const std::string& op = - tok->next()->originalName().empty() ? tok->next()->str() : tok->next()->originalName(); + tok->next()->originalName().empty() ? tok->strAt(1) : tok->next()->originalName(); throw InternalError( tok, "Syntax Error: AST broken, '" + op + "' doesn't have two operands.", InternalError::AST); } @@ -1969,7 +1969,7 @@ void TokenList::simplifyPlatformTypes() if (tok->str() == "::") { tok->deleteThis(); } else if (tok->str() == "std") { - if (tok->next()->str() != "::") + if (tok->strAt(1) != "::") continue; inStd = true; tok->deleteNext(); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 35ba611b563..b687f7b9f04 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2499,7 +2499,7 @@ struct MemberExpressionAnalyzer : SubExpressionAnalyzer { return false; if (!exact) return true; - return tok->next()->str() == varname; + return tok->strAt(1) == varname; } }; @@ -2722,7 +2722,7 @@ static std::vector getLifetimeTokens(const Token* tok, } if (Token::Match(tok->tokAt(-2), ". %name% (") && tok->tokAt(-2)->originalName() != "->" && astIsContainer(tok->tokAt(-2)->astOperand1())) { const Library::Container* library = getLibraryContainer(tok->tokAt(-2)->astOperand1()); - const Library::Container::Yield y = library->getYield(tok->previous()->str()); + const Library::Container::Yield y = library->getYield(tok->strAt(-1)); if (y == Library::Container::Yield::AT_INDEX || y == Library::Container::Yield::ITEM) { errorPath.emplace_back(tok->previous(), "Accessing container."); return ValueFlow::LifetimeToken::setAddressOf( @@ -5755,7 +5755,7 @@ struct ConditionHandler { if (!Token::Match(top->previous(), "if|while|for (")) return; - if (top->previous()->str() == "for") { + if (top->strAt(-1) == "for") { if (!Token::Match(condTok, "%comp%")) return; if (!Token::simpleMatch(condTok->astParent(), ";")) @@ -6743,9 +6743,9 @@ static void valueFlowSwitchVariable(const TokenList &tokenlist, const SymbolData } if (Token::Match(tok, "case %num% :")) { std::list values; - values.emplace_back(MathLib::toBigNumber(tok->next()->str())); + values.emplace_back(MathLib::toBigNumber(tok->strAt(1))); values.back().condition = tok; - values.back().errorPath.emplace_back(tok, "case " + tok->next()->str() + ": " + vartok->str() + " is " + tok->next()->str() + " here."); + values.back().errorPath.emplace_back(tok, "case " + tok->strAt(1) + ": " + vartok->str() + " is " + tok->strAt(1) + " here."); bool known = false; if ((Token::simpleMatch(tok->previous(), "{") || Token::simpleMatch(tok->tokAt(-2), "break ;")) && !Token::Match(tok->tokAt(3), ";| case")) known = true; @@ -6754,9 +6754,9 @@ static void valueFlowSwitchVariable(const TokenList &tokenlist, const SymbolData tok = tok->tokAt(3); if (!tok->isName()) tok = tok->next(); - values.emplace_back(MathLib::toBigNumber(tok->next()->str())); + values.emplace_back(MathLib::toBigNumber(tok->strAt(1))); values.back().condition = tok; - values.back().errorPath.emplace_back(tok, "case " + tok->next()->str() + ": " + vartok->str() + " is " + tok->next()->str() + " here."); + values.back().errorPath.emplace_back(tok, "case " + tok->strAt(1) + ": " + vartok->str() + " is " + tok->strAt(1) + " here."); } for (auto val = values.cbegin(); val != values.cend(); ++val) { valueFlowReverse(tokenlist, @@ -8367,7 +8367,7 @@ static void valueFlowUnknownFunctionReturn(TokenList &tokenlist, const Settings for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->astParent() || tok->str() != "(" || !tok->previous()->isName()) continue; - if (settings.checkUnknownFunctionReturn.find(tok->previous()->str()) == settings.checkUnknownFunctionReturn.end()) + if (settings.checkUnknownFunctionReturn.find(tok->strAt(-1)) == settings.checkUnknownFunctionReturn.end()) continue; std::vector unknownValues = settings.library.unknownReturnValues(tok->astOperand1()); if (unknownValues.empty()) diff --git a/lib/vf_common.cpp b/lib/vf_common.cpp index c0d17e2ed18..7505e89c36d 100644 --- a/lib/vf_common.cpp +++ b/lib/vf_common.cpp @@ -153,7 +153,7 @@ namespace ValueFlow const Token *tok2 = tok->tokAt(2); // skip over tokens to find variable or type while (tok2 && !tok2->isStandardType() && Token::Match(tok2, "%name% ::|.|[")) { - if (tok2->next()->str() == "[") + if (tok2->strAt(1) == "[") tok2 = tok2->linkAt(1)->next(); else tok2 = tok2->tokAt(2); diff --git a/lib/vf_settokenvalue.cpp b/lib/vf_settokenvalue.cpp index 7c0965d367f..51275fe469d 100644 --- a/lib/vf_settokenvalue.cpp +++ b/lib/vf_settokenvalue.cpp @@ -350,7 +350,7 @@ namespace ValueFlow } Value pvalue = value; if (!value.subexpressions.empty() && Token::Match(parent, ". %var%")) { - if (contains(value.subexpressions, parent->next()->str())) + if (contains(value.subexpressions, parent->strAt(1))) pvalue.subexpressions.clear(); else return; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 2c8fca7827f..0c73f301820 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -2309,7 +2309,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(!foo->hasBody()); const Token*parenthesis = foo->tokenDef->next(); - ASSERT(parenthesis->str() == "(" && parenthesis->previous()->str() == "foo"); + ASSERT(parenthesis->str() == "(" && parenthesis->strAt(-1) == "foo"); ASSERT(parenthesis->valueType()->type == ValueType::Type::CONTAINER); } diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 937b5bf57cd..91f24d9f12d 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -122,13 +122,13 @@ class TestToken : public TestFixture { token->next()->insertToken("3"); Token *last = token->tokAt(2); ASSERT_EQUALS(token->str(), "1"); - ASSERT_EQUALS(token->next()->str(), "2"); + ASSERT_EQUALS(token->strAt(1), "2"); // cppcheck-suppress redundantNextPrevious - this is intentional ASSERT_EQUALS(token->tokAt(2)->str(), "3"); ASSERT_EQUALS_MSG(true, last->next() == nullptr, "Null was expected"); ASSERT_EQUALS(last->str(), "3"); - ASSERT_EQUALS(last->previous()->str(), "2"); + ASSERT_EQUALS(last->strAt(-1), "2"); // cppcheck-suppress redundantNextPrevious - this is intentional ASSERT_EQUALS(last->tokAt(-2)->str(), "1"); ASSERT_EQUALS_MSG(true, token->previous() == nullptr, "Null was expected"); From 6f5e064ca60c070c8deb49045715550f8b6f6656 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 1 Jun 2024 23:01:25 +0200 Subject: [PATCH 3/6] const --- lib/tokenize.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index b56df5df959..4c1f7707540 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6749,7 +6749,7 @@ void Tokenizer::simplifyFunctionParameters() // First step: Get list of argument names in parentheses std::map argumentNames; bool bailOut = false; - Token * tokparam = nullptr; + const Token * tokparam = nullptr; //take count of the function name.. const std::string& funcName(tok->str()); From b306d907fe23ee03e8ea8b9830ddbf18e5103a8e Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sat, 1 Jun 2024 23:17:22 +0200 Subject: [PATCH 4/6] Fix --- lib/symboldatabase.cpp | 4 ++-- lib/tokenize.cpp | 2 +- test/testtokenize.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 0ed2154c591..bbaee127edd 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1353,9 +1353,9 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() const Type *type = tok->function()->retType; Token* membertok; if (tok->linkAt(1)->strAt(1) == ".") - membertok = tok->linkAt(1)->next()->next(); + membertok = tok->linkAt(1)->tokAt(2); else - membertok = tok->linkAt(1)->linkAt(1)->next()->next(); + membertok = tok->linkAt(1)->linkAt(1)->tokAt(2); if (type) { const Variable *membervar = membertok->variable(); if (!membervar) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4c1f7707540..4c5e9d414c9 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7786,7 +7786,7 @@ void Tokenizer::simplifyIfSwitchForInit() // Simplify, the initialization expression is broken out.. semicolon->insertToken(tok->str()); semicolon->next()->insertToken("("); - Token::createMutualLinks(semicolon->next()->next(), endpar); + Token::createMutualLinks(semicolon->tokAt(2), endpar); tok->deleteNext(); tok->str("{"); endscope->insertToken("}"); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index d530d416692..5e1322ba958 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -3297,7 +3297,7 @@ class TestTokenizer : public TestFixture { SimpleTokenizer tokenizer(settings0, *this); ASSERT(tokenizer.tokenize(code)); const Token *A = Token::findsimplematch(tokenizer.tokens(), "A <"); - ASSERT_EQUALS(true, A->next()->link() == A->tokAt(3)); + ASSERT_EQUALS(true, A->linkAt(1) == A->tokAt(3)); } { // #8851 @@ -3305,7 +3305,7 @@ class TestTokenizer : public TestFixture { "void basic_json() {}"; SimpleTokenizer tokenizer(settings0, *this); ASSERT(tokenizer.tokenize(code)); - ASSERT_EQUALS(true, Token::simpleMatch(tokenizer.tokens()->next()->link(), "> void")); + ASSERT_EQUALS(true, Token::simpleMatch(tokenizer.tokens()->linkAt(1), "> void")); } { @@ -3325,8 +3325,8 @@ class TestTokenizer : public TestFixture { ASSERT(tokenizer.tokenize(code)); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "template <"); const Token *tok2 = Token ::findsimplematch(tokenizer.tokens(), "same_as <"); - ASSERT(tok1->next()->link() == tok1->tokAt(7)); - ASSERT(tok2->next()->link() == tok2->tokAt(3)); + ASSERT(tok1->linkAt(1) == tok1->tokAt(7)); + ASSERT(tok2->linkAt(1) == tok2->tokAt(3)); } { From 6d21a593f1af70bb94c24a1178bfae42366a8bf6 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 2 Jun 2024 00:31:00 +0200 Subject: [PATCH 5/6] Amend --- lib/tokenize.cpp | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4c5e9d414c9..0f69d44bd74 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -8192,7 +8192,7 @@ void Tokenizer::validateC() const syntaxErrorC(tok, "template<..."); if (Token::Match(tok, "%name% :: %name%")) syntaxErrorC(tok, tok->str() + tok->strAt(1) + tok->strAt(2)); - if (Token::Match(tok, "class|namespace %name% [:{]")) + if (Token::Match(tok, "class|namespace %name% :|::|{")) syntaxErrorC(tok, tok->str() + tok->strAt(1) + tok->strAt(2)); } } @@ -8708,7 +8708,8 @@ void Tokenizer::findGarbageCode() const syntaxError(tok); if (Token::Match(tok, "typedef [,;:]")) syntaxError(tok); - if (Token::Match(tok, "! %comp%")) + if (Token::Match(tok, "!|~ %comp%") && + !(isCPP() && tok->strAt(1) == ">" && Token::simpleMatch(tok->tokAt(-1), "operator"))) syntaxError(tok); if (Token::Match(tok, "] %name%") && (!isCPP() || !(tok->tokAt(-1) && Token::simpleMatch(tok->tokAt(-2), "delete [")))) { if (tok->next()->isUpperCaseName()) @@ -8782,30 +8783,27 @@ void Tokenizer::findGarbageCode() const // Garbage templates.. if (isCPP()) { for (const Token *tok = tokens(); tok; tok = tok->next()) { - if (Token::simpleMatch(tok, "< >")) { - if (!(Token::Match(tok->tokAt(-1), "%name%") || (tok->tokAt(-1) && Token::Match(tok->tokAt(-2), "operator %op%")))) - syntaxError(tok); - if (!tok->tokAt(-1) || tok->tokAt(-1)->isLiteral()) - syntaxError(tok); - } + if (Token::simpleMatch(tok, "< >") && !(Token::Match(tok->tokAt(-1), "%name%") || (tok->tokAt(-1) && Token::Match(tok->tokAt(-2), "operator %op%")))) + syntaxError(tok); + if (Token::simpleMatch(tok, ": template") && !Token::Match(tok->tokAt(-1), "public|private|protected")) + syntaxError(tok); if (!Token::simpleMatch(tok, "template <")) continue; if (!tok->tokAt(2) || tok->tokAt(2)->isLiteral()) syntaxError(tok); - if (tok->previous() && !Token::Match(tok->previous(), ":|;|{|}|)|>|\"C++\"")) { + if (tok->previous() && !Token::Match(tok->previous(), ":|,|;|{|}|)|<|>|\"C++\"")) { if (tok->previous()->isUpperCaseName()) unknownMacroError(tok->previous()); else syntaxError(tok); } - const Token * const tok1 = tok; - tok = tok->next()->findClosingBracket(); - if (!tok) - syntaxError(tok1); - if (!Token::Match(tok, ">|>> ::|...| %name%") && - !Token::Match(tok, ">|>> [ [ %name%") && - !Token::Match(tok, "> >|*")) - syntaxError(tok->next() ? tok->next() : tok1); + const Token * const tok1 = tok->next()->findClosingBracket(); + if (!tok1) + syntaxError(tok); + if (!Token::Match(tok1, ">|>> ::|...| %name%") && + !Token::Match(tok1, ">|>> [ [ %name%") && + !Token::Match(tok1, "> >|*")) + syntaxError(tok1->next() ? tok1->next() : tok); } } From 915001ca96e62ea1f883182adfc35157162181b7 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 2 Jun 2024 00:57:38 +0200 Subject: [PATCH 6/6] Undo --- lib/templatesimplifier.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index bf21d51c5e0..5933b279481 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -833,6 +833,8 @@ void TemplateSimplifier::getTemplateInstantiations() } else if (Token::Match(tok->previous(), "(|{|}|;|=|>|<<|:|.|*|&|return|<|,|!|[ %name% ::|<|(") || Token::Match(tok->previous(), "%type% %name% ::|<") || Token::Match(tok->tokAt(-2), "[,:] private|protected|public %name% ::|<")) { + if (!tok->scopeInfo()) + syntaxError(tok); std::string scopeName = tok->scopeInfo()->name; std::string qualification; Token * qualificationTok = tok;