Optimization: Speed up Tokenizer::findGarbageCode() (by 15% in my test case) by avoiding iterating through token list multiple times
This commit is contained in:
parent
a9cea9ad7c
commit
09a30bd6b5
|
@ -9403,18 +9403,24 @@ void Tokenizer::findGarbageCode() const
|
||||||
{
|
{
|
||||||
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
|
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;
|
||||||
|
|
||||||
// initialization: = {
|
const std::set<std::string> nonConsecutiveKeywords{ "break",
|
||||||
|
"continue",
|
||||||
|
"for",
|
||||||
|
"goto",
|
||||||
|
"if",
|
||||||
|
"return",
|
||||||
|
"switch",
|
||||||
|
"throw",
|
||||||
|
"typedef",
|
||||||
|
"while" };
|
||||||
|
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||||
if (!Token::simpleMatch(tok, "= {"))
|
// initialization: = {
|
||||||
continue;
|
if (Token::simpleMatch(tok, "= {") && Token::simpleMatch(tok->linkAt(1), "} ("))
|
||||||
if (Token::simpleMatch(tok->linkAt(1), "} ("))
|
|
||||||
syntaxError(tok->linkAt(1));
|
syntaxError(tok->linkAt(1));
|
||||||
}
|
|
||||||
|
|
||||||
// Inside [] there can't be ; or various keywords
|
// Inside [] there can't be ; or various keywords
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
else if (tok->str() == "[") {
|
||||||
if (tok->str() != "[")
|
|
||||||
continue;
|
|
||||||
for (const Token* inner = tok->next(); inner != tok->link(); inner = inner->next()) {
|
for (const Token* inner = tok->next(); inner != tok->link(); inner = inner->next()) {
|
||||||
if (Token::Match(inner, "(|["))
|
if (Token::Match(inner, "(|["))
|
||||||
inner = inner->link();
|
inner = inner->link();
|
||||||
|
@ -9424,25 +9430,18 @@ void Tokenizer::findGarbageCode() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// UNKNOWN_MACRO(return)
|
// UNKNOWN_MACRO(return)
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
|
||||||
if (Token::Match(tok, "throw|return )") && Token::Match(tok->linkAt(1)->previous(), "%name% ("))
|
if (Token::Match(tok, "throw|return )") && Token::Match(tok->linkAt(1)->previous(), "%name% ("))
|
||||||
unknownMacroError(tok->linkAt(1)->previous());
|
unknownMacroError(tok->linkAt(1)->previous());
|
||||||
}
|
|
||||||
|
|
||||||
// UNKNOWN_MACRO(return)
|
// UNKNOWN_MACRO(return)
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
else if (Token::Match(tok, "%name% throw|return") && std::isupper(tok->str()[0]))
|
||||||
if (Token::Match(tok, "%name% throw|return") && std::isupper(tok->str()[0]))
|
|
||||||
unknownMacroError(tok);
|
unknownMacroError(tok);
|
||||||
}
|
|
||||||
|
|
||||||
// Assign/increment/decrement literal
|
// Assign/increment/decrement literal
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
else if (Token::Match(tok, "!!) %num%|%str%|%char% %assign%|++|--"))
|
||||||
if (Token::Match(tok, "!!) %num%|%str%|%char% %assign%|++|--"))
|
|
||||||
syntaxError(tok, tok->next()->str() + " " + tok->strAt(2));
|
syntaxError(tok, tok->next()->str() + " " + tok->strAt(2));
|
||||||
}
|
|
||||||
|
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
if (tok->isControlFlowKeyword() && Token::Match(tok, "if|while|for|switch")) { // if|while|for|switch (EXPR) { ... }
|
||||||
if (Token::Match(tok, "if|while|for|switch")) { // if|while|for|switch (EXPR) { ... }
|
|
||||||
if (tok->previous() && !Token::Match(tok->previous(), "%name%|:|;|{|}|)")) {
|
if (tok->previous() && !Token::Match(tok->previous(), "%name%|:|;|{|}|)")) {
|
||||||
if (Token::Match(tok->previous(), "[,(]")) {
|
if (Token::Match(tok->previous(), "[,(]")) {
|
||||||
const Token *prev = tok->previous();
|
const Token *prev = tok->previous();
|
||||||
|
@ -9464,6 +9463,20 @@ void Tokenizer::findGarbageCode() const
|
||||||
syntaxError(tok);
|
syntaxError(tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keyword keyword
|
||||||
|
if (tok->isName() && nonConsecutiveKeywords.count(tok->str()) != 0) {
|
||||||
|
if (Token::Match(tok, "%name% %name%") && nonConsecutiveKeywords.count(tok->next()->str()) == 1)
|
||||||
|
syntaxError(tok);
|
||||||
|
const Token* prev = tok;
|
||||||
|
while (prev && prev->isName())
|
||||||
|
prev = prev->previous();
|
||||||
|
if (Token::Match(prev, "%op%|%num%|%str%|%char%")) {
|
||||||
|
if (!Token::simpleMatch(tok->tokAt(-2), "operator \"\" if") &&
|
||||||
|
!Token::simpleMatch(tok->tokAt(-2), "extern \"C\""))
|
||||||
|
syntaxError(tok, prev == tok->previous() ? (prev->str() + " " + tok->str()) : (prev->str() + " .. " + tok->str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keywords in global scope
|
// Keywords in global scope
|
||||||
|
@ -9486,32 +9499,6 @@ void Tokenizer::findGarbageCode() const
|
||||||
syntaxError(tok, "keyword '" + tok->str() + "' is not allowed in global scope");
|
syntaxError(tok, "keyword '" + tok->str() + "' is not allowed in global scope");
|
||||||
}
|
}
|
||||||
|
|
||||||
// keyword keyword
|
|
||||||
const std::set<std::string> nonConsecutiveKeywords{"break",
|
|
||||||
"continue",
|
|
||||||
"for",
|
|
||||||
"goto",
|
|
||||||
"if",
|
|
||||||
"return",
|
|
||||||
"switch",
|
|
||||||
"throw",
|
|
||||||
"typedef",
|
|
||||||
"while"};
|
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
|
||||||
if (!tok->isName() || nonConsecutiveKeywords.count(tok->str()) == 0)
|
|
||||||
continue;
|
|
||||||
if (Token::Match(tok, "%name% %name%") && nonConsecutiveKeywords.count(tok->next()->str()) == 1)
|
|
||||||
syntaxError(tok);
|
|
||||||
const Token *prev = tok;
|
|
||||||
while (prev && prev->isName())
|
|
||||||
prev = prev->previous();
|
|
||||||
if (Token::Match(prev, "%op%|%num%|%str%|%char%")) {
|
|
||||||
if (!Token::simpleMatch(tok->tokAt(-2), "operator \"\" if") &&
|
|
||||||
!Token::simpleMatch(tok->tokAt(-2), "extern \"C\""))
|
|
||||||
syntaxError(tok, prev == tok->previous() ? (prev->str() + " " + tok->str()) : (prev->str() + " .. " + tok->str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// case keyword must be inside switch
|
// case keyword must be inside switch
|
||||||
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "switch (")) {
|
if (Token::simpleMatch(tok, "switch (")) {
|
||||||
|
|
Loading…
Reference in New Issue