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.
This commit is contained in:
PKEuS 2022-06-08 16:58:57 +02:00 committed by GitHub
parent 4bd189c3c8
commit 1275b5275e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 91 additions and 112 deletions

View File

@ -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;

View File

@ -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) &&

View File

@ -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;

View File

@ -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();

View File

@ -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<const Token *> 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);

View File

@ -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;

View File

@ -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<std::multimap<const Function*, int>::const_iterator, std::multimap<const Function*, int>::const_iterator> range = c_strFuncParam.equal_range(tok->function());
for (std::multimap<const Function*, int>::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

View File

@ -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());

View File

@ -646,8 +646,9 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
bool newFunc = true; // Is this function already in the database?
for (std::multimap<std::string, const Function *>::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<std::string, const Function*>::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<Token *>(i.name)->enumerator(&i);
}
std::set<std::string> 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<Token *>(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<Token *>(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<std::string, const Function *>::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<std::string, const Function*>::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<Function *>(i->second);
function = const_cast<Function *>(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<Scope::UsingInfo>::const_iterator it2;
std::vector<Scope::UsingInfo>::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<std::string, const Function *>::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<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
Function * func = const_cast<Function *>(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<Scope>::const_iterator scope = scopeList.begin(); scope != scopeList.end(); ++scope) {
for (std::list<Scope>::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<Function>::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<Variable>::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<Variable>::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<Scope *>::const_iterator nsi;
std::size_t count = scope->nestedList.size();
for (nsi = scope->nestedList.begin(); nsi != scope->nestedList.end(); ++nsi) {
for (std::vector<Scope*>::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<Scope::UsingInfo>::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<std::string, const Function *>::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<std::string, const Function*>::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<std::string>& 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<Scope *>::const_iterator it = scope->nestedList.begin(), end = scope->nestedList.end(); it != end; ++it) {
for (std::vector<Scope *>::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<Scope *>::const_iterator s = scope->nestedList.begin(); s != scope->nestedList.end(); ++s) {
for (std::vector<Scope *>::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<Scope*>::const_iterator s = scope->nestedList.begin(); s != scope->nestedList.end(); ++s) {
for (std::vector<Scope*>::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<std::string, const Function *>::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<std::string, const Function*>::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<std::string, const Function *>::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<std::string, const Function *>::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<Scope::UsingInfo>::const_iterator it = startScope->usingList.begin();
for (std::vector<Scope::UsingInfo>::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<std::string, const Function *>::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<std::string, const Function*>::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;

View File

@ -1033,10 +1033,10 @@ public:
std::multimap<std::string, const Function *> functionMap;
std::list<Variable> varlist;
const Scope *nestedIn;
std::list<Scope *> nestedList;
std::vector<Scope *> nestedList;
nonneg int numConstructors;
nonneg int numCopyOrMoveConstructors;
std::list<UsingInfo> usingList;
std::vector<UsingInfo> usingList;
ScopeType type;
Type* definedType;
std::map<std::string, Type*> 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<std::string>& 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<std::string> mTokensThatAreNotEnumeratorValues;
};

View File

@ -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;

View File

@ -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<const Token*, const Token*> 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<const Token*, const Token*> 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());

View File

@ -12203,7 +12203,7 @@ void Tokenizer::printUnknownTypes() const
if (!mSymbolDatabase)
return;
std::multimap<std::string, const Token *> unknowns;
std::vector<std::pair<std::string, const Token *>> 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<std::string, const Token *>(name, nameTok));
unknowns.emplace_back(std::make_pair(name, nameTok));
}
if (!unknowns.empty()) {
std::string last;
int count = 0;
for (std::multimap<std::string, const Token *>::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) {

View File

@ -2181,9 +2181,9 @@ static bool bifurcate(const Token* tok, const std::set<nonneg int>& 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();