From 1275b5275eb396a6b57304ddc9572792e6e08b50 Mon Sep 17 00:00:00 2001 From: PKEuS <731902+PKEuS@users.noreply.github.com> Date: Wed, 8 Jun 2022 16:58:57 +0200 Subject: [PATCH] LCppC backport: Various optimizations (#4182) * Optimization: Use Token::eIncDecOp instead of expensive Token::Match calls Merged from LCppC. * Small Optimizations: - Moved a std::set that is only need during initialization of SymbolDatabase to function scope - Use std::vector instead of std::list Merged from LCppC. * Optimization: Refactorized various Token::Match calls and surrounding conditions Merged from LCppC. * Refactorization: Cleanup usage of std::multimap Merged from LCppC. --- lib/astutils.cpp | 10 ++--- lib/checkautovariables.cpp | 2 +- lib/checkcondition.cpp | 2 +- lib/checkio.cpp | 2 +- lib/checkleakautovar.cpp | 4 +- lib/checkother.cpp | 18 ++++----- lib/checkstl.cpp | 9 ++--- lib/programmemory.cpp | 2 +- lib/symboldatabase.cpp | 83 ++++++++++++++++++-------------------- lib/symboldatabase.h | 9 ++--- lib/templatesimplifier.cpp | 6 +-- lib/token.cpp | 46 +++++++++------------ lib/tokenize.cpp | 6 +-- lib/valueflow.cpp | 4 +- 14 files changed, 91 insertions(+), 112 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 07096a2f5..e50d6e86e 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -885,7 +885,7 @@ bool exprDependsOnThis(const Token* expr, bool onVar, nonneg int depth) if (classScope && classScope->isClassOrStruct()) return contains(classScope->findAssociatedScopes(), expr->function()->nestedIn); return false; - } else if (onVar && Token::Match(expr, "%var%") && expr->variable()) { + } else if (onVar && expr->variable()) { const Variable* var = expr->variable(); return (var->isPrivate() || var->isPublic() || var->isProtected()); } @@ -1287,7 +1287,7 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2 return true; // Follow variable - if (followVar && !tok_str_eq && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) { + if (followVar && !tok_str_eq && (tok1->varId() || tok2->varId())) { const Token * varTok1 = followVariableExpression(tok1, cpp, tok2); if ((varTok1->str() == tok2->str()) || isSameConstantValue(macro, varTok1, tok2)) { followVariableExpressionError(tok1, varTok1, errors); @@ -2156,7 +2156,7 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti parenTok = parenTok->link()->next(); const bool possiblyPassedByReference = (parenTok->next() == tok1 || Token::Match(tok1->previous(), ", %name% [,)}]")); - if (!tok->function() && !tok->variable() && Token::Match(tok, "%name%")) { + if (!tok->function() && !tok->variable() && tok->isName()) { if (settings) { const bool requireInit = settings->library.isuninitargbad(tok, 1 + argnr); const bool requireNonNull = settings->library.isnullargbad(tok, 1 + argnr); @@ -2238,7 +2238,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, while (Token::simpleMatch(tok2->astParent(), "?") || (Token::simpleMatch(tok2->astParent(), ":") && Token::simpleMatch(tok2->astParent()->astParent(), "?"))) tok2 = tok2->astParent(); - if (Token::Match(tok2->astParent(), "++|--")) + if (tok2->astParent() && tok2->astParent()->tokType() == Token::eIncDecOp) return true; auto skipRedundantPtrOp = [](const Token* tok, const Token* parent) { @@ -2816,7 +2816,7 @@ static const Token* getLHSVariableRecursive(const Token* tok) const Variable *getLHSVariable(const Token *tok) { - if (!Token::Match(tok, "%assign%")) + if (!tok || !tok->isAssignmentOp()) return nullptr; if (!tok->astOperand1()) return nullptr; diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 741790cda..e85796d61 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -214,7 +214,7 @@ void CheckAutoVariables::assignFunctionArg() // TODO: What happens if this is removed? if (tok->astParent()) continue; - if (!(tok->isAssignmentOp() || Token::Match(tok, "++|--")) || !Token::Match(tok->astOperand1(), "%var%")) + if (!(tok->isAssignmentOp() || tok->tokType() == Token::eIncDecOp) || !Token::Match(tok->astOperand1(), "%var%")) continue; const Token* const vartok = tok->astOperand1(); if (isNonReferenceArg(vartok) && diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 4c3597396..cf082e1dc 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1439,7 +1439,7 @@ void CheckCondition::alwaysTrueFalse() continue; if (Token::Match(tok, "%oror%|&&|:")) continue; - if (Token::Match(tok, "%comp%") && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true)) + if (tok->isComparisonOp() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true)) continue; if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<")) continue; diff --git a/lib/checkio.cpp b/lib/checkio.cpp index dbdf484c4..c3c347cc8 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -1340,7 +1340,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings, // Use AST type info // TODO: This is a bailout so that old code is used in simple cases. Remove the old code and always use the AST type. - if (!Token::Match(arg, "%str% ,|)") && !(Token::Match(arg,"%var%") && arg->variable() && arg->variable()->isArray())) { + if (!Token::Match(arg, "%str% ,|)") && !(arg->variable() && arg->variable()->isArray())) { const Token *top = arg; while (top->str() == "(" && !top->isCast()) top = top->next(); diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 9c841f9cd..3ba2da1a5 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -501,7 +501,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken, } if (tok3->str() == "(" && Token::Match(tok3->astOperand1(), "UNLIKELY|LIKELY")) { return ChildrenToVisit::op2; - } else if (tok3->str() == "(" && Token::Match(tok3->previous(), "%name%")) { + } else if (tok3->str() == "(" && tok3->previous()->isName()) { const std::vector params = getArguments(tok3->previous()); for (const Token *par : params) { if (!par->isComparisonOp()) @@ -1020,7 +1020,7 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO (tok3->valueType()->typeSize(*mSettings) == 0) || (tok3->valueType()->typeSize(*mSettings) >= mSettings->sizeof_pointer))) tok3 = tok3->astOperand2() ? tok3->astOperand2() : tok3->astOperand1(); - if (Token::Match(tok3, "%varid%", varid)) + if (tok3 && tok3->varId() == varid) tok2 = tok3->next(); else if (Token::Match(tok3, "& %varid% . %name%", varid)) tok2 = tok3->tokAt(4); diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 46bc618d9..3800b9251 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -228,7 +228,7 @@ void CheckOther::clarifyStatement() const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { - if (Token::Match(tok, "* %name%") && tok->astOperand1()) { + if (tok->astOperand1() && Token::Match(tok, "* %name%")) { const Token *tok2 = tok->previous(); while (tok2 && tok2->str() == "*") @@ -445,7 +445,7 @@ void CheckOther::checkRedundantAssignment() if (Token::simpleMatch(tok, "try {")) // todo: check try blocks tok = tok->linkAt(1); - if ((tok->isAssignmentOp() || Token::Match(tok, "++|--")) && tok->astOperand1()) { + if ((tok->isAssignmentOp() || tok->tokType() == Token::eIncDecOp) && tok->astOperand1()) { if (tok->astParent()) continue; @@ -1777,7 +1777,7 @@ static bool isVarDeclOp(const Token* tok) if (vartok && vartok->variable() && vartok->variable()->nameToken() == vartok) return true; const Token * typetok = tok->astOperand1(); - return isType(typetok, Token::Match(vartok, "%var%")); + return isType(typetok, vartok && vartok->varId() != 0); } static bool isBracketAccess(const Token* tok) @@ -1800,9 +1800,9 @@ static bool isConstStatement(const Token *tok, bool cpp) return false; if (tok->isExpandedMacro()) return false; - if (Token::Match(tok, "%bool%|%num%|%str%|%char%|nullptr|NULL")) + if (tok->varId() != 0) return true; - if (Token::Match(tok, "%var%")) + if (Token::Match(tok, "%bool%|%num%|%str%|%char%|nullptr|NULL")) return true; if (Token::Match(tok, "*|&|&&") && (Token::Match(tok->previous(), "::|.|const|volatile|restrict") || isVarDeclOp(tok))) @@ -1939,7 +1939,7 @@ void CheckOther::checkIncompleteStatement() if (mTokenizer->isCPP() && tok->str() == "&" && !(tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isIntegral())) // Possible archive continue; - bool inconclusive = Token::Match(tok, "%cop%"); + bool inconclusive = tok->isConstOp(); if (mSettings->certainty.isEnabled(Certainty::inconclusive) || !inconclusive) constStatementError(tok, tok->isNumber() ? "numeric" : "string", inconclusive); } @@ -3117,7 +3117,7 @@ void CheckOther::checkEvaluationOrder() const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope * functionScope : symbolDatabase->functionScopes) { for (const Token* tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { - if (!Token::Match(tok, "++|--") && !tok->isAssignmentOp()) + if (tok->tokType() != Token::eIncDecOp && !tok->isAssignmentOp()) continue; if (!tok->astOperand1()) continue; @@ -3470,7 +3470,7 @@ void CheckOther::shadowError(const Token *var, const Token *shadowed, std::strin static bool isVariableExpression(const Token* tok) { - if (Token::Match(tok, "%var%")) + if (tok->varId() != 0) return true; if (Token::simpleMatch(tok, ".")) return isVariableExpression(tok->astOperand1()) && @@ -3498,7 +3498,7 @@ void CheckOther::checkKnownArgument() continue; if (!tok->hasKnownIntValue()) continue; - if (Token::Match(tok, "++|--")) + if (tok->tokType() == Token::eIncDecOp) continue; if (isConstVarExpression(tok)) continue; diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index a5ad67d43..9b3a5effe 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1583,10 +1583,8 @@ static const Token *skipLocalVars(const Token *tok) return tok; return skipLocalVars(semi->next()); } - if (Token::Match(top, "%assign%")) { + if (tok->isAssignmentOp()) { const Token *varTok = top->astOperand1(); - if (!Token::Match(varTok, "%var%")) - return tok; const Variable *var = varTok->variable(); if (!var) return tok; @@ -1956,8 +1954,7 @@ void CheckStl::string_c_str() if (var->isPointer()) string_c_strError(tok); } - } else if (printPerformance && tok->function() && Token::Match(tok, "%name% ( !!)") && c_strFuncParam.find(tok->function()) != c_strFuncParam.end() && - tok->str() != scope.className) { + } else if (printPerformance && tok->function() && Token::Match(tok, "%name% ( !!)") && tok->str() != scope.className) { const std::pair::const_iterator, std::multimap::const_iterator> range = c_strFuncParam.equal_range(tok->function()); for (std::multimap::const_iterator i = range.first; i != range.second; ++i) { if (i->second == 0) @@ -2613,7 +2610,7 @@ void CheckStl::useStlAlgorithm() if (!Token::simpleMatch(splitTok, ":")) continue; const Token *loopVar = splitTok->previous(); - if (!Token::Match(loopVar, "%var%")) + if (loopVar->varId() == 0) continue; // Check for single assignment diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index ac761f61c..96dc48714 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -663,7 +663,7 @@ static ValueFlow::Value executeImpl(const Token* expr, ProgramMemory& pm, const } else if (expr->str() == "," && expr->astOperand1() && expr->astOperand2()) { execute(expr->astOperand1(), pm); return execute(expr->astOperand2(), pm); - } else if (Token::Match(expr, "++|--") && expr->astOperand1() && expr->astOperand1()->exprId() != 0) { + } else if (expr->tokType() == Token::eIncDecOp && expr->astOperand1() && expr->astOperand1()->exprId() != 0) { if (!pm.hasValue(expr->astOperand1()->exprId())) return unknown; ValueFlow::Value& lhs = pm.at(expr->astOperand1()->exprId()); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index d05ce6e47..466374866 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -646,8 +646,9 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() } bool newFunc = true; // Is this function already in the database? - for (std::multimap::const_iterator i = scope->functionMap.find(tok->str()); i != scope->functionMap.end() && i->first == tok->str(); ++i) { - if (i->second->argsMatch(scope, i->second->argDef, argStart, emptyString, 0)) { + auto range = scope->functionMap.equal_range(tok->str()); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { + if (it->second->argsMatch(scope, it->second->argDef, argStart, emptyString, 0)) { newFunc = false; break; } @@ -1319,6 +1320,8 @@ void SymbolDatabase::createSymbolDatabaseEnums() const_cast(i.name)->enumerator(&i); } + std::set tokensThatAreNotEnumeratorValues; + for (Scope &scope : scopeList) { if (scope.type != Scope::eEnum) continue; @@ -1330,7 +1333,7 @@ void SymbolDatabase::createSymbolDatabaseEnums() mTokenizer->syntaxError(enumerator.start); for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) { if (tok3->tokType() == Token::eName) { - const Enumerator * e = findEnumerator(tok3); + const Enumerator * e = findEnumerator(tok3, tokensThatAreNotEnumeratorValues); if (e) const_cast(tok3)->enumerator(e); } @@ -1343,7 +1346,7 @@ void SymbolDatabase::createSymbolDatabaseEnums() for (const Token* tok = mTokenizer->list.front(); tok != mTokenizer->list.back(); tok = tok->next()) { if (tok->tokType() != Token::eName) continue; - const Enumerator * enumerator = findEnumerator(tok); + const Enumerator * enumerator = findEnumerator(tok, tokensThatAreNotEnumeratorValues); if (enumerator) const_cast(tok)->enumerator(enumerator); } @@ -1417,12 +1420,10 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars() continue; if (!scope->isExecutable()) continue; - if (!Token::Match(tok, "%name%")) + if (tok->varId() != 0) continue; if (!tok->isNameOnly()) continue; - if (Token::Match(tok, "%var%")) - continue; if (tok->type()) continue; if (Token::Match(tok->next(), "::|.|(|:|%var%")) @@ -1763,7 +1764,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const // skip over qualification while (Token::simpleMatch(tok1, "::")) { tok1 = tok1->previous(); - if (Token::Match(tok1, "%name%")) + if (tok1 && tok1->isName()) tok1 = tok1->previous(); else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%")) tok1 = tok1->link()->tokAt(-2); @@ -1810,7 +1811,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const return false; // skip over return type - if (Token::Match(tok1, "%name%")) { + if (tok1 && tok1->isName()) { if (tok1->str() == "return") return false; if (tok1->str() != "friend") @@ -1820,7 +1821,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const // skip over qualification while (Token::simpleMatch(tok1, "::")) { tok1 = tok1->previous(); - if (Token::Match(tok1, "%name%")) + if (tok1 && tok1->isName()) tok1 = tok1->previous(); else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%")) tok1 = tok1->link()->tokAt(-2); @@ -2931,12 +2932,13 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co Function* function = nullptr; // Lambda functions are always unique if (tok->str() != "[") { - for (std::multimap::iterator i = scope->functionMap.find(tok->str()); i != scope->functionMap.end() && i->first == tok->str(); ++i) { - const Function *f = i->second; + auto range = scope->functionMap.equal_range(tok->str()); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { + const Function *f = it->second; if (f->hasBody()) continue; if (f->argsMatch(scope, f->argDef, argStart, emptyString, 0)) { - function = const_cast(i->second); + function = const_cast(it->second); break; } } @@ -3019,7 +3021,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To // check in namespace if using found if (*scope == scope1 && !scope1->usingList.empty()) { - std::list::const_iterator it2; + std::vector::const_iterator it2; for (it2 = scope1->usingList.begin(); it2 != scope1->usingList.end(); ++it2) { if (it2->scope) { Function * func = findFunctionInScope(tok1, it2->scope, path, path_length); @@ -3090,7 +3092,8 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To } if (match) { - for (std::multimap::iterator it = scope1->functionMap.find((*tok)->str()); it != scope1->functionMap.end() && it->first == (*tok)->str(); ++it) { + auto range = scope1->functionMap.equal_range((*tok)->str()); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { Function * func = const_cast(it->second); if (!func->hasBody()) { if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) { @@ -3597,17 +3600,15 @@ void SymbolDatabase::printOut(const char *title) const if (title) std::cout << "\n### " << title << " ###\n"; - for (std::list::const_iterator scope = scopeList.begin(); scope != scopeList.end(); ++scope) { + for (std::list::const_iterator scope = scopeList.cbegin(); scope != scopeList.cend(); ++scope) { std::cout << "Scope: " << &*scope << " " << scope->type << std::endl; std::cout << " className: " << scope->className << std::endl; std::cout << " classDef: " << tokenToString(scope->classDef, mTokenizer) << std::endl; std::cout << " bodyStart: " << tokenToString(scope->bodyStart, mTokenizer) << std::endl; std::cout << " bodyEnd: " << tokenToString(scope->bodyEnd, mTokenizer) << std::endl; - std::list::const_iterator func; - // find the function body if not implemented inline - for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { + for (auto func = scope->functionList.cbegin(); func != scope->functionList.cend(); ++func) { std::cout << " Function: " << &*func << std::endl; std::cout << " name: " << tokenToString(func->tokenDef, mTokenizer) << std::endl; std::cout << " type: " << (func->type == Function::eConstructor? "Constructor" : @@ -3686,17 +3687,13 @@ void SymbolDatabase::printOut(const char *title) const std::cout << " nestedIn: " << scopeToString(func->nestedIn, mTokenizer) << std::endl; std::cout << " functionScope: " << scopeToString(func->functionScope, mTokenizer) << std::endl; - std::list::const_iterator var; - - for (var = func->argumentList.begin(); var != func->argumentList.end(); ++var) { + for (auto var = func->argumentList.cbegin(); var != func->argumentList.cend(); ++var) { std::cout << " Variable: " << &*var << std::endl; printVariable(&*var, " "); } } - std::list::const_iterator var; - - for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) { + for (auto var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) { std::cout << " Variable: " << &*var << std::endl; printVariable(&*var, " "); } @@ -3741,10 +3738,8 @@ void SymbolDatabase::printOut(const char *title) const std::cout << " nestedList[" << scope->nestedList.size() << "] = ("; - std::list::const_iterator nsi; - std::size_t count = scope->nestedList.size(); - for (nsi = scope->nestedList.begin(); nsi != scope->nestedList.end(); ++nsi) { + for (std::vector::const_iterator nsi = scope->nestedList.cbegin(); nsi != scope->nestedList.cend(); ++nsi) { std::cout << " " << (*nsi) << " " << (*nsi)->type << " " << (*nsi)->className; if (count-- > 1) std::cout << ","; @@ -3752,9 +3747,7 @@ void SymbolDatabase::printOut(const char *title) const std::cout << " )" << std::endl; - std::list::const_iterator use; - - for (use = scope->usingList.begin(); use != scope->usingList.end(); ++use) { + for (auto use = scope->usingList.cbegin(); use != scope->usingList.cend(); ++use) { std::cout << " using: " << use->scope << " " << use->start->strAt(2); const Token *tok1 = use->start->tokAt(3); while (tok1 && tok1->str() == "::") { @@ -4160,7 +4153,8 @@ const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType const Scope *parent = derivedFromType->classScope; // check if function defined in base class - for (std::multimap::const_iterator it = parent->functionMap.find(tokenDef->str()); it != parent->functionMap.end() && it->first == tokenDef->str(); ++it) { + auto range = parent->functionMap.equal_range(tokenDef->str()); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { const Function * func = it->second; if (func->hasVirtualSpecifier()) { // Base is virtual and of same name const Token *temp1 = func->tokenDef->previous(); @@ -4714,13 +4708,13 @@ const Token * Scope::addEnum(const Token * tok, bool isCpp) return tok2; } -const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const +const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::set& tokensThatAreNotEnumeratorValues) const { const Scope * scope = tok->scope(); const std::string &tokStr = tok->str(); - if (mTokensThatAreNotEnumeratorValues.find(tokStr) != mTokensThatAreNotEnumeratorValues.end()) { + if (tokensThatAreNotEnumeratorValues.find(tokStr) != tokensThatAreNotEnumeratorValues.end()) { return nullptr; } @@ -4761,7 +4755,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const return enumerator; // enum else { - for (std::list::const_iterator it = scope->nestedList.begin(), end = scope->nestedList.end(); it != end; ++it) { + for (std::vector::const_iterator it = scope->nestedList.begin(), end = scope->nestedList.end(); it != end; ++it) { enumerator = (*it)->findEnumerator(tokStr); if (enumerator) @@ -4776,7 +4770,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const if (enumerator) return enumerator; - for (std::list::const_iterator s = scope->nestedList.begin(); s != scope->nestedList.end(); ++s) { + for (std::vector::const_iterator s = scope->nestedList.begin(); s != scope->nestedList.end(); ++s) { enumerator = (*s)->findEnumerator(tokStr); if (enumerator) @@ -4807,7 +4801,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const if (enumerator) return enumerator; - for (std::list::const_iterator s = scope->nestedList.begin(); s != scope->nestedList.end(); ++s) { + for (std::vector::const_iterator s = scope->nestedList.begin(); s != scope->nestedList.end(); ++s) { enumerator = (*s)->findEnumerator(tokStr); if (enumerator) @@ -4816,7 +4810,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const } } - mTokensThatAreNotEnumeratorValues.insert(tokStr); + tokensThatAreNotEnumeratorValues.insert(tokStr); return nullptr; } @@ -4986,7 +4980,8 @@ void Scope::findFunctionInBase(const std::string & name, nonneg int args, std::v if (base->classScope == this) // Ticket #5120, #5125: Recursive class; tok should have been found already continue; - for (std::multimap::const_iterator it = base->classScope->functionMap.find(name); it != base->classScope->functionMap.end() && it->first == name; ++it) { + auto range = base->classScope->functionMap.equal_range(name); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { const Function *func = it->second; if ((func->isVariadic() && args >= (func->argCount() - 1)) || (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount()))) { @@ -5127,7 +5122,8 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const const std::size_t args = arguments.size(); auto addMatchingFunctions = [&](const Scope *scope) { - for (std::multimap::const_iterator it = scope->functionMap.find(tok->str()); it != scope->functionMap.cend() && it->first == tok->str(); ++it) { + auto range = scope->functionMap.equal_range(tok->str()); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { const Function *func = it->second; if (!isCall || args == func->argCount() || (func->isVariadic() && args >= (func->minArgCount() - 1)) || @@ -5677,7 +5673,7 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc // check using namespaces while (startScope) { - for (std::list::const_iterator it = startScope->usingList.begin(); + for (std::vector::const_iterator it = startScope->usingList.begin(); it != startScope->usingList.end(); ++it) { tok = startTok; scope = it->scope; @@ -5796,9 +5792,8 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n const Function * function = nullptr; const bool destructor = func->strAt(-1) == "~"; - for (std::multimap::const_iterator it = ns->functionMap.find(func->str()); - it != ns->functionMap.end() && it->first == func->str(); ++it) { - + auto range = ns->functionMap.equal_range(func->str()); + for (std::multimap::const_iterator it = range.first; it != range.second; ++it) { if (it->second->argsMatch(ns, it->second->argDef, func->next(), path, path_length) && it->second->isDestructor() == destructor) { function = it->second; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 0cafd4067..2e946e597 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1033,10 +1033,10 @@ public: std::multimap functionMap; std::list varlist; const Scope *nestedIn; - std::list nestedList; + std::vector nestedList; nonneg int numConstructors; nonneg int numCopyOrMoveConstructors; - std::list usingList; + std::vector usingList; ScopeType type; Type* definedType; std::map definedTypesMap; @@ -1481,7 +1481,7 @@ private: /** Whether iName is a keyword as defined in http://en.cppreference.com/w/c/keyword and http://en.cppreference.com/w/cpp/keyword*/ bool isReservedName(const std::string& iName) const; - const Enumerator * findEnumerator(const Token * tok) const; + const Enumerator * findEnumerator(const Token * tok, std::set& tokensThatAreNotEnumeratorValues) const; void setValueType(Token *tok, const ValueType &valuetype); void setValueType(Token *tok, const Variable &var); @@ -1499,9 +1499,6 @@ private: bool mIsCpp; ValueType::Sign mDefaultSignedness; - - /** "negative cache" list of tokens that we find are not enumeration values */ - mutable std::set mTokensThatAreNotEnumeratorValues; }; diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index c98dda935..2bb695933 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -822,8 +822,8 @@ void TemplateSimplifier::getTemplateInstantiations() fullName = tok->str(); // get all declarations with this name - for (auto pos = functionNameMap.lower_bound(tok->str()); - pos != functionNameMap.upper_bound(tok->str()); ++pos) { + auto range = functionNameMap.equal_range(tok->str()); + for (auto pos = range.first; pos != range.second; ++pos) { // look for declaration with same qualification or constructor with same qualification if (pos->second->fullName() == fullName || (pos->second->scope() == fullName && tok->str() == pos->second->name())) { @@ -2550,7 +2550,7 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end) for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) { if (Token::Match(tok, "( %num%|%bool% )") && - (tok->previous() && !Token::Match(tok->previous(), "%name%"))) { + (tok->previous() && !tok->previous()->isName())) { tok->deleteThis(); tok->deleteNext(); again = true; diff --git a/lib/token.cpp b/lib/token.cpp index 020344261..f61ae5c91 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1508,7 +1508,7 @@ bool Token::isUnaryPreOp() const { if (!astOperand1() || astOperand2()) return false; - if (!Token::Match(this, "++|--")) + if (this->tokType() != Token::eIncDecOp) return true; const Token *tokbefore = mPrevious; const Token *tokafter = mNext; @@ -2197,7 +2197,13 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok) if (typeTok != nullptr) *typeTok = tok; const Token* lhsVarTok{}; - if (Token::simpleMatch(tok, "return")) { + if (tok->type()) { + return tok->type(); + } else if (tok->variable()) { + return tok->variable()->type(); + } else if (tok->function()) { + return tok->function()->retType; + } else if (Token::simpleMatch(tok, "return")) { const Scope *scope = tok->scope(); if (!scope) return nullptr; @@ -2205,18 +2211,6 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok) if (!function) return nullptr; return function->retType; - } else if (Token::Match(tok, "%type%")) { - return tok->type(); - } else if (Token::Match(tok, "%var%")) { - const Variable *var = tok->variable(); - if (!var) - return nullptr; - return var->type(); - } else if (Token::Match(tok, "%name%")) { - const Function *function = tok->function(); - if (!function) - return nullptr; - return function->retType; } else if (Token::Match(tok->previous(), "%type%|= (|{")) { return typeOf(tok->previous(), typeTok); } else if (Token::simpleMatch(tok, "=") && (lhsVarTok = getLHSVariableToken(tok)) != tok->next()) { @@ -2251,20 +2245,10 @@ std::pair Token::typeDecl(const Token * tok) { if (!tok) return {}; - if (Token::simpleMatch(tok, "return")) { - const Scope *scope = tok->scope(); - if (!scope) - return {}; - const Function *function = scope->function; - if (!function) - return {}; - return {function->retDef, function->returnDefEnd()}; - } else if (Token::Match(tok, "%type%")) { + else if (tok->type()) { return {tok, tok->next()}; - } else if (Token::Match(tok, "%var%")) { + } else if (tok->variable()) { const Variable *var = tok->variable(); - if (!var) - return {}; if (!var->typeStartToken() || !var->typeEndToken()) return {}; if (Token::simpleMatch(var->typeStartToken(), "auto")) { @@ -2278,10 +2262,16 @@ std::pair Token::typeDecl(const Token * tok) } } return {var->typeStartToken(), var->typeEndToken()->next()}; - } else if (Token::Match(tok->previous(), "%name% (")) { - const Function *function = tok->previous()->function(); + } else if (Token::simpleMatch(tok, "return")) { + const Scope* scope = tok->scope(); + if (!scope) + return {}; + const Function* function = scope->function; if (!function) return {}; + return { function->retDef, function->returnDefEnd() }; + } else if (tok->previous()->function()) { + const Function *function = tok->previous()->function(); return {function->retDef, function->returnDefEnd()}; } else if (Token::simpleMatch(tok, "=")) { return Token::typeDecl(tok->astOperand1()); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 84971a5e0..993517533 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -12203,7 +12203,7 @@ void Tokenizer::printUnknownTypes() const if (!mSymbolDatabase) return; - std::multimap unknowns; + std::vector> unknowns; for (int i = 1; i <= mVarId; ++i) { const Variable *var = mSymbolDatabase->getVariableFromVarId(i); @@ -12252,14 +12252,14 @@ void Tokenizer::printUnknownTypes() const } } - unknowns.insert(std::pair(name, nameTok)); + unknowns.emplace_back(std::make_pair(name, nameTok)); } if (!unknowns.empty()) { std::string last; int count = 0; - for (std::multimap::const_iterator it = unknowns.begin(); it != unknowns.end(); ++it) { + for (auto it = unknowns.begin(); it != unknowns.end(); ++it) { // skip types is std namespace because they are not interesting if (it->first.find("std::") != 0) { if (it->first != last) { diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index e4e143521..93877fca3 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2181,9 +2181,9 @@ static bool bifurcate(const Token* tok, const std::set& varids, cons return true; if (tok->hasKnownIntValue()) return true; - if (Token::Match(tok, "%cop%")) + if (tok->isConstOp()) return bifurcate(tok->astOperand1(), varids, settings, depth) && bifurcate(tok->astOperand2(), varids, settings, depth); - if (Token::Match(tok, "%var%")) { + if (tok->varId() != 0) { if (varids.count(tok->varId()) > 0) return true; const Variable* var = tok->variable();