Symbol database: add global space and add all global functions and variables to it. Ticket: #2198
This commit is contained in:
parent
3fba8b52c0
commit
27cae2f0d7
|
@ -79,8 +79,8 @@ void CheckClass::constructors()
|
||||||
{
|
{
|
||||||
SymbolDatabase::SpaceInfo *info = *i;
|
SymbolDatabase::SpaceInfo *info = *i;
|
||||||
|
|
||||||
// don't check namespaces
|
// only check classes and structures
|
||||||
if (info->type == SymbolDatabase::SpaceInfo::Namespace || info->type == SymbolDatabase::SpaceInfo::Function)
|
if (!info->isClassOrStruct())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// There are no constructors.
|
// There are no constructors.
|
||||||
|
@ -98,25 +98,25 @@ void CheckClass::constructors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<SymbolDatabase::Func>::const_iterator it;
|
std::list<SymbolDatabase::Func>::const_iterator func;
|
||||||
|
|
||||||
for (it = info->functionList.begin(); it != info->functionList.end(); ++it)
|
for (func = info->functionList.begin(); func != info->functionList.end(); ++func)
|
||||||
{
|
{
|
||||||
if (!it->hasBody || !(it->type == SymbolDatabase::Func::Constructor || it->type == SymbolDatabase::Func::CopyConstructor || it->type == SymbolDatabase::Func::OperatorEqual))
|
if (!func->hasBody || !(func->type == SymbolDatabase::Func::Constructor || func->type == SymbolDatabase::Func::CopyConstructor || func->type == SymbolDatabase::Func::OperatorEqual))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Mark all variables not used
|
// Mark all variables not used
|
||||||
info->clearAllVar();
|
info->clearAllVar();
|
||||||
|
|
||||||
std::list<std::string> callstack;
|
std::list<std::string> callstack;
|
||||||
info->initializeVarList(*it, callstack);
|
info->initializeVarList(*func, callstack);
|
||||||
|
|
||||||
// Check if any variables are uninitialized
|
// Check if any variables are uninitialized
|
||||||
std::list<SymbolDatabase::Var>::const_iterator var;
|
std::list<SymbolDatabase::Var>::const_iterator var;
|
||||||
for (var = info->varlist.begin(); var != info->varlist.end(); ++var)
|
for (var = info->varlist.begin(); var != info->varlist.end(); ++var)
|
||||||
{
|
{
|
||||||
// skip classes for regular constructor
|
// skip classes for regular constructor
|
||||||
if (var->isClass && it->type == SymbolDatabase::Func::Constructor)
|
if (var->isClass && func->type == SymbolDatabase::Func::Constructor)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (var->assign || var->init || var->isStatic)
|
if (var->assign || var->init || var->isStatic)
|
||||||
|
@ -126,13 +126,13 @@ void CheckClass::constructors()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// It's non-static and it's not initialized => error
|
// It's non-static and it's not initialized => error
|
||||||
if (it->type == SymbolDatabase::Func::OperatorEqual)
|
if (func->type == SymbolDatabase::Func::OperatorEqual)
|
||||||
{
|
{
|
||||||
const Token *operStart = 0;
|
const Token *operStart = 0;
|
||||||
if (it->token->str() == "=")
|
if (func->token->str() == "=")
|
||||||
operStart = it->token->tokAt(1);
|
operStart = func->token->tokAt(1);
|
||||||
else
|
else
|
||||||
operStart = it->token->tokAt(3);
|
operStart = func->token->tokAt(3);
|
||||||
|
|
||||||
bool classNameUsed = false;
|
bool classNameUsed = false;
|
||||||
for (const Token *operTok = operStart; operTok != operStart->link(); operTok = operTok->next())
|
for (const Token *operTok = operStart; operTok != operStart->link(); operTok = operTok->next())
|
||||||
|
@ -145,10 +145,10 @@ void CheckClass::constructors()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classNameUsed)
|
if (classNameUsed)
|
||||||
operatorEqVarError(it->token, info->className, var->token->str());
|
operatorEqVarError(func->token, info->className, var->token->str());
|
||||||
}
|
}
|
||||||
else if (it->access != SymbolDatabase::Private)
|
else if (func->access != SymbolDatabase::Private)
|
||||||
uninitVarError(it->token, info->className, var->token->str());
|
uninitVarError(func->token, info->className, var->token->str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,8 +196,8 @@ void CheckClass::privateFunctions()
|
||||||
{
|
{
|
||||||
SymbolDatabase::SpaceInfo *info = *i;
|
SymbolDatabase::SpaceInfo *info = *i;
|
||||||
|
|
||||||
// don't check namespaces
|
// only check classes and structures
|
||||||
if (info->type == SymbolDatabase::SpaceInfo::Namespace || info->type == SymbolDatabase::SpaceInfo::Function)
|
if (!info->isClassOrStruct())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// dont check derived classes
|
// dont check derived classes
|
||||||
|
@ -545,7 +545,8 @@ void CheckClass::operatorEqRetRefThis()
|
||||||
{
|
{
|
||||||
const SymbolDatabase::SpaceInfo *info = *i;
|
const SymbolDatabase::SpaceInfo *info = *i;
|
||||||
|
|
||||||
if (info->type == SymbolDatabase::SpaceInfo::Class || info->type == SymbolDatabase::SpaceInfo::Struct)
|
// only check classes and structures
|
||||||
|
if (info->isClassOrStruct())
|
||||||
{
|
{
|
||||||
std::list<SymbolDatabase::Func>::const_iterator func;
|
std::list<SymbolDatabase::Func>::const_iterator func;
|
||||||
|
|
||||||
|
@ -896,6 +897,10 @@ void CheckClass::checkConst()
|
||||||
{
|
{
|
||||||
SymbolDatabase::SpaceInfo *info = *it;
|
SymbolDatabase::SpaceInfo *info = *it;
|
||||||
|
|
||||||
|
// only check classes and structures
|
||||||
|
if (!info->isClassOrStruct())
|
||||||
|
continue;
|
||||||
|
|
||||||
std::list<SymbolDatabase::Func>::const_iterator func;
|
std::list<SymbolDatabase::Func>::const_iterator func;
|
||||||
|
|
||||||
for (func = info->functionList.begin(); func != info->functionList.end(); ++func)
|
for (func = info->functionList.begin(); func != info->functionList.end(); ++func)
|
||||||
|
@ -905,7 +910,7 @@ void CheckClass::checkConst()
|
||||||
{
|
{
|
||||||
// get last token of return type
|
// get last token of return type
|
||||||
const Token *previous = func->tokenDef->isName() ? func->token->previous() : func->token->tokAt(-2);
|
const Token *previous = func->tokenDef->isName() ? func->token->previous() : func->token->tokAt(-2);
|
||||||
while (previous->str() == "::")
|
while (previous && previous->str() == "::")
|
||||||
previous = previous->tokAt(-2);
|
previous = previous->tokAt(-2);
|
||||||
|
|
||||||
// does the function return a pointer or reference?
|
// does the function return a pointer or reference?
|
||||||
|
@ -970,7 +975,7 @@ void CheckClass::checkConst()
|
||||||
{
|
{
|
||||||
std::string classname = info->className;
|
std::string classname = info->className;
|
||||||
SymbolDatabase::SpaceInfo *nest = info->nestedIn;
|
SymbolDatabase::SpaceInfo *nest = info->nestedIn;
|
||||||
while (nest)
|
while (nest && nest->type != SymbolDatabase::SpaceInfo::Global)
|
||||||
{
|
{
|
||||||
classname = std::string(nest->className + "::" + classname);
|
classname = std::string(nest->className + "::" + classname);
|
||||||
nest = nest->nestedIn;
|
nest = nest->nestedIn;
|
||||||
|
|
|
@ -39,7 +39,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
: _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger)
|
: _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger)
|
||||||
{
|
{
|
||||||
// find all namespaces (class,struct and namespace)
|
// find all namespaces (class,struct and namespace)
|
||||||
SpaceInfo *info = 0;
|
SpaceInfo *info = new SpaceInfo(this, NULL, NULL);
|
||||||
|
spaceInfoList.push_back(info);
|
||||||
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
|
||||||
|
@ -49,7 +50,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
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
|
||||||
if (new_info->type == SpaceInfo::Class || new_info->type == SpaceInfo::Struct)
|
if (new_info->isClassOrStruct())
|
||||||
{
|
{
|
||||||
// goto initial '{'
|
// goto initial '{'
|
||||||
tok2 = initBaseInfo(new_info, tok);
|
tok2 = initBaseInfo(new_info, tok);
|
||||||
|
@ -66,8 +67,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if in space
|
else
|
||||||
else if (info)
|
|
||||||
{
|
{
|
||||||
// check for end of space
|
// check for end of space
|
||||||
if (tok == info->classEnd)
|
if (tok == info->classEnd)
|
||||||
|
@ -241,13 +241,66 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
info->friendList.push_back(friendInfo);
|
info->friendList.push_back(friendInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info->type == SpaceInfo::Namespace)
|
else if (info->type == SpaceInfo::Namespace || info->type == SpaceInfo::Global)
|
||||||
addIfFunction(&info, &tok);
|
{
|
||||||
}
|
const Token *funcStart = 0;
|
||||||
|
const Token *argStart = 0;
|
||||||
|
|
||||||
// not in SpaceInfo
|
// function?
|
||||||
else
|
if (isFunction(tok, &funcStart, &argStart))
|
||||||
addIfFunction(&info, &tok);
|
{
|
||||||
|
// has body?
|
||||||
|
if (Token::Match(argStart->link(), ") const| {|:"))
|
||||||
|
{
|
||||||
|
// class function
|
||||||
|
if (tok->previous() && tok->previous()->str() == "::")
|
||||||
|
addFunction(&info, &tok, argStart);
|
||||||
|
|
||||||
|
// regular function
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Func function;
|
||||||
|
|
||||||
|
// save the function definition argument start '('
|
||||||
|
function.argDef = argStart;
|
||||||
|
|
||||||
|
// save the access type
|
||||||
|
function.access = Public;
|
||||||
|
|
||||||
|
// save the function name location
|
||||||
|
function.tokenDef = funcStart;
|
||||||
|
function.token = funcStart;
|
||||||
|
|
||||||
|
function.isInline = false;
|
||||||
|
function.hasBody = true;
|
||||||
|
function.arg = function.argDef;
|
||||||
|
function.type = Func::Function;
|
||||||
|
|
||||||
|
info->functionList.push_back(function);
|
||||||
|
|
||||||
|
addNewFunction(&info, &tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function returning function pointer with body
|
||||||
|
else if (Token::simpleMatch(argStart->link(), ") ) (") &&
|
||||||
|
Token::Match(argStart->link()->tokAt(2)->link(), ") const| {"))
|
||||||
|
{
|
||||||
|
const Token *tok1 = funcStart;
|
||||||
|
|
||||||
|
// class function
|
||||||
|
if (tok1->previous()->str() == "::")
|
||||||
|
addFunction(&info, &tok1, argStart);
|
||||||
|
|
||||||
|
// regular function
|
||||||
|
else
|
||||||
|
addNewFunction(&info, &tok1);
|
||||||
|
|
||||||
|
tok = tok1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<SpaceInfo *>::iterator it;
|
std::list<SpaceInfo *>::iterator it;
|
||||||
|
@ -440,14 +493,14 @@ bool SymbolDatabase::argsMatch(const Token *first, const Token *second, const st
|
||||||
|
|
||||||
void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Token *argStart)
|
void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Token *argStart)
|
||||||
{
|
{
|
||||||
const Token *tok1 = (*tok)->tokAt(-2);
|
const Token *tok1 = (*tok)->tokAt(-2); // skip class/struct name
|
||||||
int count = 0;
|
int count = 0;
|
||||||
bool added = false;
|
bool added = false;
|
||||||
std::string path;
|
std::string path;
|
||||||
unsigned int path_length = 0;
|
unsigned int path_length = 0;
|
||||||
|
|
||||||
// back up to head of path
|
// back up to head of path
|
||||||
while (tok1->previous() && tok1->previous()->str() == "::")
|
while (tok1 && tok1->previous() && tok1->previous()->str() == "::")
|
||||||
{
|
{
|
||||||
path = tok1->str() + " :: " + path;
|
path = tok1->str() + " :: " + path;
|
||||||
tok1 = tok1->tokAt(-2);
|
tok1 = tok1->tokAt(-2);
|
||||||
|
@ -468,35 +521,28 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke
|
||||||
{
|
{
|
||||||
SpaceInfo *info1 = *it1;
|
SpaceInfo *info1 = *it1;
|
||||||
|
|
||||||
// is this class at global scope?
|
|
||||||
if (*info)
|
|
||||||
{
|
|
||||||
if (!info1->nestedIn)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (info1->nestedIn)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
if (info1->className == tok1->str() &&
|
if (info1->className == tok1->str() && (info1->type != SpaceInfo::Function))
|
||||||
((*info) ? (info1->nestedIn->className == (*info)->className) : true))
|
|
||||||
{
|
{
|
||||||
SpaceInfo *info2 = info1;
|
// do the spaces match (same space) or do their names match (multiple namespaces)
|
||||||
|
if ((*info == info1->nestedIn) || (*info && info1 &&
|
||||||
while (info2 && count > 0)
|
(*info)->className == info1->nestedIn->className && !(*info)->className.empty() &&
|
||||||
|
(*info)->type == info1->nestedIn->type))
|
||||||
{
|
{
|
||||||
count--;
|
SpaceInfo *info2 = info1;
|
||||||
tok1 = tok1->tokAt(2);
|
|
||||||
info2 = info2->findInNestedList(tok1->str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0 && info2)
|
while (info2 && count > 0)
|
||||||
{
|
{
|
||||||
match = true;
|
count--;
|
||||||
info1 = info2;
|
tok1 = tok1->tokAt(2);
|
||||||
|
info2 = info2->findInNestedList(tok1->str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0 && info2)
|
||||||
|
{
|
||||||
|
match = true;
|
||||||
|
info1 = info2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,45 +631,6 @@ void SymbolDatabase::addNewFunction(SymbolDatabase::SpaceInfo **info, const Toke
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDatabase::addIfFunction(SpaceInfo **info, const Token **tok)
|
|
||||||
{
|
|
||||||
const Token *funcStart = 0;
|
|
||||||
const Token *argStart = 0;
|
|
||||||
|
|
||||||
// function?
|
|
||||||
if (isFunction(*tok, &funcStart, &argStart))
|
|
||||||
{
|
|
||||||
// has body?
|
|
||||||
if (Token::Match(argStart->link(), ") const| {|:"))
|
|
||||||
{
|
|
||||||
// class function
|
|
||||||
if ((*tok)->previous() && (*tok)->previous()->str() == "::")
|
|
||||||
addFunction(info, tok, argStart);
|
|
||||||
|
|
||||||
// regular function
|
|
||||||
else
|
|
||||||
addNewFunction(info, tok);
|
|
||||||
}
|
|
||||||
|
|
||||||
// function returning function pointer with body
|
|
||||||
else if (Token::simpleMatch(argStart->link(), ") ) (") &&
|
|
||||||
Token::Match(argStart->link()->tokAt(2)->link(), ") const| {"))
|
|
||||||
{
|
|
||||||
const Token *tok1 = funcStart;
|
|
||||||
|
|
||||||
// class function
|
|
||||||
if (tok1->previous()->str() == "::")
|
|
||||||
addFunction(info, &tok1, argStart);
|
|
||||||
|
|
||||||
// regular function
|
|
||||||
else
|
|
||||||
addNewFunction(info, &tok1);
|
|
||||||
|
|
||||||
*tok = tok1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token *SymbolDatabase::initBaseInfo(SpaceInfo *info, const Token *tok)
|
const Token *SymbolDatabase::initBaseInfo(SpaceInfo *info, const Token *tok)
|
||||||
{
|
{
|
||||||
// goto initial '{'
|
// goto initial '{'
|
||||||
|
@ -697,7 +704,12 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD
|
||||||
nestedIn(nestedIn_),
|
nestedIn(nestedIn_),
|
||||||
numConstructors(0)
|
numConstructors(0)
|
||||||
{
|
{
|
||||||
if (classDef->str() == "class")
|
if (!classDef)
|
||||||
|
{
|
||||||
|
type = SpaceInfo::Global;
|
||||||
|
access = Public;
|
||||||
|
}
|
||||||
|
else if (classDef->str() == "class")
|
||||||
{
|
{
|
||||||
type = SpaceInfo::Class;
|
type = SpaceInfo::Class;
|
||||||
className = classDef->next()->str();
|
className = classDef->next()->str();
|
||||||
|
@ -732,31 +744,48 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD
|
||||||
nestedIn->nestedList.push_back(this);
|
nestedIn->nestedList.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get variable list..
|
||||||
void SymbolDatabase::SpaceInfo::getVarList()
|
void SymbolDatabase::SpaceInfo::getVarList()
|
||||||
{
|
{
|
||||||
// Get variable list..
|
AccessControl varaccess = type == Class ? Private : Public;
|
||||||
unsigned int indentlevel = 0;
|
const Token *start;
|
||||||
AccessControl varaccess = type == Struct ? Public : Private;
|
|
||||||
for (const Token *tok = classStart; tok; tok = tok->next())
|
if (classStart)
|
||||||
|
start = classStart->next();
|
||||||
|
else
|
||||||
|
start = check->_tokenizer->tokens();
|
||||||
|
|
||||||
|
for (const Token *tok = start; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (!tok->next())
|
if (tok->str() == "}")
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (tok->str() == "{")
|
// Is it a function?
|
||||||
++indentlevel;
|
else if (tok->str() == "{")
|
||||||
else if (tok->str() == "}")
|
|
||||||
{
|
{
|
||||||
if (indentlevel <= 1)
|
tok = tok->link();
|
||||||
break;
|
continue;
|
||||||
--indentlevel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indentlevel != 1)
|
// Is it a nested class or structure?
|
||||||
continue;
|
else if (Token::Match(tok, "class|struct|union|namespace %type% :|{"))
|
||||||
|
{
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
while (tok && tok->str() != "{")
|
||||||
|
tok = tok->next();
|
||||||
|
if (tok)
|
||||||
|
{
|
||||||
|
// skip implementation
|
||||||
|
tok = tok->link();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Borland C++: Skip all variables in the __published section.
|
// Borland C++: Skip all variables in the __published section.
|
||||||
// These are automaticly initialized.
|
// These are automaticly initialized.
|
||||||
if (tok->str() == "__published:")
|
else if (tok->str() == "__published:")
|
||||||
{
|
{
|
||||||
for (; tok; tok = tok->next())
|
for (; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
|
@ -772,165 +801,177 @@ void SymbolDatabase::SpaceInfo::getVarList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// "private:" "public:" "protected:" etc
|
// "private:" "public:" "protected:" etc
|
||||||
bool b = false;
|
else if (tok->str() == "public:")
|
||||||
if (tok->str() == "public:")
|
|
||||||
{
|
{
|
||||||
varaccess = Public;
|
varaccess = Public;
|
||||||
b = true;
|
continue;
|
||||||
}
|
}
|
||||||
else if (tok->str() == "protected:")
|
else if (tok->str() == "protected:")
|
||||||
{
|
{
|
||||||
varaccess = Protected;
|
varaccess = Protected;
|
||||||
b = true;
|
continue;
|
||||||
}
|
}
|
||||||
else if (tok->str() == "private:")
|
else if (tok->str() == "private:")
|
||||||
{
|
{
|
||||||
varaccess = Private;
|
varaccess = Private;
|
||||||
b = true;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for start of statement..
|
|
||||||
if (! Token::Match(tok, "[;{}]") && ! b)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This is the start of a statement
|
|
||||||
const Token *next = tok->next();
|
|
||||||
const Token *vartok = 0;
|
|
||||||
|
|
||||||
// If next token contains a ":".. it is not part of a variable declaration
|
|
||||||
if (next->str().find(":") != std::string::npos)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Is it a forward declaration?
|
// Is it a forward declaration?
|
||||||
if (Token::Match(next, "class|struct|union %var% ;"))
|
else if (Token::Match(tok, "class|struct|union %var% ;"))
|
||||||
{
|
{
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// It it a nested class or structure?
|
|
||||||
if (Token::Match(next, "class|struct|union %type% :|{"))
|
|
||||||
{
|
|
||||||
tok = tok->tokAt(2);
|
|
||||||
while (tok->str() != "{")
|
|
||||||
tok = tok->next();
|
|
||||||
// skip implementation
|
|
||||||
tok = tok->link();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Borland C++: Ignore properties..
|
// Borland C++: Ignore properties..
|
||||||
if (next->str() == "__property")
|
else if (tok->str() == "__property")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Search for start of statement..
|
||||||
|
else if (!tok->previous() || !Token::Match(tok->previous(), ";|{|}|public:|protected:|private:"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This is the start of a statement
|
||||||
|
const Token *vartok = 0;
|
||||||
|
|
||||||
// Is it const..?
|
// Is it const..?
|
||||||
bool isConst = false;
|
bool isConst = false;
|
||||||
if (next->str() == "const")
|
if (tok->str() == "const")
|
||||||
{
|
{
|
||||||
next = next->next();
|
tok = tok->next();
|
||||||
isConst = true;
|
isConst = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a static variable?
|
// Is it a static variable?
|
||||||
const bool isStatic(Token::simpleMatch(next, "static"));
|
const bool isStatic(Token::simpleMatch(tok, "static"));
|
||||||
if (isStatic)
|
if (isStatic)
|
||||||
{
|
{
|
||||||
next = next->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a mutable variable?
|
// Is it a mutable variable?
|
||||||
const bool isMutable(Token::simpleMatch(next, "mutable"));
|
const bool isMutable(Token::simpleMatch(tok, "mutable"));
|
||||||
if (isMutable)
|
if (isMutable)
|
||||||
{
|
{
|
||||||
next = next->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it const..?
|
// Is it const..?
|
||||||
if (next->str() == "const")
|
if (tok->str() == "const")
|
||||||
{
|
{
|
||||||
next = next->next();
|
tok = tok->next();
|
||||||
isConst = true;
|
isConst = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a variable declaration?
|
|
||||||
bool isClass = false;
|
bool isClass = false;
|
||||||
if (Token::Match(next, "%type% %var% ;|:"))
|
|
||||||
|
// Is it a variable declaration?
|
||||||
|
if (Token::Match(tok, "%type% %var% ;|:"))
|
||||||
{
|
{
|
||||||
if (!next->isStandardType())
|
if (!tok->isStandardType())
|
||||||
isClass = true;
|
isClass = true;
|
||||||
|
|
||||||
vartok = next->tokAt(1);
|
vartok = tok->tokAt(1);
|
||||||
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
else if (Token::Match(tok, "%type% :: %type% %var% ;"))
|
||||||
|
{
|
||||||
|
isClass = true;
|
||||||
|
vartok = tok->tokAt(3);
|
||||||
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
else if (Token::Match(tok, "%type% :: %type% :: %type% %var% ;"))
|
||||||
|
{
|
||||||
|
isClass = true;
|
||||||
|
vartok = tok->tokAt(5);
|
||||||
|
tok = vartok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Structure?
|
// Structure?
|
||||||
else if (Token::Match(next, "struct|union %type% %var% ;"))
|
else if (Token::Match(tok, "struct|union %type% %var% ;"))
|
||||||
{
|
{
|
||||||
vartok = next->tokAt(2);
|
vartok = tok->tokAt(2);
|
||||||
|
tok = vartok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer?
|
// Pointer?
|
||||||
else if (Token::Match(next, "%type% * %var% ;"))
|
else if (Token::Match(tok, "%type% * %var% ;"))
|
||||||
vartok = next->tokAt(2);
|
{
|
||||||
else if (Token::Match(next, "%type% %type% * %var% ;"))
|
vartok = tok->tokAt(2);
|
||||||
vartok = next->tokAt(3);
|
tok = vartok->next();
|
||||||
else if (Token::Match(next, "%type% :: %type% * %var% ;"))
|
}
|
||||||
vartok = next->tokAt(4);
|
else if (Token::Match(tok, "%type% %type% * %var% ;"))
|
||||||
else if (Token::Match(next, "%type% :: %type% :: %type% * %var% ;"))
|
{
|
||||||
vartok = next->tokAt(6);
|
vartok = tok->tokAt(3);
|
||||||
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
else if (Token::Match(tok, "%type% :: %type% * %var% ;"))
|
||||||
|
{
|
||||||
|
vartok = tok->tokAt(4);
|
||||||
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
else if (Token::Match(tok, "%type% :: %type% :: %type% * %var% ;"))
|
||||||
|
{
|
||||||
|
vartok = tok->tokAt(6);
|
||||||
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
|
||||||
// Array?
|
// Array?
|
||||||
else if (Token::Match(next, "%type% %var% [") && next->next()->str() != "operator")
|
else if (Token::Match(tok, "%type% %var% [") && tok->next()->str() != "operator")
|
||||||
{
|
{
|
||||||
if (!next->isStandardType())
|
if (!tok->isStandardType())
|
||||||
isClass = true;
|
isClass = true;
|
||||||
|
|
||||||
vartok = next->tokAt(1);
|
vartok = tok->tokAt(1);
|
||||||
|
tok = vartok->next()->link()->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer array?
|
// Pointer array?
|
||||||
else if (Token::Match(next, "%type% * %var% ["))
|
else if (Token::Match(tok, "%type% * %var% ["))
|
||||||
vartok = next->tokAt(2);
|
|
||||||
else if (Token::Match(next, "%type% :: %type% * %var% ["))
|
|
||||||
vartok = next->tokAt(4);
|
|
||||||
else if (Token::Match(next, "%type% :: %type% :: %type% * %var% ["))
|
|
||||||
vartok = next->tokAt(6);
|
|
||||||
|
|
||||||
// std::string..
|
|
||||||
else if (Token::Match(next, "%type% :: %type% %var% ;"))
|
|
||||||
{
|
{
|
||||||
isClass = true;
|
vartok = tok->tokAt(2);
|
||||||
vartok = next->tokAt(3);
|
tok = vartok->next();
|
||||||
}
|
}
|
||||||
else if (Token::Match(next, "%type% :: %type% :: %type% %var% ;"))
|
else if (Token::Match(tok, "%type% :: %type% * %var% ["))
|
||||||
{
|
{
|
||||||
isClass = true;
|
vartok = tok->tokAt(4);
|
||||||
vartok = next->tokAt(5);
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
else if (Token::Match(tok, "%type% :: %type% :: %type% * %var% ["))
|
||||||
|
{
|
||||||
|
vartok = tok->tokAt(6);
|
||||||
|
tok = vartok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container..
|
// Container..
|
||||||
else if (Token::Match(next, "%type% :: %type% <") ||
|
else if (Token::Match(tok, "%type% :: %type% <") ||
|
||||||
Token::Match(next, "%type% <"))
|
Token::Match(tok, "%type% <"))
|
||||||
{
|
{
|
||||||
// find matching ">"
|
// find matching ">"
|
||||||
int level = 0;
|
int level = 0;
|
||||||
for (; next; next = next->next())
|
for (; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if (next->str() == "<")
|
if (tok->str() == "<")
|
||||||
level++;
|
level++;
|
||||||
else if (next->str() == ">")
|
else if (tok->str() == ">")
|
||||||
{
|
{
|
||||||
level--;
|
level--;
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (next && Token::Match(next, "> %var% ;"))
|
if (tok && Token::Match(tok, "> %var% ;"))
|
||||||
{
|
{
|
||||||
isClass = true;
|
isClass = true;
|
||||||
vartok = next->tokAt(1);
|
vartok = tok->tokAt(1);
|
||||||
|
tok = vartok->next();
|
||||||
|
}
|
||||||
|
else if (tok && Token::Match(tok, "> * %var% ;"))
|
||||||
|
{
|
||||||
|
vartok = tok->tokAt(2);
|
||||||
|
tok = vartok->next();
|
||||||
}
|
}
|
||||||
else if (next && Token::Match(next, "> * %var% ;"))
|
|
||||||
vartok = next->tokAt(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the vartok was set in the if-blocks above, create a entry for this variable..
|
// If the vartok was set in the if-blocks above, create a entry for this variable..
|
||||||
|
|
|
@ -147,7 +147,7 @@ public:
|
||||||
class SpaceInfo
|
class SpaceInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum SpaceType { Class, Struct, Union, Namespace, Function };
|
enum SpaceType { Global, Class, Struct, Union, Namespace, Function };
|
||||||
|
|
||||||
SpaceInfo(SymbolDatabase *check_, const Token *classDef_, SpaceInfo *nestedIn_);
|
SpaceInfo(SymbolDatabase *check_, const Token *classDef_, SpaceInfo *nestedIn_);
|
||||||
|
|
||||||
|
@ -166,6 +166,11 @@ public:
|
||||||
AccessControl access;
|
AccessControl access;
|
||||||
unsigned int numConstructors;
|
unsigned int numConstructors;
|
||||||
|
|
||||||
|
bool isClassOrStruct() const
|
||||||
|
{
|
||||||
|
return (type == Class || type == Struct);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief find if name is in nested list
|
* @brief find if name is in nested list
|
||||||
* @param name name of nested space
|
* @param name name of nested space
|
||||||
|
@ -237,7 +242,6 @@ public:
|
||||||
private:
|
private:
|
||||||
void addFunction(SpaceInfo **info, const Token **tok, const Token *argStart);
|
void addFunction(SpaceInfo **info, const Token **tok, const Token *argStart);
|
||||||
void addNewFunction(SpaceInfo **info, const Token **tok);
|
void addNewFunction(SpaceInfo **info, const Token **tok);
|
||||||
void addIfFunction(SpaceInfo **info, const Token **tok);
|
|
||||||
|
|
||||||
bool isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const;
|
bool isFunction(const Token *tok, const Token **funcStart, const Token **argStart) const;
|
||||||
bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
|
bool argsMatch(const Token *first, const Token *second, const std::string &path, unsigned int depth) const;
|
||||||
|
|
Loading…
Reference in New Issue