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()) if (classScope && classScope->isClassOrStruct())
return contains(classScope->findAssociatedScopes(), expr->function()->nestedIn); return contains(classScope->findAssociatedScopes(), expr->function()->nestedIn);
return false; return false;
} else if (onVar && Token::Match(expr, "%var%") && expr->variable()) { } else if (onVar && expr->variable()) {
const Variable* var = expr->variable(); const Variable* var = expr->variable();
return (var->isPrivate() || var->isPublic() || var->isProtected()); 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; return true;
// Follow variable // 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); const Token * varTok1 = followVariableExpression(tok1, cpp, tok2);
if ((varTok1->str() == tok2->str()) || isSameConstantValue(macro, varTok1, tok2)) { if ((varTok1->str() == tok2->str()) || isSameConstantValue(macro, varTok1, tok2)) {
followVariableExpressionError(tok1, varTok1, errors); followVariableExpressionError(tok1, varTok1, errors);
@ -2156,7 +2156,7 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
parenTok = parenTok->link()->next(); parenTok = parenTok->link()->next();
const bool possiblyPassedByReference = (parenTok->next() == tok1 || Token::Match(tok1->previous(), ", %name% [,)}]")); 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) { if (settings) {
const bool requireInit = settings->library.isuninitargbad(tok, 1 + argnr); const bool requireInit = settings->library.isuninitargbad(tok, 1 + argnr);
const bool requireNonNull = settings->library.isnullargbad(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(), "?"))) while (Token::simpleMatch(tok2->astParent(), "?") || (Token::simpleMatch(tok2->astParent(), ":") && Token::simpleMatch(tok2->astParent()->astParent(), "?")))
tok2 = tok2->astParent(); tok2 = tok2->astParent();
if (Token::Match(tok2->astParent(), "++|--")) if (tok2->astParent() && tok2->astParent()->tokType() == Token::eIncDecOp)
return true; return true;
auto skipRedundantPtrOp = [](const Token* tok, const Token* parent) { 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) const Variable *getLHSVariable(const Token *tok)
{ {
if (!Token::Match(tok, "%assign%")) if (!tok || !tok->isAssignmentOp())
return nullptr; return nullptr;
if (!tok->astOperand1()) if (!tok->astOperand1())
return nullptr; return nullptr;

View File

@ -214,7 +214,7 @@ void CheckAutoVariables::assignFunctionArg()
// TODO: What happens if this is removed? // TODO: What happens if this is removed?
if (tok->astParent()) if (tok->astParent())
continue; 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; continue;
const Token* const vartok = tok->astOperand1(); const Token* const vartok = tok->astOperand1();
if (isNonReferenceArg(vartok) && if (isNonReferenceArg(vartok) &&

View File

@ -1439,7 +1439,7 @@ void CheckCondition::alwaysTrueFalse()
continue; continue;
if (Token::Match(tok, "%oror%|&&|:")) if (Token::Match(tok, "%oror%|&&|:"))
continue; 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; continue;
if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<")) if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<"))
continue; continue;

View File

@ -1340,7 +1340,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
// Use AST type info // 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. // 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; const Token *top = arg;
while (top->str() == "(" && !top->isCast()) while (top->str() == "(" && !top->isCast())
top = top->next(); 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")) { if (tok3->str() == "(" && Token::Match(tok3->astOperand1(), "UNLIKELY|LIKELY")) {
return ChildrenToVisit::op2; 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()); const std::vector<const Token *> params = getArguments(tok3->previous());
for (const Token *par : params) { for (const Token *par : params) {
if (!par->isComparisonOp()) 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) == 0) ||
(tok3->valueType()->typeSize(*mSettings) >= mSettings->sizeof_pointer))) (tok3->valueType()->typeSize(*mSettings) >= mSettings->sizeof_pointer)))
tok3 = tok3->astOperand2() ? tok3->astOperand2() : tok3->astOperand1(); tok3 = tok3->astOperand2() ? tok3->astOperand2() : tok3->astOperand1();
if (Token::Match(tok3, "%varid%", varid)) if (tok3 && tok3->varId() == varid)
tok2 = tok3->next(); tok2 = tok3->next();
else if (Token::Match(tok3, "& %varid% . %name%", varid)) else if (Token::Match(tok3, "& %varid% . %name%", varid))
tok2 = tok3->tokAt(4); tok2 = tok3->tokAt(4);

View File

@ -228,7 +228,7 @@ void CheckOther::clarifyStatement()
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
for (const Scope * scope : symbolDatabase->functionScopes) { for (const Scope * scope : symbolDatabase->functionScopes) {
for (const Token* tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { 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(); const Token *tok2 = tok->previous();
while (tok2 && tok2->str() == "*") while (tok2 && tok2->str() == "*")
@ -445,7 +445,7 @@ void CheckOther::checkRedundantAssignment()
if (Token::simpleMatch(tok, "try {")) if (Token::simpleMatch(tok, "try {"))
// todo: check try blocks // todo: check try blocks
tok = tok->linkAt(1); tok = tok->linkAt(1);
if ((tok->isAssignmentOp() || Token::Match(tok, "++|--")) && tok->astOperand1()) { if ((tok->isAssignmentOp() || tok->tokType() == Token::eIncDecOp) && tok->astOperand1()) {
if (tok->astParent()) if (tok->astParent())
continue; continue;
@ -1777,7 +1777,7 @@ static bool isVarDeclOp(const Token* tok)
if (vartok && vartok->variable() && vartok->variable()->nameToken() == vartok) if (vartok && vartok->variable() && vartok->variable()->nameToken() == vartok)
return true; return true;
const Token * typetok = tok->astOperand1(); 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) static bool isBracketAccess(const Token* tok)
@ -1800,9 +1800,9 @@ static bool isConstStatement(const Token *tok, bool cpp)
return false; return false;
if (tok->isExpandedMacro()) if (tok->isExpandedMacro())
return false; return false;
if (Token::Match(tok, "%bool%|%num%|%str%|%char%|nullptr|NULL")) if (tok->varId() != 0)
return true; return true;
if (Token::Match(tok, "%var%")) if (Token::Match(tok, "%bool%|%num%|%str%|%char%|nullptr|NULL"))
return true; return true;
if (Token::Match(tok, "*|&|&&") && if (Token::Match(tok, "*|&|&&") &&
(Token::Match(tok->previous(), "::|.|const|volatile|restrict") || isVarDeclOp(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())) if (mTokenizer->isCPP() && tok->str() == "&" && !(tok->astOperand1()->valueType() && tok->astOperand1()->valueType()->isIntegral()))
// Possible archive // Possible archive
continue; continue;
bool inconclusive = Token::Match(tok, "%cop%"); bool inconclusive = tok->isConstOp();
if (mSettings->certainty.isEnabled(Certainty::inconclusive) || !inconclusive) if (mSettings->certainty.isEnabled(Certainty::inconclusive) || !inconclusive)
constStatementError(tok, tok->isNumber() ? "numeric" : "string", inconclusive); constStatementError(tok, tok->isNumber() ? "numeric" : "string", inconclusive);
} }
@ -3117,7 +3117,7 @@ void CheckOther::checkEvaluationOrder()
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
for (const Scope * functionScope : symbolDatabase->functionScopes) { for (const Scope * functionScope : symbolDatabase->functionScopes) {
for (const Token* tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { 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; continue;
if (!tok->astOperand1()) if (!tok->astOperand1())
continue; continue;
@ -3470,7 +3470,7 @@ void CheckOther::shadowError(const Token *var, const Token *shadowed, std::strin
static bool isVariableExpression(const Token* tok) static bool isVariableExpression(const Token* tok)
{ {
if (Token::Match(tok, "%var%")) if (tok->varId() != 0)
return true; return true;
if (Token::simpleMatch(tok, ".")) if (Token::simpleMatch(tok, "."))
return isVariableExpression(tok->astOperand1()) && return isVariableExpression(tok->astOperand1()) &&
@ -3498,7 +3498,7 @@ void CheckOther::checkKnownArgument()
continue; continue;
if (!tok->hasKnownIntValue()) if (!tok->hasKnownIntValue())
continue; continue;
if (Token::Match(tok, "++|--")) if (tok->tokType() == Token::eIncDecOp)
continue; continue;
if (isConstVarExpression(tok)) if (isConstVarExpression(tok))
continue; continue;

View File

@ -1583,10 +1583,8 @@ static const Token *skipLocalVars(const Token *tok)
return tok; return tok;
return skipLocalVars(semi->next()); return skipLocalVars(semi->next());
} }
if (Token::Match(top, "%assign%")) { if (tok->isAssignmentOp()) {
const Token *varTok = top->astOperand1(); const Token *varTok = top->astOperand1();
if (!Token::Match(varTok, "%var%"))
return tok;
const Variable *var = varTok->variable(); const Variable *var = varTok->variable();
if (!var) if (!var)
return tok; return tok;
@ -1956,8 +1954,7 @@ void CheckStl::string_c_str()
if (var->isPointer()) if (var->isPointer())
string_c_strError(tok); string_c_strError(tok);
} }
} else if (printPerformance && tok->function() && Token::Match(tok, "%name% ( !!)") && c_strFuncParam.find(tok->function()) != c_strFuncParam.end() && } else if (printPerformance && tok->function() && Token::Match(tok, "%name% ( !!)") && tok->str() != scope.className) {
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()); 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) { for (std::multimap<const Function*, int>::const_iterator i = range.first; i != range.second; ++i) {
if (i->second == 0) if (i->second == 0)
@ -2613,7 +2610,7 @@ void CheckStl::useStlAlgorithm()
if (!Token::simpleMatch(splitTok, ":")) if (!Token::simpleMatch(splitTok, ":"))
continue; continue;
const Token *loopVar = splitTok->previous(); const Token *loopVar = splitTok->previous();
if (!Token::Match(loopVar, "%var%")) if (loopVar->varId() == 0)
continue; continue;
// Check for single assignment // 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()) { } else if (expr->str() == "," && expr->astOperand1() && expr->astOperand2()) {
execute(expr->astOperand1(), pm); execute(expr->astOperand1(), pm);
return execute(expr->astOperand2(), 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())) if (!pm.hasValue(expr->astOperand1()->exprId()))
return unknown; return unknown;
ValueFlow::Value& lhs = pm.at(expr->astOperand1()->exprId()); 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? 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) { auto range = scope->functionMap.equal_range(tok->str());
if (i->second->argsMatch(scope, i->second->argDef, argStart, emptyString, 0)) { 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; newFunc = false;
break; break;
} }
@ -1319,6 +1320,8 @@ void SymbolDatabase::createSymbolDatabaseEnums()
const_cast<Token *>(i.name)->enumerator(&i); const_cast<Token *>(i.name)->enumerator(&i);
} }
std::set<std::string> tokensThatAreNotEnumeratorValues;
for (Scope &scope : scopeList) { for (Scope &scope : scopeList) {
if (scope.type != Scope::eEnum) if (scope.type != Scope::eEnum)
continue; continue;
@ -1330,7 +1333,7 @@ void SymbolDatabase::createSymbolDatabaseEnums()
mTokenizer->syntaxError(enumerator.start); mTokenizer->syntaxError(enumerator.start);
for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) { for (const Token * tok3 = enumerator.start; tok3 && tok3 != enumerator.end->next(); tok3 = tok3->next()) {
if (tok3->tokType() == Token::eName) { if (tok3->tokType() == Token::eName) {
const Enumerator * e = findEnumerator(tok3); const Enumerator * e = findEnumerator(tok3, tokensThatAreNotEnumeratorValues);
if (e) if (e)
const_cast<Token *>(tok3)->enumerator(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()) { for (const Token* tok = mTokenizer->list.front(); tok != mTokenizer->list.back(); tok = tok->next()) {
if (tok->tokType() != Token::eName) if (tok->tokType() != Token::eName)
continue; continue;
const Enumerator * enumerator = findEnumerator(tok); const Enumerator * enumerator = findEnumerator(tok, tokensThatAreNotEnumeratorValues);
if (enumerator) if (enumerator)
const_cast<Token *>(tok)->enumerator(enumerator); const_cast<Token *>(tok)->enumerator(enumerator);
} }
@ -1417,12 +1420,10 @@ void SymbolDatabase::createSymbolDatabaseIncompleteVars()
continue; continue;
if (!scope->isExecutable()) if (!scope->isExecutable())
continue; continue;
if (!Token::Match(tok, "%name%")) if (tok->varId() != 0)
continue; continue;
if (!tok->isNameOnly()) if (!tok->isNameOnly())
continue; continue;
if (Token::Match(tok, "%var%"))
continue;
if (tok->type()) if (tok->type())
continue; continue;
if (Token::Match(tok->next(), "::|.|(|:|%var%")) if (Token::Match(tok->next(), "::|.|(|:|%var%"))
@ -1763,7 +1764,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
// skip over qualification // skip over qualification
while (Token::simpleMatch(tok1, "::")) { while (Token::simpleMatch(tok1, "::")) {
tok1 = tok1->previous(); tok1 = tok1->previous();
if (Token::Match(tok1, "%name%")) if (tok1 && tok1->isName())
tok1 = tok1->previous(); tok1 = tok1->previous();
else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%")) else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%"))
tok1 = tok1->link()->tokAt(-2); tok1 = tok1->link()->tokAt(-2);
@ -1810,7 +1811,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
return false; return false;
// skip over return type // skip over return type
if (Token::Match(tok1, "%name%")) { if (tok1 && tok1->isName()) {
if (tok1->str() == "return") if (tok1->str() == "return")
return false; return false;
if (tok1->str() != "friend") if (tok1->str() != "friend")
@ -1820,7 +1821,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
// skip over qualification // skip over qualification
while (Token::simpleMatch(tok1, "::")) { while (Token::simpleMatch(tok1, "::")) {
tok1 = tok1->previous(); tok1 = tok1->previous();
if (Token::Match(tok1, "%name%")) if (tok1 && tok1->isName())
tok1 = tok1->previous(); tok1 = tok1->previous();
else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%")) else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%"))
tok1 = tok1->link()->tokAt(-2); tok1 = tok1->link()->tokAt(-2);
@ -2931,12 +2932,13 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
Function* function = nullptr; Function* function = nullptr;
// Lambda functions are always unique // Lambda functions are always unique
if (tok->str() != "[") { 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) { auto range = scope->functionMap.equal_range(tok->str());
const Function *f = i->second; for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
const Function *f = it->second;
if (f->hasBody()) if (f->hasBody())
continue; continue;
if (f->argsMatch(scope, f->argDef, argStart, emptyString, 0)) { if (f->argsMatch(scope, f->argDef, argStart, emptyString, 0)) {
function = const_cast<Function *>(i->second); function = const_cast<Function *>(it->second);
break; break;
} }
} }
@ -3019,7 +3021,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
// check in namespace if using found // check in namespace if using found
if (*scope == scope1 && !scope1->usingList.empty()) { 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) { for (it2 = scope1->usingList.begin(); it2 != scope1->usingList.end(); ++it2) {
if (it2->scope) { if (it2->scope) {
Function * func = findFunctionInScope(tok1, it2->scope, path, path_length); 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) { 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); Function * func = const_cast<Function *>(it->second);
if (!func->hasBody()) { if (!func->hasBody()) {
if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) { if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
@ -3597,17 +3600,15 @@ void SymbolDatabase::printOut(const char *title) const
if (title) if (title)
std::cout << "\n### " << title << " ###\n"; 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 << "Scope: " << &*scope << " " << scope->type << std::endl;
std::cout << " className: " << scope->className << std::endl; std::cout << " className: " << scope->className << std::endl;
std::cout << " classDef: " << tokenToString(scope->classDef, mTokenizer) << std::endl; std::cout << " classDef: " << tokenToString(scope->classDef, mTokenizer) << std::endl;
std::cout << " bodyStart: " << tokenToString(scope->bodyStart, mTokenizer) << std::endl; std::cout << " bodyStart: " << tokenToString(scope->bodyStart, mTokenizer) << std::endl;
std::cout << " bodyEnd: " << tokenToString(scope->bodyEnd, 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 // 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 << " Function: " << &*func << std::endl;
std::cout << " name: " << tokenToString(func->tokenDef, mTokenizer) << std::endl; std::cout << " name: " << tokenToString(func->tokenDef, mTokenizer) << std::endl;
std::cout << " type: " << (func->type == Function::eConstructor? "Constructor" : 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 << " nestedIn: " << scopeToString(func->nestedIn, mTokenizer) << std::endl;
std::cout << " functionScope: " << scopeToString(func->functionScope, mTokenizer) << std::endl; std::cout << " functionScope: " << scopeToString(func->functionScope, mTokenizer) << std::endl;
std::list<Variable>::const_iterator var; for (auto var = func->argumentList.cbegin(); var != func->argumentList.cend(); ++var) {
for (var = func->argumentList.begin(); var != func->argumentList.end(); ++var) {
std::cout << " Variable: " << &*var << std::endl; std::cout << " Variable: " << &*var << std::endl;
printVariable(&*var, " "); printVariable(&*var, " ");
} }
} }
std::list<Variable>::const_iterator var; for (auto var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
std::cout << " Variable: " << &*var << std::endl; std::cout << " Variable: " << &*var << std::endl;
printVariable(&*var, " "); printVariable(&*var, " ");
} }
@ -3741,10 +3738,8 @@ void SymbolDatabase::printOut(const char *title) const
std::cout << " nestedList[" << scope->nestedList.size() << "] = ("; std::cout << " nestedList[" << scope->nestedList.size() << "] = (";
std::list<Scope *>::const_iterator nsi;
std::size_t count = scope->nestedList.size(); 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; std::cout << " " << (*nsi) << " " << (*nsi)->type << " " << (*nsi)->className;
if (count-- > 1) if (count-- > 1)
std::cout << ","; std::cout << ",";
@ -3752,9 +3747,7 @@ void SymbolDatabase::printOut(const char *title) const
std::cout << " )" << std::endl; std::cout << " )" << std::endl;
std::list<Scope::UsingInfo>::const_iterator use; for (auto use = scope->usingList.cbegin(); use != scope->usingList.cend(); ++use) {
for (use = scope->usingList.begin(); use != scope->usingList.end(); ++use) {
std::cout << " using: " << use->scope << " " << use->start->strAt(2); std::cout << " using: " << use->scope << " " << use->start->strAt(2);
const Token *tok1 = use->start->tokAt(3); const Token *tok1 = use->start->tokAt(3);
while (tok1 && tok1->str() == "::") { while (tok1 && tok1->str() == "::") {
@ -4160,7 +4153,8 @@ const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType
const Scope *parent = derivedFromType->classScope; const Scope *parent = derivedFromType->classScope;
// check if function defined in base class // 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; const Function * func = it->second;
if (func->hasVirtualSpecifier()) { // Base is virtual and of same name if (func->hasVirtualSpecifier()) { // Base is virtual and of same name
const Token *temp1 = func->tokenDef->previous(); const Token *temp1 = func->tokenDef->previous();
@ -4714,13 +4708,13 @@ const Token * Scope::addEnum(const Token * tok, bool isCpp)
return tok2; 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 Scope * scope = tok->scope();
const std::string &tokStr = tok->str(); const std::string &tokStr = tok->str();
if (mTokensThatAreNotEnumeratorValues.find(tokStr) != mTokensThatAreNotEnumeratorValues.end()) { if (tokensThatAreNotEnumeratorValues.find(tokStr) != tokensThatAreNotEnumeratorValues.end()) {
return nullptr; return nullptr;
} }
@ -4761,7 +4755,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const
return enumerator; return enumerator;
// enum // enum
else { 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); enumerator = (*it)->findEnumerator(tokStr);
if (enumerator) if (enumerator)
@ -4776,7 +4770,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const
if (enumerator) if (enumerator)
return 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); enumerator = (*s)->findEnumerator(tokStr);
if (enumerator) if (enumerator)
@ -4807,7 +4801,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const
if (enumerator) if (enumerator)
return 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); enumerator = (*s)->findEnumerator(tokStr);
if (enumerator) if (enumerator)
@ -4816,7 +4810,7 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const
} }
} }
mTokensThatAreNotEnumeratorValues.insert(tokStr); tokensThatAreNotEnumeratorValues.insert(tokStr);
return nullptr; 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 if (base->classScope == this) // Ticket #5120, #5125: Recursive class; tok should have been found already
continue; 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; const Function *func = it->second;
if ((func->isVariadic() && args >= (func->argCount() - 1)) || if ((func->isVariadic() && args >= (func->argCount() - 1)) ||
(args == func->argCount() || (args < func->argCount() && args >= func->minArgCount()))) { (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(); const std::size_t args = arguments.size();
auto addMatchingFunctions = [&](const Scope *scope) { 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; const Function *func = it->second;
if (!isCall || args == func->argCount() || if (!isCall || args == func->argCount() ||
(func->isVariadic() && args >= (func->minArgCount() - 1)) || (func->isVariadic() && args >= (func->minArgCount() - 1)) ||
@ -5677,7 +5673,7 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
// check using namespaces // check using namespaces
while (startScope) { 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) { it != startScope->usingList.end(); ++it) {
tok = startTok; tok = startTok;
scope = it->scope; scope = it->scope;
@ -5796,9 +5792,8 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
const Function * function = nullptr; const Function * function = nullptr;
const bool destructor = func->strAt(-1) == "~"; const bool destructor = func->strAt(-1) == "~";
for (std::multimap<std::string, const Function *>::const_iterator it = ns->functionMap.find(func->str()); auto range = ns->functionMap.equal_range(func->str());
it != ns->functionMap.end() && it->first == func->str(); ++it) { 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) && if (it->second->argsMatch(ns, it->second->argDef, func->next(), path, path_length) &&
it->second->isDestructor() == destructor) { it->second->isDestructor() == destructor) {
function = it->second; function = it->second;

View File

@ -1033,10 +1033,10 @@ public:
std::multimap<std::string, const Function *> functionMap; std::multimap<std::string, const Function *> functionMap;
std::list<Variable> varlist; std::list<Variable> varlist;
const Scope *nestedIn; const Scope *nestedIn;
std::list<Scope *> nestedList; std::vector<Scope *> nestedList;
nonneg int numConstructors; nonneg int numConstructors;
nonneg int numCopyOrMoveConstructors; nonneg int numCopyOrMoveConstructors;
std::list<UsingInfo> usingList; std::vector<UsingInfo> usingList;
ScopeType type; ScopeType type;
Type* definedType; Type* definedType;
std::map<std::string, Type*> definedTypesMap; 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*/ /** 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; 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 ValueType &valuetype);
void setValueType(Token *tok, const Variable &var); void setValueType(Token *tok, const Variable &var);
@ -1499,9 +1499,6 @@ private:
bool mIsCpp; bool mIsCpp;
ValueType::Sign mDefaultSignedness; 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(); fullName = tok->str();
// get all declarations with this name // get all declarations with this name
for (auto pos = functionNameMap.lower_bound(tok->str()); auto range = functionNameMap.equal_range(tok->str());
pos != functionNameMap.upper_bound(tok->str()); ++pos) { for (auto pos = range.first; pos != range.second; ++pos) {
// look for declaration with same qualification or constructor with same qualification // look for declaration with same qualification or constructor with same qualification
if (pos->second->fullName() == fullName || if (pos->second->fullName() == fullName ||
(pos->second->scope() == fullName && tok->str() == pos->second->name())) { (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()) { for (Token *tok = first->next(); tok && tok != end; tok = tok->next()) {
if (Token::Match(tok, "( %num%|%bool% )") && if (Token::Match(tok, "( %num%|%bool% )") &&
(tok->previous() && !Token::Match(tok->previous(), "%name%"))) { (tok->previous() && !tok->previous()->isName())) {
tok->deleteThis(); tok->deleteThis();
tok->deleteNext(); tok->deleteNext();
again = true; again = true;

View File

@ -1508,7 +1508,7 @@ bool Token::isUnaryPreOp() const
{ {
if (!astOperand1() || astOperand2()) if (!astOperand1() || astOperand2())
return false; return false;
if (!Token::Match(this, "++|--")) if (this->tokType() != Token::eIncDecOp)
return true; return true;
const Token *tokbefore = mPrevious; const Token *tokbefore = mPrevious;
const Token *tokafter = mNext; const Token *tokafter = mNext;
@ -2197,7 +2197,13 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok)
if (typeTok != nullptr) if (typeTok != nullptr)
*typeTok = tok; *typeTok = tok;
const Token* lhsVarTok{}; 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(); const Scope *scope = tok->scope();
if (!scope) if (!scope)
return nullptr; return nullptr;
@ -2205,18 +2211,6 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok)
if (!function) if (!function)
return nullptr; return nullptr;
return function->retType; 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%|= (|{")) { } else if (Token::Match(tok->previous(), "%type%|= (|{")) {
return typeOf(tok->previous(), typeTok); return typeOf(tok->previous(), typeTok);
} else if (Token::simpleMatch(tok, "=") && (lhsVarTok = getLHSVariableToken(tok)) != tok->next()) { } 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) if (!tok)
return {}; return {};
if (Token::simpleMatch(tok, "return")) { else if (tok->type()) {
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%")) {
return {tok, tok->next()}; return {tok, tok->next()};
} else if (Token::Match(tok, "%var%")) { } else if (tok->variable()) {
const Variable *var = tok->variable(); const Variable *var = tok->variable();
if (!var)
return {};
if (!var->typeStartToken() || !var->typeEndToken()) if (!var->typeStartToken() || !var->typeEndToken())
return {}; return {};
if (Token::simpleMatch(var->typeStartToken(), "auto")) { 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()}; return {var->typeStartToken(), var->typeEndToken()->next()};
} else if (Token::Match(tok->previous(), "%name% (")) { } else if (Token::simpleMatch(tok, "return")) {
const Function *function = tok->previous()->function(); const Scope* scope = tok->scope();
if (!scope)
return {};
const Function* function = scope->function;
if (!function) if (!function)
return {}; return {};
return { function->retDef, function->returnDefEnd() };
} else if (tok->previous()->function()) {
const Function *function = tok->previous()->function();
return {function->retDef, function->returnDefEnd()}; return {function->retDef, function->returnDefEnd()};
} else if (Token::simpleMatch(tok, "=")) { } else if (Token::simpleMatch(tok, "=")) {
return Token::typeDecl(tok->astOperand1()); return Token::typeDecl(tok->astOperand1());

View File

@ -12203,7 +12203,7 @@ void Tokenizer::printUnknownTypes() const
if (!mSymbolDatabase) if (!mSymbolDatabase)
return; return;
std::multimap<std::string, const Token *> unknowns; std::vector<std::pair<std::string, const Token *>> unknowns;
for (int i = 1; i <= mVarId; ++i) { for (int i = 1; i <= mVarId; ++i) {
const Variable *var = mSymbolDatabase->getVariableFromVarId(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()) { if (!unknowns.empty()) {
std::string last; std::string last;
int count = 0; 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 // skip types is std namespace because they are not interesting
if (it->first.find("std::") != 0) { if (it->first.find("std::") != 0) {
if (it->first != last) { 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; return true;
if (tok->hasKnownIntValue()) if (tok->hasKnownIntValue())
return true; return true;
if (Token::Match(tok, "%cop%")) if (tok->isConstOp())
return bifurcate(tok->astOperand1(), varids, settings, depth) && bifurcate(tok->astOperand2(), varids, settings, depth); 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) if (varids.count(tok->varId()) > 0)
return true; return true;
const Variable* var = tok->variable(); const Variable* var = tok->variable();