Optimize Tokenizer::setVarIdPass1

This commit is contained in:
Daniel Marjamäki 2018-05-29 18:41:05 +02:00
parent 5861a3844a
commit 14e60210c9
2 changed files with 107 additions and 38 deletions

View File

@ -2387,7 +2387,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
static void setVarIdStructMembers(Token **tok1,
std::map<unsigned int, std::map<std::string, unsigned int> >& structMembers,
unsigned int *_varId)
unsigned int *varId)
{
Token *tok = *tok1;
@ -2406,8 +2406,8 @@ static void setVarIdStructMembers(Token **tok1,
tok = tok->next();
const std::map<std::string, unsigned int>::iterator it = members.find(tok->str());
if (it == members.end()) {
members[tok->str()] = ++(*_varId);
tok->varId(*_varId);
members[tok->str()] = ++(*varId);
tok->varId(*varId);
} else {
tok->varId(it->second);
}
@ -2431,8 +2431,8 @@ static void setVarIdStructMembers(Token **tok1,
std::map<std::string, unsigned int>& members = structMembers[struct_varid];
const std::map<std::string, unsigned int>::iterator it = members.find(tok->str());
if (it == members.end()) {
members[tok->str()] = ++(*_varId);
tok->varId(*_varId);
members[tok->str()] = ++(*varId);
tok->varId(*varId);
} else {
tok->varId(it->second);
}
@ -2443,7 +2443,7 @@ static void setVarIdStructMembers(Token **tok1,
void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
const std::map<std::string, unsigned int> &variableId,
const VariableMap &variableMap,
const unsigned int scopeStartVarId,
std::map<unsigned int, std::map<std::string,unsigned int> >& structMembers)
{
@ -2486,8 +2486,8 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
--indentlevel;
inEnum = false;
} else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
if (it != variableId.end()) {
const std::map<std::string, unsigned int>::const_iterator it = variableMap.find(tok->str());
if (it != variableMap.end()) {
tok->varId(it->second);
}
} else if (tok->isName() && tok->varId() <= scopeStartVarId) {
@ -2504,10 +2504,10 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
}
if (!inEnum) {
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
if (it != variableId.end()) {
const std::map<std::string, unsigned int>::const_iterator it = variableMap.find(tok->str());
if (it != variableMap.end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, &_varId);
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
}
}
}
@ -2575,11 +2575,8 @@ void Tokenizer::setVarIdPass1()
// Variable declarations can't start with "return" etc.
const std::set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp;
// variable id
_varId = 0;
std::map<std::string, unsigned int> variableId;
VariableMap variableMap;
std::map<unsigned int, std::map<std::string, unsigned int> > structMembers;
std::stack< std::map<std::string, unsigned int> > scopeInfo;
std::stack<VarIdScopeInfo> scopeStack;
@ -2597,12 +2594,10 @@ void Tokenizer::setVarIdPass1()
if (tok->str() == ":")
initlist = true;
else if (tok->str() == ";") {
if (scopeInfo.empty())
if (!variableMap.leaveScope())
cppcheckError(tok);
variableId.swap(scopeInfo.top());
scopeInfo.pop();
} else if (tok->str() == "{")
scopeStack.push(VarIdScopeInfo(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/false, _varId));
scopeStack.push(VarIdScopeInfo(true, scopeStack.top().isStructInit || tok->strAt(-1) == "=", /*isEnum=*/false, *variableMap.getVarId()));
} else if (!initlist && tok->str()=="(") {
const Token * newFunctionDeclEnd = nullptr;
if (!scopeStack.top().isExecutable)
@ -2615,7 +2610,7 @@ void Tokenizer::setVarIdPass1()
if (newFunctionDeclEnd && newFunctionDeclEnd != functionDeclEndToken) {
functionDeclEndStack.push(newFunctionDeclEnd);
functionDeclEndToken = newFunctionDeclEnd;
scopeInfo.push(variableId);
variableMap.enterScope();
}
} else if (Token::Match(tok, "{|}")) {
inlineFunction = false;
@ -2635,10 +2630,10 @@ void Tokenizer::setVarIdPass1()
isExecutable = ((scopeStack.top().isExecutable || initlist || tok->strAt(-1) == "else") &&
!isClassStructUnionEnumStart(tok));
if (!(scopeStack.top().isStructInit || tok->strAt(-1) == "="))
scopeInfo.push(variableId);
variableMap.enterScope();
}
initlist = false;
scopeStack.push(VarIdScopeInfo(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", isEnumStart(tok), _varId));
scopeStack.push(VarIdScopeInfo(isExecutable, scopeStack.top().isStructInit || tok->strAt(-1) == "=", isEnumStart(tok), *variableMap.getVarId()));
} else { /* if (tok->str() == "}") */
bool isNamespace = false;
for (const Token *tok1 = tok->link()->previous(); tok1 && tok1->isName(); tok1 = tok1->previous()) {
@ -2650,18 +2645,13 @@ void Tokenizer::setVarIdPass1()
// Set variable ids in class declaration..
if (!initlist && !isC() && !scopeStack.top().isExecutable && tok->link() && !isNamespace) {
setVarIdClassDeclaration(tok->link(),
variableId,
variableMap,
scopeStack.top().startVarid,
structMembers);
}
if (!scopeStack.top().isStructInit) {
if (scopeInfo.empty()) {
variableId.clear();
} else {
variableId.swap(scopeInfo.top());
scopeInfo.pop();
}
variableMap.leaveScope();
}
scopeStack.pop();
@ -2707,7 +2697,7 @@ void Tokenizer::setVarIdPass1()
bool decl;
try { /* Ticket #8151 */
decl = setVarIdParseDeclaration(&tok2, variableId, scopeStack.top().isExecutable, isCPP(), isC());
decl = setVarIdParseDeclaration(&tok2, variableMap.map(), scopeStack.top().isExecutable, isCPP(), isC());
} catch (const Token * errTok) {
syntaxError(errTok);
}
@ -2747,7 +2737,7 @@ void Tokenizer::setVarIdPass1()
continue;
if (tok3->isLiteral() ||
(tok3->isName() && (variableId.find(tok3->str()) != variableId.end())) ||
(tok3->isName() && variableMap.hasVariable(tok3->str())) ||
tok3->isOp() ||
tok3->str() == "(" ||
notstart.find(tok3->str()) != notstart.end()) {
@ -2765,7 +2755,7 @@ void Tokenizer::setVarIdPass1()
decl = false;
if (decl) {
variableId[prev2->str()] = ++_varId;
variableMap.addVariable(prev2->str());
// set varid for template parameters..
tok = tok->next();
@ -2774,8 +2764,11 @@ void Tokenizer::setVarIdPass1()
if (tok && tok->str() == "<") {
const Token *end = tok->findClosingBracket();
while (tok != end) {
if (tok->isName() && variableId.find(tok->str()) != variableId.end())
tok->varId(variableId[tok->str()]);
if (tok->isName()) {
const std::map<std::string, unsigned int>::const_iterator it = variableMap.find(tok->str());
if (it != variableMap.end())
tok->varId(it->second);
}
tok = tok->next();
}
}
@ -2830,10 +2823,10 @@ void Tokenizer::setVarIdPass1()
}
if (!scopeStack.top().isEnum) {
const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
if (it != variableId.end()) {
const std::map<std::string, unsigned int>::const_iterator it = variableMap.find(tok->str());
if (it != variableMap.end()) {
tok->varId(it->second);
setVarIdStructMembers(&tok, structMembers, &_varId);
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
}
}
} else if (Token::Match(tok, "::|. %name%")) {
@ -2848,6 +2841,8 @@ void Tokenizer::setVarIdPass1()
tok = tok->previous();
}
}
_varId = *variableMap.getVarId();
}
namespace {
@ -10359,3 +10354,48 @@ void Tokenizer::simplifyNamespaceAliases()
}
}
}
Tokenizer::VariableMap::VariableMap() : varId(0) {}
void Tokenizer::VariableMap::enterScope()
{
scopeInfo.push(std::list<std::pair<std::string, unsigned int>>());
}
bool Tokenizer::VariableMap::leaveScope()
{
if (scopeInfo.empty())
return false;
for (const std::pair<std::string, unsigned int> &outerVariable : scopeInfo.top()) {
if (outerVariable.second != 0)
variableId[outerVariable.first] = outerVariable.second;
else
variableId.erase(outerVariable.first);
}
scopeInfo.pop();
return true;
}
void Tokenizer::VariableMap::addVariable(const std::string &varname)
{
if (scopeInfo.empty()) {
variableId[varname] = ++varId;
return;
}
std::map<std::string, unsigned int>::iterator it = variableId.find(varname);
if (it == variableId.end()) {
scopeInfo.top().push_back(std::pair<std::string, unsigned int>(varname, 0));
variableId[varname] = ++varId;
return;
}
scopeInfo.top().push_back(std::pair<std::string, unsigned int>(varname, it->second));
it->second = ++varId;
}
bool Tokenizer::VariableMap::hasVariable(const std::string &varname) const
{
return variableId.find(varname) != variableId.end();
}

View File

@ -29,6 +29,7 @@
#include <list>
#include <map>
#include <string>
#include <stack>
class Settings;
class SymbolDatabase;
@ -49,6 +50,34 @@ class CPPCHECKLIB Tokenizer {
friend class TestSimplifyTypedef;
friend class TestTokenizer;
friend class SymbolDatabase;
/** Class used in Tokenizer::setVarIdPass1 */
class VariableMap {
private:
std::map<std::string, unsigned int> variableId;
std::stack<std::list<std::pair<std::string, unsigned int> > > scopeInfo;
mutable unsigned int varId;
public:
VariableMap();
void enterScope();
bool leaveScope();
void addVariable(const std::string &varname);
bool hasVariable(const std::string &varname) const;
std::map<std::string, unsigned int>::const_iterator find(const std::string &varname) const {
return variableId.find(varname);
}
std::map<std::string, unsigned int>::const_iterator end() const {
return variableId.end();
}
const std::map<std::string, unsigned int> &map() const {
return variableId;
}
unsigned int *getVarId() const {
return &varId;
}
};
public:
Tokenizer();
Tokenizer(const Settings * settings, ErrorLogger *errorLogger);
@ -712,7 +741,7 @@ private:
void unsupportedTypedef(const Token *tok) const;
void setVarIdClassDeclaration(const Token * const startToken,
const std::map<std::string, unsigned int> &variableId,
const VariableMap &variableMap,
const unsigned int scopeStartVarId,
std::map<unsigned int, std::map<std::string,unsigned int> >& structMembers);