SymbolDatabase: Removed redundant 'else'
This commit is contained in:
parent
b7321e8dde
commit
7bdd001a5f
|
@ -337,490 +337,488 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
|
|||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
else {
|
||||
// check for end of scope
|
||||
if (tok == scope->classEnd) {
|
||||
access.erase(scope);
|
||||
scope = const_cast<Scope*>(scope->nestedIn);
|
||||
continue;
|
||||
// check for end of scope
|
||||
else if (tok == scope->classEnd) {
|
||||
access.erase(scope);
|
||||
scope = const_cast<Scope*>(scope->nestedIn);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if in class or structure
|
||||
else if (scope->type == Scope::eClass || scope->type == Scope::eStruct) {
|
||||
const Token *funcStart = nullptr;
|
||||
const Token *argStart = nullptr;
|
||||
const Token *declEnd = nullptr;
|
||||
|
||||
// What section are we in..
|
||||
if (tok->str() == "private:")
|
||||
access[scope] = Private;
|
||||
else if (tok->str() == "protected:")
|
||||
access[scope] = Protected;
|
||||
else if (tok->str() == "public:" || tok->str() == "__published:")
|
||||
access[scope] = Public;
|
||||
else if (Token::Match(tok, "public|protected|private %name% :")) {
|
||||
if (tok->str() == "private")
|
||||
access[scope] = Private;
|
||||
else if (tok->str() == "protected")
|
||||
access[scope] = Protected;
|
||||
else
|
||||
access[scope] = Public;
|
||||
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
// check if in class or structure
|
||||
else if (scope->type == Scope::eClass || scope->type == Scope::eStruct) {
|
||||
const Token *funcStart = nullptr;
|
||||
const Token *argStart = nullptr;
|
||||
const Token *declEnd = nullptr;
|
||||
// class function?
|
||||
else if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
|
||||
if (tok->previous()->str() != "::" || tok->strAt(-2) == scope->className) {
|
||||
Function function;
|
||||
|
||||
// What section are we in..
|
||||
if (tok->str() == "private:")
|
||||
access[scope] = Private;
|
||||
else if (tok->str() == "protected:")
|
||||
access[scope] = Protected;
|
||||
else if (tok->str() == "public:" || tok->str() == "__published:")
|
||||
access[scope] = Public;
|
||||
else if (Token::Match(tok, "public|protected|private %name% :")) {
|
||||
if (tok->str() == "private")
|
||||
access[scope] = Private;
|
||||
else if (tok->str() == "protected")
|
||||
access[scope] = Protected;
|
||||
else
|
||||
access[scope] = Public;
|
||||
// save the function definition argument start '('
|
||||
function.argDef = argStart;
|
||||
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
// save the access type
|
||||
function.access = access[scope];
|
||||
|
||||
// class function?
|
||||
else if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
|
||||
if (tok->previous()->str() != "::" || tok->strAt(-2) == scope->className) {
|
||||
Function function;
|
||||
// save the function name location
|
||||
function.tokenDef = funcStart;
|
||||
|
||||
// save the function definition argument start '('
|
||||
function.argDef = argStart;
|
||||
// save the function parent scope
|
||||
function.nestedIn = scope;
|
||||
|
||||
// save the access type
|
||||
function.access = access[scope];
|
||||
// operator function
|
||||
if (function.tokenDef->isOperatorKeyword()) {
|
||||
function.isOperator(true);
|
||||
|
||||
// save the function name location
|
||||
function.tokenDef = funcStart;
|
||||
// 'operator =' is special
|
||||
if (function.tokenDef->str() == "operator=")
|
||||
function.type = Function::eOperatorEqual;
|
||||
}
|
||||
|
||||
// save the function parent scope
|
||||
function.nestedIn = scope;
|
||||
// class constructor/destructor
|
||||
else if (function.tokenDef->str() == scope->className) {
|
||||
// destructor
|
||||
if (function.tokenDef->previous()->str() == "~")
|
||||
function.type = Function::eDestructor;
|
||||
|
||||
// operator function
|
||||
if (function.tokenDef->isOperatorKeyword()) {
|
||||
function.isOperator(true);
|
||||
|
||||
// 'operator =' is special
|
||||
if (function.tokenDef->str() == "operator=")
|
||||
function.type = Function::eOperatorEqual;
|
||||
}
|
||||
|
||||
// class constructor/destructor
|
||||
else if (function.tokenDef->str() == scope->className) {
|
||||
// destructor
|
||||
if (function.tokenDef->previous()->str() == "~")
|
||||
function.type = Function::eDestructor;
|
||||
|
||||
// copy/move constructor?
|
||||
else if (Token::Match(function.tokenDef, "%name% ( const| %name% &|&& &| %name%| )") ||
|
||||
Token::Match(function.tokenDef, "%name% ( const| %name% <")) {
|
||||
const Token* typeTok = function.tokenDef->tokAt(2);
|
||||
if (typeTok->str() == "const")
|
||||
typeTok = typeTok->next();
|
||||
if (typeTok->strAt(1) == "<") { // TODO: Remove this branch (#4710)
|
||||
if (Token::Match(typeTok->linkAt(1), "> & %name%| )"))
|
||||
function.type = Function::eCopyConstructor;
|
||||
else if (Token::Match(typeTok->linkAt(1), "> &&|& & %name%| )"))
|
||||
function.type = Function::eMoveConstructor;
|
||||
else
|
||||
function.type = Function::eConstructor;
|
||||
} else if (typeTok->strAt(1) == "&&" || typeTok->strAt(2) == "&")
|
||||
// copy/move constructor?
|
||||
else if (Token::Match(function.tokenDef, "%name% ( const| %name% &|&& &| %name%| )") ||
|
||||
Token::Match(function.tokenDef, "%name% ( const| %name% <")) {
|
||||
const Token* typeTok = function.tokenDef->tokAt(2);
|
||||
if (typeTok->str() == "const")
|
||||
typeTok = typeTok->next();
|
||||
if (typeTok->strAt(1) == "<") { // TODO: Remove this branch (#4710)
|
||||
if (Token::Match(typeTok->linkAt(1), "> & %name%| )"))
|
||||
function.type = Function::eCopyConstructor;
|
||||
else if (Token::Match(typeTok->linkAt(1), "> &&|& & %name%| )"))
|
||||
function.type = Function::eMoveConstructor;
|
||||
else
|
||||
function.type = Function::eCopyConstructor;
|
||||
|
||||
if (typeTok->str() != function.tokenDef->str())
|
||||
function.type = Function::eConstructor; // Overwrite, if types are not identical
|
||||
}
|
||||
// regular constructor
|
||||
function.type = Function::eConstructor;
|
||||
} else if (typeTok->strAt(1) == "&&" || typeTok->strAt(2) == "&")
|
||||
function.type = Function::eMoveConstructor;
|
||||
else
|
||||
function.type = Function::eConstructor;
|
||||
function.type = Function::eCopyConstructor;
|
||||
|
||||
if (function.tokenDef->previous()->str() == "explicit")
|
||||
function.isExplicit(true);
|
||||
if (typeTok->str() != function.tokenDef->str())
|
||||
function.type = Function::eConstructor; // Overwrite, if types are not identical
|
||||
}
|
||||
// regular constructor
|
||||
else
|
||||
function.type = Function::eConstructor;
|
||||
|
||||
if (function.tokenDef->previous()->str() == "explicit")
|
||||
function.isExplicit(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok;
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) {
|
||||
// virtual function
|
||||
if (tok1->previous()->str() == "virtual") {
|
||||
function.isVirtual(true);
|
||||
break;
|
||||
}
|
||||
|
||||
const Token *tok1 = tok;
|
||||
// static function
|
||||
else if (tok1->previous()->str() == "static") {
|
||||
function.isStatic(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// friend function
|
||||
else if (tok1->previous()->str() == "friend") {
|
||||
function.isFriend(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
|
||||
// find the return type
|
||||
if (!function.isConstructor() && !function.isDestructor()) {
|
||||
if (argStart->link()->strAt(1) == ".") // Trailing return type
|
||||
function.retDef = argStart->link()->tokAt(2);
|
||||
else {
|
||||
while (tok1 && Token::Match(tok1->next(), "virtual|static|friend|const|struct|union|enum"))
|
||||
tok1 = tok1->next();
|
||||
|
||||
if (tok1)
|
||||
function.retDef = tok1;
|
||||
}
|
||||
}
|
||||
|
||||
const Token *end = function.argDef->link();
|
||||
|
||||
// const function
|
||||
if (end->next()->str() == "const")
|
||||
function.isConst(true);
|
||||
|
||||
// count the number of constructors
|
||||
if (function.isConstructor())
|
||||
scope->numConstructors++;
|
||||
if (function.type == Function::eCopyConstructor ||
|
||||
function.type == Function::eMoveConstructor)
|
||||
scope->numCopyOrMoveConstructors++;
|
||||
|
||||
// assume implementation is inline (definition and implementation same)
|
||||
function.token = function.tokenDef;
|
||||
function.arg = function.argDef;
|
||||
|
||||
// out of line function
|
||||
if (_tokenizer->isFunctionHead(end, ";")) {
|
||||
// find the function implementation later
|
||||
tok = end->next();
|
||||
|
||||
if (tok->str() == "const")
|
||||
tok = tok->next();
|
||||
|
||||
if (tok->str() == "&") {
|
||||
function.hasLvalRefQualifier(true);
|
||||
tok = tok->next();
|
||||
} else if (tok->str() == "&&") {
|
||||
function.hasRvalRefQualifier(true);
|
||||
tok = tok->next();
|
||||
} else if (tok->str() == "noexcept") {
|
||||
function.isNoExcept(!Token::simpleMatch(tok->next(), "( false )"));
|
||||
tok = tok->next();
|
||||
if (tok->str() == "(")
|
||||
tok = tok->link()->next();
|
||||
} else if (Token::simpleMatch(tok, "throw (")) {
|
||||
function.isThrow(true);
|
||||
if (tok->strAt(2) != ")")
|
||||
function.throwArg = end->tokAt(2);
|
||||
tok = tok->linkAt(1)->next();
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "= %any% ;")) {
|
||||
function.isPure(tok->strAt(1) == "0");
|
||||
function.isDefault(tok->strAt(1) == "default");
|
||||
function.isDelete(tok->strAt(1) == "delete");
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
// skip over unknown tokens
|
||||
while (tok && tok->str() != ";")
|
||||
tok = tok->next();
|
||||
|
||||
scope->addFunction(function);
|
||||
}
|
||||
|
||||
// inline function
|
||||
else {
|
||||
function.isInline(true);
|
||||
function.hasBody(true);
|
||||
|
||||
if (Token::Match(end, ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
|
||||
if (end->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (end->strAt(arg) == "(")
|
||||
function.noexceptArg = end->tokAt(arg + 1);
|
||||
|
||||
function.isNoExcept(true);
|
||||
} else if (Token::Match(end, ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
if (end->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (end->strAt(arg) != ")")
|
||||
function.throwArg = end->tokAt(arg);
|
||||
|
||||
function.isThrow(true);
|
||||
} else if (Token::Match(end, ") const| &|&&| [;{]")) {
|
||||
int arg = 1;
|
||||
|
||||
if (end->strAt(arg) == "const")
|
||||
arg++;
|
||||
|
||||
if (end->strAt(arg) == "&")
|
||||
function.hasLvalRefQualifier(true);
|
||||
else if (end->strAt(arg) == "&&")
|
||||
function.hasRvalRefQualifier(true);
|
||||
}
|
||||
|
||||
// find start of function '{'
|
||||
bool foundInitList = false;
|
||||
while (end && end->str() != "{" && end->str() != ";") {
|
||||
if (end->link() && Token::Match(end, "(|<")) {
|
||||
end = end->link();
|
||||
} else if (foundInitList &&
|
||||
Token::Match(end, "%name%|> {") &&
|
||||
Token::Match(end->linkAt(1), "} ,|{")) {
|
||||
end = end->linkAt(1);
|
||||
} else {
|
||||
if (end->str() == ":")
|
||||
foundInitList = true;
|
||||
end = end->next();
|
||||
}
|
||||
}
|
||||
|
||||
if (!end || end->str() == ";")
|
||||
continue;
|
||||
|
||||
scope->addFunction(function);
|
||||
|
||||
Function* funcptr = &scope->functionList.back();
|
||||
const Token *tok2 = funcStart;
|
||||
|
||||
addNewFunction(&scope, &tok2);
|
||||
if (scope) {
|
||||
scope->functionOf = function.nestedIn;
|
||||
scope->function = funcptr;
|
||||
scope->function->functionScope = scope;
|
||||
}
|
||||
|
||||
tok = tok2;
|
||||
}
|
||||
}
|
||||
|
||||
// nested class or friend function?
|
||||
else {
|
||||
/** @todo check entire qualification for match */
|
||||
Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2));
|
||||
|
||||
if (nested)
|
||||
addClassFunction(&scope, &tok, argStart);
|
||||
else {
|
||||
/** @todo handle friend functions */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// friend class declaration?
|
||||
else if (_tokenizer->isCPP() && Token::Match(tok, "friend class| ::| %any% ;|::")) {
|
||||
Type::FriendInfo friendInfo;
|
||||
|
||||
// save the name start
|
||||
friendInfo.nameStart = tok->strAt(1) == "class" ? tok->tokAt(2) : tok->next();
|
||||
friendInfo.nameEnd = friendInfo.nameStart;
|
||||
|
||||
// skip leading "::"
|
||||
if (friendInfo.nameEnd->str() == "::")
|
||||
friendInfo.nameEnd = friendInfo.nameEnd->next();
|
||||
|
||||
// skip qualification "name ::"
|
||||
while (friendInfo.nameEnd && friendInfo.nameEnd->strAt(1) == "::")
|
||||
friendInfo.nameEnd = friendInfo.nameEnd->tokAt(2);
|
||||
|
||||
// save the name
|
||||
if (friendInfo.nameEnd)
|
||||
friendInfo.name = friendInfo.nameEnd->str();
|
||||
|
||||
// fill this in after parsing is complete
|
||||
friendInfo.type = 0;
|
||||
|
||||
if (!scope->definedType)
|
||||
_tokenizer->syntaxError(tok);
|
||||
|
||||
scope->definedType->friendList.push_back(friendInfo);
|
||||
}
|
||||
} else if (scope->type == Scope::eNamespace || scope->type == Scope::eGlobal) {
|
||||
const Token *funcStart = nullptr;
|
||||
const Token *argStart = nullptr;
|
||||
const Token *declEnd = nullptr;
|
||||
|
||||
// function?
|
||||
if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
|
||||
// has body?
|
||||
if (declEnd && declEnd->str() == "{") {
|
||||
tok = funcStart;
|
||||
|
||||
// class function
|
||||
if (tok->previous() && tok->previous()->str() == "::")
|
||||
addClassFunction(&scope, &tok, argStart);
|
||||
|
||||
// class destructor
|
||||
else if (tok->previous() &&
|
||||
tok->previous()->str() == "~" &&
|
||||
tok->strAt(-2) == "::")
|
||||
addClassFunction(&scope, &tok, argStart);
|
||||
|
||||
// regular function
|
||||
else {
|
||||
Function* function = addGlobalFunction(scope, tok, argStart, funcStart);
|
||||
|
||||
if (!function)
|
||||
_tokenizer->syntaxError(tok);
|
||||
|
||||
// global functions can't be const but we have tests that are
|
||||
if (Token::Match(argStart->link(), ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (argStart->link()->strAt(arg) == "(")
|
||||
function->noexceptArg = argStart->link()->tokAt(arg + 1);
|
||||
|
||||
function->isNoExcept(true);
|
||||
} else if (Token::Match(argStart->link(), ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (argStart->link()->strAt(arg) != ")")
|
||||
function->throwArg = argStart->link()->tokAt(arg);
|
||||
|
||||
function->isThrow(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok->previous();
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) {
|
||||
// virtual function
|
||||
if (tok1->previous()->str() == "virtual") {
|
||||
function.isVirtual(true);
|
||||
break;
|
||||
}
|
||||
|
||||
while (tok1 && !Token::Match(tok1, ";|}|{")) {
|
||||
// static function
|
||||
else if (tok1->previous()->str() == "static") {
|
||||
function.isStatic(true);
|
||||
if (tok1->str() == "static") {
|
||||
function->isStaticLocal(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// friend function
|
||||
else if (tok1->previous()->str() == "friend") {
|
||||
function.isFriend(true);
|
||||
// extern function
|
||||
else if (tok1->str() == "extern") {
|
||||
function->isExtern(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
|
||||
// find the return type
|
||||
if (!function.isConstructor() && !function.isDestructor()) {
|
||||
if (argStart->link()->strAt(1) == ".") // Trailing return type
|
||||
function.retDef = argStart->link()->tokAt(2);
|
||||
else {
|
||||
while (tok1 && Token::Match(tok1->next(), "virtual|static|friend|const|struct|union|enum"))
|
||||
tok1 = tok1->next();
|
||||
|
||||
if (tok1)
|
||||
function.retDef = tok1;
|
||||
}
|
||||
}
|
||||
|
||||
const Token *end = function.argDef->link();
|
||||
|
||||
// const function
|
||||
if (end->next()->str() == "const")
|
||||
function.isConst(true);
|
||||
|
||||
// count the number of constructors
|
||||
if (function.isConstructor())
|
||||
scope->numConstructors++;
|
||||
if (function.type == Function::eCopyConstructor ||
|
||||
function.type == Function::eMoveConstructor)
|
||||
scope->numCopyOrMoveConstructors++;
|
||||
|
||||
// assume implementation is inline (definition and implementation same)
|
||||
function.token = function.tokenDef;
|
||||
function.arg = function.argDef;
|
||||
|
||||
// out of line function
|
||||
if (_tokenizer->isFunctionHead(end, ";")) {
|
||||
// find the function implementation later
|
||||
tok = end->next();
|
||||
|
||||
if (tok->str() == "const")
|
||||
tok = tok->next();
|
||||
|
||||
if (tok->str() == "&") {
|
||||
function.hasLvalRefQualifier(true);
|
||||
tok = tok->next();
|
||||
} else if (tok->str() == "&&") {
|
||||
function.hasRvalRefQualifier(true);
|
||||
tok = tok->next();
|
||||
} else if (tok->str() == "noexcept") {
|
||||
function.isNoExcept(!Token::simpleMatch(tok->next(), "( false )"));
|
||||
tok = tok->next();
|
||||
if (tok->str() == "(")
|
||||
tok = tok->link()->next();
|
||||
} else if (Token::simpleMatch(tok, "throw (")) {
|
||||
function.isThrow(true);
|
||||
if (tok->strAt(2) != ")")
|
||||
function.throwArg = end->tokAt(2);
|
||||
tok = tok->linkAt(1)->next();
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "= %any% ;")) {
|
||||
function.isPure(tok->strAt(1) == "0");
|
||||
function.isDefault(tok->strAt(1) == "default");
|
||||
function.isDelete(tok->strAt(1) == "delete");
|
||||
tok = tok->tokAt(2);
|
||||
}
|
||||
|
||||
// skip over unknown tokens
|
||||
while (tok && tok->str() != ";")
|
||||
tok = tok->next();
|
||||
|
||||
scope->addFunction(function);
|
||||
}
|
||||
|
||||
// inline function
|
||||
else {
|
||||
function.isInline(true);
|
||||
function.hasBody(true);
|
||||
|
||||
if (Token::Match(end, ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
|
||||
if (end->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (end->strAt(arg) == "(")
|
||||
function.noexceptArg = end->tokAt(arg + 1);
|
||||
|
||||
function.isNoExcept(true);
|
||||
} else if (Token::Match(end, ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
if (end->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (end->strAt(arg) != ")")
|
||||
function.throwArg = end->tokAt(arg);
|
||||
|
||||
function.isThrow(true);
|
||||
} else if (Token::Match(end, ") const| &|&&| [;{]")) {
|
||||
int arg = 1;
|
||||
|
||||
if (end->strAt(arg) == "const")
|
||||
arg++;
|
||||
|
||||
if (end->strAt(arg) == "&")
|
||||
function.hasLvalRefQualifier(true);
|
||||
else if (end->strAt(arg) == "&&")
|
||||
function.hasRvalRefQualifier(true);
|
||||
}
|
||||
|
||||
// find start of function '{'
|
||||
bool foundInitList = false;
|
||||
while (end && end->str() != "{" && end->str() != ";") {
|
||||
if (end->link() && Token::Match(end, "(|<")) {
|
||||
end = end->link();
|
||||
} else if (foundInitList &&
|
||||
Token::Match(end, "%name%|> {") &&
|
||||
Token::Match(end->linkAt(1), "} ,|{")) {
|
||||
end = end->linkAt(1);
|
||||
} else {
|
||||
if (end->str() == ":")
|
||||
foundInitList = true;
|
||||
end = end->next();
|
||||
}
|
||||
}
|
||||
|
||||
if (!end || end->str() == ";")
|
||||
continue;
|
||||
|
||||
scope->addFunction(function);
|
||||
|
||||
Function* funcptr = &scope->functionList.back();
|
||||
const Token *tok2 = funcStart;
|
||||
|
||||
addNewFunction(&scope, &tok2);
|
||||
if (scope) {
|
||||
scope->functionOf = function.nestedIn;
|
||||
scope->function = funcptr;
|
||||
scope->function->functionScope = scope;
|
||||
}
|
||||
|
||||
tok = tok2;
|
||||
}
|
||||
}
|
||||
|
||||
// nested class or friend function?
|
||||
else {
|
||||
/** @todo check entire qualification for match */
|
||||
Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2));
|
||||
|
||||
if (nested)
|
||||
addClassFunction(&scope, &tok, argStart);
|
||||
else {
|
||||
/** @todo handle friend functions */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// friend class declaration?
|
||||
else if (_tokenizer->isCPP() && Token::Match(tok, "friend class| ::| %any% ;|::")) {
|
||||
Type::FriendInfo friendInfo;
|
||||
|
||||
// save the name start
|
||||
friendInfo.nameStart = tok->strAt(1) == "class" ? tok->tokAt(2) : tok->next();
|
||||
friendInfo.nameEnd = friendInfo.nameStart;
|
||||
|
||||
// skip leading "::"
|
||||
if (friendInfo.nameEnd->str() == "::")
|
||||
friendInfo.nameEnd = friendInfo.nameEnd->next();
|
||||
|
||||
// skip qualification "name ::"
|
||||
while (friendInfo.nameEnd && friendInfo.nameEnd->strAt(1) == "::")
|
||||
friendInfo.nameEnd = friendInfo.nameEnd->tokAt(2);
|
||||
|
||||
// save the name
|
||||
if (friendInfo.nameEnd)
|
||||
friendInfo.name = friendInfo.nameEnd->str();
|
||||
|
||||
// fill this in after parsing is complete
|
||||
friendInfo.type = 0;
|
||||
|
||||
if (!scope->definedType)
|
||||
// syntax error?
|
||||
if (!scope)
|
||||
_tokenizer->syntaxError(tok);
|
||||
|
||||
scope->definedType->friendList.push_back(friendInfo);
|
||||
}
|
||||
} else if (scope->type == Scope::eNamespace || scope->type == Scope::eGlobal) {
|
||||
const Token *funcStart = nullptr;
|
||||
const Token *argStart = nullptr;
|
||||
const Token *declEnd = nullptr;
|
||||
// function prototype?
|
||||
else if (declEnd && declEnd->str() == ";") {
|
||||
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) {
|
||||
if (Function::argsMatch(scope, i->second->argDef->next(), argStart->next(), "", 0)) {
|
||||
newFunc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// function?
|
||||
if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) {
|
||||
// has body?
|
||||
if (declEnd && declEnd->str() == "{") {
|
||||
tok = funcStart;
|
||||
// save function prototype in database
|
||||
if (newFunc) {
|
||||
Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
|
||||
|
||||
// class function
|
||||
if (tok->previous() && tok->previous()->str() == "::")
|
||||
addClassFunction(&scope, &tok, argStart);
|
||||
if (Token::Match(argStart->link(), ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
|
||||
// class destructor
|
||||
else if (tok->previous() &&
|
||||
tok->previous()->str() == "~" &&
|
||||
tok->strAt(-2) == "::")
|
||||
addClassFunction(&scope, &tok, argStart);
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
// regular function
|
||||
else {
|
||||
Function* function = addGlobalFunction(scope, tok, argStart, funcStart);
|
||||
if (argStart->link()->strAt(arg) == "(")
|
||||
func->noexceptArg = argStart->link()->tokAt(arg + 1);
|
||||
|
||||
if (!function)
|
||||
_tokenizer->syntaxError(tok);
|
||||
func->isNoExcept(true);
|
||||
} else if (Token::Match(argStart->link(), ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
// global functions can't be const but we have tests that are
|
||||
if (Token::Match(argStart->link(), ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
if (argStart->link()->strAt(arg) != ")")
|
||||
func->throwArg = argStart->link()->tokAt(arg);
|
||||
|
||||
if (argStart->link()->strAt(arg) == "(")
|
||||
function->noexceptArg = argStart->link()->tokAt(arg + 1);
|
||||
|
||||
function->isNoExcept(true);
|
||||
} else if (Token::Match(argStart->link(), ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (argStart->link()->strAt(arg) != ")")
|
||||
function->throwArg = argStart->link()->tokAt(arg);
|
||||
|
||||
function->isThrow(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok->previous();
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1 && !Token::Match(tok1, ";|}|{")) {
|
||||
// static function
|
||||
if (tok1->str() == "static") {
|
||||
function->isStaticLocal(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// extern function
|
||||
else if (tok1->str() == "extern") {
|
||||
function->isExtern(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
func->isThrow(true);
|
||||
}
|
||||
|
||||
// syntax error?
|
||||
if (!scope)
|
||||
_tokenizer->syntaxError(tok);
|
||||
}
|
||||
// function prototype?
|
||||
else if (declEnd && declEnd->str() == ";") {
|
||||
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) {
|
||||
if (Function::argsMatch(scope, i->second->argDef->next(), argStart->next(), "", 0)) {
|
||||
newFunc = false;
|
||||
const Token *tok1 = tok->previous();
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1 && !Token::Match(tok1, ";|}|{")) {
|
||||
// extern function
|
||||
if (tok1->str() == "extern") {
|
||||
func->isExtern(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
|
||||
// save function prototype in database
|
||||
if (newFunc) {
|
||||
Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
|
||||
|
||||
if (Token::Match(argStart->link(), ") const| noexcept")) {
|
||||
int arg = 2;
|
||||
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (argStart->link()->strAt(arg) == "(")
|
||||
func->noexceptArg = argStart->link()->tokAt(arg + 1);
|
||||
|
||||
func->isNoExcept(true);
|
||||
} else if (Token::Match(argStart->link(), ") const| throw (")) {
|
||||
int arg = 3;
|
||||
|
||||
if (argStart->link()->strAt(1) == "const")
|
||||
arg++;
|
||||
|
||||
if (argStart->link()->strAt(arg) != ")")
|
||||
func->throwArg = argStart->link()->tokAt(arg);
|
||||
|
||||
func->isThrow(true);
|
||||
}
|
||||
|
||||
const Token *tok1 = tok->previous();
|
||||
|
||||
// look for end of previous statement
|
||||
while (tok1 && !Token::Match(tok1, ";|}|{")) {
|
||||
// extern function
|
||||
if (tok1->str() == "extern") {
|
||||
func->isExtern(true);
|
||||
break;
|
||||
}
|
||||
|
||||
tok1 = tok1->previous();
|
||||
}
|
||||
}
|
||||
|
||||
tok = declEnd;
|
||||
continue;
|
||||
}
|
||||
|
||||
tok = declEnd;
|
||||
continue;
|
||||
}
|
||||
} else if (scope->isExecutable()) {
|
||||
if (Token::Match(tok, "else|try|do {")) {
|
||||
const Token* tok1 = tok->next();
|
||||
if (tok->str() == "else")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eElse, tok1));
|
||||
if (tok->str() == "do")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eDo, tok1));
|
||||
else //if (tok->str() == "try")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eTry, tok1));
|
||||
}
|
||||
} else if (scope->isExecutable()) {
|
||||
if (Token::Match(tok, "else|try|do {")) {
|
||||
const Token* tok1 = tok->next();
|
||||
if (tok->str() == "else")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eElse, tok1));
|
||||
if (tok->str() == "do")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eDo, tok1));
|
||||
else //if (tok->str() == "try")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eTry, tok1));
|
||||
|
||||
tok = tok1;
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
} else if (Token::Match(tok, "if|for|while|catch|switch (") && Token::simpleMatch(tok->next()->link(), ") {")) {
|
||||
const Token *scopeStartTok = tok->next()->link()->next();
|
||||
if (tok->str() == "if")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eIf, scopeStartTok));
|
||||
else if (tok->str() == "for") {
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eFor, scopeStartTok));
|
||||
} else if (tok->str() == "while")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eWhile, scopeStartTok));
|
||||
else if (tok->str() == "catch") {
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eCatch, scopeStartTok));
|
||||
} else // if (tok->str() == "switch")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eSwitch, scopeStartTok));
|
||||
tok = tok1;
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
} else if (Token::Match(tok, "if|for|while|catch|switch (") && Token::simpleMatch(tok->next()->link(), ") {")) {
|
||||
const Token *scopeStartTok = tok->next()->link()->next();
|
||||
if (tok->str() == "if")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eIf, scopeStartTok));
|
||||
else if (tok->str() == "for") {
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eFor, scopeStartTok));
|
||||
} else if (tok->str() == "while")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eWhile, scopeStartTok));
|
||||
else if (tok->str() == "catch") {
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eCatch, scopeStartTok));
|
||||
} else // if (tok->str() == "switch")
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eSwitch, scopeStartTok));
|
||||
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
if (scope->type == Scope::eFor)
|
||||
scope->checkVariable(tok->tokAt(2), Local, &_settings->library); // check for variable declaration and add it to new scope if found
|
||||
else if (scope->type == Scope::eCatch)
|
||||
scope->checkVariable(tok->tokAt(2), Throw, &_settings->library); // check for variable declaration and add it to new scope if found
|
||||
tok = scopeStartTok;
|
||||
} else if (tok->str() == "{") {
|
||||
if (tok->previous()->varId())
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
if (scope->type == Scope::eFor)
|
||||
scope->checkVariable(tok->tokAt(2), Local, &_settings->library); // check for variable declaration and add it to new scope if found
|
||||
else if (scope->type == Scope::eCatch)
|
||||
scope->checkVariable(tok->tokAt(2), Throw, &_settings->library); // check for variable declaration and add it to new scope if found
|
||||
tok = scopeStartTok;
|
||||
} else if (tok->str() == "{") {
|
||||
if (tok->previous()->varId())
|
||||
tok = tok->link();
|
||||
else {
|
||||
const Token* tok2 = tok->previous();
|
||||
while (!Token::Match(tok2, ";|}|{|)"))
|
||||
tok2 = tok2->previous();
|
||||
if (tok2->next() != tok && tok2->strAt(1) != ".")
|
||||
tok2 = nullptr; // No lambda
|
||||
|
||||
if (tok2 && tok2->str() == ")" && tok2->link()->strAt(-1) == "]") {
|
||||
scopeList.push_back(Scope(this, tok2->link()->linkAt(-1), scope, Scope::eLambda, tok));
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
} else if (!Token::Match(tok->previous(), "=|,|(|return") && !(tok->strAt(-1) == ")" && Token::Match(tok->linkAt(-1)->previous(), "=|,|(|return"))) {
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eUnconditional, tok));
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
} else {
|
||||
tok = tok->link();
|
||||
else {
|
||||
const Token* tok2 = tok->previous();
|
||||
while (!Token::Match(tok2, ";|}|{|)"))
|
||||
tok2 = tok2->previous();
|
||||
if (tok2->next() != tok && tok2->strAt(1) != ".")
|
||||
tok2 = nullptr; // No lambda
|
||||
|
||||
if (tok2 && tok2->str() == ")" && tok2->link()->strAt(-1) == "]") {
|
||||
scopeList.push_back(Scope(this, tok2->link()->linkAt(-1), scope, Scope::eLambda, tok));
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
} else if (!Token::Match(tok->previous(), "=|,|(|return") && !(tok->strAt(-1) == ")" && Token::Match(tok->linkAt(-1)->previous(), "=|,|(|return"))) {
|
||||
scopeList.push_back(Scope(this, tok, scope, Scope::eUnconditional, tok));
|
||||
scope->nestedList.push_back(&scopeList.back());
|
||||
scope = &scopeList.back();
|
||||
} else {
|
||||
tok = tok->link();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue