diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 065e024f1..935d91128 100644 --- a/lib/tokenize.cpp +++ b/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 allMemberFunctions; - std::list 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 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::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 funclist; - { - const std::string funcpattern(classname + " :: %var% ("); - for (std::list::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::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& type, std::stack& 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; diff --git a/lib/tokenize.h b/lib/tokenize.h index f0b80006c..45ec27c08 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -116,8 +116,7 @@ public: void createTokens(std::istream &code); /** Set variable id */ - void setVarIdOld(); - void setVarIdNew(); + void setVarId(); /** * Simplify tokenlist diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 4c9a7ab01..0d8718545 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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); diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index a49fc3771..1daca7a4d 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -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"