Tokenizer: Use new setVarId function. Removed the old one.

This commit is contained in:
Daniel Marjamäki 2012-04-22 11:36:31 +02:00
parent 3d2b5a30fe
commit d5f6cfcfa8
4 changed files with 10 additions and 475 deletions

View File

@ -2242,15 +2242,9 @@ bool Tokenizer::tokenize(std::istream &code,
if (!preprocessorCondition) {
if (m_timerResults) {
Timer t("Tokenizer::tokenize::setVarId", _settings->_showtime, m_timerResults);
if (isC())
setVarIdNew();
else
setVarIdOld();
setVarId();
} else {
if (isC())
setVarIdNew();
else
setVarIdOld();
setVarId();
}
createLinks2();
@ -2891,7 +2885,7 @@ static void setVarIdStructMembers(Token **tok1,
}
void Tokenizer::setVarIdNew()
void Tokenizer::setVarId()
{
// Clear all variable ids
for (Token *tok = _tokens; tok; tok = tok->next())
@ -3115,453 +3109,6 @@ void Tokenizer::setVarIdNew()
}
}
void Tokenizer::setVarIdOld()
{
// Clear all variable ids
for (Token *tok = _tokens; tok; tok = tok->next())
tok->varId(0);
// Set variable ids..
_varId = 0;
unsigned int executableScope = 0;
for (Token *tok = _tokens; tok; tok = tok->next()) {
if (tok->str() == "{") {
if (executableScope)
executableScope++;
else if (tok->strAt(-1) == ")" || Token::simpleMatch(tok->tokAt(-2), ") const"))
executableScope = 1;
} else if (executableScope >= 1 && tok->str() == "}")
--executableScope;
if (tok != _tokens && !Token::Match(tok, "[;{}(,] %type%") && !Token::Match(tok, "[;{}(,] ::"))
continue;
// Ticket #3104 - "if (NOT x)"
if (tok->str() == "(" && tok->next()->str() == "NOT")
continue;
if (_errorLogger)
_errorLogger->reportProgress(_files[0], "Tokenize (set variable id)", tok->progressValue());
// If pattern is "( %type% *|& %var% )" then check if it's a
// variable declaration or a multiplication / mask
if (Token::Match(tok, "( %type% *|& %var% [),]") && !tok->next()->isStandardType()) {
if (!Token::Match(tok->previous(), "%type%"))
continue;
if (Token::Match(tok->previous(), "return|if|while"))
continue;
if (tok->link() && !Token::Match(tok->link()->next(), "const| {") &&
(!tok->link()->next() || tok->link()->next()->str() != ":"))
continue;
}
if (Token::Match(tok, "[,;{}(] %type%") || Token::Match(tok, "[;{}(,] ::")) {
// not function declaration?
// TODO: Better checking
if (Token::Match(tok->tokAt(-2), "= %var% (")) {
continue;
}
if (tok->str() == "(" &&
tok->previous() &&
!tok->previous()->isName() &&
tok->strAt(-2) != "operator")
continue;
if (executableScope && tok->str() == "(" && Token::simpleMatch(tok->link(),") ;")) {
tok = tok->link();
continue;
}
tok = tok->next();
}
if (tok->str() == "new")
continue;
if (tok->str() == "throw" && isCPP())
continue;
if (tok->str() == "virtual")
continue;
if (Token::Match(tok, "class|struct|union %type% :|{|;")) {
if (tok->strAt(2) == ":") {
while (tok->next() && !Token::Match(tok->next(),"[;{]"))
tok = tok->next();
}
continue;
}
while (Token::Match(tok, "public:|private:|protected:"))
tok = tok->next();
if (!tok)
break;
if (tok->str() == "unsigned")
tok = tok->next();
if (Token::Match(tok, "using namespace| %type% ;")) {
tok = tok->next();
continue;
}
if (Token::Match(tok, "goto %any% ;"))
continue;
if (Token::Match(tok, "else|return|typedef|delete|sizeof"))
continue;
while (Token::Match(tok, "const|static|extern|;|mutable"))
tok = tok->next();
if (tok && tok->str() == "friend")
continue;
if (Token::Match(tok, "struct %type%"))
tok = tok->next();
// skip global namespace prefix
if (tok && tok->str() == "::")
tok = tok->next();
while (Token::Match(tok, "%var% ::"))
tok = tok->tokAt(2);
// Skip template arguments..
if (Token::Match(tok, "%type% <")) {
int level = 1;
bool again;
Token *tok2 = tok->tokAt(2);
do { // Look for start of templates or template arguments
if (!tok2) // syntax error
return;
again = false;
if (tok2 && tok2->str() == "const")
tok2 = tok2->next();
if (tok2 && tok2->str() == "::")
tok2 = tok2->next();
while (Token::Match(tok2, "%var% ::"))
tok2 = tok2->tokAt(2);
if (Token::Match(tok2, "%type% <")) {
++level;
tok2 = tok2->tokAt(2);
again = true;
} else if (Token::Match(tok2, "%type% *|&| ,")) {
tok2 = tok2->tokAt(2);
if (!tok2) // syntax error
return;
if (tok2->str() == ",") {
tok2 = tok2->next();
if (!tok2) // syntax error
return;
}
again = true;
} else if (level > 1 && (Token::Match(tok2, "%type% *|&| >") ||
Token::Match(tok2, "%num% >"))) {
--level;
while (tok2->str() != ">")
tok2 = tok2->next();
tok2 = tok2->next();
if (!tok2) // syntax error
return;
if (tok2->str() == ",") {
tok2 = tok2->next();
if (!tok2) // syntax error
return;
}
if (level == 1 && tok2->str() == ">")
break;
again = true;
} else {
while (tok2 && (tok2->isName() || tok2->isNumber() || tok2->str() == "*" || tok2->str() == "&" || tok2->str() == ","))
tok2 = tok2->next();
if (tok2 && tok2->str() == "(") {
tok2 = tok2->link()->next();
if (tok2 && tok2->str() == "(")
tok2 = tok2->link()->next();
again = true;
}
}
} while (again);
do { // Look for end of templates
again = false;
if (level == 1 && Token::Match(tok2, "> %var%"))
tok = tok2;
else if (level > 1 && tok2 && tok2->str() == ">") {
--level;
if (level == 0)
tok = tok2;
else {
tok2 = tok2->next();
again = true;
}
} else if (level == 1 && Token::Match(tok2, "> ::|*|& %var%"))
tok = tok2->next();
else
continue; // Not code that I understand / not a variable declaration
} while (again);
}
if (Token::Match(tok, "%str%"))
continue;
// Determine name of declared variable..
std::string varname;
Token *tok2 = tok ? tok->next() : 0;
while (tok2) {
if (tok2->isName()) {
if (tok2->str() == "const")
varname.clear();
else
varname = tok2->str();
} else if (tok2->str() != "*" && tok2->str() != "&")
break;
// a type can't have varid
if (tok2->previous()->varId() > 0) {
tok2 = 0;
break;
}
tok2 = tok2->next();
}
if (executableScope && Token::simpleMatch(tok2, ") ;"))
continue;
if (Token::Match(tok2 ? tok2->tokAt(-2) : 0, "class|struct %type% ;"))
continue;
// End of tokens reached..
if (!tok2)
break;
if (varname == "operator" && Token::Match(tok2, "=|+|-|*|/|[| ]| ("))
continue;
if (varname == "new" && Token::Match(tok2->tokAt(-2), "operator new (|["))
continue;
// Is it a function?
if (tok2->str() == "(") {
const Token* const tok3 = tok2->next();
// Search for function declaration, e.g. void f();
if (Token::simpleMatch(tok3, ") ;"))
continue;
// Search for function declaration, e.g. void f( int c );
if (!tok3->isNumber() &&
!tok3->isBoolean() &&
tok3->str()[0] != '"' &&
tok3->str()[0] != '\'' &&
tok3->str() != "*" &&
tok3->str() != "&" &&
tok3->varId() == 0)
continue;
}
// Don't set variable id for 'AAA a[0] = 0;' declaration (#2638)
if (tok2->previous()->varId() && tok2->str() == "[") {
const Token *tok3 = tok2;
while (tok3 && tok3->str() == "[") {
tok3 = tok3->link();
tok3 = tok3 ? tok3->next() : NULL;
}
if (Token::Match(tok3, "= !!{"))
continue;
}
// Variable declaration found => Set variable ids
if (Token::Match(tok2, "[,();[=]") && !varname.empty()) {
// Are we in a class declaration?
// Then start at the start of the class declaration..
while (NULL != (tok2 = tok2->previous())) {
if (tok2->str() == "}" || tok2->str() == ")")
tok2 = tok2->link();
else if (tok2->str() == "(")
break;
else if (tok2->str() == "{") {
while (NULL != (tok2 = tok2->previous())) {
if (Token::Match(tok2, "[,;{})]")) {
if (!Token::Match(tok2, ", public|protected|private"))
break;
}
if (Token::Match(tok2, "class|struct"))
break;
}
break;
}
}
/** @todo better handling when classes in different scopes have the same name */
std::string className;
if (Token::Match(tok2, "class|struct %type% [:{]"))
className = tok2->next()->str();
// Set start token
if (Token::Match(tok2, "class|struct")) {
while (tok2->str() != "{")
tok2 = tok2->next();
} else
tok2 = tok;
++_varId;
int indentlevel = 0;
int parlevel = 0;
bool funcDeclaration = false;
while (NULL != (tok2 = tok2->next())) {
const char c = tok2->str()[0];
if (c == varname[0]) {
if (tok2->str() == varname && (className.empty() || tok2->varId() == 0)) {
const std::string &prev = tok2->previous()->str();
/** @todo better handling when classes in different scopes have the same name */
if (!className.empty() && Token::Match(tok2->tokAt(-3), ("!!:: " + className + " ::").c_str()))
tok2->varId(_varId);
else if (tok2->str() == varname && prev != "struct" && prev != "union" && prev != "::" && prev != "." && (!tok2->next() || tok2->next()->str() != "::"))
tok2->varId(_varId);
}
} else if (c == '{')
++indentlevel;
else if (c == '}') {
--indentlevel;
if (indentlevel < 0)
break;
// We have reached the end of a loop: "for( int i;;) { }"
if (funcDeclaration && indentlevel <= 0)
break;
} else if (c == '(')
++parlevel;
else if (c == ')') {
// Is this a function parameter or a variable declared in for example a for loop?
if (parlevel == 0 && indentlevel == 0 && Token::Match(tok2, ") const| {"))
funcDeclaration = true;
else
--parlevel;
} else if (parlevel < 0 && c == ';')
break;
}
}
}
// Member functions and variables in this source
std::list<Token *> allMemberFunctions;
std::list<Token *> allMemberVars;
{
for (Token *tok2 = _tokens; tok2; tok2 = tok2->next()) {
if (Token::Match(tok2, "%var% :: %var%")) {
if (tok2->strAt(3) == "(")
allMemberFunctions.push_back(tok2);
else if (tok2->tokAt(2)->varId() != 0)
allMemberVars.push_back(tok2);
}
}
}
// class members..
for (Token *tok = _tokens; tok; tok = tok->next()) {
if (Token::Match(tok, "class|struct %var% {|:")) {
const std::string &classname(tok->next()->str());
// What member variables are there in this class?
std::map<std::string, unsigned int> varlist;
const Token* tokStart = Token::findsimplematch(tok, "{");
if (tokStart) {
for (const Token *tok2 = tokStart->next(); tok2 != tok->link(); tok2 = tok2->next()) {
// skip parentheses..
if (tok2->str() == "{")
tok2 = tok2->link();
else if (tok2->str() == "(")
tok2 = tok2->link();
// Found a member variable..
else if (tok2->varId() > 0)
varlist[tok2->str()] = tok2->varId();
}
}
// Are there any member variables in this class?
if (varlist.empty())
continue;
// Member variables
for (std::list<Token *>::iterator func = allMemberVars.begin(); func != allMemberVars.end(); ++func) {
if (!Token::simpleMatch(*func, classname.c_str()))
continue;
Token *tok2 = *func;
tok2 = tok2->tokAt(2);
tok2->varId(varlist[tok2->str()]);
}
// Member functions for this class..
std::list<Token *> funclist;
{
const std::string funcpattern(classname + " :: %var% (");
for (std::list<Token *>::iterator func = allMemberFunctions.begin(); func != allMemberFunctions.end(); ++func) {
Token *tok2 = *func;
// Found a class function..
if (Token::Match(tok2, funcpattern.c_str())) {
// Goto the end parenthesis..
tok2 = tok2->linkAt(3);
if (!tok2)
break;
// If this is a function implementation.. add it to funclist
if (Token::Match(tok2, ") const|volatile| {")) {
if (tok2->next()->str() != "{")
tok2 = tok2->next();
funclist.push_back(tok2->next());
}
}
}
}
// Update the variable ids..
// Parse each function..
for (std::list<Token *>::iterator func = funclist.begin(); func != funclist.end(); ++func) {
for (Token *tok2 = (*func)->next(); tok2 != (*func)->link(); tok2 = tok2->next()) {
if (tok2->varId() == 0 &&
tok2->strAt(-1) != "." &&
varlist.find(tok2->str()) != varlist.end()) {
tok2->varId(varlist[tok2->str()]);
}
}
}
}
}
// Struct/Class members
for (Token *tok = _tokens; tok; tok = tok->next()) {
// str.clear is a variable
// str.clear() is a member function
if (tok->varId() != 0 &&
Token::Match(tok->next(), ". %var% !!(") &&
tok->tokAt(2)->varId() == 0) {
++_varId;
const std::string pattern(std::string(". ") + tok->strAt(2));
for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
if (tok2->varId() == tok->varId()) {
if (Token::Match(tok2->next(), pattern.c_str()))
tok2->tokAt(2)->varId(_varId);
}
}
}
}
}
static bool linkBrackets(Tokenizer* tokenizer, std::stack<const Token*>& type, std::stack<Token*>& links, Token* token, char open, char close)
{
if (token->str()[0] == open) {
@ -4072,15 +3619,9 @@ bool Tokenizer::simplifyTokenList()
// In case variable declarations have been updated...
if (m_timerResults) {
Timer t("Tokenizer::simplifyTokenList::setVarId", _settings->_showtime, m_timerResults);
if (isC())
setVarIdNew();
else
setVarIdOld();
setVarId();
} else {
if (isC())
setVarIdNew();
else
setVarIdOld();
setVarId();
}
bool modified = true;

View File

@ -116,8 +116,7 @@ public:
void createTokens(std::istream &code);
/** Set variable id */
void setVarIdOld();
void setVarIdNew();
void setVarId();
/**
* Simplify tokenlist

View File

@ -3066,12 +3066,7 @@ private:
"2: int f@1 ( x ) ;\n"
"3: return f@1 ;\n"
"4: }\n");
const std::string actual("\n\n##file 0\n"
"1: int foo ( ) {\n"
"2: int f ( x ) ;\n"
"3: return f ;\n"
"4: }\n");
TODO_ASSERT_EQUALS(expected, actual, tokenizeDebugListing(code));
ASSERT_EQUALS(expected, tokenizeDebugListing(code));
}
void varid36() { // ticket #2980 (segmentation fault)
@ -3418,8 +3413,8 @@ private:
"8: void foo :: bar ( )\n"
"9: {\n"
"10: POINT pOutput@3 ; pOutput@3 = { 0 , 0 } ;\n"
"11: int x@4 ; x@4 = pOutput@3 . x@6 ;\n"
"12: int y@5 ; y@5 = pOutput@3 . y@7 ;\n"
"11: int x@4 ; x@4 = pOutput@3 . x@5 ;\n"
"12: int y@6 ; y@6 = pOutput@3 . y@7 ;\n"
"13: }\n");
ASSERT_EQUALS(expected, actual);

View File

@ -401,7 +401,7 @@ private:
"{\n"
" int i(a);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (style) Variable 'i' is assigned a value that is never used\n", errout.str());
functionVariableUsage("void foo()\n"
"{\n"