Refactorization: Speedup function lookup in symboldatabase (#6277) (Part 2)
This commit is contained in:
parent
417f42f732
commit
1aa3adbb46
|
@ -433,7 +433,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
// find the function implementation later
|
// find the function implementation later
|
||||||
tok = end->next();
|
tok = end->next();
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default or delete
|
// default or delete
|
||||||
|
@ -445,7 +445,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
|
|
||||||
tok = end->tokAt(3);
|
tok = end->tokAt(3);
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// noexcept;
|
// noexcept;
|
||||||
|
@ -465,7 +465,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// noexcept(...);
|
// noexcept(...);
|
||||||
|
@ -488,7 +488,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw();
|
// throw();
|
||||||
|
@ -515,7 +515,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pure virtual function
|
// pure virtual function
|
||||||
|
@ -527,13 +527,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
else
|
else
|
||||||
tok = end->tokAt(3);
|
tok = end->tokAt(3);
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'const' or unknown macro (#5197)
|
// 'const' or unknown macro (#5197)
|
||||||
else if (Token::Match(end, ") %any% ;")) {
|
else if (Token::Match(end, ") %any% ;")) {
|
||||||
tok = end->tokAt(2);
|
tok = end->tokAt(2);
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// inline function
|
// inline function
|
||||||
|
@ -569,7 +569,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
if (!end || end->str() == ";")
|
if (!end || end->str() == ";")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
|
|
||||||
Function* funcptr = &scope->functionList.back();
|
Function* funcptr = &scope->functionList.back();
|
||||||
const Token *tok2 = funcStart;
|
const Token *tok2 = funcStart;
|
||||||
|
@ -691,8 +691,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
// function prototype?
|
// function prototype?
|
||||||
else if (scopeBegin->str() == ";") {
|
else if (scopeBegin->str() == ";") {
|
||||||
bool newFunc = true; // Is this function already in the database?
|
bool newFunc = true; // Is this function already in the database?
|
||||||
for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
|
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->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) {
|
if (Function::argsMatch(scope, i->second->argDef->next(), argStart->next(), "", 0)) {
|
||||||
newFunc = false;
|
newFunc = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1526,12 +1526,12 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
|
||||||
Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart)
|
Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart)
|
||||||
{
|
{
|
||||||
Function* function = 0;
|
Function* function = 0;
|
||||||
for (std::list<Function>::iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
|
for (std::multimap<std::string, const Function *>::iterator i = scope->functionMap.find(tok->str()); i != scope->functionMap.end() && i->first == tok->str(); ++i) {
|
||||||
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) {
|
if (Function::argsMatch(scope, i->second->argDef->next(), argStart->next(), "", 0)) {
|
||||||
function = &*i;
|
function = const_cast<Function *>(i->second);
|
||||||
// copy attributes from function prototype to function
|
// copy attributes from function prototype to function
|
||||||
Token* to = const_cast<Token *>(tok);
|
Token* to = const_cast<Token *>(tok);
|
||||||
const Token* from = i->tokenDef;
|
const Token* from = function->tokenDef;
|
||||||
to->isAttributeConstructor(from->isAttributeConstructor());
|
to->isAttributeConstructor(from->isAttributeConstructor());
|
||||||
to->isAttributeDestructor(from->isAttributeDestructor());
|
to->isAttributeDestructor(from->isAttributeDestructor());
|
||||||
to->isAttributePure(from->isAttributePure());
|
to->isAttributePure(from->isAttributePure());
|
||||||
|
@ -1591,7 +1591,7 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok,
|
||||||
if (tok1)
|
if (tok1)
|
||||||
function.retDef = tok1;
|
function.retDef = tok1;
|
||||||
|
|
||||||
scope->functionList.push_back(function);
|
scope->addFunction(function);
|
||||||
return &scope->functionList.back();
|
return &scope->functionList.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1697,10 +1697,9 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
std::list<Function>::iterator func;
|
for (std::multimap<std::string, const Function *>::iterator it = scope1->functionMap.find((*tok)->str()); it != scope1->functionMap.end() && it->first == (*tok)->str(); ++it) {
|
||||||
|
Function * func = const_cast<Function *>(it->second);
|
||||||
for (func = scope1->functionList.begin(); func != scope1->functionList.end(); ++func) {
|
if (!func->hasBody) {
|
||||||
if (!func->hasBody && func->tokenDef->str() == (*tok)->str()) {
|
|
||||||
if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
|
||||||
if (func->type == Function::eDestructor && destructor) {
|
if (func->type == Function::eDestructor && destructor) {
|
||||||
func->hasBody = true;
|
func->hasBody = true;
|
||||||
|
@ -1882,9 +1881,10 @@ void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) cons
|
||||||
const Function* Type::getFunction(const std::string& funcName) const
|
const Function* Type::getFunction(const std::string& funcName) const
|
||||||
{
|
{
|
||||||
if (classScope) {
|
if (classScope) {
|
||||||
for (std::list<Function>::const_iterator i = classScope->functionList.begin(); i != classScope->functionList.end(); ++i)
|
std::multimap<std::string, const Function *>::const_iterator it = classScope->functionMap.find(funcName);
|
||||||
if (i->name() == funcName)
|
|
||||||
return &*i;
|
if (it != classScope->functionMap.end())
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < derivedFrom.size(); i++) {
|
for (std::size_t i = 0; i < derivedFrom.size(); i++) {
|
||||||
|
@ -2473,11 +2473,10 @@ bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const
|
||||||
if (derivedFromType && derivedFromType->classScope) {
|
if (derivedFromType && derivedFromType->classScope) {
|
||||||
const Scope *parent = derivedFromType->classScope;
|
const Scope *parent = derivedFromType->classScope;
|
||||||
|
|
||||||
std::list<Function>::const_iterator func;
|
|
||||||
|
|
||||||
// check if function defined in base class
|
// check if function defined in base class
|
||||||
for (func = parent->functionList.begin(); func != parent->functionList.end(); ++func) {
|
for (std::multimap<std::string, const Function *>::const_iterator it = parent->functionMap.find(tokenDef->str()); it != parent->functionMap.end() && it->first == tokenDef->str(); ++it) {
|
||||||
if (func->isVirtual && func->tokenDef->str() == tokenDef->str()) { // Base is virtual and of same name
|
const Function * func = it->second;
|
||||||
|
if (func->isVirtual) { // Base is virtual and of same name
|
||||||
const Token *temp1 = func->tokenDef->previous();
|
const Token *temp1 = func->tokenDef->previous();
|
||||||
const Token *temp2 = tokenDef->previous();
|
const Token *temp2 = tokenDef->previous();
|
||||||
bool returnMatch = true;
|
bool returnMatch = true;
|
||||||
|
@ -2898,6 +2897,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *typeTok) const
|
const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *typeTok) const
|
||||||
|
@ -2939,7 +2939,7 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void Scope::findFunctionInBase(const Token * tok, size_t args, std::vector<const Function *> & matches) const
|
void Scope::findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const
|
||||||
{
|
{
|
||||||
if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) {
|
if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) {
|
||||||
for (std::size_t i = 0; i < definedType->derivedFrom.size(); ++i) {
|
for (std::size_t i = 0; i < definedType->derivedFrom.size(); ++i) {
|
||||||
|
@ -2948,16 +2948,14 @@ void Scope::findFunctionInBase(const Token * tok, size_t args, std::vector<const
|
||||||
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::list<Function>::const_iterator it = base->classScope->functionList.begin(); it != base->classScope->functionList.end(); ++it) {
|
for (std::multimap<std::string, const Function *>::const_iterator it = base->classScope->functionMap.find(name); it != base->classScope->functionMap.end() && it->first == name; ++it) {
|
||||||
if (it->tokenDef->str() == tok->str()) {
|
const Function *func = it->second;
|
||||||
const Function *func = &*it;
|
|
||||||
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
|
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
|
||||||
matches.push_back(func);
|
matches.push_back(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
base->classScope->findFunctionInBase(tok, args, matches);
|
base->classScope->findFunctionInBase(name, args, matches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2989,17 +2987,15 @@ const Function* Scope::findFunction(const Token *tok) const
|
||||||
|
|
||||||
// find all the possible functions that could match
|
// find all the possible functions that could match
|
||||||
const std::size_t args = arguments.size();
|
const std::size_t args = arguments.size();
|
||||||
for (std::list<Function>::const_iterator it = functionList.begin(); it != functionList.end(); ++it) {
|
for (std::multimap<std::string, const Function *>::const_iterator it = functionMap.find(tok->str()); it != functionMap.end() && it->first == tok->str(); ++it) {
|
||||||
if (it->tokenDef->str() == tok->str()) {
|
const Function *func = it->second;
|
||||||
const Function *func = &*it;
|
|
||||||
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
|
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
|
||||||
matches.push_back(func);
|
matches.push_back(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// check in base classes
|
// check in base classes
|
||||||
findFunctionInBase(tok, args, matches);
|
findFunctionInBase(tok->str(), args, matches);
|
||||||
|
|
||||||
// check each function against the arguments in the function call for a match
|
// check each function against the arguments in the function call for a match
|
||||||
for (std::size_t i = 0; i < matches.size();) {
|
for (std::size_t i = 0; i < matches.size();) {
|
||||||
|
@ -3451,16 +3447,13 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
|
||||||
{
|
{
|
||||||
const Function * function = nullptr;
|
const Function * function = nullptr;
|
||||||
|
|
||||||
std::list<Function>::const_iterator it;
|
for (std::multimap<std::string, const Function *>::const_iterator it = ns->functionMap.find(func->str());
|
||||||
|
it != ns->functionMap.end() && it->first == func->str(); ++it) {
|
||||||
for (it = ns->functionList.begin(); it != ns->functionList.end(); ++it) {
|
if (Function::argsMatch(ns, func->tokAt(2), it->second->argDef->next(), "", 0)) {
|
||||||
if (it->name() == func->str()) {
|
function = it->second;
|
||||||
if (Function::argsMatch(ns, func->tokAt(2), it->argDef->next(), "", 0)) {
|
|
||||||
function = &*it;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!function) {
|
if (!function) {
|
||||||
const Scope * scope = ns->findRecordInNestedList(func->str());
|
const Scope * scope = ns->findRecordInNestedList(func->str());
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
@ -692,6 +693,7 @@ public:
|
||||||
const Token *classStart; // '{' token
|
const Token *classStart; // '{' token
|
||||||
const Token *classEnd; // '}' token
|
const Token *classEnd; // '}' token
|
||||||
std::list<Function> functionList;
|
std::list<Function> functionList;
|
||||||
|
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::list<Scope *> nestedList;
|
||||||
|
@ -763,6 +765,14 @@ public:
|
||||||
|
|
||||||
const Function *getDestructor() const;
|
const Function *getDestructor() const;
|
||||||
|
|
||||||
|
void addFunction(const Function & func) {
|
||||||
|
functionList.push_back(func);
|
||||||
|
|
||||||
|
const Function * back = &functionList.back();
|
||||||
|
|
||||||
|
functionMap.insert(make_pair(back->tokenDef->str(), back));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get the number of nested scopes that are not functions
|
* @brief get the number of nested scopes that are not functions
|
||||||
*
|
*
|
||||||
|
@ -800,7 +810,7 @@ private:
|
||||||
*/
|
*/
|
||||||
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const;
|
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const;
|
||||||
|
|
||||||
void findFunctionInBase(const Token * tok, size_t args, std::vector<const Function *> & matches) const;
|
void findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPPCHECKLIB SymbolDatabase {
|
class CPPCHECKLIB SymbolDatabase {
|
||||||
|
|
Loading…
Reference in New Issue