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:
PKEuS 2012-04-18 13:00:34 +02:00
parent 1793bf8928
commit f6fd44910a
3 changed files with 48 additions and 47 deletions

View File

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

View File

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

View File

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