Optimization: Speed up SymbolDatabase creation and Tokenizer::findGarbageCode() by using Token::isKeyword() for pre-checks

This commit is contained in:
PKEuS 2020-05-17 17:32:31 +02:00
parent f6788c0472
commit c155062cf2
2 changed files with 43 additions and 41 deletions

View File

@ -127,11 +127,12 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
"SymbolDatabase",
tok->progressValue());
// Locate next class
if ((mTokenizer->isCPP() && ((Token::Match(tok, "class|struct|union|namespace ::| %name% {|:|::|<") &&
!Token::Match(tok->previous(), "new|friend|const|enum|typedef|mutable|volatile|using|)|(|<")) ||
(Token::Match(tok, "enum class| %name% {") ||
Token::Match(tok, "enum class| %name% : %name% {"))))
|| (mTokenizer->isC() && Token::Match(tok, "struct|union|enum %name% {"))) {
if ((mTokenizer->isCPP() && tok->isKeyword() &&
((Token::Match(tok, "class|struct|union|namespace ::| %name% {|:|::|<") &&
!Token::Match(tok->previous(), "new|friend|const|enum|typedef|mutable|volatile|using|)|(|<")) ||
(Token::Match(tok, "enum class| %name% {") ||
Token::Match(tok, "enum class| %name% : %name% {"))))
|| (mTokenizer->isC() && tok->isKeyword() && Token::Match(tok, "struct|union|enum %name% {"))) {
const Token *tok2 = tok->tokAt(2);
if (tok->strAt(1) == "::")
@ -297,7 +298,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// Namespace and unknown macro (#3854)
else if (mTokenizer->isCPP() &&
else if (mTokenizer->isCPP() && tok->isKeyword() &&
Token::Match(tok, "namespace %name% %type% (") &&
tok->tokAt(2)->isUpperCaseName() &&
Token::simpleMatch(tok->linkAt(3), ") {")) {
@ -325,7 +326,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// forward declaration
else if (Token::Match(tok, "class|struct|union %name% ;") &&
else if (tok->isKeyword() && Token::Match(tok, "class|struct|union %name% ;") &&
tok->strAt(-1) != "friend") {
if (!findType(tok->next(), scope)) {
// fill typeList..
@ -337,7 +338,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// using namespace
else if (mTokenizer->isCPP() && Token::Match(tok, "using namespace ::| %type% ;|::")) {
else if (mTokenizer->isCPP() && tok->isKeyword() && Token::Match(tok, "using namespace ::| %type% ;|::")) {
Scope::UsingInfo using_info;
using_info.start = tok; // save location
@ -357,7 +358,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// using type alias
else if (mTokenizer->isCPP() && Token::Match(tok, "using %name% =")) {
else if (mTokenizer->isCPP() && tok->isKeyword() && Token::Match(tok, "using %name% =")) {
if (tok->strAt(-1) != ">" && !findType(tok->next(), scope)) {
// fill typeList..
typeList.emplace_back(tok, nullptr, scope);
@ -372,7 +373,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// unnamed struct and union
else if (Token::Match(tok, "struct|union {") &&
else if (tok->isKeyword() && Token::Match(tok, "struct|union {") &&
Token::Match(tok->next()->link(), "} *|&| %name% ;|[|=")) {
scopeList.emplace_back(this, tok, scope);
@ -414,9 +415,9 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// anonymous struct, union and namespace
else if ((Token::Match(tok, "struct|union {") &&
Token::simpleMatch(tok->next()->link(), "} ;")) ||
Token::simpleMatch(tok, "namespace {")) {
else if (tok->isKeyword() && ((Token::Match(tok, "struct|union {") &&
Token::simpleMatch(tok->next()->link(), "} ;")) ||
Token::simpleMatch(tok, "namespace {"))) {
scopeList.emplace_back(this, tok, scope);
Scope *new_scope = &scopeList.back();
@ -448,7 +449,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// forward declared enum
else if (Token::Match(tok, "enum class| %name% ;") || Token::Match(tok, "enum class| %name% : %name% ;")) {
else if (tok->isKeyword() && (Token::Match(tok, "enum class| %name% ;") || Token::Match(tok, "enum class| %name% : %name% ;"))) {
typeList.emplace_back(tok, nullptr, scope);
Type* new_type = &typeList.back();
scope->definedTypesMap[new_type->name()] = new_type;
@ -561,7 +562,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
// friend class declaration?
else if (mTokenizer->isCPP() && Token::Match(tok, "friend class| ::| %any% ;|::")) {
else if (mTokenizer->isCPP() && tok->isKeyword() && Token::Match(tok, "friend class| ::| %any% ;|::")) {
Type::FriendInfo friendInfo;
// save the name start
@ -643,7 +644,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
}
}
} else if (scope->isExecutable()) {
if (Token::Match(tok, "else|try|do {")) {
if (tok->isKeyword() && Token::Match(tok, "else|try|do {")) {
const Token* tok1 = tok->next();
if (tok->str() == "else")
scopeList.emplace_back(this, tok, scope, Scope::eElse, tok1);
@ -655,7 +656,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
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(), ") {")) {
} else if (tok->isKeyword() && 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.emplace_back(this, tok, scope, Scope::eIf, scopeStartTok);
@ -1055,7 +1056,7 @@ void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass)
// Set function call pointers
for (const Token* tok = mTokenizer->list.front(); tok != mTokenizer->list.back(); tok = tok->next()) {
if (!tok->function() && tok->varId() == 0 && Token::Match(tok, "%name% (") && !isReservedName(tok->str())) {
if (!tok->function() && tok->varId() == 0 && tok->linkAt(1) && Token::Match(tok, "%name% (") && !isReservedName(tok->str())) {
const Function *function = findFunction(tok);
if (function)
const_cast<Token *>(tok)->function(function);
@ -1575,6 +1576,9 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
}
}
else if (!tok->isName() || !tok->next() || !tok->next()->link())
return false;
// regular function?
else if (Token::Match(tok, "%name% (") && !isReservedName(tok->str()) && tok->previous() &&
(Token::Match(tok->previous(), "%name%|>|&|*|::|~") || // Either a return type or scope qualifier in front of tok
@ -3840,7 +3844,7 @@ void Scope::getVariableList(const Settings* settings)
}
// Is it a nested class or structure?
else if (Token::Match(tok, "class|struct|union|namespace %type% :|{")) {
else if (tok->isKeyword() && Token::Match(tok, "class|struct|union|namespace %type% :|{")) {
tok = tok->tokAt(2);
while (tok && tok->str() != "{")
tok = tok->next();
@ -3850,7 +3854,7 @@ void Scope::getVariableList(const Settings* settings)
continue;
} else
break;
} else if (Token::Match(tok, "struct|union {")) {
} else if (tok->isKeyword() && Token::Match(tok, "struct|union {")) {
if (Token::Match(tok->next()->link(), "} %name% ;|[")) {
tok = tok->next()->link()->tokAt(2);
continue;
@ -3888,7 +3892,7 @@ void Scope::getVariableList(const Settings* settings)
}
// Is it a forward declaration?
else if (Token::Match(tok, "class|struct|union %name% ;")) {
else if (tok->isKeyword() && Token::Match(tok, "class|struct|union %name% ;")) {
tok = tok->tokAt(2);
continue;
}
@ -3898,7 +3902,7 @@ void Scope::getVariableList(const Settings* settings)
continue;
// skip return, goto and delete
else if (Token::Match(tok, "return|delete|goto")) {
else if (tok->isKeyword() && Token::Match(tok, "return|delete|goto")) {
while (tok->next() &&
tok->next()->str() != ";" &&
tok->next()->str() != "}" /* ticket #4994 */) {
@ -3908,7 +3912,7 @@ void Scope::getVariableList(const Settings* settings)
}
// skip case/default
if (Token::Match(tok, "case|default")) {
if (tok->isKeyword() && Token::Match(tok, "case|default")) {
while (tok->next() && !Token::Match(tok->next(), "[:;{}]"))
tok = tok->next();
continue;
@ -3930,18 +3934,18 @@ void Scope::getVariableList(const Settings* settings)
const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, const Settings* settings)
{
// Is it a throw..?
if (Token::Match(tok, "throw %any% (") &&
if (tok->isKeyword() && Token::Match(tok, "throw %any% (") &&
Token::simpleMatch(tok->linkAt(2), ") ;")) {
return tok->linkAt(2);
}
if ((Token::Match(tok, "throw %any% :: %any% (") &&
Token::simpleMatch(tok->linkAt(4), ") ;"))) {
if (tok->isKeyword() && Token::Match(tok, "throw %any% :: %any% (") &&
Token::simpleMatch(tok->linkAt(4), ") ;")) {
return tok->linkAt(4);
}
// friend?
if (Token::Match(tok, "friend %type%") && tok->next()->varId() == 0) {
if (tok->isKeyword() && Token::Match(tok, "friend %type%") && tok->next()->varId() == 0) {
const Token *next = Token::findmatch(tok->tokAt(2), ";|{");
if (next && next->str() == "{")
next = next->link();
@ -3949,14 +3953,14 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, con
}
// skip const|volatile|static|mutable|extern
while (Token::Match(tok, "const|volatile|static|mutable|extern")) {
while (tok->isKeyword() && Token::Match(tok, "const|volatile|static|mutable|extern")) {
tok = tok->next();
}
// the start of the type tokens does not include the above modifiers
const Token *typestart = tok;
if (Token::Match(tok, "class|struct|union|enum")) {
if (tok->isKeyword() && Token::Match(tok, "class|struct|union|enum")) {
tok = tok->next();
}
@ -5875,7 +5879,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
valuetype.sign = ValueType::Sign::SIGNED;
}
setValueType(tok, valuetype);
} else if (tok->str() == "(") {
} else if (tok->link() && tok->str() == "(") {
// cast
if (tok->isCast() && !tok->astOperand2() && Token::Match(tok, "( %name%")) {
ValueType valuetype;
@ -6014,7 +6018,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
setValueType(tok, *tok->variable());
} else if (tok->enumerator()) {
setValueType(tok, *tok->enumerator());
} else if (mIsCpp && tok->str() == "new") {
} else if (tok->isKeyword() && tok->str() == "new") {
const Token *typeTok = tok->next();
if (Token::Match(typeTok, "( std| ::| nothrow )"))
typeTok = typeTok->link()->next();
@ -6053,7 +6057,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
vt.sign = (vt.type == ValueType::Type::CHAR) ? mDefaultSignedness : ValueType::Sign::SIGNED;
}
setValueType(tok, vt);
} else if (tok->str() == "return" && tok->scope()) {
} else if (tok->isKeyword() && tok->str() == "return" && tok->scope()) {
const Scope* fscope = tok->scope();
while (fscope && !fscope->function)
fscope = fscope->nestedIn;

View File

@ -9401,7 +9401,7 @@ void Tokenizer::reportUnknownMacros()
void Tokenizer::findGarbageCode() const
{
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
const std::set<std::string> nonConsecutiveKeywords{ "break",
"continue",
@ -9430,7 +9430,7 @@ void Tokenizer::findGarbageCode() const
}
// UNKNOWN_MACRO(return)
if (Token::Match(tok, "throw|return )") && Token::Match(tok->linkAt(1)->previous(), "%name% ("))
if (tok->isKeyword() && Token::Match(tok, "throw|return )") && Token::Match(tok->linkAt(1)->previous(), "%name% ("))
unknownMacroError(tok->linkAt(1)->previous());
// UNKNOWN_MACRO(return)
@ -9465,7 +9465,7 @@ void Tokenizer::findGarbageCode() const
}
// keyword keyword
if (tok->isName() && nonConsecutiveKeywords.count(tok->str()) != 0) {
if (tok->isKeyword() && nonConsecutiveKeywords.count(tok->str()) != 0) {
if (Token::Match(tok, "%name% %name%") && nonConsecutiveKeywords.count(tok->next()->str()) == 1)
syntaxError(tok);
const Token* prev = tok;
@ -9487,15 +9487,13 @@ void Tokenizer::findGarbageCode() const
"if",
"return",
"switch",
"while"};
if (isCPP()) {
nonGlobalKeywords.insert("try");
nonGlobalKeywords.insert("catch");
}
"while",
"try",
"catch"};
for (const Token *tok = tokens(); tok; tok = tok->next()) {
if (tok->str() == "{")
tok = tok->link();
else if (tok->isName() && nonGlobalKeywords.count(tok->str()) && !Token::Match(tok->tokAt(-2), "operator %str%"))
else if (tok->isKeyword() && nonGlobalKeywords.count(tok->str()) && !Token::Match(tok->tokAt(-2), "operator %str%"))
syntaxError(tok, "keyword '" + tok->str() + "' is not allowed in global scope");
}