Tokenizer: Use new setVarId function. Removed the old one.
This commit is contained in:
parent
3d2b5a30fe
commit
d5f6cfcfa8
469
lib/tokenize.cpp
469
lib/tokenize.cpp
|
@ -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;
|
||||
|
|
|
@ -116,8 +116,7 @@ public:
|
|||
void createTokens(std::istream &code);
|
||||
|
||||
/** Set variable id */
|
||||
void setVarIdOld();
|
||||
void setVarIdNew();
|
||||
void setVarId();
|
||||
|
||||
/**
|
||||
* Simplify tokenlist
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue