Refactorizations in SymbolDatabase:
- Replaced Scope::access by a locally stored std::map, because its a temporary status variable that is only necessary when creating the symboldatabase - Moved SymbolDatabase::argsMatch to Function::argsMatch, because its function specific - Improved Scope::findClosingBracket: Improved reliability, made it static and faster
This commit is contained in:
parent
1793bf8928
commit
f6fd44910a
|
@ -46,6 +46,9 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
// pointer to current scope
|
// pointer to current scope
|
||||||
Scope *scope = &scopeList.back();
|
Scope *scope = &scopeList.back();
|
||||||
|
|
||||||
|
// Store current access in each scope (depends on evaluation progress)
|
||||||
|
std::map<const Scope*, AccessControl> access;
|
||||||
|
|
||||||
// find all scopes
|
// find all scopes
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
// Locate next class
|
// Locate next class
|
||||||
|
@ -53,6 +56,11 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
scopeList.push_back(Scope(this, tok, scope));
|
scopeList.push_back(Scope(this, tok, scope));
|
||||||
|
|
||||||
Scope *new_scope = &scopeList.back();
|
Scope *new_scope = &scopeList.back();
|
||||||
|
if (tok->str() == "class")
|
||||||
|
access[new_scope] = Private;
|
||||||
|
else if (tok->str() == "struct")
|
||||||
|
access[new_scope] = Public;
|
||||||
|
|
||||||
const Token *tok2 = tok->tokAt(2);
|
const Token *tok2 = tok->tokAt(2);
|
||||||
|
|
||||||
// only create base list for classes and structures
|
// only create base list for classes and structures
|
||||||
|
@ -111,6 +119,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
scopeList.push_back(Scope(this, tok, scope));
|
scopeList.push_back(Scope(this, tok, scope));
|
||||||
|
|
||||||
Scope *new_scope = &scopeList.back();
|
Scope *new_scope = &scopeList.back();
|
||||||
|
access[new_scope] = Public;
|
||||||
|
|
||||||
std::vector<Dimension> dimensions;
|
std::vector<Dimension> dimensions;
|
||||||
|
|
||||||
|
@ -130,7 +139,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
if (varNameTok->next()->str() == "[")
|
if (varNameTok->next()->str() == "[")
|
||||||
isArray = arrayDimensions(dimensions, varNameTok->next());
|
isArray = arrayDimensions(dimensions, varNameTok->next());
|
||||||
|
|
||||||
scope->addVariable(varNameTok, tok, tok, scope->access, false, false, false, true, new_scope, scope, isArray, isPointer, isReference, dimensions);
|
scope->addVariable(varNameTok, tok, tok, access[scope], false, false, false, true, new_scope, scope, isArray, isPointer, isReference, dimensions);
|
||||||
|
|
||||||
const Token *tok2 = tok->next();
|
const Token *tok2 = tok->next();
|
||||||
|
|
||||||
|
@ -156,6 +165,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
scopeList.push_back(Scope(this, tok, scope));
|
scopeList.push_back(Scope(this, tok, scope));
|
||||||
|
|
||||||
Scope *new_scope = &scopeList.back();
|
Scope *new_scope = &scopeList.back();
|
||||||
|
access[new_scope] = Public;
|
||||||
|
|
||||||
const Token *tok2 = tok->next();
|
const Token *tok2 = tok->next();
|
||||||
|
|
||||||
|
@ -189,18 +199,18 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
|
|
||||||
// What section are we in..
|
// What section are we in..
|
||||||
if (tok->str() == "private:")
|
if (tok->str() == "private:")
|
||||||
scope->access = Private;
|
access[scope] = Private;
|
||||||
else if (tok->str() == "protected:")
|
else if (tok->str() == "protected:")
|
||||||
scope->access = Protected;
|
access[scope] = Protected;
|
||||||
else if (tok->str() == "public:" || tok->str() == "__published:")
|
else if (tok->str() == "public:" || tok->str() == "__published:")
|
||||||
scope->access = Public;
|
access[scope] = Public;
|
||||||
else if (Token::Match(tok, "public|protected|private %var% :")) {
|
else if (Token::Match(tok, "public|protected|private %var% :")) {
|
||||||
if (tok->str() == "private")
|
if (tok->str() == "private")
|
||||||
scope->access = Private;
|
access[scope] = Private;
|
||||||
else if (tok->str() == "protected")
|
else if (tok->str() == "protected")
|
||||||
scope->access = Protected;
|
access[scope] = Protected;
|
||||||
else
|
else
|
||||||
scope->access = Public;
|
access[scope] = Public;
|
||||||
|
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
|
@ -213,7 +223,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
function.argDef = argStart;
|
function.argDef = argStart;
|
||||||
|
|
||||||
// save the access type
|
// save the access type
|
||||||
function.access = scope->access;
|
function.access = access[scope];
|
||||||
|
|
||||||
// save the function name location
|
// save the function name location
|
||||||
function.tokenDef = funcStart;
|
function.tokenDef = funcStart;
|
||||||
|
@ -425,7 +435,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
else if (Token::simpleMatch(argStart->link(), ") ;")) {
|
else if (Token::simpleMatch(argStart->link(), ") ;")) {
|
||||||
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::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
|
||||||
if (i->tokenDef->str() == tok->str() && argsMatch(scope, i->argDef, argStart, "", 0))
|
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef, argStart, "", 0))
|
||||||
newFunc = false;
|
newFunc = false;
|
||||||
}
|
}
|
||||||
// save function prototype in database
|
// save function prototype in database
|
||||||
|
@ -441,7 +451,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
Token::simpleMatch(argStart->link()->linkAt(2), ") ;")) {
|
Token::simpleMatch(argStart->link()->linkAt(2), ") ;")) {
|
||||||
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::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
|
||||||
if (i->tokenDef->str() == tok->str() && argsMatch(scope, i->argDef, argStart, "", 0))
|
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef, argStart, "", 0))
|
||||||
newFunc = false;
|
newFunc = false;
|
||||||
}
|
}
|
||||||
// save function prototype in database
|
// save function prototype in database
|
||||||
|
@ -807,14 +817,12 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int depth)
|
bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int depth)
|
||||||
{
|
{
|
||||||
bool match = false;
|
|
||||||
while (first->str() == second->str()) {
|
while (first->str() == second->str()) {
|
||||||
// at end of argument list
|
// at end of argument list
|
||||||
if (first->str() == ")") {
|
if (first->str() == ")") {
|
||||||
match = true;
|
return true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip default value assignment
|
// skip default value assignment
|
||||||
|
@ -824,12 +832,10 @@ bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Tok
|
||||||
if (second->next()->str() == "=") {
|
if (second->next()->str() == "=") {
|
||||||
second = second->nextArgument();
|
second = second->nextArgument();
|
||||||
if (!first || !second) { // End of argument list (first or second)
|
if (!first || !second) { // End of argument list (first or second)
|
||||||
match = !first && !second;
|
return !first && !second;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else if (!first) { // End of argument list (first)
|
} else if (!first) { // End of argument list (first)
|
||||||
match = second->next() && second->next()->str() == ")";
|
return second->next() && second->next()->str() == ")";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +871,7 @@ bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Tok
|
||||||
if (Token::Match(second->next(), param.c_str())) {
|
if (Token::Match(second->next(), param.c_str())) {
|
||||||
second = second->tokAt(int(depth) * 2);
|
second = second->tokAt(int(depth) * 2);
|
||||||
} else if (depth > 1) {
|
} else if (depth > 1) {
|
||||||
std::string short_path = path;
|
std::string short_path = path;
|
||||||
|
|
||||||
// remove last " :: "
|
// remove last " :: "
|
||||||
short_path.resize(short_path.size() - 4);
|
short_path.resize(short_path.size() - 4);
|
||||||
|
@ -892,14 +898,14 @@ bool SymbolDatabase::argsMatch(const Scope *scope, const Token *first, const Tok
|
||||||
second = second->next();
|
second = second->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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::list<Function>::iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
|
||||||
if (i->tokenDef->str() == tok->str() && argsMatch(scope, i->argDef, argStart, "", 0))
|
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef, argStart, "", 0))
|
||||||
function = &*i;
|
function = &*i;
|
||||||
}
|
}
|
||||||
if (!function)
|
if (!function)
|
||||||
|
@ -1031,7 +1037,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
||||||
for (func = scope1->functionList.begin(); func != scope1->functionList.end(); ++func) {
|
for (func = scope1->functionList.begin(); func != scope1->functionList.end(); ++func) {
|
||||||
if (!func->hasBody && func->tokenDef->str() == (*tok)->str()) {
|
if (!func->hasBody && func->tokenDef->str() == (*tok)->str()) {
|
||||||
if (func->type == Function::eDestructor && destructor) {
|
if (func->type == Function::eDestructor && destructor) {
|
||||||
if (argsMatch(scope1, func->tokenDef->next(), (*tok)->next(), path, path_length)) {
|
if (Function::argsMatch(scope1, func->tokenDef->next(), (*tok)->next(), path, path_length)) {
|
||||||
func->hasBody = true;
|
func->hasBody = true;
|
||||||
func->token = *tok;
|
func->token = *tok;
|
||||||
func->arg = argStart;
|
func->arg = argStart;
|
||||||
|
@ -1041,7 +1047,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
|
||||||
func->start = start;
|
func->start = start;
|
||||||
}
|
}
|
||||||
} else if (func->type != Function::eDestructor && !destructor) {
|
} else if (func->type != Function::eDestructor && !destructor) {
|
||||||
if (argsMatch(scope1, func->tokenDef->next(), (*tok)->next(), path, path_length)) {
|
if (Function::argsMatch(scope1, func->tokenDef->next(), (*tok)->next(), path, path_length)) {
|
||||||
// normal function?
|
// normal function?
|
||||||
if (!func->retFuncPtr && (*tok)->next()->link()) {
|
if (!func->retFuncPtr && (*tok)->next()->link()) {
|
||||||
if ((func->isConst && (*tok)->next()->link()->next()->str() == "const") ||
|
if ((func->isConst && (*tok)->next()->link()->next()->str() == "const") ||
|
||||||
|
@ -1569,10 +1575,12 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token *typeTok = startTok->tokAt(isConstVar ? 1 : 0);
|
||||||
|
|
||||||
// check for argument with no name or missing varid
|
// check for argument with no name or missing varid
|
||||||
if (!endTok) {
|
if (!endTok) {
|
||||||
if (tok->previous()->isName()) {
|
if (tok->previous()->isName()) {
|
||||||
if (tok->previous() != startTok->tokAt(isConstVar ? 1 : 0)) {
|
if (tok->previous() != typeTok) {
|
||||||
nameTok = tok->previous();
|
nameTok = tok->previous();
|
||||||
endTok = nameTok->previous();
|
endTok = nameTok->previous();
|
||||||
|
|
||||||
|
@ -1584,10 +1592,6 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Function
|
||||||
endTok = tok->previous();
|
endTok = tok->previous();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Token *typeTok = startTok;
|
|
||||||
if (isConstVar)
|
|
||||||
typeTok = typeTok->next();
|
|
||||||
|
|
||||||
const Scope *argType = NULL;
|
const Scope *argType = NULL;
|
||||||
if (!typeTok->isStandardType())
|
if (!typeTok->isStandardType())
|
||||||
argType = symbolDatabase->findVariableType(scope, typeTok);
|
argType = symbolDatabase->findVariableType(scope, typeTok);
|
||||||
|
@ -1658,7 +1662,7 @@ bool Function::isImplicitlyVirtual_rec(const Scope* scope, bool& safe) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for matching function parameters
|
// check for matching function parameters
|
||||||
if (returnMatch && SymbolDatabase::argsMatch(scope, func->argDef, argDef, "", 0)) {
|
if (returnMatch && argsMatch(scope, func->argDef, argDef, "", 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1686,7 +1690,6 @@ Scope::Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_, S
|
||||||
classStart(start_),
|
classStart(start_),
|
||||||
classEnd(start_->link()),
|
classEnd(start_->link()),
|
||||||
nestedIn(nestedIn_),
|
nestedIn(nestedIn_),
|
||||||
access(Public),
|
|
||||||
numConstructors(0),
|
numConstructors(0),
|
||||||
needInitialization(Scope::Unknown),
|
needInitialization(Scope::Unknown),
|
||||||
functionOf(NULL),
|
functionOf(NULL),
|
||||||
|
@ -1707,31 +1710,25 @@ Scope::Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_) :
|
||||||
{
|
{
|
||||||
if (!classDef) {
|
if (!classDef) {
|
||||||
type = Scope::eGlobal;
|
type = Scope::eGlobal;
|
||||||
access = Public;
|
|
||||||
} else if (classDef->str() == "class") {
|
} else if (classDef->str() == "class") {
|
||||||
type = Scope::eClass;
|
type = Scope::eClass;
|
||||||
className = classDef->next()->str();
|
className = classDef->next()->str();
|
||||||
access = Private;
|
|
||||||
} else if (classDef->str() == "struct") {
|
} else if (classDef->str() == "struct") {
|
||||||
type = Scope::eStruct;
|
type = Scope::eStruct;
|
||||||
// anonymous and unnamed structs don't have a name
|
// anonymous and unnamed structs don't have a name
|
||||||
if (classDef->next()->str() != "{")
|
if (classDef->next()->str() != "{")
|
||||||
className = classDef->next()->str();
|
className = classDef->next()->str();
|
||||||
access = Public;
|
|
||||||
} else if (classDef->str() == "union") {
|
} else if (classDef->str() == "union") {
|
||||||
type = Scope::eUnion;
|
type = Scope::eUnion;
|
||||||
// anonymous and unnamed unions don't have a name
|
// anonymous and unnamed unions don't have a name
|
||||||
if (classDef->next()->str() != "{")
|
if (classDef->next()->str() != "{")
|
||||||
className = classDef->next()->str();
|
className = classDef->next()->str();
|
||||||
access = Public;
|
|
||||||
} else if (classDef->str() == "namespace") {
|
} else if (classDef->str() == "namespace") {
|
||||||
type = Scope::eNamespace;
|
type = Scope::eNamespace;
|
||||||
className = classDef->next()->str();
|
className = classDef->next()->str();
|
||||||
access = Public;
|
|
||||||
} else {
|
} else {
|
||||||
type = Scope::eFunction;
|
type = Scope::eFunction;
|
||||||
className = classDef->str();
|
className = classDef->str();
|
||||||
access = Public;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2044,24 +2041,26 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
|
||||||
return NULL != vartok;
|
return NULL != vartok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scope::findClosingBracket(const Token* tok, const Token*& close) const
|
bool Scope::findClosingBracket(const Token* tok, const Token*& close)
|
||||||
{
|
{
|
||||||
bool found = false;
|
|
||||||
if (NULL != tok && tok->str() == "<") {
|
if (NULL != tok && tok->str() == "<") {
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
for (close = tok; (close != NULL) && (close->str() != ";") && (close->str() != "="); close = close->next()) {
|
for (close = tok; close != NULL; close = close->next()) {
|
||||||
if (close->str() == "<") {
|
if (close->str() == "{" || close->str() == "[" || close->str() == "(")
|
||||||
|
close = close->link();
|
||||||
|
else if (close->str() == "}" || close->str() == "]" || close->str() == ")" || close->str() == ";" || close->str() == "=")
|
||||||
|
return false;
|
||||||
|
else if (close->str() == "<") {
|
||||||
++depth;
|
++depth;
|
||||||
} else if (close->str() == ">") {
|
} else if (close->str() == ">") {
|
||||||
if (--depth == 0) {
|
if (--depth == 0) {
|
||||||
found = true;
|
return true;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -409,6 +409,8 @@ public:
|
||||||
Scope *functionScope; // scope of function body
|
Scope *functionScope; // scope of function body
|
||||||
std::list<Variable> argumentList; // argument list
|
std::list<Variable> argumentList; // argument list
|
||||||
|
|
||||||
|
static bool argsMatch(const Scope *info, const Token *first, const Token *second, const std::string &path, unsigned int depth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isImplicitlyVirtual_rec(const Scope* scope, bool& safe) const;
|
bool isImplicitlyVirtual_rec(const Scope* scope, bool& safe) const;
|
||||||
};
|
};
|
||||||
|
@ -448,7 +450,6 @@ public:
|
||||||
std::list<FriendInfo> friendList;
|
std::list<FriendInfo> friendList;
|
||||||
Scope *nestedIn;
|
Scope *nestedIn;
|
||||||
std::list<Scope *> nestedList;
|
std::list<Scope *> nestedList;
|
||||||
AccessControl access;
|
|
||||||
unsigned int numConstructors;
|
unsigned int numConstructors;
|
||||||
NeedInitialization needInitialization;
|
NeedInitialization needInitialization;
|
||||||
std::list<const Token *> usingList;
|
std::list<const Token *> usingList;
|
||||||
|
@ -524,6 +525,7 @@ public:
|
||||||
*/
|
*/
|
||||||
const Variable *getVariable(const std::string &varname) const;
|
const Variable *getVariable(const std::string &varname) const;
|
||||||
|
|
||||||
|
static bool findClosingBracket(const Token* tok, const Token*& close);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief helper function for getVariableList()
|
* @brief helper function for getVariableList()
|
||||||
|
@ -535,7 +537,6 @@ private:
|
||||||
* @return true if tok points to a variable declaration, false otherwise
|
* @return true if tok points to a variable declaration, false otherwise
|
||||||
*/
|
*/
|
||||||
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer, bool &isReference) const;
|
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray, bool &isPointer, bool &isReference) const;
|
||||||
bool findClosingBracket(const Token* tok, const Token*& close) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SymbolDatabase {
|
class SymbolDatabase {
|
||||||
|
@ -559,8 +560,6 @@ public:
|
||||||
|
|
||||||
const Scope* findScopeByName(const std::string& name) const;
|
const Scope* findScopeByName(const std::string& name) const;
|
||||||
|
|
||||||
static bool argsMatch(const Scope *info, const Token *first, const Token *second, const std::string &path, unsigned int depth);
|
|
||||||
|
|
||||||
bool isClassOrStruct(const std::string &type) const {
|
bool isClassOrStruct(const std::string &type) const {
|
||||||
return bool(classAndStructTypes.find(type) != classAndStructTypes.end());
|
return bool(classAndStructTypes.find(type) != classAndStructTypes.end());
|
||||||
}
|
}
|
||||||
|
|
|
@ -492,6 +492,9 @@ private:
|
||||||
givenACodeSampleToTokenize var("X < (2 < 1) > x1;\n");
|
givenACodeSampleToTokenize var("X < (2 < 1) > x1;\n");
|
||||||
|
|
||||||
found = si.findClosingBracket(var.tokens()->next(), t);
|
found = si.findClosingBracket(var.tokens()->next(), t);
|
||||||
|
ASSERT(found);
|
||||||
|
|
||||||
|
found = si.findClosingBracket(var.tokens()->tokAt(4), t);
|
||||||
ASSERT(!found);
|
ASSERT(!found);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue