Cppcheck
tokenize.cpp
Go to the documentation of this file.
00001 /*
00002  * Cppcheck - A tool for static C/C++ code analysis
00003  * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 
00020 //---------------------------------------------------------------------------
00021 #include "tokenize.h"
00022 #include "mathlib.h"
00023 #include "settings.h"
00024 #include "check.h"
00025 #include "path.h"
00026 #include "symboldatabase.h"
00027 #include "templatesimplifier.h"
00028 #include "timer.h"
00029 
00030 #include <cstring>
00031 #include <sstream>
00032 #include <cassert>
00033 #include <cctype>
00034 #include <stack>
00035 
00036 //---------------------------------------------------------------------------
00037 
00038 Tokenizer::Tokenizer() :
00039     list(0),
00040     _settings(0),
00041     _errorLogger(0),
00042     _symbolDatabase(0),
00043     _varId(0),
00044     _codeWithTemplates(false), //is there any templates?
00045     m_timerResults(NULL)
00046 {
00047 }
00048 
00049 Tokenizer::Tokenizer(const Settings *settings, ErrorLogger *errorLogger) :
00050     list(settings),
00051     _settings(settings),
00052     _errorLogger(errorLogger),
00053     _symbolDatabase(0),
00054     _varId(0),
00055     _codeWithTemplates(false), //is there any templates?
00056     m_timerResults(NULL)
00057 {
00058     // make sure settings are specified
00059     assert(_settings);
00060 }
00061 
00062 Tokenizer::~Tokenizer()
00063 {
00064     delete _symbolDatabase;
00065 }
00066 
00067 
00068 //---------------------------------------------------------------------------
00069 // SizeOfType - gives the size of a type
00070 //---------------------------------------------------------------------------
00071 
00072 unsigned int Tokenizer::sizeOfType(const Token *type) const
00073 {
00074     if (!type || type->str().empty())
00075         return 0;
00076 
00077     if (type->type() == Token::eString)
00078         return static_cast<unsigned int>(Token::getStrLength(type) + 1);
00079 
00080     std::map<std::string, unsigned int>::const_iterator it = _typeSize.find(type->str());
00081     if (it == _typeSize.end())
00082         return 0;
00083     else if (type->isLong()) {
00084         if (type->str() == "double")
00085             return _settings->sizeof_long_double;
00086         else if (type->str() == "long")
00087             return _settings->sizeof_long_long;
00088     }
00089 
00090     return it->second;
00091 }
00092 
00093 //---------------------------------------------------------------------------
00094 
00095 Token *Tokenizer::copyTokens(Token *dest, const Token *first, const Token *last, bool one_line)
00096 {
00097     std::stack<Token *> links;
00098     Token *tok2 = dest;
00099     unsigned int linenrs = dest->linenr();
00100     unsigned int commonFileIndex = dest->fileIndex();
00101     for (const Token *tok = first; tok != last->next(); tok = tok->next()) {
00102         tok2->insertToken(tok->str());
00103         tok2 = tok2->next();
00104         tok2->fileIndex(commonFileIndex);
00105         tok2->linenr(linenrs);
00106         tok2->type(tok->type());
00107         tok2->isUnsigned(tok->isUnsigned());
00108         tok2->isSigned(tok->isSigned());
00109         tok2->isPointerCompare(tok->isPointerCompare());
00110         tok2->isLong(tok->isLong());
00111         tok2->isUnused(tok->isUnused());
00112         tok2->setExpandedMacro(tok->isExpandedMacro());
00113         tok2->varId(tok->varId());
00114 
00115         // Check for links and fix them up
00116         if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{")
00117             links.push(tok2);
00118         else if (tok2->str() == ")" || tok2->str() == "]" || tok2->str() == "}") {
00119             if (links.empty())
00120                 return tok2;
00121 
00122             Token * link = links.top();
00123 
00124             tok2->link(link);
00125             link->link(tok2);
00126 
00127             links.pop();
00128         }
00129         if (!one_line && tok->next())
00130             linenrs += tok->next()->linenr() - tok->linenr();
00131     }
00132     return tok2;
00133 }
00134 
00135 //---------------------------------------------------------------------------
00136 
00137 void Tokenizer::duplicateTypedefError(const Token *tok1, const Token *tok2, const std::string &type) const
00138 {
00139     if (tok1 && !(_settings->isEnabled("style") && _settings->inconclusive))
00140         return;
00141 
00142     std::list<const Token*> locationList;
00143     locationList.push_back(tok1);
00144     locationList.push_back(tok2);
00145     const std::string tok2_str = tok2 ? tok2->str() : std::string("name");
00146 
00147     reportError(locationList, Severity::style, "variableHidingTypedef",
00148                 std::string("The " + type + " '" + tok2_str + "' hides a typedef with the same name."), true);
00149 }
00150 
00151 void Tokenizer::duplicateDeclarationError(const Token *tok1, const Token *tok2, const std::string &type) const
00152 {
00153     if (tok1 && !(_settings->isEnabled("style")))
00154         return;
00155 
00156     std::list<const Token*> locationList;
00157     locationList.push_back(tok1);
00158     locationList.push_back(tok2);
00159     const std::string tok2_str = tok2 ? tok2->str() : std::string("name");
00160 
00161     reportError(locationList, Severity::style, "unnecessaryForwardDeclaration",
00162                 std::string("The " + type + " '" + tok2_str + "' forward declaration is unnecessary. Type " + type + " is already declared earlier."));
00163 }
00164 
00165 // check if this statement is a duplicate definition
00166 bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef, bool undefinedStruct) const
00167 {
00168     // check for an end of definition
00169     const Token * tok = *tokPtr;
00170     if (tok && Token::Match(tok->next(), ";|,|[|=|)|>|(|{")) {
00171         const Token * end = tok->next();
00172 
00173         if (end->str() == "[") {
00174             end = end->link()->next();
00175         } else if (end->str() == ",") {
00176             // check for derived class
00177             if (Token::Match(tok->previous(), "public|private|protected"))
00178                 return false;
00179 
00180             // find end of definition
00181             while (end && end->next() && !Token::Match(end->next(), ";|)|>")) {
00182                 if (end->next()->str() == "(")
00183                     end = end->linkAt(1);
00184 
00185                 end = end->next();
00186             }
00187             if (end)
00188                 end = end->next();
00189         } else if (end->str() == "(") {
00190             if (tok->previous()->str().find("operator")  == 0) {
00191                 // conversion operator
00192                 return false;
00193             } else if (tok->previous()->str() == "typedef") {
00194                 // typedef of function returning this type
00195                 return false;
00196             } else if (Token::Match(tok->previous(), "public:|private:|protected:")) {
00197                 return false;
00198             } else if (tok->previous()->str() == ">") {
00199                 if (!Token::Match(tok->tokAt(-2), "%type%"))
00200                     return false;
00201 
00202                 if (!Token::Match(tok->tokAt(-3), ",|<"))
00203                     return false;
00204 
00205                 duplicateTypedefError(*tokPtr, name, "template instantiation");
00206                 *tokPtr = end->link();
00207                 return true;
00208             }
00209         }
00210 
00211         if (end) {
00212             if (Token::simpleMatch(end, ") {")) { // function parameter ?
00213                 // look backwards
00214                 if (Token::Match(tok->previous(), "%type%") &&
00215                     !Token::Match(tok->previous(), "return|new|const")) {
00216                     duplicateTypedefError(*tokPtr, name, "function parameter");
00217                     // duplicate definition so skip entire function
00218                     *tokPtr = end->next()->link();
00219                     return true;
00220                 }
00221             } else if (end->str() == ">") { // template parameter ?
00222                 // look backwards
00223                 if (Token::Match(tok->previous(), "%type%") &&
00224                     !Token::Match(tok->previous(), "return|new|const|volatile")) {
00225                     // duplicate definition so skip entire template
00226                     while (end && end->str() != "{")
00227                         end = end->next();
00228                     if (end) {
00229                         duplicateTypedefError(*tokPtr, name, "template parameter");
00230                         *tokPtr = end->link();
00231                         return true;
00232                     }
00233                 }
00234             } else {
00235                 // look backwards
00236                 if (Token::Match(tok->previous(), "typedef|}|>") ||
00237                     (tok->previous()->str() == "*" && tok->next()->str() != "(") ||
00238                     (Token::Match(tok->previous(), "%type%") &&
00239                      (!Token::Match(tok->previous(), "return|new|const|friend|public|private|protected|throw|extern") &&
00240                       !Token::simpleMatch(tok->tokAt(-2), "friend class")))) {
00241                     // scan backwards for the end of the previous statement
00242                     while (tok && tok->previous() && !Token::Match(tok->previous(), ";|{")) {
00243                         if (tok->previous()->str() == "}") {
00244                             tok = tok->previous()->link();
00245                         } else if (tok->previous()->str() == "typedef") {
00246                             duplicateTypedefError(*tokPtr, name, "typedef");
00247                             return true;
00248                         } else if (tok->previous()->str() == "enum") {
00249                             duplicateTypedefError(*tokPtr, name, "enum");
00250                             return true;
00251                         } else if (tok->previous()->str() == "struct") {
00252                             if (tok->strAt(-2) == "typedef" &&
00253                                 tok->next()->str() == "{" &&
00254                                 typeDef->strAt(3) != "{") {
00255                                 // declaration after forward declaration
00256                                 return true;
00257                             } else if (tok->next()->str() == "{") {
00258                                 if (!undefinedStruct)
00259                                     duplicateTypedefError(*tokPtr, name, "struct");
00260                                 return true;
00261                             } else if (Token::Match(tok->next(), ")|*")) {
00262                                 return true;
00263                             } else if (tok->next()->str() == name->str()) {
00264                                 return true;
00265                             } else if (tok->next()->str() != ";") {
00266                                 duplicateTypedefError(*tokPtr, name, "struct");
00267                                 return true;
00268                             } else {
00269                                 // forward declaration after declaration
00270                                 duplicateDeclarationError(*tokPtr, name, "struct");
00271                                 return false;
00272                             }
00273                         } else if (tok->previous()->str() == "union") {
00274                             if (tok->next()->str() != ";") {
00275                                 duplicateTypedefError(*tokPtr, name, "union");
00276                                 return true;
00277                             } else {
00278                                 // forward declaration after declaration
00279                                 duplicateDeclarationError(*tokPtr, name, "union");
00280                                 return false;
00281                             }
00282                         } else if (tok->previous()->str() == "class") {
00283                             if (tok->next()->str() != ";") {
00284                                 duplicateTypedefError(*tokPtr, name, "class");
00285                                 return true;
00286                             } else {
00287                                 // forward declaration after declaration
00288                                 duplicateDeclarationError(*tokPtr, name, "class");
00289                                 return false;
00290                             }
00291                         }
00292 
00293                         tok = tok->previous();
00294                     }
00295 
00296                     duplicateTypedefError(*tokPtr, name, "variable");
00297                     return true;
00298                 }
00299             }
00300         }
00301     }
00302 
00303     return false;
00304 }
00305 
00306 void Tokenizer::unsupportedTypedef(const Token *tok) const
00307 {
00308     if (!_settings->debugwarnings)
00309         return;
00310 
00311     std::ostringstream str;
00312     const Token *tok1 = tok;
00313     unsigned int level = 0;
00314     while (tok) {
00315         if (level == 0 && tok->str() == ";")
00316             break;
00317         else if (tok->str() == "{")
00318             ++level;
00319         else if (tok->str() == "}") {
00320             if (!level)
00321                 break;
00322             --level;
00323         }
00324 
00325         if (tok != tok1)
00326             str << " ";
00327         str << tok->str();
00328         tok = tok->next();
00329     }
00330     if (tok)
00331         str << " ;";
00332 
00333     reportError(tok1, Severity::debug, "debug",
00334                 "Failed to parse \'" + str.str() + "\'. The checking continues anyway.");
00335 }
00336 
00337 Token * Tokenizer::deleteInvalidTypedef(Token *typeDef)
00338 {
00339     Token *tok = NULL;
00340 
00341     // remove typedef but leave ;
00342     while (typeDef->next()) {
00343         if (typeDef->next()->str() == ";") {
00344             typeDef->deleteNext();
00345             break;
00346         } else if (typeDef->next()->str() == "{")
00347             Token::eraseTokens(typeDef, typeDef->linkAt(1));
00348         else if (typeDef->next()->str() == "}")
00349             break;
00350         typeDef->deleteNext();
00351     }
00352 
00353     if (typeDef != list.front()) {
00354         tok = typeDef->previous();
00355         tok->deleteNext();
00356     } else {
00357         list.front()->deleteThis();
00358         tok = list.front();
00359     }
00360 
00361     return tok;
00362 }
00363 
00364 struct Space {
00365     std::string className;
00366     const Token * classEnd;
00367     bool isNamespace;
00368 };
00369 
00370 static Token *splitDefinitionFromTypedef(Token *tok)
00371 {
00372     Token *tok1;
00373     std::string name;
00374     bool isConst = false;
00375 
00376     if (tok->next()->str() == "const") {
00377         tok->deleteNext();
00378         isConst = true;
00379     }
00380 
00381     if (tok->strAt(2) == "{") { // unnamed
00382         tok1 = tok->linkAt(2);
00383 
00384         if (tok1 && tok1->next()) {
00385             // use typedef name if available
00386             if (Token::Match(tok1->next(), "%type%"))
00387                 name = tok1->next()->str();
00388             else { // create a unique name
00389                 static unsigned int count = 0;
00390                 name = "Unnamed" + MathLib::longToString(count++);
00391             }
00392             tok->next()->insertToken(name);
00393         } else
00394             return NULL;
00395     } else if (tok->strAt(3) == ":") {
00396         tok1 = tok->tokAt(4);
00397         while (tok1 && tok1->str() != "{")
00398             tok1 = tok1->next();
00399         if (!tok1)
00400             return NULL;
00401 
00402         tok1 = tok1->link();
00403 
00404         name = tok->strAt(2);
00405     } else { // has a name
00406         tok1 = tok->linkAt(3);
00407 
00408         if (!tok1)
00409             return NULL;
00410 
00411         name = tok->strAt(2);
00412     }
00413 
00414     tok1->insertToken(";");
00415     tok1 = tok1->next();
00416 
00417     if (tok1->next() && tok1->next()->str() == ";" && tok1->previous()->str() == "}") {
00418         tok->deleteThis();
00419         tok1->deleteThis();
00420         return NULL;
00421     } else {
00422         tok1->insertToken("typedef");
00423         tok1 = tok1->next();
00424         Token * tok3 = tok1;
00425         if (isConst) {
00426             tok1->insertToken("const");
00427             tok1 = tok1->next();
00428         }
00429         tok1->insertToken(tok->next()->str()); // struct, union or enum
00430         tok1 = tok1->next();
00431         tok1->insertToken(name);
00432         tok->deleteThis();
00433         tok = tok3;
00434     }
00435 
00436     return tok;
00437 }
00438 
00439 /* This function is called when processing function related typedefs.
00440  * If simplifyTypedef generates an "Internal Error" message and the
00441  * code that generated it deals in some way with functions, then this
00442  * function will probably need to be extended to handle a new function
00443  * related pattern */
00444 static Token *processFunc(Token *tok2, bool inOperator)
00445 {
00446     if (tok2->next() && tok2->next()->str() != ")" &&
00447         tok2->next()->str() != ",") {
00448         // skip over tokens for some types of canonicalization
00449         if (Token::Match(tok2->next(), "( * %type% ) ("))
00450             tok2 = tok2->linkAt(5);
00451         else if (Token::Match(tok2->next(), "* ( * %type% ) ("))
00452             tok2 = tok2->linkAt(6);
00453         else if (Token::Match(tok2->next(), "* ( * %type% ) ;"))
00454             tok2 = tok2->tokAt(5);
00455         else if (Token::Match(tok2->next(), "* ( %type% [") &&
00456                  Token::Match(tok2->linkAt(4), "] ) ;|="))
00457             tok2 = tok2->linkAt(4)->next();
00458         else if (Token::Match(tok2->next(), "* ( * %type% ("))
00459             tok2 = tok2->linkAt(5)->next();
00460         else if (Token::simpleMatch(tok2->next(), "* [") &&
00461                  Token::simpleMatch(tok2->linkAt(2), "] ;"))
00462             tok2 = tok2->next();
00463         else {
00464             if (tok2->next()->str() == "(")
00465                 tok2 = tok2->next()->link();
00466             else if (!inOperator && !Token::Match(tok2->next(), "[|>|;")) {
00467                 tok2 = tok2->next();
00468 
00469                 while (Token::Match(tok2, "*|&") &&
00470                        !Token::Match(tok2->next(), ")|>"))
00471                     tok2 = tok2->next();
00472 
00473                 // skip over namespace
00474                 while (Token::Match(tok2, "%var% ::"))
00475                     tok2 = tok2->tokAt(2);
00476 
00477                 if (!tok2)
00478                     return NULL;
00479 
00480                 if (tok2->str() == "(" &&
00481                     tok2->link()->next()->str() == "(") {
00482                     tok2 = tok2->link();
00483 
00484                     if (tok2->next()->str() == "(")
00485                         tok2 = tok2->next()->link();
00486                 }
00487 
00488                 // skip over typedef parameter
00489                 if (tok2->next() && tok2->next()->str() == "(") {
00490                     tok2 = tok2->next()->link();
00491 
00492                     if (tok2->next()->str() == "(")
00493                         tok2 = tok2->next()->link();
00494                 }
00495             }
00496         }
00497     }
00498     return tok2;
00499 }
00500 
00501 void Tokenizer::simplifyTypedef()
00502 {
00503     std::vector<Space> spaceInfo;
00504     bool isNamespace = false;
00505     std::string className;
00506     bool hasClass = false;
00507     bool goback = false;
00508     for (Token *tok = list.front(); tok; tok = tok->next()) {
00509         if (_errorLogger && !list.getFiles().empty())
00510             _errorLogger->reportProgress(list.getFiles()[0], "Tokenize (typedef)", tok->progressValue());
00511 
00512         if (goback) {
00513             //jump back once, see the comment at the end of the function
00514             goback = false;
00515             tok = tok->previous();
00516         }
00517 
00518         // Skip typedefs inside parentheses (#2453 and #4002)
00519         if (tok->str() == "(" && tok->strAt(1) == "typedef") {
00520             tok = tok->next();
00521             continue;
00522         }
00523 
00524         if (Token::Match(tok, "class|struct|namespace %any%") &&
00525             (!tok->previous() || (tok->previous() && tok->previous()->str() != "enum"))) {
00526             isNamespace = (tok->str() == "namespace");
00527             hasClass = true;
00528             className = tok->next()->str();
00529             continue;
00530         } else if (hasClass && tok->str() == ";") {
00531             hasClass = false;
00532             continue;
00533         } else if (hasClass && tok->str() == "{") {
00534             Space info;
00535             info.isNamespace = isNamespace;
00536             info.className = className;
00537             info.classEnd = tok->link();
00538             spaceInfo.push_back(info);
00539 
00540             hasClass = false;
00541             continue;
00542         } else if (!spaceInfo.empty() && tok->str() == "}" && spaceInfo.back().classEnd == tok) {
00543             spaceInfo.pop_back();
00544             continue;
00545         } else if (tok->str() != "typedef")
00546             continue;
00547 
00548         // pull struct, union, enum or class definition out of typedef
00549         // use typedef name for unnamed struct, union, enum or class
00550         if (Token::Match(tok->next(), "const| struct|enum|union|class %type% {") ||
00551             Token::Match(tok->next(), "const| struct|enum|union|class {")) {
00552             Token *tok1 = splitDefinitionFromTypedef(tok);
00553             if (!tok1)
00554                 continue;
00555             tok = tok1;
00556         } else if (Token::Match(tok->next(), "const| struct|class %type% :")) {
00557             Token *tok1 = tok;
00558             while (tok1 && tok1->str() != ";" && tok1->str() != "{")
00559                 tok1 = tok1->next();
00560             if (tok1 && tok1->str() == "{") {
00561                 tok1 = splitDefinitionFromTypedef(tok);
00562                 if (!tok1)
00563                     continue;
00564                 tok = tok1;
00565             }
00566         }
00567 
00568         /** @todo add support for union */
00569         bool undefinedStruct = false;
00570         if (Token::Match(tok, "typedef enum|struct %type% %type% ;") && tok->strAt(2) == tok->strAt(3)) {
00571             if (tok->next()->str() == "enum") {
00572                 tok->deleteNext(3);
00573                 tok->deleteThis();
00574                 if (tok->next())
00575                     tok->deleteThis();
00576                 //now the next token to process is 'tok', not 'tok->next()';
00577                 goback = true;
00578                 continue;
00579             } else {
00580                 const std::string pattern("struct " + tok->strAt(2) + " {|:");
00581                 const Token *tok2 = Token::findmatch(list.front(), pattern.c_str(), tok);
00582                 if (!tok2)
00583                     undefinedStruct = true;
00584             }
00585         }
00586 
00587         Token *typeName;
00588         std::list<std::string> pointers;
00589         Token *typeStart = 0;
00590         Token *typeEnd = 0;
00591         Token *argStart = 0;
00592         Token *argEnd = 0;
00593         Token *arrayStart = 0;
00594         Token *arrayEnd = 0;
00595         Token *specStart = 0;
00596         Token *specEnd = 0;
00597         Token *typeDef = tok;
00598         Token *argFuncRetStart = 0;
00599         Token *argFuncRetEnd = 0;
00600         Token *funcStart = 0;
00601         Token *funcEnd = 0;
00602         Token *tokOffset = tok->next();
00603         bool function = false;
00604         bool functionPtr = false;
00605         bool functionRef = false;
00606         bool functionRetFuncPtr = false;
00607         bool functionPtrRetFuncPtr = false;
00608         bool ptrToArray = false;
00609         bool refToArray = false;
00610         bool ptrMember = false;
00611         bool typeOf = false;
00612         Token *namespaceStart = 0;
00613         Token *namespaceEnd = 0;
00614 
00615         // check for invalid input
00616         if (!tok->next()) {
00617             syntaxError(tok);
00618             return;
00619         }
00620 
00621         if (tok->next()->str() == "::" || Token::Match(tok->next(), "%type%")) {
00622             typeStart = tok->next();
00623 
00624             while (Token::Match(tokOffset, "const|signed|unsigned|struct|enum %type%") ||
00625                    (tokOffset->next() && tokOffset->next()->isStandardType()))
00626                 tokOffset = tokOffset->next();
00627 
00628             typeEnd = tokOffset;
00629             tokOffset = tokOffset->next();
00630 
00631             bool atEnd = false;
00632             while (!atEnd) {
00633                 if (tokOffset && tokOffset->str() == "::") {
00634                     typeEnd = tokOffset;
00635                     tokOffset = tokOffset->next();
00636                 }
00637 
00638                 if (Token::Match(tokOffset, "%type%") &&
00639                     tokOffset->next() && !Token::Match(tokOffset->next(), "[|;|,|(")) {
00640                     typeEnd = tokOffset;
00641                     tokOffset = tokOffset->next();
00642                 } else if (Token::simpleMatch(tokOffset, "const (")) {
00643                     typeEnd = tokOffset;
00644                     tokOffset = tokOffset->next();
00645                     atEnd = true;
00646                 } else
00647                     atEnd = true;
00648             }
00649         } else
00650             continue; // invalid input
00651 
00652         // check for invalid input
00653         if (!tokOffset) {
00654             syntaxError(tok);
00655             return;
00656         }
00657 
00658         // check for template
00659         if (tokOffset->str() == "<") {
00660             tokOffset->findClosingBracket(typeEnd);
00661 
00662             while (typeEnd && Token::Match(typeEnd->next(), ":: %type%"))
00663                 typeEnd = typeEnd->tokAt(2);
00664 
00665             if (!typeEnd) {
00666                 // internal error
00667                 return;
00668             }
00669 
00670             while (Token::Match(typeEnd->next(), "const|volatile"))
00671                 typeEnd = typeEnd->next();
00672 
00673             tok = typeEnd;
00674             tokOffset = tok->next();
00675         }
00676 
00677         // check for pointers and references
00678         while (Token::Match(tokOffset, "*|&|const")) {
00679             pointers.push_back(tokOffset->str());
00680             tokOffset = tokOffset->next();
00681         }
00682 
00683         // check for invalid input
00684         if (!tokOffset) {
00685             syntaxError(tok);
00686             return;
00687         }
00688 
00689         if (Token::Match(tokOffset, "%type%")) {
00690             // found the type name
00691             typeName = tokOffset;
00692             tokOffset = tokOffset->next();
00693 
00694             // check for array
00695             if (tokOffset && tokOffset->str() == "[") {
00696                 arrayStart = tokOffset;
00697 
00698                 bool atEnd = false;
00699                 while (!atEnd) {
00700                     while (tokOffset->next() && !Token::Match(tokOffset->next(), ";|,")) {
00701                         tokOffset = tokOffset->next();
00702                     }
00703 
00704                     if (!tokOffset->next())
00705                         return; // invalid input
00706                     else if (tokOffset->next()->str() == ";")
00707                         atEnd = true;
00708                     else if (tokOffset->str() == "]")
00709                         atEnd = true;
00710                     else
00711                         tokOffset = tokOffset->next();
00712                 }
00713 
00714                 arrayEnd = tokOffset;
00715                 tokOffset = tokOffset->next();
00716             }
00717 
00718             // check for end or another
00719             if (Token::Match(tokOffset, ";|,"))
00720                 tok = tokOffset;
00721 
00722             // or a function typedef
00723             else if (tokOffset && tokOffset->str() == "(") {
00724                 // unhandled typedef, skip it and continue
00725                 if (typeName->str() == "void") {
00726                     unsupportedTypedef(typeDef);
00727                     tok = deleteInvalidTypedef(typeDef);
00728                     if (tok == list.front())
00729                         //now the next token to process is 'tok', not 'tok->next()';
00730                         goback = true;
00731                     continue;
00732                 }
00733 
00734                 // unhandled function pointer, skip it and continue
00735                 // TODO: handle such typedefs. See ticket #3314
00736                 else if (Token::Match(tokOffset, "( %type% ::") &&
00737                          Token::Match(tokOffset->link()->tokAt(-3), ":: * %var% ) (")) {
00738                     unsupportedTypedef(typeDef);
00739                     tok = deleteInvalidTypedef(typeDef);
00740                     if (tok == list.front())
00741                         //now the next token to process is 'tok', not 'tok->next()';
00742                         goback = true;
00743                     continue;
00744                 }
00745 
00746                 // function pointer
00747                 else if (Token::Match(tokOffset, "( * %var% ) (")) {
00748                     // name token wasn't a name, it was part of the type
00749                     typeEnd = typeEnd->next();
00750                     functionPtr = true;
00751                     tokOffset = tokOffset->next();
00752                     funcStart = tokOffset;
00753                     funcEnd = tokOffset;
00754                     tokOffset = tokOffset->tokAt(3);
00755                     typeName = tokOffset->tokAt(-2);
00756                     argStart = tokOffset;
00757                     argEnd = tokOffset->link();
00758                     tok = argEnd->next();
00759                 }
00760 
00761                 // function
00762                 else if (Token::Match(tokOffset->link(), ") const| ;|,")) {
00763                     function = true;
00764                     if (tokOffset->link()->next()->str() == "const") {
00765                         specStart = tokOffset->link()->next();
00766                         specEnd = specStart;
00767                     }
00768                     argStart = tokOffset;
00769                     argEnd = tokOffset->link();
00770                     tok = argEnd->next();
00771                     if (specStart)
00772                         tok = tok->next();
00773                 }
00774 
00775                 // syntax error
00776                 else {
00777                     syntaxError(tok);
00778                     return;
00779                 }
00780             }
00781 
00782             // unhandled typedef, skip it and continue
00783             else {
00784                 unsupportedTypedef(typeDef);
00785                 tok = deleteInvalidTypedef(typeDef);
00786                 if (tok == list.front())
00787                     //now the next token to process is 'tok', not 'tok->next()';
00788                     goback = true;
00789                 continue;
00790             }
00791         }
00792 
00793         // typeof: typedef __typeof__ ( ... ) type;
00794         else if (Token::simpleMatch(tokOffset->previous(), "__typeof__ (") &&
00795                  Token::Match(tokOffset->link(), ") %type% ;")) {
00796             argStart = tokOffset;
00797             argEnd = tokOffset->link();
00798             typeName = tokOffset->link()->next();
00799             tok = typeName->next();
00800             typeOf = true;
00801         }
00802 
00803         // function: typedef ... ( .... type )( ... );
00804         //           typedef ... (( .... type )( ... ));
00805         //           typedef ... ( * ( .... type )( ... ));
00806         else if ((tokOffset->str() == "(" &&
00807                   Token::Match(tokOffset->link()->previous(), "%type% ) (") &&
00808                   Token::Match(tokOffset->link()->next()->link(), ") const|volatile|;")) ||
00809                  (Token::simpleMatch(tokOffset, "( (") &&
00810                   Token::Match(tokOffset->next()->link()->previous(), "%type% ) (") &&
00811                   Token::Match(tokOffset->next()->link()->next()->link(), ") const|volatile| ) ;|,")) ||
00812                  (Token::simpleMatch(tokOffset, "( * (") &&
00813                   Token::Match(tokOffset->linkAt(2)->previous(), "%type% ) (") &&
00814                   Token::Match(tokOffset->linkAt(2)->next()->link(), ") const|volatile| ) ;|,"))) {
00815             if (tokOffset->next()->str() == "(")
00816                 tokOffset = tokOffset->next();
00817             else if (Token::simpleMatch(tokOffset, "( * (")) {
00818                 pointers.push_back("*");
00819                 tokOffset = tokOffset->tokAt(2);
00820             }
00821 
00822             if (tokOffset->link()->strAt(-2) == "*")
00823                 functionPtr = true;
00824             else
00825                 function = true;
00826             funcStart = tokOffset->next();
00827             tokOffset = tokOffset->link();
00828             funcEnd = tokOffset->tokAt(-2);
00829             typeName = tokOffset->previous();
00830             argStart = tokOffset->next();
00831             argEnd = tokOffset->next()->link();
00832             tok = argEnd->next();
00833             Token *spec = tok;
00834             if (Token::Match(spec, "const|volatile")) {
00835                 specStart = spec;
00836                 specEnd = spec;
00837                 while (Token::Match(spec->next(), "const|volatile")) {
00838                     specEnd = spec->next();
00839                     spec = specEnd;
00840                 }
00841                 tok = specEnd->next();
00842             }
00843             if (tok->str() == ")")
00844                 tok = tok->next();
00845         }
00846 
00847         else if (Token::Match(tokOffset, "( %type% (")) {
00848             function = true;
00849             if (tokOffset->link()->next()) {
00850                 tok = tokOffset->link()->next();
00851                 tokOffset = tokOffset->tokAt(2);
00852                 typeName = tokOffset->previous();
00853                 argStart = tokOffset;
00854                 argEnd = tokOffset->link();
00855             } else {
00856                 // internal error
00857                 continue;
00858             }
00859         }
00860 
00861         // pointer to function returning pointer to function
00862         else if (Token::Match(tokOffset, "( * ( * %type% ) (") &&
00863                  Token::simpleMatch(tokOffset->linkAt(6), ") ) (") &&
00864                  Token::Match(tokOffset->linkAt(6)->linkAt(2), ") ;|,")) {
00865             functionPtrRetFuncPtr = true;
00866 
00867             tokOffset = tokOffset->tokAt(6);
00868             typeName = tokOffset->tokAt(-2);
00869             argStart = tokOffset;
00870             argEnd = tokOffset->link();
00871 
00872             argFuncRetStart = argEnd->tokAt(2);
00873             argFuncRetEnd = argFuncRetStart->link();
00874 
00875             tok = argFuncRetEnd->next();
00876         }
00877 
00878         // function returning pointer to function
00879         else if (Token::Match(tokOffset, "( * %type% (") &&
00880                  Token::simpleMatch(tokOffset->linkAt(3), ") ) (") &&
00881                  Token::Match(tokOffset->linkAt(3)->linkAt(2), ") ;|,")) {
00882             functionRetFuncPtr = true;
00883 
00884             tokOffset = tokOffset->tokAt(3);
00885             typeName = tokOffset->previous();
00886             argStart = tokOffset;
00887             argEnd = tokOffset->link();
00888 
00889             argFuncRetStart = argEnd->tokAt(2);
00890             argFuncRetEnd = argFuncRetStart->link();
00891 
00892             tok = argFuncRetEnd->next();
00893         } else if (Token::Match(tokOffset, "( * ( %type% ) (")) {
00894             functionRetFuncPtr = true;
00895 
00896             tokOffset = tokOffset->tokAt(5);
00897             typeName = tokOffset->tokAt(-2);
00898             argStart = tokOffset;
00899             argEnd = tokOffset->link();
00900 
00901             argFuncRetStart = argEnd->tokAt(2);
00902             argFuncRetEnd = argFuncRetStart->link();
00903 
00904             tok = argFuncRetEnd->next();
00905         }
00906 
00907         // pointer/reference to array
00908         else if (Token::Match(tokOffset, "( *|& %type% ) [")) {
00909             ptrToArray = (tokOffset->next()->str() == "*");
00910             refToArray = (tokOffset->next()->str() == "&");
00911             tokOffset = tokOffset->tokAt(2);
00912             typeName = tokOffset;
00913             arrayStart = tokOffset->tokAt(2);
00914             arrayEnd = arrayStart->link();
00915             tok = arrayEnd->next();
00916         }
00917 
00918         // pointer to class member
00919         else if (Token::Match(tokOffset, "( %type% :: * %type% ) ;")) {
00920             tokOffset = tokOffset->tokAt(2);
00921             namespaceStart = tokOffset->previous();
00922             namespaceEnd = tokOffset;
00923             ptrMember = true;
00924             tokOffset = tokOffset->tokAt(2);
00925             typeName = tokOffset;
00926             tok = tokOffset->tokAt(2);
00927         }
00928 
00929         // unhandled typedef, skip it and continue
00930         else {
00931             unsupportedTypedef(typeDef);
00932             tok = deleteInvalidTypedef(typeDef);
00933             if (tok == list.front())
00934                 //now the next token to process is 'tok', not 'tok->next()';
00935                 goback = true;
00936             continue;
00937         }
00938 
00939         bool done = false;
00940         bool ok = true;
00941 
00942         while (!done) {
00943             std::string pattern = typeName->str();
00944             int scope = 0;
00945             bool inScope = true;
00946             bool exitThisScope = false;
00947             int exitScope = 0;
00948             bool simplifyType = false;
00949             bool inMemberFunc = false;
00950             int memberScope = 0;
00951             bool globalScope = false;
00952             std::size_t classLevel = spaceInfo.size();
00953 
00954             for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
00955                 // check for end of scope
00956                 if (tok2->str() == "}") {
00957                     // check for end of member function
00958                     if (inMemberFunc) {
00959                         --memberScope;
00960                         if (memberScope == 0)
00961                             inMemberFunc = false;
00962                     }
00963 
00964                     if (classLevel > 0 && tok2 == spaceInfo[classLevel - 1].classEnd) {
00965                         --classLevel;
00966                         pattern.clear();
00967 
00968                         for (std::size_t i = classLevel; i < spaceInfo.size(); ++i)
00969                             pattern += (spaceInfo[i].className + " :: ");
00970 
00971                         pattern += typeName->str();
00972                     } else {
00973                         --scope;
00974                         if (scope < 0)
00975                             inScope = false;
00976 
00977                         if (exitThisScope) {
00978                             if (scope < exitScope)
00979                                 exitThisScope = false;
00980                         }
00981                     }
00982                 }
00983 
00984                 // check for operator typedef
00985                 /** @todo add support for multi-token operators */
00986                 else if (tok2->str() == "operator" &&
00987                          tok2->next()->str() == typeName->str() &&
00988                          tok2->strAt(2) == "(" &&
00989                          Token::Match(tok2->linkAt(2), ") const| {")) {
00990                     // check for qualifier
00991                     if (tok2->previous()->str() == "::") {
00992                         // check for available and matching class name
00993                         if (!spaceInfo.empty() && classLevel < spaceInfo.size() &&
00994                             tok2->strAt(-2) == spaceInfo[classLevel].className) {
00995                             tok2 = tok2->next();
00996                             simplifyType = true;
00997                         }
00998                     }
00999                 }
01000 
01001                 // check for member functions
01002                 else if (Token::Match(tok2, ") const| {")) {
01003                     const Token *func = tok2->link()->previous();
01004                     if (!func)
01005                         continue;
01006 
01007                     if (func->previous()) { // Ticket #4239
01008                         /** @todo add support for multi-token operators */
01009                         if (func->previous()->str() == "operator")
01010                             func = func->previous();
01011 
01012                         // check for qualifier
01013                         if (func->previous()->str() == "::") {
01014                             // check for available and matching class name
01015                             if (!spaceInfo.empty() && classLevel < spaceInfo.size() &&
01016                                 func->strAt(-2) == spaceInfo[classLevel].className) {
01017                                 memberScope = 0;
01018                                 inMemberFunc = true;
01019                             }
01020                         }
01021                     }
01022                 }
01023 
01024                 // check for entering a new namespace
01025                 else if (Token::Match(tok2, "namespace %any% {")) {
01026                     if (classLevel < spaceInfo.size() &&
01027                         spaceInfo[classLevel].isNamespace &&
01028                         spaceInfo[classLevel].className == tok2->next()->str()) {
01029                         ++classLevel;
01030                         pattern.clear();
01031                         for (std::size_t i = classLevel; i < spaceInfo.size(); ++i)
01032                             pattern += (spaceInfo[i].className + " :: ");
01033 
01034                         pattern += typeName->str();
01035                     }
01036                     ++scope;
01037                 }
01038 
01039                 // check for entering a new scope
01040                 else if (tok2->str() == "{") {
01041                     // keep track of scopes within member function
01042                     if (inMemberFunc)
01043                         ++memberScope;
01044 
01045                     ++scope;
01046                 }
01047 
01048                 // check for typedef that can be substituted
01049                 else if (Token::Match(tok2, pattern.c_str()) ||
01050                          (inMemberFunc && tok2->str() == typeName->str())) {
01051                     std::string pattern1;
01052 
01053                     // member function class variables don't need qualification
01054                     if (inMemberFunc && tok2->str() == typeName->str())
01055                         pattern1 = tok2->str();
01056                     else
01057                         pattern1 = pattern;
01058 
01059                     if (pattern1.find("::") != std::string::npos) { // has a "something ::"
01060                         if (tok2->strAt(-1) == "::") {
01061                             tok2->tokAt(-2)->deleteNext();
01062                             globalScope = true;
01063                         }
01064 
01065                         for (std::size_t i = classLevel; i < spaceInfo.size(); ++i) {
01066                             tok2->deleteNext(2);
01067                         }
01068                         simplifyType = true;
01069                     } else if ((inScope && !exitThisScope) || inMemberFunc) {
01070                         if (tok2->strAt(-1) == "::") {
01071                             // Don't replace this typename if it's preceded by "::" unless it's a namespace
01072                             if (!spaceInfo.empty() && (tok2->strAt(-2) == spaceInfo[0].className) && spaceInfo[0].isNamespace) {
01073                                 tok2->tokAt(-3)->deleteNext(2);
01074                                 simplifyType = true;
01075                             }
01076                         } else if (Token::Match(tok2->previous(), "case %type% :")) {
01077                             tok2 = tok2->next();
01078                         } else if (duplicateTypedef(&tok2, typeName, typeDef, undefinedStruct)) {
01079                             exitScope = scope;
01080 
01081                             // skip to end of scope if not already there
01082                             if (tok2->str() != "}") {
01083                                 while (tok2->next()) {
01084                                     if (tok2->next()->str() == "{")
01085                                         tok2 = tok2->linkAt(1)->previous();
01086                                     else if (tok2->next()->str() == "}")
01087                                         break;
01088 
01089                                     tok2 = tok2->next();
01090                                 }
01091                             }
01092                         } else if (tok2->previous()->str() != ".") {
01093                             simplifyType = true;
01094                         }
01095                     }
01096                 }
01097 
01098                 if (simplifyType) {
01099                     // can't simplify 'operator functionPtr ()' and 'functionPtr operator ... ()'
01100                     if (functionPtr && (tok2->previous()->str() == "operator" ||
01101                                         tok2->next()->str() == "operator")) {
01102                         simplifyType = false;
01103                         tok2 = tok2->next();
01104                         continue;
01105                     }
01106 
01107                     // There are 2 categories of typedef substitutions:
01108                     // 1. variable declarations that preserve the variable name like
01109                     //    global, local, and function parameters
01110                     // 2. not variable declarations that have no name like derived
01111                     //    classes, casts, operators, and template parameters
01112 
01113                     // try to determine which category this substitution is
01114                     bool inCast = false;
01115                     bool inTemplate = false;
01116                     bool inOperator = false;
01117                     bool inSizeof = false;
01118 
01119                     // check for derived class: class A : some_typedef {
01120                     bool isDerived = Token::Match(tok2->previous(), "public|protected|private %type% {|,");
01121 
01122                     // check for cast: (some_typedef) A or static_cast<some_typedef>(A)
01123                     // todo: check for more complicated casts like: (const some_typedef *)A
01124                     if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")" && tok2->strAt(-2) != "sizeof") ||
01125                         (tok2->previous()->str() == "<" && Token::simpleMatch(tok2->next(), "> (")))
01126                         inCast = true;
01127 
01128                     // check for template parameters: t<some_typedef> t1
01129                     else if (Token::Match(tok2->previous(), "<|,") &&
01130                              Token::Match(tok2->next(), "&|*| &|*| >|,"))
01131                         inTemplate = true;
01132 
01133                     else if (Token::Match(tok2->tokAt(-2), "sizeof ( %type% )"))
01134                         inSizeof = true;
01135 
01136                     // check for operator
01137                     if (tok2->strAt(-1) == "operator" ||
01138                         Token::simpleMatch(tok2->tokAt(-2), "operator const"))
01139                         inOperator = true;
01140 
01141                     // skip over class or struct in derived class declaration
01142                     bool structRemoved = false;
01143                     if (isDerived && Token::Match(typeStart, "class|struct")) {
01144                         if (typeStart->str() == "struct")
01145                             structRemoved = true;
01146                         typeStart = typeStart->next();
01147                     }
01148 
01149                     // start substituting at the typedef name by replacing it with the type
01150                     tok2->str(typeStart->str());
01151 
01152                     // restore qualification if it was removed
01153                     if (typeStart->str() == "struct" || structRemoved) {
01154                         if (structRemoved)
01155                             tok2 = tok2->previous();
01156 
01157                         if (globalScope) {
01158                             tok2->insertToken("::");
01159                             tok2 = tok2->next();
01160                         }
01161 
01162                         for (std::size_t i = classLevel; i < spaceInfo.size(); ++i) {
01163                             tok2->insertToken(spaceInfo[i].className);
01164                             tok2 = tok2->next();
01165                             tok2->insertToken("::");
01166                             tok2 = tok2->next();
01167                         }
01168                     }
01169 
01170                     // add remainder of type
01171                     tok2 = copyTokens(tok2, typeStart->next(), typeEnd);
01172 
01173                     if (!pointers.empty()) {
01174                         std::list<std::string>::const_iterator iter;
01175                         for (iter = pointers.begin(); iter != pointers.end(); ++iter) {
01176                             tok2->insertToken(*iter);
01177                             tok2 = tok2->next();
01178                         }
01179                     }
01180 
01181                     if (funcStart && funcEnd) {
01182                         tok2->insertToken("(");
01183                         tok2 = tok2->next();
01184                         Token *tok3 = tok2;
01185                         tok2 = copyTokens(tok2, funcStart, funcEnd);
01186 
01187                         if (!inCast)
01188                             tok2 = processFunc(tok2, inOperator);
01189 
01190                         if (!tok2)
01191                             break;
01192 
01193                         tok2->insertToken(")");
01194                         tok2 = tok2->next();
01195                         Token::createMutualLinks(tok2, tok3);
01196 
01197                         tok2 = copyTokens(tok2, argStart, argEnd);
01198 
01199                         if (specStart) {
01200                             Token *spec = specStart;
01201                             tok2->insertToken(spec->str());
01202                             tok2 = tok2->next();
01203                             while (spec != specEnd) {
01204                                 spec = spec->next();
01205                                 tok2->insertToken(spec->str());
01206                                 tok2 = tok2->next();
01207                             }
01208                         }
01209                     }
01210 
01211                     else if (functionPtr || functionRef || function) {
01212                         // don't add parentheses around function names because it
01213                         // confuses other simplifications
01214                         bool needParen = true;
01215                         if (!inTemplate && function && tok2->next() && tok2->next()->str() != "*")
01216                             needParen = false;
01217                         if (needParen) {
01218                             tok2->insertToken("(");
01219                             tok2 = tok2->next();
01220                         }
01221                         Token *tok3 = tok2;
01222                         if (namespaceStart) {
01223                             const Token *tok4 = namespaceStart;
01224 
01225                             while (tok4 != namespaceEnd) {
01226                                 tok2->insertToken(tok4->str());
01227                                 tok2 = tok2->next();
01228                                 tok4 = tok4->next();
01229                             }
01230                             tok2->insertToken(namespaceEnd->str());
01231                             tok2 = tok2->next();
01232                         }
01233                         if (functionPtr) {
01234                             tok2->insertToken("*");
01235                             tok2 = tok2->next();
01236                         } else if (functionRef) {
01237                             tok2->insertToken("&");
01238                             tok2 = tok2->next();
01239                         }
01240 
01241                         if (!inCast)
01242                             tok2 = processFunc(tok2, inOperator);
01243 
01244                         if (needParen) {
01245                             tok2->insertToken(")");
01246                             tok2 = tok2->next();
01247                             Token::createMutualLinks(tok2, tok3);
01248                         }
01249 
01250                         tok2 = copyTokens(tok2, argStart, argEnd);
01251 
01252                         if (inTemplate)
01253                             tok2 = tok2->next();
01254 
01255                         if (specStart) {
01256                             Token *spec = specStart;
01257                             tok2->insertToken(spec->str());
01258                             tok2 = tok2->next();
01259                             while (spec != specEnd) {
01260                                 spec = spec->next();
01261                                 tok2->insertToken(spec->str());
01262                                 tok2 = tok2->next();
01263                             }
01264                         }
01265                     } else if (functionRetFuncPtr || functionPtrRetFuncPtr) {
01266                         tok2->insertToken("(");
01267                         tok2 = tok2->next();
01268                         Token *tok3 = tok2;
01269                         tok2->insertToken("*");
01270                         tok2 = tok2->next();
01271 
01272                         Token * tok4 = 0;
01273                         if (functionPtrRetFuncPtr) {
01274                             tok2->insertToken("(");
01275                             tok2 = tok2->next();
01276                             tok4 = tok2;
01277                             tok2->insertToken("*");
01278                             tok2 = tok2->next();
01279                         }
01280 
01281                         // skip over variable name if there
01282                         if (!inCast) {
01283                             if (tok2->next()->str() != ")")
01284                                 tok2 = tok2->next();
01285                         }
01286 
01287                         if (tok4 && functionPtrRetFuncPtr) {
01288                             tok2->insertToken(")");
01289                             tok2 = tok2->next();
01290                             Token::createMutualLinks(tok2, tok4);
01291                         }
01292 
01293                         tok2 = copyTokens(tok2, argStart, argEnd);
01294 
01295                         tok2->insertToken(")");
01296                         tok2 = tok2->next();
01297                         Token::createMutualLinks(tok2, tok3);
01298 
01299                         tok2 = copyTokens(tok2, argFuncRetStart, argFuncRetEnd);
01300                     } else if (ptrToArray || refToArray) {
01301                         tok2->insertToken("(");
01302                         tok2 = tok2->next();
01303                         Token *tok3 = tok2;
01304 
01305                         if (ptrToArray)
01306                             tok2->insertToken("*");
01307                         else
01308                             tok2->insertToken("&");
01309                         tok2 = tok2->next();
01310 
01311                         // skip over name
01312                         if (tok2->next()->str() != ")") {
01313                             if (tok2->next()->str() != "(")
01314                                 tok2 = tok2->next();
01315 
01316                             // check for function and skip over args
01317                             if (tok2->next()->str() == "(")
01318                                 tok2 = tok2->next()->link();
01319 
01320                             // check for array
01321                             if (tok2->next()->str() == "[")
01322                                 tok2 = tok2->next()->link();
01323                         } else {
01324                             // syntax error
01325                         }
01326 
01327                         tok2->insertToken(")");
01328                         Token::createMutualLinks(tok2->next(), tok3);
01329                     } else if (ptrMember) {
01330                         if (Token::simpleMatch(tok2, "* (")) {
01331                             tok2->insertToken("*");
01332                             tok2 = tok2->next();
01333                         } else {
01334                             tok2->insertToken("(");
01335                             tok2 = tok2->next();
01336                             Token *tok3 = tok2;
01337 
01338                             const Token *tok4 = namespaceStart;
01339 
01340                             while (tok4 != namespaceEnd) {
01341                                 tok2->insertToken(tok4->str());
01342                                 tok2 = tok2->next();
01343                                 tok4 = tok4->next();
01344                             }
01345                             tok2->insertToken(namespaceEnd->str());
01346                             tok2 = tok2->next();
01347 
01348                             tok2->insertToken("*");
01349                             tok2 = tok2->next();
01350 
01351                             // skip over name
01352                             tok2 = tok2->next();
01353 
01354                             tok2->insertToken(")");
01355                             tok2 = tok2->next();
01356                             Token::createMutualLinks(tok2, tok3);
01357                         }
01358                     } else if (typeOf) {
01359                         tok2 = copyTokens(tok2, argStart, argEnd);
01360                     } else if (tok2->tokAt(2) && tok2->strAt(2) == "[") {
01361                         while (tok2->tokAt(2) && tok2->strAt(2) == "[")
01362                             tok2 = tok2->linkAt(2)->previous();
01363                     }
01364 
01365                     if (arrayStart && arrayEnd) {
01366                         do {
01367                             if (!tok2->next()) {
01368                                 syntaxError(tok2);
01369                                 return; // can't recover so quit
01370                             }
01371 
01372                             if (!inCast && !inSizeof)
01373                                 tok2 = tok2->next();
01374 
01375                             // reference to array?
01376                             if (tok2->str() == "&") {
01377                                 tok2 = tok2->previous();
01378                                 tok2->insertToken("(");
01379                                 Token *tok3 = tok2->next();
01380 
01381                                 // handle missing variable name
01382                                 if (tok2->strAt(3) == ")" || tok2->strAt(3) == ",")
01383                                     tok2 = tok2->tokAt(2);
01384                                 else
01385                                     tok2 = tok2->tokAt(3);
01386 
01387                                 tok2->insertToken(")");
01388                                 tok2 = tok2->next();
01389                                 Token::createMutualLinks(tok2, tok3);
01390                             }
01391 
01392                             if (!tok2->next()) {
01393                                 syntaxError(tok2);
01394                                 return; // can't recover so quit
01395                             }
01396 
01397                             tok2 = copyTokens(tok2, arrayStart, arrayEnd);
01398                             tok2 = tok2->next();
01399 
01400                             if (tok2->str() == "=") {
01401                                 if (tok2->next()->str() == "{")
01402                                     tok2 = tok2->next()->link()->next();
01403                                 else if (tok2->next()->str().at(0) == '\"')
01404                                     tok2 = tok2->tokAt(2);
01405                             }
01406                         } while (Token::Match(tok2, ", %var% ;|'|=|,"));
01407                     }
01408 
01409                     simplifyType = false;
01410                 }
01411             }
01412 
01413             if (tok->str() == ";")
01414                 done = true;
01415             else if (tok->str() == ",") {
01416                 arrayStart = 0;
01417                 arrayEnd = 0;
01418                 tokOffset = tok->next();
01419                 pointers.clear();
01420 
01421                 while (Token::Match(tokOffset, "*|&")) {
01422                     pointers.push_back(tokOffset->str());
01423                     tokOffset = tokOffset->next();
01424                 }
01425 
01426                 if (Token::Match(tokOffset, "%type%")) {
01427                     typeName = tokOffset;
01428                     tokOffset = tokOffset->next();
01429 
01430                     if (tokOffset && tokOffset->str() == "[") {
01431                         arrayStart = tokOffset;
01432 
01433                         bool atEnd = false;
01434                         while (!atEnd) {
01435                             while (tokOffset->next() && !Token::Match(tokOffset->next(), ";|,"))
01436                                 tokOffset = tokOffset->next();
01437 
01438                             if (!tokOffset->next())
01439                                 return; // invalid input
01440                             else if (tokOffset->next()->str() == ";")
01441                                 atEnd = true;
01442                             else if (tokOffset->str() == "]")
01443                                 atEnd = true;
01444                             else
01445                                 tokOffset = tokOffset->next();
01446                         }
01447 
01448                         arrayEnd = tokOffset;
01449                         tokOffset = tokOffset->next();
01450                     }
01451 
01452                     if (Token::Match(tokOffset, ";|,"))
01453                         tok = tokOffset;
01454                     else {
01455                         // we encountered a typedef we don't support yet so just continue
01456                         done = true;
01457                         ok = false;
01458                     }
01459                 } else {
01460                     // we encountered a typedef we don't support yet so just continue
01461                     done = true;
01462                     ok = false;
01463                 }
01464             } else {
01465                 // something is really wrong (internal error)
01466                 done = true;
01467                 ok = false;
01468             }
01469         }
01470 
01471         if (ok) {
01472             // remove typedef
01473             Token::eraseTokens(typeDef, tok);
01474 
01475             if (typeDef != list.front()) {
01476                 tok = typeDef->previous();
01477                 tok->deleteNext();
01478                 //no need to remove last token in the list
01479                 if (tok->tokAt(2))
01480                     tok->deleteNext();
01481             } else {
01482                 list.front()->deleteThis();
01483                 //no need to remove last token in the list
01484                 if (list.front()->next())
01485                     list.front()->deleteThis();
01486                 tok = list.front();
01487                 //now the next token to process is 'tok', not 'tok->next()';
01488                 goback = true;
01489             }
01490         }
01491     }
01492 }
01493 
01494 void Tokenizer::simplifyMulAndParens()
01495 {
01496     for (Token *tok = list.front()->tokAt(3); tok; tok = tok->next()) {
01497         if (tok->isName()) {
01498             //fix ticket #2784 - improved by ticket #3184
01499             unsigned int closedpars = 0;
01500             Token *tokend = tok->next();
01501             Token *tokbegin = tok->previous();
01502             while (tokend && tokend->str() == ")") {
01503                 ++closedpars;
01504                 tokend = tokend->next();
01505             }
01506             if (!tokend || !(tokend->isAssignmentOp()))
01507                 continue;
01508             while (tokbegin && (tokbegin->str() == "&" || tokbegin->str() == "(")) {
01509                 if (tokbegin->str() == "&") {
01510                     if (Token::Match(tokbegin->tokAt(-2), "[;{}&(] *")) {
01511                         //remove '* &'
01512                         tokbegin = tokbegin->tokAt(-2);
01513                         tokbegin->deleteNext(2);
01514                     } else if (Token::Match(tokbegin->tokAt(-3), "[;{}&(] * (")) {
01515                         if (!closedpars)
01516                             break;
01517                         --closedpars;
01518                         //remove ')'
01519                         tok->deleteNext();
01520                         //remove '* ( &'
01521                         tokbegin = tokbegin->tokAt(-3);
01522                         tokbegin->deleteNext(3);
01523                     } else
01524                         break;
01525                 } else if (tokbegin->str() == "(") {
01526                     if (!closedpars)
01527                         break;
01528 
01529                     //find consecutive opening parentheses
01530                     unsigned int openpars = 0;
01531                     while (tokbegin && tokbegin->str() == "(" && openpars <= closedpars) {
01532                         ++openpars;
01533                         tokbegin = tokbegin->previous();
01534                     }
01535                     if (!tokbegin || openpars > closedpars)
01536                         break;
01537 
01538                     if ((openpars == closedpars && Token::Match(tokbegin, "[;{}]")) ||
01539                         Token::Match(tokbegin->tokAt(-2), "[;{}&(] * &") ||
01540                         Token::Match(tokbegin->tokAt(-3), "[;{}&(] * ( &")) {
01541                         //remove the excessive parentheses around the variable
01542                         while (openpars--) {
01543                             tok->deleteNext();
01544                             tokbegin->deleteNext();
01545                             --closedpars;
01546                         }
01547                     } else
01548                         break;
01549                 }
01550             }
01551         }
01552     }
01553 }
01554 
01555 bool Tokenizer::tokenize(std::istream &code,
01556                          const char FileName[],
01557                          const std::string &configuration)
01558 {
01559     // make sure settings specified
01560     assert(_settings);
01561 
01562     // Fill the map _typeSize..
01563     fillTypeSizes();
01564 
01565     _configuration = configuration;
01566 
01567     if (!list.createTokens(code, Path::getRelativePath(Path::simplifyPath(FileName), _settings->_basePaths))) {
01568         cppcheckError(0);
01569         return false;
01570     }
01571 
01572     // if MACRO
01573     for (Token *tok = list.front(); tok; tok = tok->next()) {
01574         if (Token::Match(tok, "if|for|while|BOOST_FOREACH %var% (")) {
01575             if (Token::simpleMatch(tok, "for each"))
01576                 // 'for each ( )' -> 'for ( )'
01577                 tok->deleteNext();
01578             else {
01579                 syntaxError(tok);
01580                 return false;
01581             }
01582         }
01583     }
01584 
01585     // remove MACRO in variable declaration: MACRO int x;
01586     removeMacroInVarDecl();
01587 
01588     // Combine strings
01589     combineStrings();
01590 
01591     // replace inline SQL with "asm()" (Oracle PRO*C). Ticket: #1959
01592     simplifySQL();
01593 
01594     // replace __LINE__ macro with line number
01595     simplifyFileAndLineMacro();
01596 
01597     // Concatenate double sharp: 'a ## b' -> 'ab'
01598     concatenateDoubleSharp();
01599 
01600     if (!createLinks()) {
01601         // Source has syntax errors, can't proceed
01602         return false;
01603     }
01604 
01605     // replace 'NULL' and similar '0'-defined macros with '0'
01606     simplifyNull();
01607 
01608     // replace 'sin(0)' to '0' and other similar math expressions
01609     simplifyMathExpressions();
01610 
01611     // combine "- %num%"
01612     concatenateNegativeNumberAndAnyPositive();
01613 
01614     // simplify simple calculations
01615     for (Token *tok = list.front() ? list.front()->next() : NULL; tok; tok = tok->next()) {
01616         if (tok->isNumber())
01617             TemplateSimplifier::simplifyNumericCalculations(tok->previous());
01618     }
01619 
01620     // remove extern "C" and extern "C" {}
01621     if (isCPP())
01622         simplifyExternC();
01623 
01624     // simplify weird but legal code: "[;{}] ( { code; } ) ;"->"[;{}] code;"
01625     simplifyRoundCurlyParentheses();
01626 
01627     // check for simple syntax errors..
01628     for (const Token *tok = list.front(); tok; tok = tok->next()) {
01629         if (Token::simpleMatch(tok, "> struct {") &&
01630             Token::simpleMatch(tok->linkAt(2), "} ;")) {
01631             syntaxError(tok);
01632             list.deallocateTokens();
01633             return false;
01634         }
01635     }
01636 
01637     if (!simplifyAddBraces())
01638         return false;
01639 
01640     // Combine tokens..
01641     combineOperators();
01642 
01643     // Simplify: 0[foo] -> *(foo)
01644     for (Token* tok = list.front(); tok; tok = tok->next()) {
01645         if (Token::simpleMatch(tok, "0 [") && tok->linkAt(1)) {
01646             tok->str("*");
01647             tok->next()->str("(");
01648             tok->linkAt(1)->str(")");
01649         }
01650     }
01651 
01652     // Remove "volatile", "inline", "register", and "restrict"
01653     simplifyKeyword();
01654 
01655     // Convert K&R function declarations to modern C
01656     simplifyVarDecl(true);
01657     if (!simplifyFunctionParameters())
01658         return false;
01659 
01660     // specify array size..
01661     arraySize();
01662 
01663     // simplify labels and 'case|default'-like syntaxes
01664     if (!simplifyLabelsCaseDefault())
01665         return false;
01666 
01667     // simplify '[;{}] * & ( %any% ) =' to '%any% ='
01668     simplifyMulAndParens();
01669 
01670     // ";a+=b;" => ";a=a+b;"
01671     simplifyCompoundAssignment();
01672 
01673     if (hasComplicatedSyntaxErrorsInTemplates()) {
01674         list.deallocateTokens();
01675         return false;
01676     }
01677 
01678     // Remove __declspec()
01679     simplifyDeclspec();
01680 
01681     // remove some unhandled macros in global scope
01682     removeMacrosInGlobalScope();
01683 
01684     // remove calling conventions __cdecl, __stdcall..
01685     simplifyCallingConvention();
01686 
01687     // remove __attribute__((?))
01688     simplifyAttribute();
01689 
01690     // remove unnecessary member qualification..
01691     removeUnnecessaryQualification();
01692 
01693     // Add std:: in front of std classes, when using namespace std; was given
01694     simplifyNamespaceStd();
01695 
01696     // remove Microsoft MFC..
01697     simplifyMicrosoftMFC();
01698 
01699     // convert Microsoft memory functions
01700     simplifyMicrosoftMemoryFunctions();
01701 
01702     // convert Microsoft string functions
01703     simplifyMicrosoftStringFunctions();
01704 
01705     // Remove Qt signals and slots
01706     simplifyQtSignalsSlots();
01707 
01708     // remove Borland stuff..
01709     simplifyBorland();
01710 
01711     // Remove __builtin_expect, likely and unlikely
01712     simplifyBuiltinExpect();
01713 
01714     if (hasEnumsWithTypedef()) {
01715         // #2449: syntax error: enum with typedef in it
01716         list.deallocateTokens();
01717         return false;
01718     }
01719 
01720     simplifyDebugNew();
01721 
01722     // typedef..
01723     if (m_timerResults) {
01724         Timer t("Tokenizer::tokenize::simplifyTypedef", _settings->_showtime, m_timerResults);
01725         simplifyTypedef();
01726     } else {
01727         simplifyTypedef();
01728     }
01729 
01730     for (Token* tok = list.front(); tok;) {
01731         if (Token::Match(tok, "union|struct|class union|struct|class"))
01732             tok->deleteNext();
01733         else
01734             tok = tok->next();
01735     }
01736 
01737     // class x y {
01738     if (_settings->isEnabled("information")) {
01739         for (const Token *tok = list.front(); tok; tok = tok->next()) {
01740             if (Token::Match(tok, "class %type% %type% [:{]")) {
01741                 unhandled_macro_class_x_y(tok);
01742             }
01743         }
01744     }
01745 
01746     // catch bad typedef canonicalization
01747     //
01748     // to reproduce bad typedef, download upx-ucl from:
01749     // http://packages.debian.org/sid/upx-ucl
01750     // analyse the file src/stub/src/i386-linux.elf.interp-main.c
01751     if (!validate()) {
01752         // Source has syntax errors, can't proceed
01753         return false;
01754     }
01755 
01756     // enum..
01757     simplifyEnum();
01758 
01759     // Remove __asm..
01760     simplifyAsm();
01761 
01762     // When the assembly code has been cleaned up, no @ is allowed
01763     for (const Token *tok = list.front(); tok; tok = tok->next()) {
01764         if (tok->str() == "(")
01765             tok = tok->link();
01766         else if (tok->str()[0] == '@') {
01767             list.deallocateTokens();
01768             return false;
01769         }
01770     }
01771 
01772     // convert platform dependent types to standard types
01773     // 32 bits: size_t -> unsigned long
01774     // 64 bits: size_t -> unsigned long long
01775     simplifyPlatformTypes();
01776 
01777     // collapse compound standard types into a single token
01778     // unsigned long long int => long _isUnsigned=true,_isLong=true
01779     simplifyStdType();
01780 
01781     // simplify bit fields..
01782     simplifyBitfields();
01783 
01784     // Use "<" comparison instead of ">"
01785     simplifyComparisonOrder();
01786 
01787     // Simplify '(p == 0)' to '(!p)'
01788     simplifyIfNot();
01789     simplifyIfNotNull();
01790 
01791     //simplify for: move out start-statement "for (a;b;c);" => "{ a; for(;b;c); }"
01792     //not enabled because it fails many tests with testrunner.
01793     //@todo fix these fails before enabling this simplification
01794     /*for (Token* tok = list.front(); tok; tok = tok->next()) {
01795         if (tok->str() == "(" && ( !tok->previous() || tok->previous()->str() != "for")) {
01796             tok = tok->link();
01797             continue;
01798         }
01799         if (!Token::Match(tok->previous(),"[{};] for ("))
01800             continue;
01801 
01802         //find the two needed semicolons inside the 'for'
01803         const Token *firstsemicolon = Token::findsimplematch(tok->next(), ";", tok->next()->link());
01804         if (!firstsemicolon)
01805             continue;
01806         const Token *secondsemicolon = Token::findsimplematch(firstsemicolon->next(), ";", tok->next()->link());
01807         if (!secondsemicolon)
01808             continue;
01809         if (Token::findsimplematch(secondsemicolon->next(), ";", tok->next()->link()))
01810             continue;       //no more than two semicolons!
01811         if (!tok->next()->link()->next())
01812             continue;       //there should be always something after 'for (...)'
01813 
01814         Token *fortok = tok;
01815         Token *begin = tok->tokAt(2);
01816         Token *end = tok->next()->link();
01817         if ( begin->str() != ";" ) {
01818             tok = tok->previous();
01819             tok->insertToken(";");
01820             tok->insertToken("{");
01821             tok = tok->next();
01822             if (end->next()->str() =="{") {
01823                 end = end->next()->link();
01824                 end->insertToken("}");
01825                 Token::createMutualLinks(tok, end->next());
01826                 end = end->link()->previous();
01827             } else {
01828                 if (end->next()->str() != ";")
01829                     end->insertToken(";");
01830                 end = end->next();
01831                 end->insertToken("}");
01832                 Token::createMutualLinks(tok, end->next());
01833             }
01834             end = firstsemicolon->previous();
01835             Token::move(begin, end, tok);
01836             tok = fortok;
01837             end = fortok->next()->link();
01838         }
01839         //every 'for' is changed to 'for(;b;c), now it's possible to convert the 'for' to a 'while'.
01840         //precisely, 'for(;b;c){code}'-> 'while(b){code + c;}'
01841         fortok->str("while");
01842         begin = firstsemicolon->previous();
01843         begin->deleteNext();
01844         begin = secondsemicolon->previous();
01845         begin->deleteNext();
01846         begin = begin->next();
01847         if (begin->str() == ")") {        //'for(;b;)' -> 'while(b)'
01848             if (begin->previous()->str() == "(")    //'for(;;)' -> 'while(true)'
01849                 begin->previous()->insertToken("true");
01850             tok = fortok;
01851             continue;
01852         }
01853         if (end->next()->str() =="{") {
01854             tok = end->next()->link()->previous();
01855             tok->insertToken(";");
01856         } else {
01857             tok = end;
01858             if (end->next()->str() != ";")
01859                 tok->insertToken(";");
01860             tok->insertToken("{");
01861             tok = tok->tokAt(2);
01862             tok->insertToken("}");
01863             Token::createMutualLinks(tok->previous(), tok->next());
01864             tok = tok->previous();
01865         }
01866         end = end->previous();
01867         Token::move(begin, end, tok);
01868         tok = fortok;
01869     }*/
01870 
01871     simplifyConst();
01872 
01873     // struct simplification "struct S {} s; => struct S { } ; S s ;
01874     simplifyStructDecl();
01875 
01876     // struct initialization (must be used before simplifyVarDecl)
01877     simplifyStructInit();
01878 
01879     // Change initialisation of variable to assignment
01880     simplifyInitVar();
01881 
01882     // Split up variable declarations.
01883     simplifyVarDecl(false);
01884 
01885     // specify array size.. needed when arrays are split
01886     arraySize();
01887 
01888     // f(x=g())   =>   x=g(); f(x)
01889     simplifyAssignmentInFunctionCall();
01890 
01891     // x = ({ 123; });  =>   { x = 123; }
01892     simplifyAssignmentBlock();
01893 
01894     simplifyVariableMultipleAssign();
01895 
01896     // Remove redundant parentheses
01897     simplifyRedundantParentheses();
01898     for (Token *tok = list.front(); tok; tok = tok->next())
01899         while (TemplateSimplifier::simplifyNumericCalculations(tok))
01900             ;
01901 
01902     // Handle templates..
01903     simplifyTemplates();
01904 
01905     // Simplify templates.. sometimes the "simplifyTemplates" fail and
01906     // then unsimplified function calls etc remain. These have the
01907     // "wrong" syntax. So this function will just fix so that the
01908     // syntax is corrected.
01909     TemplateSimplifier::cleanupAfterSimplify(list.front());
01910 
01911     // Simplify the operator "?:"
01912     simplifyConditionOperator();
01913 
01914     // remove exception specifications..
01915     removeExceptionSpecifications();
01916 
01917     // Collapse operator name tokens into single token
01918     // operator = => operator=
01919     simplifyOperatorName();
01920 
01921     // Simplify pointer to standard types (C only)
01922     simplifyPointerToStandardType();
01923 
01924     // simplify function pointers
01925     simplifyFunctionPointers();
01926 
01927     // "if (not p)" => "if (!p)"
01928     // "if (p and q)" => "if (p && q)"
01929     // "if (p or q)" => "if (p || q)"
01930     while (simplifyLogicalOperators()) { }
01931 
01932     // Change initialisation of variable to assignment
01933     simplifyInitVar();
01934 
01935     // Split up variable declarations.
01936     simplifyVarDecl(false);
01937 
01938     if (m_timerResults) {
01939         Timer t("Tokenizer::tokenize::setVarId", _settings->_showtime, m_timerResults);
01940         setVarId();
01941     } else {
01942         setVarId();
01943     }
01944 
01945     createLinks2();
01946 
01947     // Change initialisation of variable to assignment
01948     simplifyInitVar();
01949 
01950     // Convert e.g. atol("0") into 0
01951     simplifyMathFunctions();
01952 
01953     simplifyDoublePlusAndDoubleMinus();
01954 
01955     simplifyArrayAccessSyntax();
01956 
01957     list.front()->assignProgressValues();
01958 
01959     removeRedundantSemicolons();
01960 
01961     simplifyParameterVoid();
01962 
01963     simplifyRedundantConsecutiveBraces();
01964 
01965     simplifyEmptyNamespaces();
01966 
01967     bool valid = validate();
01968     if (valid)
01969         createSymbolDatabase();
01970     return valid;
01971 }
01972 //---------------------------------------------------------------------------
01973 
01974 bool Tokenizer::tokenizeCondition(const std::string &code)
01975 {
01976     assert(_settings);
01977 
01978     // Fill the map _typeSize..
01979     fillTypeSizes();
01980 
01981     {
01982         std::istringstream istr(code);
01983         if (!list.createTokens(istr, "")) {
01984             cppcheckError(0);
01985             return false;
01986         }
01987     }
01988 
01989     // Combine strings
01990     combineStrings();
01991 
01992     // Remove "volatile", "inline", "register", and "restrict"
01993     simplifyKeyword();
01994 
01995     // convert platform dependent types to standard types
01996     // 32 bits: size_t -> unsigned long
01997     // 64 bits: size_t -> unsigned long long
01998     simplifyPlatformTypes();
01999 
02000     // collapse compound standard types into a single token
02001     // unsigned long long int => long _isUnsigned=true,_isLong=true
02002     simplifyStdType();
02003 
02004     // Concatenate double sharp: 'a ## b' -> 'ab'
02005     concatenateDoubleSharp();
02006 
02007     if (!createLinks()) {
02008         // Source has syntax errors, can't proceed
02009         return false;
02010     }
02011 
02012     // replace 'NULL' and similar '0'-defined macros with '0'
02013     simplifyNull();
02014 
02015     // replace 'sin(0)' to '0' and other similar math expressions
02016     simplifyMathExpressions();
02017 
02018     // combine "- %num%"
02019     concatenateNegativeNumberAndAnyPositive();
02020 
02021     // simplify simple calculations
02022     for (Token *tok = list.front() ? list.front()->next() : NULL;
02023          tok;
02024          tok = tok->next()) {
02025         if (tok->isNumber())
02026             TemplateSimplifier::simplifyNumericCalculations(tok->previous());
02027     }
02028 
02029     combineOperators();
02030 
02031     simplifyRedundantParentheses();
02032     for (Token *tok = list.front();
02033          tok;
02034          tok = tok->next())
02035         while (TemplateSimplifier::simplifyNumericCalculations(tok))
02036             ;
02037 
02038     while (simplifyLogicalOperators()) { }
02039 
02040     // Convert e.g. atol("0") into 0
02041     simplifyMathFunctions();
02042 
02043     simplifyDoublePlusAndDoubleMinus();
02044 
02045     return true;
02046 }
02047 
02048 bool Tokenizer::hasComplicatedSyntaxErrorsInTemplates()
02049 {
02050     const Token *tok = TemplateSimplifier::hasComplicatedSyntaxErrorsInTemplates(list.front());
02051     if (tok) {
02052         syntaxError(tok);
02053         return true;
02054     }
02055 
02056     return false;
02057 }
02058 
02059 bool Tokenizer::hasEnumsWithTypedef()
02060 {
02061     for (const Token *tok = list.front(); tok; tok = tok->next()) {
02062         if (Token::Match(tok, "enum %var% {")) {
02063             tok = tok->tokAt(2);
02064             const Token *tok2 = Token::findsimplematch(tok, "typedef", tok->link());
02065             if (tok2) {
02066                 syntaxError(tok2);
02067                 return true;
02068             }
02069         }
02070     }
02071 
02072     return false;
02073 }
02074 
02075 void Tokenizer::fillTypeSizes()
02076 {
02077     _typeSize.clear();
02078     _typeSize["char"] = 1;
02079     _typeSize["bool"] = _settings->sizeof_bool;
02080     _typeSize["short"] = _settings->sizeof_short;
02081     _typeSize["int"] = _settings->sizeof_int;
02082     _typeSize["long"] = _settings->sizeof_long;
02083     _typeSize["float"] = _settings->sizeof_float;
02084     _typeSize["double"] = _settings->sizeof_double;
02085     _typeSize["wchar_t"] = _settings->sizeof_wchar_t;
02086     _typeSize["size_t"] = _settings->sizeof_size_t;
02087     _typeSize["*"] = _settings->sizeof_pointer;
02088 }
02089 
02090 void Tokenizer::combineOperators()
02091 {
02092     // Combine tokens..
02093     for (Token *tok = list.front();
02094          tok && tok->next();
02095          tok = tok->next()) {
02096         const char c1 = tok->str()[0];
02097 
02098         if (tok->str().length() == 1 && tok->next()->str().length() == 1) {
02099             const char c2 = tok->next()->str()[0];
02100 
02101             // combine +-*/ and =
02102             if (c2 == '=' && (std::strchr("+-*/%&|^=!<>", c1))) {
02103                 tok->str(tok->str() + c2);
02104                 tok->deleteNext();
02105                 continue;
02106             }
02107 
02108             // replace "->" with "."
02109             else if (c1 == '-' && c2 == '>') {
02110                 tok->str(".");
02111                 tok->deleteNext();
02112                 continue;
02113             }
02114         }
02115 
02116         else if (tok->str() == ">>" && tok->next()->str() == "=") {
02117             tok->str(">>=");
02118             tok->deleteNext();
02119         }
02120 
02121         else if (tok->str() == "<<" && tok->next()->str() == "=") {
02122             tok->str("<<=");
02123             tok->deleteNext();
02124         }
02125 
02126         else if ((c1 == 'p' || c1 == '_') && tok->next()->str() == ":" && tok->strAt(2) != ":") {
02127             if (tok->str() == "private" || tok->str() == "protected" || tok->str() == "public" || tok->str() == "__published") {
02128                 tok->str(tok->str() + ":");
02129                 tok->deleteNext();
02130                 continue;
02131             }
02132         }
02133     }
02134 }
02135 
02136 void Tokenizer::combineStrings()
02137 {
02138     // Combine wide strings
02139     for (Token *tok = list.front();
02140          tok;
02141          tok = tok->next()) {
02142         while (tok->str() == "L" && tok->next() && tok->next()->type() == Token::eString) {
02143             // Combine 'L "string"'
02144             tok->str(tok->next()->str());
02145             tok->deleteNext();
02146             tok->isLong(true);
02147         }
02148     }
02149 
02150     // Combine strings
02151     for (Token *tok = list.front();
02152          tok;
02153          tok = tok->next()) {
02154         if (tok->str()[0] != '"')
02155             continue;
02156 
02157         tok->str(simplifyString(tok->str()));
02158         while (tok->next() && tok->next()->type() == Token::eString) {
02159             tok->next()->str(simplifyString(tok->next()->str()));
02160 
02161             // Two strings after each other, combine them
02162             tok->concatStr(tok->next()->str());
02163             tok->deleteNext();
02164         }
02165     }
02166 }
02167 
02168 void Tokenizer::concatenateDoubleSharp()
02169 {
02170     for (Token *tok = list.front(); tok; tok = tok->next()) {
02171         while (Token::Match(tok, "%num%|%var% ## %num%|%var%")) {
02172             tok->str(tok->str() + tok->strAt(2));
02173             tok->deleteNext(2);
02174         }
02175     }
02176 }
02177 
02178 void Tokenizer::simplifyFileAndLineMacro()
02179 {
02180     for (Token *tok = list.front(); tok; tok = tok->next()) {
02181         if (tok->str() == "__FILE__")
02182             tok->str(list.file(tok));
02183         else if (tok->str() == "__LINE__")
02184             tok->str(MathLib::longToString(tok->linenr()));
02185     }
02186 }
02187 
02188 void Tokenizer::simplifyNull()
02189 {
02190     for (Token *tok = list.front(); tok; tok = tok->next()) {
02191         if (tok->str() == "NULL" && !Token::Match(tok->previous(), "[(,] NULL [,)]"))
02192             tok->str("0");
02193         else if (tok->str() == "__null" || tok->str() == "'\\0'" || tok->str() == "'\\x0'")
02194             tok->str("0");
02195         else if (tok->isNumber() &&
02196                  MathLib::isInt(tok->str()) &&
02197                  MathLib::toLongNumber(tok->str()) == 0)
02198             tok->str("0");
02199     }
02200 
02201     // nullptr..
02202     if (isCPP() && _settings->standards.cpp == Standards::CPP11) {
02203         for (Token *tok = list.front(); tok; tok = tok->next()) {
02204             if (tok->str() == "nullptr")
02205                 tok->str("0");
02206         }
02207     }
02208 }
02209 
02210 void Tokenizer::concatenateNegativeNumberAndAnyPositive()
02211 {
02212     for (Token *tok = list.front(); tok; tok = tok->next()) {
02213         if (!Token::Match(tok, "?|:|,|(|[|{|return|case|sizeof|%op% +|-") || tok->type() == Token::eIncDecOp)
02214             continue;
02215         if (tok->next()->str() == "+")
02216             tok->deleteNext();
02217         else if (Token::Match(tok->next(), "- %num%")) {
02218             tok->deleteNext();
02219             tok->next()->str("-" + tok->next()->str());
02220         }
02221     }
02222 }
02223 
02224 void Tokenizer::simplifyExternC()
02225 {
02226     for (Token *tok = list.front(); tok; tok = tok->next()) {
02227         if (Token::Match(tok, "extern \"C\" {|")) {
02228             if (tok->strAt(2) == "{") {
02229                 tok->linkAt(2)->deleteThis();
02230                 tok->deleteNext(2);
02231             } else
02232                 tok->deleteNext();
02233             tok->deleteThis();
02234         }
02235     }
02236 }
02237 
02238 void Tokenizer::simplifyRoundCurlyParentheses()
02239 {
02240     for (Token *tok = list.front(); tok; tok = tok->next()) {
02241         while (Token::Match(tok, "[;{}] ( {") &&
02242                Token::simpleMatch(tok->linkAt(2), "} ) ;")) {
02243             tok->linkAt(2)->previous()->deleteNext(3);
02244             tok->deleteNext(2);
02245         }
02246         if (Token::Match(tok, "( { %bool%|%char%|%num%|%str%|%var% ; } )")) {
02247             tok->deleteNext();
02248             tok->deleteThis();
02249             tok->deleteNext(3);
02250         }
02251     }
02252 }
02253 
02254 void Tokenizer::simplifySQL()
02255 {
02256     for (Token *tok = list.front(); tok; tok = tok->next()) {
02257         if (Token::simpleMatch(tok, "EXEC SQL")) {
02258             const Token *end = tok->tokAt(2);
02259             while (end && end->str() != ";")
02260                 end = end->next();
02261 
02262             std::string instruction = tok->stringifyList(end);
02263             // delete all tokens until ';'
02264             Token::eraseTokens(tok, end);
02265 
02266             // insert "asm ( "instruction" ) ;"
02267             tok->str("asm");
02268             // it can happen that 'end' is NULL when wrong code is inserted
02269             if (!tok->next())
02270                 tok->insertToken(";");
02271             tok->insertToken(")");
02272             tok->insertToken("\"" + instruction + "\"");
02273             tok->insertToken("(");
02274             // jump to ';' and continue
02275             tok = tok->tokAt(3);
02276         }
02277     }
02278 }
02279 
02280 void Tokenizer::simplifyDebugNew()
02281 {
02282     // convert Microsoft DEBUG_NEW macro to new
02283     for (Token *tok = list.front(); tok; tok = tok->next()) {
02284         if (tok->str() == "DEBUG_NEW")
02285             tok->str("new");
02286     }
02287 }
02288 
02289 void Tokenizer::simplifyArrayAccessSyntax()
02290 {
02291     // 0[a] -> a[0]
02292     for (Token *tok = list.front(); tok; tok = tok->next()) {
02293         if (Token::Match(tok, "%num% [ %var% ]")) {
02294             const std::string temp = tok->str();
02295             tok->str(tok->strAt(2));
02296             tok->tokAt(2)->str(temp);
02297         }
02298     }
02299 }
02300 
02301 void Tokenizer::simplifyParameterVoid()
02302 {
02303     for (Token* tok = list.front(); tok; tok = tok->next()) {
02304         if (Token::Match(tok, "%var% ( void )"))
02305             tok->next()->deleteNext();
02306     }
02307 }
02308 
02309 void Tokenizer::simplifyRedundantConsecutiveBraces()
02310 {
02311     // Remove redundant consecutive braces, i.e. '.. { { .. } } ..' -> '.. { .. } ..'.
02312     for (Token *tok = list.front(); tok;) {
02313         if (Token::simpleMatch(tok, "= {")) {
02314             tok = tok->linkAt(1);
02315         } else if (Token::simpleMatch(tok, "{ {") && Token::simpleMatch(tok->next()->link(), "} }")) {
02316             //remove internal parentheses
02317             tok->next()->link()->deleteThis();
02318             tok->deleteNext();
02319         } else
02320             tok = tok->next();
02321     }
02322 }
02323 
02324 void Tokenizer::simplifyDoublePlusAndDoubleMinus()
02325 {
02326     // Convert + + into + and + - into -
02327     for (Token *tok = list.front(); tok; tok = tok->next()) {
02328         while (tok->next()) {
02329             if (tok->str() == "+") {
02330                 if (tok->next()->str() == "+") {
02331                     tok->deleteNext();
02332                     continue;
02333                 } else if (tok->next()->str()[0] == '-') {
02334                     tok = tok->next();
02335                     if (tok->str().size() == 1) {
02336                         tok = tok->previous();
02337                         tok->str("-");
02338                         tok->deleteNext();
02339                     } else if (tok->isNumber()) {
02340                         tok->str(tok->str().substr(1));
02341                         tok = tok->previous();
02342                         tok->str("-");
02343                     }
02344                     continue;
02345                 }
02346             } else if (tok->str() == "-") {
02347                 if (tok->next()->str() == "+") {
02348                     tok->deleteNext();
02349                     continue;
02350                 } else if (tok->next()->str()[0] == '-') {
02351                     tok = tok->next();
02352                     if (tok->str().size() == 1) {
02353                         tok = tok->previous();
02354                         tok->str("+");
02355                         tok->deleteNext();
02356                     } else if (tok->isNumber()) {
02357                         tok->str(tok->str().substr(1));
02358                         tok = tok->previous();
02359                         tok->str("+");
02360                     }
02361                     continue;
02362                 }
02363             }
02364 
02365             break;
02366         }
02367     }
02368 }
02369 
02370 /** Specify array size if it hasn't been given */
02371 
02372 void Tokenizer::arraySize()
02373 {
02374     bool addlength = false;
02375     for (Token *tok = list.front(); tok; tok = tok->next()) {
02376         if (Token::Match(tok, "%var% [ ] = { %str% } ;")) {
02377             Token *t = tok->tokAt(3);
02378             t->deleteNext();
02379             t->next()->deleteNext();
02380             addlength = true;
02381         }
02382 
02383         if (addlength || Token::Match(tok, "%var% [ ] = %str% ;")) {
02384             tok = tok->next();
02385             std::size_t sz = tok->strAt(3).length() - 1;
02386             tok->insertToken(MathLib::longToString((unsigned int)sz));
02387             addlength = false;
02388             tok = tok->tokAt(5);
02389         }
02390 
02391         else if (Token::Match(tok, "%var% [ ] = {")) {
02392             unsigned int sz = 1;
02393             tok = tok->next();
02394             Token *end = tok->linkAt(3);
02395             for (Token *tok2 = tok->tokAt(4); tok2 && tok2 != end; tok2 = tok2->next()) {
02396                 if (tok2->str() == "{" || tok2->str() == "(" || tok2->str() == "[")
02397                     tok2 = tok2->link();
02398                 else if (tok2->str() == "<") { // Bailout. TODO: When link() supports <>, this bailout becomes unnecessary
02399                     sz = 0;
02400                     break;
02401                 } else if (tok2->str() == ",") {
02402                     if (!Token::Match(tok2->next(), "[},]"))
02403                         ++sz;
02404                     else {
02405                         tok2 = tok2->previous();
02406                         tok2->deleteNext();
02407                     }
02408                 }
02409             }
02410 
02411             if (sz != 0)
02412                 tok->insertToken(MathLib::longToString(sz));
02413 
02414             tok = end->next() ? end->next() : end;
02415         }
02416     }
02417 }
02418 
02419 static Token *skipTernaryOp(Token *);
02420 
02421 static Token *skipTernaryOp(Token *tok)
02422 {
02423     if (!tok || tok->str() != "?")
02424         return tok;
02425     unsigned int colonlevel = 1;
02426     while (NULL != (tok = tok->next())) {
02427         if (tok->str() == "?") {
02428             ++colonlevel;
02429         } else if (tok->str() == ":") {
02430             --colonlevel;
02431             if (colonlevel == 0) {
02432                 tok = tok->next();
02433                 break;
02434             }
02435         }
02436         if (Token::Match(tok->next(), "[{};]"))
02437             break;
02438     }
02439     return tok;
02440 }
02441 
02442 /** simplify labels and case|default in the code: add a ";" if not already in.*/
02443 
02444 bool Tokenizer::simplifyLabelsCaseDefault()
02445 {
02446     bool executablescope = false;
02447     unsigned int indentlevel = 0;
02448     for (Token *tok = list.front(); tok; tok = tok->next()) {
02449         // Simplify labels in the executable scope..
02450         if (Token::Match(tok, ") const| {")) {
02451             tok = tok->next();
02452             if (tok->str() != "{")
02453                 tok = tok->next();
02454             executablescope = true;
02455         }
02456 
02457         if (!executablescope)
02458             continue;
02459 
02460         if (tok->str() == "{") {
02461             if (tok->previous()->str() == "=")
02462                 tok = tok->link();
02463             else
02464                 ++indentlevel;
02465         } else if (tok->str() == "}") {
02466             --indentlevel;
02467             if (!indentlevel) {
02468                 executablescope = false;
02469                 continue;
02470             }
02471         } else if (tok->str() == "(" || tok->str() == "[")
02472             tok = tok->link();
02473 
02474         if (Token::Match(tok, "[;{}] case")) {
02475             while (NULL != (tok = tok->next())) {
02476                 if (tok->str() == "(" || tok->str() == "[") {
02477                     tok = tok->link();
02478                 } else if (tok->str() == "?") {
02479                     tok = skipTernaryOp(tok);
02480                 }
02481                 if (Token::Match(tok->next(),"[:{};]"))
02482                     break;
02483             }
02484             if (tok->str() != "case" && tok->next()->str() == ":") {
02485                 tok = tok->next();
02486                 if (tok->next()->str() != ";")
02487                     tok->insertToken(";");
02488             } else {
02489                 syntaxError(tok);
02490                 return false;
02491             }
02492         } else if (Token::Match(tok, "[;{}] %var% : !!;")) {
02493             tok = tok->tokAt(2);
02494             tok->insertToken(";");
02495         }
02496     }
02497     return true;
02498 }
02499 
02500 
02501 
02502 
02503 void Tokenizer::simplifyTemplates()
02504 {
02505     if (isC())
02506         return;
02507 
02508     for (Token *tok = list.front(); tok; tok = tok->next()) {
02509         // #2648 - simple fix for sizeof used as template parameter
02510         // TODO: this is a bit hardcoded. make a bit more generic
02511         if (Token::Match(tok, "%var% < sizeof ( %type% ) >") && tok->tokAt(4)->isStandardType()) {
02512             Token * const tok3 = tok->next();
02513             const unsigned int sizeOfResult = sizeOfType(tok3->tokAt(3));
02514             tok3->deleteNext(4);
02515             tok3->insertToken(MathLib::longToString(sizeOfResult));
02516         }
02517     }
02518 
02519     TemplateSimplifier::simplifyTemplates(
02520         list,
02521         *_errorLogger,
02522         _settings,
02523         _codeWithTemplates);
02524 }
02525 //---------------------------------------------------------------------------
02526 
02527 
02528 static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::string,unsigned int> &variableId, bool executableScope)
02529 {
02530     const Token *tok2 = *tok;
02531 
02532     bool ref = false;
02533 
02534     if (!tok2->isName())
02535         return false;
02536 
02537     unsigned int typeCount = 0;
02538     bool hasstruct = false;   // Is there a "struct" or "class"?
02539     while (tok2) {
02540         if (tok2->isName()) {
02541             if (tok2->str() == "class" || tok2->str() == "struct" || tok2->str() == "union" || tok2->str() == "typename") {
02542                 hasstruct = true;
02543                 typeCount = 0;
02544             } else if (tok2->str() == "const") {
02545                 ;  // just skip "const"
02546             } else if (!hasstruct && variableId.find(tok2->str()) != variableId.end() && tok2->previous()->str() != "::") {
02547                 ++typeCount;
02548                 tok2 = tok2->next();
02549                 if (!tok2 || tok2->str() != "::")
02550                     break;
02551             } else {
02552                 ++typeCount;
02553             }
02554         } else if (tok2->str() == "<" && TemplateSimplifier::templateParameters(tok2) > 0) {
02555             bool ok = tok2->findClosingBracket(tok2);
02556             if (!ok || !tok2)
02557                 break;
02558         } else if (tok2->str() == "&") {
02559             ref = true;
02560         } else if (tok2->str() != "*" && tok2->str() != "::") {
02561             break;
02562         }
02563         tok2 = tok2->next();
02564     }
02565 
02566     if (tok2) {
02567         *tok = tok2;
02568 
02569         // In executable scopes, references must be assigned
02570         // Catching by reference is an exception
02571         if (executableScope && ref) {
02572             if (tok2->str() == "(" || tok2->str() == "=")
02573                 ;   // reference is assigned => ok
02574             else if (tok2->str() != ")" || tok2->link()->strAt(-1) != "catch")
02575                 return false;   // not catching by reference => not declaration
02576         }
02577     }
02578 
02579     // Check if array declaration is valid (#2638)
02580     // invalid declaration: AAA a[4] = 0;
02581     if (typeCount >= 2 && tok2 && tok2->str() == "[") {
02582         const Token *tok3 = tok2;
02583         while (tok3 && tok3->str() == "[") {
02584             tok3 = tok3->link()->next();
02585         }
02586         if (Token::Match(tok3, "= %num%"))
02587             return false;
02588     }
02589 
02590     return bool(typeCount >= 2 && tok2 && Token::Match(tok2->tokAt(-2), "!!:: %type%"));
02591 }
02592 
02593 
02594 static void setVarIdStructMembers(Token **tok1,
02595                                   std::map<unsigned int, std::map<std::string,unsigned int> > *structMembers,
02596                                   unsigned int *_varId)
02597 {
02598     Token *tok = *tok1;
02599     while (Token::Match(tok->next(), ". %var% !!(")) {
02600         const unsigned int struct_varid = tok->varId();
02601         tok = tok->tokAt(2);
02602         if (struct_varid == 0)
02603             continue;
02604 
02605         // Don't set varid for template function
02606         if (TemplateSimplifier::templateParameters(tok->next()) > 0)
02607             break;
02608 
02609         std::map<std::string,unsigned int>& members = (*structMembers)[struct_varid];
02610         if (members.empty() || members.find(tok->str()) == members.end()) {
02611             members[tok->str()] = ++(*_varId);
02612             tok->varId(*_varId);
02613         } else {
02614             tok->varId(members[tok->str()]);
02615         }
02616     }
02617     if (tok)
02618         *tok1 = tok;
02619 }
02620 
02621 
02622 static void setVarIdClassDeclaration(Token * const startToken,
02623                                      const std::map<std::string, unsigned int> &variableId,
02624                                      const unsigned int scopeStartVarId,
02625                                      std::map<unsigned int, std::map<std::string,unsigned int> > *structMembers,
02626                                      unsigned int *_varId)
02627 {
02628     // end of scope
02629     const Token * const endToken = startToken->link();
02630 
02631     // determine class name
02632     std::string className;
02633     for (const Token *tok = startToken->previous(); tok; tok = tok->previous()) {
02634         if (!tok->isName() && tok->str() != ":")
02635             break;
02636         if (Token::Match(tok, "class|struct %type% [:{]")) {
02637             className = tok->next()->str();
02638             break;
02639         }
02640     }
02641 
02642     // replace varids..
02643     unsigned int indentlevel = 0;
02644     bool initList = false;
02645     for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) {
02646         if (tok->str() == "{") {
02647             initList = false;
02648             ++indentlevel;
02649         } else if (tok->str() == "}")
02650             --indentlevel;
02651         else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %var% (")) {
02652             const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
02653             if (it != variableId.end()) {
02654                 tok->varId(it->second);
02655             }
02656         } else if (tok->isName() && tok->varId() <= scopeStartVarId) {
02657             if (indentlevel > 0) {
02658                 if (Token::Match(tok->previous(), "::|."))
02659                     continue;
02660                 if (tok->next()->str() == "::") {
02661                     if (tok->str() == className)
02662                         tok = tok->tokAt(2);
02663                     else
02664                         continue;
02665                 }
02666 
02667                 const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
02668                 if (it != variableId.end()) {
02669                     tok->varId(it->second);
02670                     setVarIdStructMembers(&tok, structMembers, _varId);
02671                 }
02672             }
02673         } else if (indentlevel == 0 && tok->str() == ":")
02674             initList = true;
02675     }
02676 }
02677 
02678 
02679 
02680 // Update the variable ids..
02681 // Parse each function..
02682 static void setVarIdClassFunction(Token * const startToken,
02683                                   const Token * const endToken,
02684                                   const std::map<std::string, unsigned int> &varlist,
02685                                   std::map<unsigned int, std::map<std::string,unsigned int> > *structMembers,
02686                                   unsigned int *_varId)
02687 {
02688     for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
02689         if (tok2->varId() == 0 && (tok2->previous()->str() != "." || tok2->strAt(-2) == "this")) {
02690             const std::map<std::string,unsigned int>::const_iterator it = varlist.find(tok2->str());
02691             if (it != varlist.end()) {
02692                 tok2->varId(it->second);
02693                 setVarIdStructMembers(&tok2, structMembers, _varId);
02694             }
02695         }
02696     }
02697 }
02698 
02699 static bool isInitList(const Token *tok)
02700 {
02701     if (!Token::Match(tok, ") : %var% ("))
02702         return false;
02703 
02704     tok = tok->linkAt(3);
02705     while (Token::Match(tok, ") , %var% ("))
02706         tok = tok->linkAt(3);
02707 
02708     return Token::simpleMatch(tok, ") {");
02709 }
02710 
02711 void Tokenizer::setVarId()
02712 {
02713     // Clear all variable ids
02714     for (Token *tok = list.front(); tok; tok = tok->next())
02715         tok->varId(0);
02716 
02717     // Variable declarations can't start with "return" etc.
02718     std::set<std::string> notstart;
02719     notstart.insert("goto");
02720     notstart.insert("NOT");
02721     notstart.insert("return");
02722     notstart.insert("sizeof");
02723     if (!isC()) {
02724         static const char *str[] = {"delete","friend","new","throw","using","virtual","explicit"};
02725         notstart.insert(str, str+(sizeof(str)/sizeof(*str)));
02726     }
02727 
02728     // variable id
02729     _varId = 0;
02730     std::map<std::string, unsigned int> variableId;
02731     std::map<unsigned int, std::map<std::string, unsigned int> > structMembers;
02732     std::stack< std::map<std::string, unsigned int> > scopeInfo;
02733     std::stack<bool> executableScope;
02734     executableScope.push(false);
02735     std::stack<unsigned int> scopestartvarid;  // varid when scope starts
02736     scopestartvarid.push(0);
02737     bool initlist = false;
02738     for (Token *tok = list.front(); tok; tok = tok->next()) {
02739 
02740         // scope info to handle shadow variables..
02741         if (!initlist && tok->str() == "(" &&
02742             (Token::simpleMatch(tok->link(), ") {") || Token::Match(tok->link(), ") %type% {") || isInitList(tok->link()))) {
02743             scopeInfo.push(variableId);
02744             initlist = Token::simpleMatch(tok->link(), ") :");
02745         } else if (tok->str() == "{") {
02746             initlist = false;
02747             // parse anonymous unions as part of the current scope
02748             if (!(tok->strAt(-1) == "union" && Token::simpleMatch(tok->link(), "} ;"))) {
02749                 scopestartvarid.push(_varId);
02750                 if (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%")) {
02751                     executableScope.push(true);
02752                 } else {
02753                     executableScope.push(executableScope.top());
02754                     scopeInfo.push(variableId);
02755                 }
02756             }
02757         } else if (tok->str() == "}") {
02758             // parse anonymous unions as part of the current scope
02759             if (!(Token::simpleMatch(tok, "} ;") && Token::simpleMatch(tok->link()->previous(), "union {"))) {
02760                 // Set variable ids in class declaration..
02761                 if (!isC() && !executableScope.top() && tok->link()) {
02762                     setVarIdClassDeclaration(tok->link(),
02763                                              variableId,
02764                                              scopestartvarid.top(),
02765                                              &structMembers,
02766                                              &_varId);
02767                 }
02768 
02769                 scopestartvarid.pop();
02770                 if (scopestartvarid.empty()) {  // should be impossible
02771                     scopestartvarid.push(0);
02772                 }
02773 
02774                 if (scopeInfo.empty()) {
02775                     variableId.clear();
02776                 } else {
02777                     variableId.swap(scopeInfo.top());
02778                     scopeInfo.pop();
02779                 }
02780 
02781                 executableScope.pop();
02782                 if (executableScope.empty()) {   // should not possibly happen
02783                     executableScope.push(false);
02784                 }
02785             }
02786         }
02787 
02788         if (tok == list.front() || Token::Match(tok, "[;{}]") ||
02789             (Token::Match(tok,"[(,]") && (!executableScope.top() || Token::simpleMatch(tok->link(), ") {"))) ||
02790             (tok->isName() && tok->str().at(tok->str().length()-1U) == ':')) {
02791 
02792             // No variable declarations in sizeof
02793             if (Token::simpleMatch(tok->previous(), "sizeof (")) {
02794                 continue;
02795             }
02796 
02797             // locate the variable name..
02798             const Token *tok2 = (tok->isName()) ? tok : tok->next();
02799 
02800             // private: protected: public: etc
02801             while (tok2 && tok2->str()[tok2->str().size() - 1U] == ':') {
02802                 tok2 = tok2->next();
02803             }
02804             if (!tok2)
02805                 break;
02806 
02807             // Variable declaration can't start with "return", etc
02808             if (notstart.find(tok2->str()) != notstart.end())
02809                 continue;
02810 
02811             const bool decl = setVarIdParseDeclaration(&tok2, variableId, executableScope.top());
02812 
02813             if (decl && Token::Match(tok2->previous(), "%type% [;[=,)]") && tok2->previous()->str() != "const") {
02814                 variableId[tok2->previous()->str()] = ++_varId;
02815                 tok = tok2->previous();
02816             }
02817 
02818             else if (decl && Token::Match(tok2->previous(), "%type% ( !!)") && Token::simpleMatch(tok2->link(), ") ;")) {
02819                 // In C++ , a variable can't be called operator+ or something like that.
02820                 if (isCPP() &&
02821                     tok2->previous()->str().size() >= 9 &&
02822                     tok2->previous()->str().compare(0, 8, "operator") == 0 &&
02823                     tok2->previous()->str()[8] != '_' &&
02824                     !std::isalnum(tok2->previous()->str()[8]))
02825                     continue;
02826 
02827                 const Token *tok3 = tok2->next();
02828                 if (!tok3->isStandardType() && tok3->str() != "void" && !Token::Match(tok3,"struct|union|class %type%") && tok3->str() != "." && !setVarIdParseDeclaration(&tok3,variableId,executableScope.top())) {
02829                     variableId[tok2->previous()->str()] = ++_varId;
02830                     tok = tok2->previous();
02831                 }
02832             }
02833         }
02834 
02835         if (tok->isName()) {
02836             // don't set variable id after a struct|enum|union
02837             if (Token::Match(tok->previous(), "struct|enum|union"))
02838                 continue;
02839 
02840             if (!isC()) {
02841                 if (tok->previous() && tok->previous()->str() == "::")
02842                     continue;
02843                 if (tok->next() && tok->next()->str() == "::")
02844                     continue;
02845             }
02846 
02847             const std::map<std::string, unsigned int>::const_iterator it = variableId.find(tok->str());
02848             if (it != variableId.end()) {
02849                 tok->varId(it->second);
02850                 setVarIdStructMembers(&tok, &structMembers, &_varId);
02851             }
02852         } else if (Token::Match(tok, "::|. %var%")) {
02853             // Don't set varid after a :: or . token
02854             tok = tok->next();
02855         } else if (tok->str() == ":" && Token::Match(tok->tokAt(-2), "class %type%")) {
02856             do {
02857                 tok = tok->next();
02858             } while (tok && (tok->isName() || tok->str() == ","));
02859             if (!tok)
02860                 break;
02861             tok = tok->previous();
02862         }
02863     }
02864 
02865     // Clear the structMembers because it will be used when member functions
02866     // are parsed. The old info is not bad, it is just redundant.
02867     structMembers.clear();
02868 
02869     // Member functions and variables in this source
02870     std::list<Token *> allMemberFunctions;
02871     std::list<Token *> allMemberVars;
02872     {
02873         for (Token *tok2 = list.front(); tok2; tok2 = tok2->next()) {
02874             if (Token::Match(tok2, "%var% :: %var%")) {
02875                 if (tok2->strAt(3) == "(")
02876                     allMemberFunctions.push_back(tok2);
02877                 else if (tok2->tokAt(2)->varId() != 0)
02878                     allMemberVars.push_back(tok2);
02879             }
02880         }
02881     }
02882 
02883     // class members..
02884     for (Token *tok = list.front(); tok; tok = tok->next()) {
02885         if (Token::Match(tok, "class|struct %var% {|:")) {
02886             const std::string &classname(tok->next()->str());
02887 
02888             // What member variables are there in this class?
02889             std::map<std::string, unsigned int> varlist;
02890             const Token* tokStart = Token::findsimplematch(tok, "{");
02891             if (tokStart) {
02892                 for (const Token *tok2 = tokStart->next(); tok2 != tokStart->link(); tok2 = tok2->next()) {
02893                     // skip parentheses..
02894                     if (tok2->str() == "{")
02895                         tok2 = tok2->link();
02896                     else if (tok2->str() == "(")
02897                         tok2 = tok2->link();
02898 
02899                     // Found a member variable..
02900                     else if (tok2->varId() > 0)
02901                         varlist[tok2->str()] = tok2->varId();
02902                 }
02903             }
02904 
02905             // Are there any member variables in this class?
02906             if (varlist.empty())
02907                 continue;
02908 
02909             // Member variables
02910             for (std::list<Token *>::iterator func = allMemberVars.begin(); func != allMemberVars.end(); ++func) {
02911                 if (!Token::simpleMatch(*func, classname.c_str()))
02912                     continue;
02913 
02914                 Token *tok2 = *func;
02915                 tok2 = tok2->tokAt(2);
02916                 tok2->varId(varlist[tok2->str()]);
02917             }
02918 
02919             // Set variable ids in member functions for this class..
02920             const std::string funcpattern(classname + " :: %var% (");
02921             for (std::list<Token *>::iterator func = allMemberFunctions.begin(); func != allMemberFunctions.end(); ++func) {
02922                 Token *tok2 = *func;
02923 
02924                 // Found a class function..
02925                 if (Token::Match(tok2, funcpattern.c_str())) {
02926                     // Goto the end parentheses..
02927                     tok2 = tok2->linkAt(3);
02928                     if (!tok2)
02929                         break;
02930 
02931                     // If this is a function implementation.. add it to funclist
02932                     if (Token::Match(tok2, ") const|volatile| {")) {
02933                         while (tok2->str() != "{")
02934                             tok2 = tok2->next();
02935                         setVarIdClassFunction(tok2, tok2->link(), varlist, &structMembers, &_varId);
02936                     }
02937 
02938                     // constructor with initializer list
02939                     if (Token::Match(tok2, ") : %var% (")) {
02940                         Token *tok3 = tok2;
02941                         while (Token::Match(tok3, ") [:,] %var% (")) {
02942                             Token *vartok = tok3->tokAt(2);
02943                             if (varlist.find(vartok->str()) != varlist.end())
02944                                 vartok->varId(varlist[vartok->str()]);
02945                             tok3 = tok3->linkAt(3);
02946                         }
02947                         if (Token::simpleMatch(tok3, ") {")) {
02948                             setVarIdClassFunction(tok2, tok3->next()->link(), varlist, &structMembers, &_varId);
02949                         }
02950                     }
02951                 }
02952             }
02953         }
02954     }
02955 }
02956 
02957 static bool linkBrackets(Tokenizer* tokenizer, std::stack<const Token*>& type, std::stack<Token*>& links, Token* token, char open, char close)
02958 {
02959     if (token->str()[0] == open) {
02960         links.push(token);
02961         type.push(token);
02962     } else if (token->str()[0] == close) {
02963         if (links.empty()) {
02964             // Error, { and } don't match.
02965             tokenizer->syntaxError(token, open);
02966             return false;
02967         }
02968         if (type.top()->str()[0] != open) {
02969             tokenizer->syntaxError(type.top(), type.top()->str()[0]);
02970             return false;
02971         }
02972         type.pop();
02973 
02974         Token::createMutualLinks(links.top(), token);
02975         links.pop();
02976     }
02977     return(true);
02978 }
02979 
02980 bool Tokenizer::createLinks()
02981 {
02982     std::stack<const Token*> type;
02983     std::stack<Token*> links1;
02984     std::stack<Token*> links2;
02985     std::stack<Token*> links3;
02986     for (Token *token = list.front(); token; token = token->next()) {
02987         if (token->link()) {
02988             token->link(0);
02989         }
02990 
02991         bool validSyntax = linkBrackets(this, type, links1, token, '{', '}');
02992         if (!validSyntax)
02993             return false;
02994 
02995         validSyntax = linkBrackets(this, type, links2, token, '(', ')');
02996         if (!validSyntax)
02997             return false;
02998 
02999         validSyntax = linkBrackets(this, type, links3, token, '[', ']');
03000         if (!validSyntax)
03001             return false;
03002     }
03003 
03004     if (!links1.empty()) {
03005         // Error, { and } don't match.
03006         syntaxError(links1.top(), '{');
03007         return false;
03008     }
03009 
03010     if (!links2.empty()) {
03011         // Error, ( and ) don't match.
03012         syntaxError(links2.top(), '(');
03013         return false;
03014     }
03015 
03016     if (!links3.empty()) {
03017         // Error, [ and ] don't match.
03018         syntaxError(links3.top(), '[');
03019         return false;
03020     }
03021 
03022     return true;
03023 }
03024 
03025 void Tokenizer::createLinks2()
03026 {
03027     if (isC())
03028         return;
03029 
03030     std::stack<Token*> type;
03031     for (Token *token = list.front(); token; token = token->next()) {
03032         if (token->link()) {
03033             if (Token::Match(token, "{|[|("))
03034                 type.push(token);
03035             else if (Token::Match(token, "}|]|)")) {
03036                 while (type.top()->str() == "<")
03037                     type.pop();
03038                 type.pop();
03039             } else
03040                 token->link(0);
03041         }
03042 
03043         else if (token->str() == ";")
03044             while (!type.empty() && type.top()->str() == "<")
03045                 type.pop();
03046         else if (token->str() == "<" && token->previous() && token->previous()->isName() && !token->previous()->varId())
03047             type.push(token);
03048         else if (token->str() == ">" || token->str() == ">>") {
03049             if (type.empty() || type.top()->str() != "<") // < and > don't match.
03050                 continue;
03051             if (token->next() && !token->next()->isName() && !Token::Match(token->next(), ">|&|*|::|,|(|)"))
03052                 continue;
03053 
03054             // Check type of open link
03055             if (type.empty() || type.top()->str() != "<" || (token->str() == ">>" && type.size() < 2)) {
03056                 continue;
03057             }
03058 
03059             Token* top = type.top();
03060             type.pop();
03061             if (token->str() == ">>" && type.top()->str() != "<") {
03062                 type.push(top);
03063                 continue;
03064             }
03065 
03066             if (token->str() == ">>") { // C++11 right angle bracket
03067                 token->str(">");
03068                 token->insertToken(">");
03069             }
03070 
03071             Token::createMutualLinks(top, token);
03072         }
03073     }
03074 }
03075 
03076 bool Tokenizer::simplifySizeof()
03077 {
03078     // Locate variable declarations and calculate the size
03079     std::map<unsigned int, std::string> sizeOfVar;
03080     for (Token *tok = list.front(); tok; tok = tok->next()) {
03081         if (tok->varId() != 0 && sizeOfVar.find(tok->varId()) == sizeOfVar.end()) {
03082             const unsigned int varId = tok->varId();
03083             if (Token::Match(tok->tokAt(-3), "[;{}(,] %type% * %var% [;,)]") ||
03084                 Token::Match(tok->tokAt(-4), "[;{}(,] const %type% * %var% [;),]") ||
03085                 Token::Match(tok->tokAt(-2), "[;{}(,] %type% %var% [;),]") ||
03086                 Token::Match(tok->tokAt(-3), "[;{}(,] const %type% %var% [;),]")) {
03087                 const unsigned int size = sizeOfType(tok->previous());
03088                 if (size == 0) {
03089                     continue;
03090                 }
03091 
03092                 sizeOfVar[varId] = MathLib::longToString(size);
03093             }
03094 
03095             else if (Token::Match(tok->previous(), "%type% %var% [ %num% ] [;=]") ||
03096                      Token::Match(tok->tokAt(-2), "%type% * %var% [ %num% ] [;=]")) {
03097                 const unsigned int size = sizeOfType(tok->previous());
03098                 if (size == 0)
03099                     continue;
03100 
03101                 sizeOfVar[varId] = MathLib::longToString(size * static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(2))));
03102             }
03103 
03104             else if (Token::Match(tok->previous(), "%type% %var% [ %num% ] [,)]") ||
03105                      Token::Match(tok->tokAt(-2), "%type% * %var% [ %num% ] [,)]")) {
03106                 Token tempTok(0);
03107                 tempTok.str("*");
03108                 sizeOfVar[varId] = MathLib::longToString(sizeOfType(&tempTok));
03109             }
03110         }
03111     }
03112 
03113     bool ret = false;
03114     for (Token *tok = list.front(); tok; tok = tok->next()) {
03115         if (tok->str() != "sizeof")
03116             continue;
03117 
03118         if (!tok->next())
03119             break;
03120 
03121         if (tok->strAt(1) == "sizeof")
03122             continue;
03123 
03124         if (Token::simpleMatch(tok->next(), ". . .")) {
03125             tok->deleteNext(3);
03126         }
03127 
03128         // sizeof 'x'
03129         if (tok->next()->type() == Token::eChar) {
03130             tok->deleteThis();
03131             std::ostringstream sz;
03132             sz << sizeof 'x';
03133             tok->str(sz.str());
03134             ret = true;
03135             continue;
03136         }
03137 
03138         // sizeof('x')
03139         if (Token::Match(tok, "sizeof ( %char% )")) {
03140             tok->deleteNext();
03141             tok->deleteThis();
03142             tok->deleteNext();
03143             std::ostringstream sz;
03144             sz << sizeof 'x';
03145             tok->str(sz.str());
03146             ret = true;
03147             continue;
03148         }
03149 
03150         // sizeof "text"
03151         if (tok->next()->type() == Token::eString) {
03152             tok->deleteThis();
03153             std::ostringstream ostr;
03154             ostr << (Token::getStrLength(tok) + 1);
03155             tok->str(ostr.str());
03156             ret = true;
03157             continue;
03158         }
03159 
03160         // sizeof ("text")
03161         if (Token::Match(tok->next(), "( %str% )")) {
03162             tok->deleteNext();
03163             tok->deleteThis();
03164             tok->deleteNext();
03165             std::ostringstream ostr;
03166             ostr << (Token::getStrLength(tok) + 1);
03167             tok->str(ostr.str());
03168             ret = true;
03169             continue;
03170         }
03171 
03172         // sizeof * (...) -> sizeof(*...)
03173         if (Token::simpleMatch(tok->next(), "* (") && !Token::simpleMatch(tok->linkAt(2), ") .")) {
03174             tok->deleteNext();
03175             tok->next()->insertToken("*");
03176         }
03177 
03178         // sizeof a++ -> sizeof(a++)
03179         if (Token::Match(tok->next(), "++|-- %var% !!.") || Token::Match(tok->next(), "%var% ++|--")) {
03180             tok->insertToken("(");
03181             tok->tokAt(3)->insertToken(")");
03182             Token::createMutualLinks(tok->next(), tok->tokAt(4));
03183         }
03184 
03185         // sizeof 1 => sizeof ( 1 )
03186         if (tok->next()->isNumber()) {
03187             Token *tok2 = tok->next();
03188             tok->insertToken("(");
03189             tok2->insertToken(")");
03190             Token::createMutualLinks(tok->next(), tok2->next());
03191         }
03192 
03193         // sizeof int -> sizeof( int )
03194         else if (tok->next()->str() != "(") {
03195             // Add parentheses around the sizeof
03196             int parlevel = 0;
03197             for (Token *tempToken = tok->next(); tempToken; tempToken = tempToken->next()) {
03198                 if (tempToken->str() == "(")
03199                     ++parlevel;
03200                 else if (tempToken->str() == ")")
03201                     --parlevel;
03202                 if (Token::Match(tempToken, "%var%")) {
03203                     while (tempToken && tempToken->next() && tempToken->next()->str() == "[") {
03204                         tempToken = tempToken->next()->link();
03205                     }
03206                     if (!tempToken || !tempToken->next()) {
03207                         break;
03208                     }
03209 
03210                     if (tempToken->next()->str() == ".") {
03211                         // We are checking a class or struct, search next varname
03212                         tempToken = tempToken->next();
03213                         continue;
03214                     } else if (tempToken->next()->type() == Token::eIncDecOp) {
03215                         // We have variable++ or variable--, there should be
03216                         // nothing after this
03217                         tempToken = tempToken->tokAt(2);
03218                     } else if (parlevel > 0 && Token::simpleMatch(tempToken->next(), ") .")) {
03219                         --parlevel;
03220                         tempToken = tempToken->tokAt(2);
03221                         continue;
03222                     }
03223 
03224                     // Ok, we should be clean. Add ) after tempToken
03225                     tok->insertToken("(");
03226                     tempToken->insertToken(")");
03227                     Token::createMutualLinks(tok->next(), tempToken->next());
03228                     break;
03229                 }
03230             }
03231         }
03232 
03233         // sizeof(type *) => sizeof(*)
03234         if (Token::Match(tok->next(), "( %type% * )")) {
03235             tok->next()->deleteNext();
03236         }
03237 
03238         if (Token::simpleMatch(tok->next(), "( * )")) {
03239             tok->str(MathLib::longToString(sizeOfType(tok->tokAt(2))));
03240             tok->deleteNext(3);
03241             ret = true;
03242         }
03243 
03244         // sizeof( a )
03245         else if (Token::Match(tok->next(), "( %var% )") && tok->tokAt(2)->varId() != 0) {
03246             if (sizeOfVar.find(tok->tokAt(2)->varId()) != sizeOfVar.end()) {
03247                 tok->deleteNext();
03248                 tok->deleteThis();
03249                 tok->deleteNext();
03250                 tok->str(sizeOfVar[tok->varId()]);
03251                 ret = true;
03252             } else {
03253                 // don't try to replace size of variable if variable has
03254                 // similar name with type (#329)
03255             }
03256         }
03257 
03258         else if (Token::Match(tok, "sizeof ( %type% )")) {
03259             unsigned int size = sizeOfType(tok->tokAt(2));
03260             if (size > 0) {
03261                 tok->str(MathLib::longToString(size));
03262                 tok->deleteNext(3);
03263                 ret = true;
03264             }
03265         }
03266 
03267         else if (Token::Match(tok, "sizeof ( * %var% )") || Token::Match(tok, "sizeof ( %var% [ %num% ] )")) {
03268             // Some default value..
03269             std::size_t sz = 0;
03270 
03271             unsigned int varid = tok->tokAt((tok->strAt(2) == "*") ? 3 : 2)->varId();
03272             if (varid != 0) {
03273                 // Try to locate variable declaration..
03274                 const Token *decltok = Token::findmatch(list.front(), "%varid%", varid);
03275                 if (Token::Match(decltok->previous(), "%type% %var% [")) {
03276                     sz = sizeOfType(decltok->previous());
03277                 } else if (Token::Match(decltok->previous(), "* %var% [")) {
03278                     sz = sizeOfType(decltok->previous());
03279                 } else if (Token::Match(decltok->tokAt(-2), "%type% * %var%")) {
03280                     sz = sizeOfType(decltok->tokAt(-2));
03281                 }
03282             } else if (tok->strAt(3) == "[" && tok->tokAt(2)->isStandardType()) {
03283                 sz = sizeOfType(tok->tokAt(2));
03284                 if (sz == 0)
03285                     continue;
03286                 sz *= static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(4)));
03287             }
03288 
03289             if (sz > 0) {
03290                 tok->str(MathLib::longToString(sz));
03291                 Token::eraseTokens(tok, tok->next()->link()->next());
03292                 ret = true;
03293             }
03294         }
03295     }
03296     return ret;
03297 }
03298 
03299 bool Tokenizer::simplifyTokenList()
03300 {
03301     // clear the _functionList so it can't contain dead pointers
03302     deleteSymbolDatabase();
03303 
03304     simplifyCharAt();
03305 
03306     // simplify references
03307     simplifyReference();
03308 
03309     simplifyStd();
03310 
03311     simplifyGoto();
03312 
03313     simplifySizeof();
03314 
03315     simplifyUndefinedSizeArray();
03316 
03317     // Replace constants..
03318     for (Token *tok = list.front(); tok; tok = tok->next()) {
03319         if (Token::Match(tok, "const static| %type% %var% = %num% ;")) {
03320             unsigned int offset = 0;
03321             if (tok->strAt(1) == "static")
03322                 offset = 1;
03323             const unsigned int varId(tok->tokAt(2 + offset)->varId());
03324             if (varId == 0) {
03325                 tok = tok->tokAt(5);
03326                 continue;
03327             }
03328 
03329             const std::string& num = tok->strAt(4 + offset);
03330             int indent = 1;
03331             for (Token *tok2 = tok->tokAt(6); tok2; tok2 = tok2->next()) {
03332                 if (tok2->str() == "{") {
03333                     ++indent;
03334                 } else if (tok2->str() == "}") {
03335                     --indent;
03336                     if (indent == 0)
03337                         break;
03338                 }
03339 
03340                 // Compare constants, but don't touch members of other structures
03341                 else if (tok2->varId() == varId) {
03342                     tok2->str(num);
03343                 }
03344             }
03345         }
03346     }
03347 
03348     simplifyCasts();
03349 
03350     // Simplify simple calculations..
03351     simplifyCalculations();
03352 
03353     // Replace "*(str + num)" => "str[num]"
03354     for (Token *tok = list.front(); tok; tok = tok->next()) {
03355         if (!Token::Match(tok, "%var%") && !tok->isNumber()
03356             && !Token::Match(tok, "]|)")
03357             && (Token::Match(tok->next(), "* ( %var% + %num%|%var% )"))) {
03358             // remove '* ('
03359             tok->deleteNext(2);
03360 
03361             tok = tok->tokAt(2);
03362             // '+'->'['
03363             tok->str("[");
03364 
03365             tok = tok->tokAt(2);
03366             tok->str("]");
03367             Token::createMutualLinks(tok->tokAt(-2), tok);
03368         }
03369     }
03370 
03371     // Replace "&str[num]" => "(str + num)"
03372     std::set<unsigned int> pod;
03373     for (const Token *tok = list.front(); tok; tok = tok->next()) {
03374         if (tok->isStandardType()) {
03375             tok = tok->next();
03376             while (tok && (tok->str() == "*" || tok->isName())) {
03377                 if (tok->varId() > 0) {
03378                     pod.insert(tok->varId());
03379                     break;
03380                 }
03381                 tok = tok->next();
03382             }
03383             if (!tok)
03384                 break;
03385         }
03386     }
03387 
03388     for (Token *tok = list.front(); tok; tok = tok->next()) {
03389         if (!Token::Match(tok, "%num%|%var%") && !Token::Match(tok, "]|)") &&
03390             (Token::Match(tok->next(), "& %var% [ %num%|%var% ]"))) {
03391             tok = tok->next();
03392 
03393             if (tok->next()->varId()) {
03394                 if (pod.find(tok->next()->varId()) == pod.end()) {
03395                     tok = tok->tokAt(5);
03396                     continue;
03397                 }
03398             }
03399 
03400             // '&' => '('
03401             tok->str("(");
03402 
03403             tok = tok->next();
03404             // '[' => '+'
03405             tok->deleteNext();
03406             tok->insertToken("+");
03407 
03408             tok = tok->tokAt(3);
03409             //remove ']'
03410             tok->str(")");
03411             Token::createMutualLinks(tok->tokAt(-4), tok);
03412         }
03413     }
03414 
03415     removeRedundantAssignment();
03416 
03417     simplifyRealloc();
03418 
03419     // Change initialisation of variable to assignment
03420     simplifyInitVar();
03421 
03422     // Simplify variable declarations
03423     simplifyVarDecl(false);
03424 
03425     elseif();
03426     simplifyErrNoInWhile();
03427     simplifyIfAssign();
03428     simplifyRedundantParentheses();
03429     simplifyIfNot();
03430     simplifyIfNotNull();
03431     simplifyIfSameInnerCondition();
03432     simplifyComparisonOrder();
03433     simplifyNestedStrcat();
03434     simplifyWhile0();
03435     simplifyFuncInWhile();
03436 
03437     simplifyIfAssign();    // could be affected by simplifyIfNot
03438 
03439     bool modified = true;
03440     while (modified) {
03441         if (_settings && _settings->terminated())
03442             return false;
03443 
03444         modified = false;
03445         modified |= simplifyConditions();
03446         modified |= simplifyFunctionReturn();
03447         modified |= simplifyKnownVariables();
03448         modified |= removeRedundantConditions();
03449         modified |= simplifyRedundantParentheses();
03450         modified |= simplifyConstTernaryOp();
03451         modified |= simplifyCalculations();
03452     }
03453 
03454     simplifyConditionOperator();
03455 
03456     // replace strlen(str)
03457     for (Token *tok = list.front(); tok; tok = tok->next()) {
03458         if (Token::Match(tok, "strlen ( %str% )")) {
03459             std::ostringstream ostr;
03460             ostr << Token::getStrLength(tok->tokAt(2));
03461             tok->str(ostr.str());
03462             tok->deleteNext(3);
03463         }
03464     }
03465 
03466     // simplify redundant for
03467     removeRedundantFor();
03468 
03469     // Remove redundant parentheses in return..
03470     for (Token *tok = list.front(); tok; tok = tok->next()) {
03471         while (Token::simpleMatch(tok, "return (")) {
03472             Token *tok2 = tok->next()->link();
03473             if (Token::simpleMatch(tok2, ") ;")) {
03474                 tok->deleteNext();
03475                 tok2->deleteThis();
03476             } else {
03477                 break;
03478             }
03479         }
03480     }
03481 
03482     simplifyReturnStrncat();
03483 
03484     removeRedundantAssignment();
03485 
03486     simplifyComma();
03487 
03488     removeRedundantSemicolons();
03489 
03490     simplifyFlowControl();
03491 
03492     simplifyRedundantConsecutiveBraces();
03493 
03494     simplifyEmptyNamespaces();
03495 
03496     if (!validate())
03497         return false;
03498 
03499     list.front()->assignProgressValues();
03500 
03501     // Create symbol database and then remove const keywords
03502     createSymbolDatabase();
03503     for (Token *tok = list.front(); tok; tok = tok->next()) {
03504         if (Token::simpleMatch(tok, "* const"))
03505             tok->deleteNext();
03506     }
03507 
03508     if (_settings->debug) {
03509         list.front()->printOut(0, list.getFiles());
03510 
03511         if (_settings->_verbose)
03512             _symbolDatabase->printOut("Symbol database");
03513     }
03514 
03515     if (_settings->debugwarnings) {
03516         printUnknownTypes();
03517     }
03518 
03519     return true;
03520 }
03521 //---------------------------------------------------------------------------
03522 
03523 void Tokenizer::removeMacrosInGlobalScope()
03524 {
03525     for (Token *tok = list.front(); tok; tok = tok->next()) {
03526         if (tok->str() == "(") {
03527             tok = tok->link();
03528             if (Token::Match(tok, ") %type% {") &&
03529                 !Token::Match(tok->next(), "const|namespace|class|struct|union"))
03530                 tok->deleteNext();
03531         }
03532 
03533         if (Token::Match(tok, "[;{}] %type%") && tok->next()->isUpperCaseName()) {
03534             const Token *tok2 = tok->tokAt(2);
03535             if (tok2 && tok2->str() == "(") {
03536                 unsigned int par = 0;
03537                 for (; tok2; tok2 = tok2->next()) {
03538                     if (tok2->str() == "(")
03539                         ++par;
03540                     else if (tok2->str() == ")") {
03541                         if (par <= 1)
03542                             break;
03543                         --par;
03544                     }
03545                 }
03546                 if (tok2 && tok2->str() == ")")
03547                     tok2 = tok2->next();
03548             }
03549 
03550             // remove unknown macros before namespace|class|struct|union
03551             if (Token::Match(tok2, "namespace|class|struct|union")) {
03552                 // is there a "{" for?
03553                 const Token *tok3 = tok2;
03554                 while (tok3 && !Token::Match(tok3,"[;{}()]"))
03555                     tok3 = tok3->next();
03556                 if (tok3 && tok3->str() == "{")
03557                     Token::eraseTokens(tok, tok2);
03558                 continue;
03559             }
03560 
03561             // remove unknown macros before foo::foo(
03562             if (Token::Match(tok2, "%type% :: %type%")) {
03563                 const Token *tok3 = tok2;
03564                 while (Token::Match(tok3, "%type% :: %type% ::"))
03565                     tok3 = tok3->tokAt(2);
03566                 if (Token::Match(tok3, "%type% :: %type% (") && tok3->str() == tok3->strAt(2))
03567                     Token::eraseTokens(tok, tok2);
03568                 continue;
03569             }
03570         }
03571 
03572         if (tok->str() == "{")
03573             tok = tok->link();
03574     }
03575 }
03576 //---------------------------------------------------------------------------
03577 
03578 void Tokenizer::removeMacroInVarDecl()
03579 {
03580     for (Token *tok = list.front(); tok; tok = tok->next()) {
03581         if (Token::Match(tok, "[;{}] %var% (") && tok->next()->isUpperCaseName()) {
03582             // goto ')' parentheses
03583             const Token *tok2 = tok;
03584             int parlevel = 0;
03585             while (tok2) {
03586                 if (tok2->str() == "(")
03587                     ++parlevel;
03588                 else if (tok2->str() == ")") {
03589                     if (--parlevel <= 0)
03590                         break;
03591                 }
03592                 tok2 = tok2->next();
03593             }
03594             tok2 = tok2 ? tok2->next() : NULL;
03595 
03596             // check if this is a variable declaration..
03597             const Token *tok3 = tok2;
03598             while (tok3 && tok3->isUpperCaseName())
03599                 tok3 = tok3->next();
03600             if (tok3 && (tok3->isStandardType() || Token::Match(tok3,"const|static|struct|union|class")))
03601                 Token::eraseTokens(tok,tok2);
03602         }
03603     }
03604 }
03605 //---------------------------------------------------------------------------
03606 
03607 void Tokenizer::removeRedundantAssignment()
03608 {
03609     for (Token *tok = list.front(); tok; tok = tok->next()) {
03610         if (tok->str() == "{")
03611             tok = tok->link();
03612 
03613         if (Token::Match(tok, ") const| {")) {
03614             // parse in this function..
03615             std::set<unsigned int> localvars;
03616             if (tok->next()->str() == "const")
03617                 tok = tok->next();
03618             const Token * const end = tok->next()->link();
03619             for (Token *tok2 = tok->next(); tok2 && tok2 != end; tok2 = tok2->next()) {
03620                 // skip local class or struct
03621                 if (Token::Match(tok2, "class|struct %type% {|:")) {
03622                     // skip to '{'
03623                     while (tok2 && tok2->str() != "{")
03624                         tok2 = tok2->next();
03625 
03626                     if (tok2)
03627                         tok2 = tok2->link(); // skip local class or struct
03628                     else
03629                         return;
03630                 } else if (Token::Match(tok2, "[;{}] %type% * %var% ;") && tok2->next()->str() != "return") {
03631                     tok2 = tok2->tokAt(3);
03632                     localvars.insert(tok2->varId());
03633                 } else if (Token::Match(tok2, "[;{}] %type% %var% ;") && tok2->next()->isStandardType()) {
03634                     tok2 = tok2->tokAt(2);
03635                     localvars.insert(tok2->varId());
03636                 } else if (tok2->varId() &&
03637                            !Token::Match(tok2->previous(), "[;{}] %var% = %char%|%num%|%var% ;")) {
03638                     localvars.erase(tok2->varId());
03639                 }
03640             }
03641             localvars.erase(0);
03642             if (!localvars.empty()) {
03643                 for (Token *tok2 = tok->next(); tok2 && tok2 != end;) {
03644                     if (Token::Match(tok2, "[;{}] %type% %var% ;") && localvars.find(tok2->tokAt(2)->varId()) != localvars.end()) {
03645                         tok2->deleteNext(3);
03646                     } else if ((Token::Match(tok2, "[;{}] %type% * %var% ;") &&
03647                                 localvars.find(tok2->tokAt(3)->varId()) != localvars.end()) ||
03648                                (Token::Match(tok2, "[;{}] %var% = %any% ;") &&
03649                                 localvars.find(tok2->next()->varId()) != localvars.end())) {
03650                         tok2->deleteNext(4);
03651                     } else
03652                         tok2 = tok2->next();
03653                 }
03654             }
03655         }
03656     }
03657 }
03658 
03659 void Tokenizer::simplifyRealloc()
03660 {
03661     for (Token *tok = list.front(); tok; tok = tok->next()) {
03662         if (tok->str() == "(" || tok->str() == "[" ||
03663             (tok->str() == "{" && tok->previous() && tok->previous()->str() == "="))
03664             tok = tok->link();
03665         else if (Token::Match(tok, "[;{}] %var% = realloc (")) {
03666             tok = tok->tokAt(3);
03667             if (Token::simpleMatch(tok->next(), "( 0 ,")) {
03668                 //no "x = realloc(0,);"
03669                 if (!Token::simpleMatch(tok->next()->link(), ") ;") || tok->next()->link()->previous() == tok->tokAt(3))
03670                     continue;
03671 
03672                 // delete "0 ,"
03673                 tok->next()->deleteNext(2);
03674 
03675                 // Change function name "realloc" to "malloc"
03676                 tok->str("malloc");
03677                 tok = tok->next()->link();
03678             } else {
03679                 Token *tok2 = tok->next()->link()->tokAt(-2);
03680                 //no "x = realloc(,0);"
03681                 if (!Token::simpleMatch(tok2, ", 0 ) ;") || tok2 == tok->tokAt(2))
03682                     continue;
03683 
03684                 //remove ", 0"
03685                 tok2 = tok2->previous();
03686                 tok2->deleteNext(2);
03687                 //change "realloc" to "free"
03688                 tok->str("free");
03689                 //insert "0" after "var ="
03690                 tok = tok->previous();
03691                 tok->insertToken("0");
03692                 //move "var = 0" between "free(...)" and ";"
03693                 tok2 = tok2->next();
03694                 Token::move(tok->previous(), tok->next(), tok2);
03695                 //add missing ";" after "free(...)"
03696                 tok2->insertToken(";");
03697                 //goto before last ";" and continue
03698                 tok = tok->next();
03699             }
03700         }
03701     }
03702 }
03703 
03704 void Tokenizer::simplifyEmptyNamespaces()
03705 {
03706     if (isC())
03707         return;
03708 
03709     bool goback = false;
03710     for (Token *tok = list.front(); tok; tok = tok ? tok->next() : NULL) {
03711         if (goback) {
03712             tok = tok->previous();
03713             goback = false;
03714         }
03715         if (tok->str() == "(" || tok->str() == "[" || tok->str() == "{") {
03716             tok = tok->link();
03717             continue;
03718         }
03719         if (!Token::Match(tok, "namespace %var% {"))
03720             continue;
03721         if (tok->strAt(3) == "}") {
03722             tok->deleteNext(3);             // remove '%var% { }'
03723             if (!tok->previous()) {
03724                 // remove 'namespace' or replace it with ';' if isolated
03725                 tok->deleteThis();
03726                 goback = true;
03727             } else {                    // '%any% namespace %any%'
03728                 tok = tok->previous();  // goto previous token
03729                 tok->deleteNext();      // remove next token: 'namespace'
03730             }
03731         } else {
03732             tok = tok->tokAt(2);
03733         }
03734     }
03735 }
03736 
03737 void Tokenizer::simplifyFlowControl()
03738 {
03739 
03740     for (Token *begin = list.front(); begin; begin = begin->next()) {
03741 
03742         if (begin->str() == "(" || begin->str() == "[" ||
03743             (begin->str() == "{" && begin->previous() && begin->strAt(-1) == "="))
03744             begin = begin->link();
03745 
03746         //function scope
03747         if (!Token::simpleMatch(begin, ") {") && !Token::Match(begin, ") %var% {"))
03748             continue;
03749 
03750         Token *end = begin->linkAt(1+(begin->next()->str() == "{" ? 0 : 1));
03751         unsigned int indentlevel = 0;
03752         bool stilldead = false;
03753 
03754         for (Token *tok = begin; tok != end; tok = tok->next()) {
03755             if (tok->str() == "(" || tok->str() == "[") {
03756                 tok = tok->link();
03757                 continue;
03758             }
03759 
03760             if (tok->str() == "{") {
03761                 if (tok->previous() && tok->previous()->str() == "=") {
03762                     tok = tok->link();
03763                     continue;
03764                 }
03765                 ++indentlevel;
03766             } else if (tok->str() == "}") {
03767                 if (!indentlevel)
03768                     break;
03769                 --indentlevel;
03770                 if (stilldead) {
03771                     eraseDeadCode(tok, 0);
03772                     if (indentlevel == 1 || tok->next()->str() != "}" || !Token::Match(tok->next()->link()->previous(), ";|{|}|do {"))
03773                         stilldead = false;
03774                     continue;
03775                 }
03776             }
03777 
03778             if (!indentlevel)
03779                 continue;
03780 
03781             if (Token::Match(tok,"continue|break ;")) {
03782                 tok = tok->next();
03783                 eraseDeadCode(tok, 0);
03784 
03785             } else if (Token::Match(tok,"return|goto") ||
03786                        Token::Match(tok,"exit|abort") ||
03787                        (tok->str() == "throw" && !isC())) {
03788                 //TODO: ensure that we exclude user-defined 'exit|abort|throw', except for 'noreturn'
03789                 //catch the first ';'
03790                 for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
03791                     if (tok2->str() == "(" || tok2->str() == "[") {
03792                         tok2 = tok2->link();
03793                     } else if (tok2->str() == ";") {
03794                         tok = tok2;
03795                         eraseDeadCode(tok, 0);
03796                         break;
03797                     } else if (Token::Match(tok2, "[{}]"))
03798                         break;  //Wrong code.
03799                 }
03800                 //if everything is removed, then remove also the code after an inferior scope
03801                 //only if the actual scope is not special
03802                 if (indentlevel > 1 && tok->next()->str() == "}" && Token::Match(tok->next()->link()->previous(), ";|{|}|do {"))
03803                     stilldead = true;
03804             }
03805         }
03806         begin = end;
03807     }
03808 }
03809 
03810 
03811 bool Tokenizer::removeRedundantConditions()
03812 {
03813     // Return value for function. Set to true if there are any simplifications
03814     bool ret = false;
03815 
03816     for (Token *tok = list.front(); tok; tok = tok->next()) {
03817         if (tok->str() != "if")
03818             continue;
03819 
03820         if (!Token::Match(tok->next(), "( %bool% ) {"))
03821             continue;
03822 
03823         // Find matching else
03824         Token *elseTag = tok->linkAt(4)->next();
03825 
03826         bool boolValue = (tok->strAt(2) == "true");
03827 
03828         // Handle if with else
03829         if (Token::simpleMatch(elseTag, "else {")) {
03830             // Handle else
03831             if (boolValue == false) {
03832                 // Convert "if( false ) {aaa;} else {bbb;}" => "{bbb;}"
03833 
03834                 //remove '(false)'
03835                 tok->deleteNext(3);
03836                 //delete dead code inside scope
03837                 eraseDeadCode(tok, elseTag);
03838                 //remove 'else'
03839                 elseTag->deleteThis();
03840                 //remove 'if'
03841                 tok->deleteThis();
03842             } else {
03843                 // Convert "if( true ) {aaa;} else {bbb;}" => "{aaa;}"
03844                 const Token *end = elseTag->next()->link()->next();
03845 
03846                 // Remove "else { bbb; }"
03847                 elseTag = elseTag->previous();
03848                 eraseDeadCode(elseTag, end);
03849 
03850                 // Remove "if( true )"
03851                 tok->deleteNext(3);
03852                 tok->deleteThis();
03853             }
03854 
03855             ret = true;
03856         }
03857 
03858         // Handle if without else
03859         else {
03860             if (boolValue == false) {
03861                 //remove '(false)'
03862                 tok->deleteNext(3);
03863                 //delete dead code inside scope
03864                 eraseDeadCode(tok, elseTag);
03865                 //remove 'if'
03866                 tok->deleteThis();
03867             } else {
03868                 // convert "if( true ) {aaa;}" => "{aaa;}"
03869                 tok->deleteNext(3);
03870                 tok->deleteThis();
03871             }
03872 
03873             ret = true;
03874         }
03875     }
03876 
03877     return ret;
03878 }
03879 
03880 void Tokenizer::removeRedundantFor()
03881 {
03882     for (Token *tok = list.front(); tok; tok = tok->next()) {
03883         if (Token::Match(tok, "[;{}] for ( %var% = %num% ; %var% < %num% ; ++| %var% ++| ) {")) {
03884             // Same variable name..
03885             const std::string varname(tok->strAt(3));
03886             const unsigned int varid(tok->tokAt(3)->varId());
03887             if (varname != tok->strAt(7))
03888                 continue;
03889             const Token *vartok = tok->tokAt(11);
03890             if (vartok->str() == "++")
03891                 vartok = vartok->next();
03892             if (varname != vartok->str())
03893                 continue;
03894 
03895             // Check that the difference of the numeric values is 1
03896             const MathLib::bigint num1(MathLib::toLongNumber(tok->strAt(5)));
03897             const MathLib::bigint num2(MathLib::toLongNumber(tok->strAt(9)));
03898             if (num1 + 1 != num2)
03899                 continue;
03900 
03901             // check how loop variable is used in loop..
03902             bool read = false;
03903             bool write = false;
03904             const Token* end = tok->linkAt(2)->next()->link();
03905             for (const Token *tok2 = tok->linkAt(2); tok2 != end; tok2 = tok2->next()) {
03906                 if (tok2->str() == varname) {
03907                     if (tok2->previous()->isArithmeticalOp() &&
03908                         tok2->next() &&
03909                         (tok2->next()->isArithmeticalOp() || tok2->next()->str() == ";")) {
03910                         read = true;
03911                     } else {
03912                         read = write = true;
03913                         break;
03914                     }
03915                 }
03916             }
03917 
03918             // Simplify loop if loop variable isn't written
03919             if (!write) {
03920                 // remove "for ("
03921                 tok->deleteNext(2);
03922 
03923                 // If loop variable is read then keep assignment before
03924                 // loop body..
03925                 if (read) {
03926                     // goto ";"
03927                     tok = tok->tokAt(4);
03928                 } else {
03929                     // remove "x = 0 ;"
03930                     tok->deleteNext(4);
03931                 }
03932 
03933                 // remove "x < 1 ; x ++ )"
03934                 tok->deleteNext(7);
03935 
03936                 // Add assignment after the loop body so the loop variable
03937                 // get the correct end value
03938                 Token *tok2 = tok->next()->link();
03939                 tok2->insertToken(";");
03940                 tok2->insertToken(MathLib::longToString(num2));
03941                 tok2->insertToken("=");
03942                 tok2->insertToken(varname);
03943                 tok2->next()->varId(varid);
03944             }
03945         }
03946     }
03947 }
03948 
03949 
03950 void Tokenizer::removeRedundantSemicolons()
03951 {
03952     for (Token *tok = list.front(); tok; tok = tok->next()) {
03953         if (tok->str() == "(") {
03954             tok = tok->link();
03955         }
03956         for (;;) {
03957             if (Token::simpleMatch(tok, "; ;")) {
03958                 tok->deleteNext();
03959             } else if (Token::simpleMatch(tok, "; { ; }")) {
03960                 tok->deleteNext(3);
03961             } else {
03962                 break;
03963             }
03964         }
03965     }
03966 }
03967 
03968 
03969 bool Tokenizer::simplifyAddBraces()
03970 {
03971     for (Token *tok = list.front(); tok; tok = tok->next()) {
03972         Token const * tokRet=simplifyAddBracesToCommand(tok);
03973         if (!tokRet)
03974             return false;
03975     }
03976     return true;
03977 }
03978 
03979 Token *Tokenizer::simplifyAddBracesToCommand(Token *tok)
03980 {
03981     Token * tokEnd=tok;
03982     if (tok->str()=="for" ||
03983         tok->str()=="BOOST_FOREACH" ||
03984         tok->str()=="switch") {
03985         tokEnd=simplifyAddBracesPair(tok,true);
03986     } else if (tok->str()=="while") {
03987         Token *tokPossibleDo=tok->previous();
03988         if (tokPossibleDo &&
03989             tokPossibleDo->str()=="}")
03990             tokPossibleDo=tokPossibleDo->link();
03991         if (tokPossibleDo)
03992             tokPossibleDo=tokPossibleDo->previous();
03993         if (!tokPossibleDo ||
03994             tokPossibleDo->str()!="do")
03995             tokEnd=simplifyAddBracesPair(tok,true);
03996     } else if (tok->str()=="do") {
03997         tokEnd=simplifyAddBracesPair(tok,false);
03998         if (tokEnd!=tok) {
03999             // walk on to next token, i.e. "while"
04000             // such that simplifyAddBracesPair does not close other braces
04001             // before the "while"
04002             if (tokEnd) {
04003                 tokEnd=tokEnd->next();
04004                 if (!tokEnd) {
04005                     // no while return input token
04006                     syntaxError(tok);
04007                     return NULL;
04008                 }
04009             }
04010         }
04011     } else if (tok->str()=="if") {
04012         tokEnd=simplifyAddBracesPair(tok,true);
04013         if (!tokEnd)
04014             return NULL;
04015         Token * tokEndNext=tokEnd->next();
04016         if (tokEndNext && tokEndNext->str()=="else") {
04017             Token * tokEndNextNext=tokEndNext->next();
04018             if (tokEndNextNext && tokEndNextNext->str()=="if") {
04019                 // do not change "else if ..." to "else { if ... }"
04020                 tokEnd=simplifyAddBracesToCommand(tokEndNextNext);
04021             } else
04022                 tokEnd=simplifyAddBracesPair(tokEndNext,false);
04023         }
04024     }
04025 
04026     return tokEnd;
04027 }
04028 
04029 Token *Tokenizer::simplifyAddBracesPair(Token *tok, bool commandWithCondition)
04030 {
04031     Token * tokCondition=tok->next();
04032     Token *tokAfterCondition=tokCondition;
04033     if (commandWithCondition) {
04034         if (!tokCondition) {
04035             // Missing condition
04036             return tok;
04037         }
04038         if (tokCondition->str()=="(")
04039             tokAfterCondition=tokCondition->link();
04040         else
04041             tokAfterCondition=NULL;
04042         if (!tokAfterCondition) {
04043             // Bad condition
04044             syntaxError(tok);
04045             return NULL;
04046         }
04047         tokAfterCondition=tokAfterCondition->next();
04048     }
04049     if (!tokAfterCondition ||
04050         ((tokAfterCondition->type()==Token::eBracket ||
04051           tokAfterCondition->type()==Token::eExtendedOp)&&
04052          Token::Match(tokAfterCondition,")|}|>|,"))) {
04053         // No tokens left where to add braces around
04054         return tok;
04055     }
04056     Token * tokBracesEnd=NULL;
04057     if (tokAfterCondition->str()=="{") {
04058         // already surrounded by braces
04059         tokBracesEnd=tokAfterCondition->link();
04060     } else {
04061         Token * tokEnd = simplifyAddBracesToCommand(tokAfterCondition);
04062         if (tokEnd->str()!="}") {
04063             // Token does not end with brace
04064             // Look for ; to add own closing brace after it
04065             while (tokEnd &&
04066                    tokEnd->str()!=";" &&
04067                    !((tokEnd->type()==Token::eBracket ||
04068                       tokEnd->type()==Token::eExtendedOp)&&
04069                      Token::Match(tokEnd,")|}|>"))) {
04070                 if (tokEnd->type()==Token::eBracket ||
04071                     (tokEnd->type()==Token::eExtendedOp && tokEnd->str()=="(")) {
04072                     Token *tokInnerCloseBraket=tokEnd->link();
04073                     if (!tokInnerCloseBraket) {
04074                         // Inner bracket does not close
04075                         return tok;
04076                     }
04077                     tokEnd=tokInnerCloseBraket;
04078                 }
04079                 tokEnd=tokEnd->next();
04080             }
04081             if (!tokEnd ||
04082                 tokEnd->str()!=";") {
04083                 // No trailing ;
04084                 return tok;
04085             }
04086         }
04087 
04088         tokAfterCondition->previous()->insertToken("{");
04089         Token * tokOpenBrace=tokAfterCondition->previous();
04090 
04091         tokEnd->insertToken("}");
04092         Token * TokCloseBrace=tokEnd->next();
04093 
04094         Token::createMutualLinks(tokOpenBrace,TokCloseBrace);
04095         tokBracesEnd=TokCloseBrace;
04096     }
04097 
04098     return tokBracesEnd;
04099 }
04100 
04101 void Tokenizer::simplifyCompoundAssignment()
04102 {
04103     // Simplify compound assignments:
04104     // "a+=b" => "a = a + b"
04105     for (Token *tok = list.front(); tok; tok = tok->next()) {
04106         if (Token::Match(tok, "[;{}] (| *| (| %var%")) {
04107             // backup current token..
04108             Token * const tok1 = tok;
04109 
04110             if (tok->next()->str() == "*")
04111                 tok = tok->next();
04112 
04113             if (tok->next() && tok->next()->str() == "(") {
04114                 tok = tok->next()->link()->next();
04115             } else {
04116                 // variable..
04117                 tok = tok->tokAt(2);
04118                 while (Token::Match(tok, ". %var%") ||
04119                        Token::Match(tok, "[|(")) {
04120                     if (tok->str() == ".")
04121                         tok = tok->tokAt(2);
04122                     else {
04123                         // goto "]" or ")"
04124                         tok = tok->link();
04125 
04126                         // goto next token..
04127                         tok = tok ? tok->next() : 0;
04128                     }
04129                 }
04130             }
04131             if (!tok)
04132                 break;
04133 
04134             // Is current token at a compound assignment: +=|-=|.. ?
04135             const std::string &str = tok->str();
04136             std::string op;  // operator used in assignment
04137             if (tok->isAssignmentOp() && str.size() == 2)
04138                 op = str.substr(0, 1);
04139             else if (tok->isAssignmentOp() && str.size() == 3)
04140                 op = str.substr(0, 2);
04141             else {
04142                 tok = tok1;
04143                 continue;
04144             }
04145 
04146             // Remove the whole statement if it says: "+=0;", "-=0;", "*=1;" or "/=1;"
04147             if (Token::Match(tok, "+=|-= 0 ;") ||
04148                 Token::Match(tok, "+=|-= '\\0' ;") ||
04149                 Token::simpleMatch(tok, "|= 0 ;") ||
04150                 Token::Match(tok, "*=|/= 1 ;")) {
04151                 tok = tok1;
04152                 while (tok->next()->str() != ";")
04153                     tok->deleteNext();
04154             } else {
04155                 // Enclose the rhs in parentheses..
04156                 if (!Token::Match(tok->tokAt(2), "[;)]")) {
04157                     // Only enclose rhs in parentheses if there is some operator
04158                     bool someOperator = false;
04159                     for (Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
04160                         if (tok2->str() == "(")
04161                             tok2 = tok2->link();
04162 
04163                         if (Token::Match(tok2->next(), "[;)]")) {
04164                             if (someOperator) {
04165                                 tok->insertToken("(");
04166                                 tok2->insertToken(")");
04167                                 Token::createMutualLinks(tok->next(), tok2->next());
04168                             }
04169                             break;
04170                         }
04171 
04172                         someOperator |= (tok2->isOp() || tok2->str() == "?");
04173                     }
04174                 }
04175 
04176                 // simplify the compound assignment..
04177                 tok->str("=");
04178                 tok->insertToken(op);
04179 
04180                 std::stack<Token *> tokend;
04181                 for (Token *tok2 = tok->previous(); tok2 && tok2 != tok1; tok2 = tok2->previous()) {
04182                     // Don't duplicate ++ and --. Put preincrement in lhs. Put
04183                     // postincrement in rhs.
04184                     if (tok2->type() == Token::eIncDecOp) {
04185                         // pre increment/decrement => don't copy
04186                         if (tok2->next()->isName()) {
04187                             continue;
04188                         }
04189 
04190                         // post increment/decrement => move from lhs to rhs
04191                         tok->insertToken(tok2->str());
04192                         tok2->deleteThis();
04193                         continue;
04194                     }
04195 
04196                     // Copy token from lhs to rhs
04197                     tok->insertToken(tok2->str());
04198                     tok->next()->varId(tok2->varId());
04199                     if (Token::Match(tok->next(), "]|)"))
04200                         tokend.push(tok->next());
04201                     else if (Token::Match(tok->next(), "(|[")) {
04202                         Token::createMutualLinks(tok->next(), tokend.top());
04203                         tokend.pop();
04204                     }
04205                 }
04206             }
04207         }
04208     }
04209 }
04210 
04211 void Tokenizer::simplifyConditionOperator()
04212 {
04213     for (Token *tok = list.front(); tok; tok = tok->next()) {
04214         if (tok->str() == "(" || tok->str() == "[" ||
04215             (tok->str() == "{" && tok->previous() && tok->previous()->str() == "="))
04216             tok = tok->link();
04217 
04218         if (Token::Match(tok, "[{};] *| %var% = %any% ? %any% : %any% ;") ||
04219             Token::Match(tok, "[{};] return %any% ? %any% : %any% ;")) {
04220 
04221             // backup varids so they can be set properly
04222             std::map<std::string, unsigned int> varid;
04223             for (const Token *tok2 = tok->next(); tok2->str() != ";"; tok2 = tok2->next()) {
04224                 if (tok2->varId())
04225                     varid[tok2->str()] = tok2->varId();
04226             }
04227 
04228             std::string var(tok->next()->str());
04229             bool isPointer = false;
04230             bool isReturn = false;
04231             if (tok->next()->str() == "*") {
04232                 tok = tok->next();
04233                 var = tok->next()->str();
04234                 isPointer = true;
04235             } else if (tok->next()->str() == "return") {
04236                 isReturn = true;
04237             }
04238 
04239             Token *tok2 = tok->tokAt(3 - (isReturn ? 1 : 0));
04240             if (!tok2->isName() && !tok2->isNumber() && tok2->str()[0] != '\"')
04241                 continue;
04242             const std::string condition(tok2->str());
04243             tok2 = tok2->tokAt(2);
04244             if (!tok2->isName() && !tok2->isNumber() && tok2->str()[0] != '\"')
04245                 continue;
04246             const std::string value1(tok2->str());
04247             tok2 = tok2->tokAt(2);
04248             if (!tok2->isName() && !tok2->isNumber() && tok2->str()[0] != '\"')
04249                 continue;
04250             const std::string value2(tok2->str());
04251 
04252             if (isPointer) {
04253                 tok = tok->previous();
04254                 tok->deleteNext(9);
04255             } else if (isReturn)
04256                 tok->deleteNext(6);
04257             else
04258                 tok->deleteNext(8);
04259 
04260             Token *starttok = 0;
04261 
04262             std::string str;
04263             if (isReturn)
04264                 str = "if ( condition ) { return value1 ; } return value2 ;";
04265             else
04266                 str = "if ( condition ) { * var = value1 ; } else { * var = value2 ; }";
04267 
04268             std::string::size_type pos1 = 0;
04269             while (pos1 != std::string::npos) {
04270                 if (str[pos1] == '*') {
04271                     pos1 += 2;
04272                     if (isPointer) {
04273                         tok->insertToken("*");
04274                         tok = tok->next();
04275                     }
04276                 }
04277                 std::string::size_type pos2 = str.find(" ", pos1);
04278                 if (pos2 == std::string::npos) {
04279                     tok->insertToken(str.substr(pos1));
04280                     pos1 = pos2;
04281                 } else {
04282                     tok->insertToken(str.substr(pos1, pos2 - pos1));
04283                     pos1 = pos2 + 1;
04284                 }
04285                 tok = tok->next();
04286 
04287                 // set links.
04288                 if (tok->str() == "(" || tok->str() == "{")
04289                     starttok = tok;
04290                 else if (starttok && (tok->str() == ")" || tok->str() == "}")) {
04291                     Token::createMutualLinks(starttok, tok);
04292                     starttok = 0;
04293                 } else if (tok->str() == "condition")
04294                     tok->str(condition);
04295                 else if (tok->str() == "var")
04296                     tok->str(var);
04297                 else if (tok->str() == "value1")
04298                     tok->str(value1);
04299                 else if (tok->str() == "value2")
04300                     tok->str(value2);
04301 
04302                 // set varid.
04303                 if (varid.find(tok->str()) != varid.end())
04304                     tok->varId(varid[tok->str()]);
04305             }
04306         }
04307     }
04308 }
04309 
04310 bool Tokenizer::simplifyConditions()
04311 {
04312     bool ret = false;
04313 
04314     for (Token *tok = list.front(); tok; tok = tok->next()) {
04315         if (Token::Match(tok, "! %bool%|%num%")) {
04316             tok->deleteThis();
04317             if (tok->str() == "0" || tok->str() == "false")
04318                 tok->str("true");
04319             else
04320                 tok->str("false");
04321 
04322             ret = true;
04323         }
04324 
04325         if (Token::simpleMatch(tok, "( true &&") ||
04326             Token::simpleMatch(tok, "&& true &&") ||
04327             Token::simpleMatch(tok->next(), "&& true )")) {
04328             tok->deleteNext(2);
04329             ret = true;
04330         }
04331 
04332         else if (Token::simpleMatch(tok, "( false ||") ||
04333                  Token::simpleMatch(tok, "|| false ||") ||
04334                  Token::simpleMatch(tok->next(), "|| false )")) {
04335             tok->deleteNext(2);
04336             ret = true;
04337         }
04338 
04339         else if (Token::simpleMatch(tok, "( true ||") ||
04340                  Token::simpleMatch(tok, "( false &&")) {
04341             Token::eraseTokens(tok->next(), tok->link());
04342             ret = true;
04343         }
04344 
04345         else if (Token::simpleMatch(tok, "|| true )") ||
04346                  Token::simpleMatch(tok, "&& false )")) {
04347             tok = tok->next();
04348             Token::eraseTokens(tok->next()->link(), tok);
04349             ret = true;
04350         }
04351 
04352         else if (Token::simpleMatch(tok, "&& false &&") ||
04353                  Token::simpleMatch(tok, "|| true ||")) {
04354             //goto '('
04355             Token *tok2 = tok;
04356             while (tok2->previous()) {
04357                 if (tok2->previous()->str() == ")")
04358                     tok2 = tok2->previous()->link();
04359                 else {
04360                     tok2 = tok2->previous();
04361                     if (tok2->str() == "(")
04362                         break;
04363                 }
04364             }
04365             if (!tok2)
04366                 continue;
04367             //move tok to 'true|false' position
04368             tok = tok->next();
04369             //remove everything before 'true|false'
04370             Token::eraseTokens(tok2, tok);
04371             //remove everything after 'true|false'
04372             Token::eraseTokens(tok, tok2->link());
04373             ret = true;
04374         }
04375 
04376         // Change numeric constant in condition to "true" or "false"
04377         if (Token::Match(tok, "if|while ( %num% )|%oror%|&&")) {
04378             tok->tokAt(2)->str((tok->strAt(2) != "0") ? "true" : "false");
04379             ret = true;
04380         }
04381         if (Token::Match(tok, "&&|%oror% %num% )|%oror%|&&")) {
04382             tok->next()->str((tok->next()->str() != "0") ? "true" : "false");
04383             ret = true;
04384         }
04385 
04386         // Reduce "(%num% == %num%)" => "(true)"/"(false)"
04387         if (Token::Match(tok, "&&|%oror%|(") &&
04388             (Token::Match(tok->next(), "%num% %any% %num%") ||
04389              Token::Match(tok->next(), "%bool% %any% %bool%")) &&
04390             Token::Match(tok->tokAt(4), "&&|%oror%|)|?")) {
04391             std::string cmp = tok->strAt(2);
04392             bool result = false;
04393             if (tok->next()->isNumber()) {
04394                 // Compare numbers
04395 
04396                 if (cmp == "==" || cmp == "!=") {
04397                     const std::string& op1(tok->next()->str());
04398                     const std::string& op2(tok->strAt(3));
04399 
04400                     bool eq = false;
04401                     if (MathLib::isInt(op1) && MathLib::isInt(op2))
04402                         eq = (MathLib::toLongNumber(op1) == MathLib::toLongNumber(op2));
04403                     else
04404                         eq = (op1 == op2);
04405 
04406                     if (cmp == "==")
04407                         result = eq;
04408                     else
04409                         result = !eq;
04410                 } else {
04411                     double op1 = MathLib::toDoubleNumber(tok->next()->str());
04412                     double op2 = MathLib::toDoubleNumber(tok->strAt(3));
04413                     if (cmp == ">=")
04414                         result = (op1 >= op2);
04415                     else if (cmp == ">")
04416                         result = (op1 > op2);
04417                     else if (cmp == "<=")
04418                         result = (op1 <= op2);
04419                     else if (cmp == "<")
04420                         result = (op1 < op2);
04421                     else
04422                         cmp = "";
04423                 }
04424             } else {
04425                 // Compare boolean
04426                 bool op1 = (tok->next()->str() == std::string("true"));
04427                 bool op2 = (tok->strAt(3) == std::string("true"));
04428 
04429                 if (cmp == "==")
04430                     result = (op1 == op2);
04431                 else if (cmp == "!=")
04432                     result = (op1 != op2);
04433                 else if (cmp == ">=")
04434                     result = (op1 >= op2);
04435                 else if (cmp == ">")
04436                     result = (op1 > op2);
04437                 else if (cmp == "<=")
04438                     result = (op1 <= op2);
04439                 else if (cmp == "<")
04440                     result = (op1 < op2);
04441                 else
04442                     cmp = "";
04443             }
04444 
04445             if (! cmp.empty()) {
04446                 tok = tok->next();
04447                 tok->deleteNext(2);
04448 
04449                 tok->str(result ? "true" : "false");
04450                 ret = true;
04451             }
04452         }
04453     }
04454 
04455     return ret;
04456 }
04457 
04458 bool Tokenizer::simplifyConstTernaryOp()
04459 {
04460     bool ret = false;
04461     for (Token *tok = list.front(); tok; tok = tok->next()) {
04462         if (tok->str() != "?")
04463             continue;
04464 
04465         if (!Token::Match(tok->tokAt(-2), "<|=|,|(|[|{|}|;|case|return %bool%|%num%") &&
04466             !Token::Match(tok->tokAt(-4), "<|=|,|(|[|{|}|;|case|return ( %bool%|%num% )"))
04467             continue;
04468 
04469         const int offset = (tok->previous()->str() == ")") ? 2 : 1;
04470 
04471         if (tok->strAt(-2*offset) == "<" && !TemplateSimplifier::templateParameters(tok->tokAt(-2*offset)))
04472             continue;
04473 
04474         // Find the token ":" then go to the next token
04475         Token *semicolon = skipTernaryOp(tok);
04476         if (!semicolon || semicolon->previous()->str() != ":" || !semicolon->next())
04477             continue;
04478 
04479         //handle the GNU extension: "x ? : y" <-> "x ? x : y"
04480         if (semicolon->previous() == tok->next())
04481             tok->insertToken(tok->strAt(-offset));
04482 
04483         // go back before the condition, if possible
04484         tok = tok->tokAt(-2);
04485         if (offset == 2) {
04486             // go further back before the "("
04487             tok = tok->tokAt(-2);
04488             //simplify the parentheses
04489             tok->deleteNext();
04490             tok->next()->deleteNext();
04491         }
04492 
04493         if (tok->next()->str() == "false" || tok->next()->str() == "0") {
04494             // Use code after semicolon, remove code before it.
04495             Token::eraseTokens(tok, semicolon);
04496 
04497             tok = tok->next();
04498             ret = true;
04499         }
04500 
04501         // The condition is true. Delete the operator after the ":"..
04502         else {
04503             // delete the condition token and the "?"
04504             tok->deleteNext(2);
04505 
04506             unsigned int ternaryOplevel = 0;
04507             for (const Token *endTok = semicolon; endTok; endTok = endTok->next()) {
04508                 if (endTok->str() == "(" || endTok->str() == "[" || endTok->str() == "{") {
04509                     endTok = endTok->link();
04510                 }
04511 
04512                 else if (endTok->str() == "?")
04513                     ++ternaryOplevel;
04514                 else if (Token::Match(endTok, ")|}|]|;|,|:")) {
04515                     if (endTok->str() == ":" && ternaryOplevel)
04516                         --ternaryOplevel;
04517                     else {
04518                         Token::eraseTokens(semicolon->tokAt(-2), endTok);
04519                         ret = true;
04520                         break;
04521                     }
04522                 }
04523             }
04524         }
04525     }
04526 
04527     return ret;
04528 }
04529 
04530 void Tokenizer::simplifyUndefinedSizeArray()
04531 {
04532     for (Token *tok = list.front(); tok; tok = tok->next()) {
04533         if (Token::Match(tok, "%type%")) {
04534             Token *tok2 = tok->next();
04535             while (tok2 && tok2->str() == "*")
04536                 tok2 = tok2->next();
04537             if (!Token::Match(tok2, "%var% [ ]"))
04538                 continue;
04539 
04540             tok = tok2->previous();
04541             Token *end = tok2->next();
04542             unsigned int count = 0;
04543             while (Token::Match(end, "[ ] [;=[]")) {
04544                 end = end->tokAt(2);
04545                 ++count;
04546             }
04547             if (Token::Match(end, "[;=]")) {
04548                 do {
04549                     tok2->deleteNext(2);
04550                     tok->insertToken("*");
04551                 } while (--count);
04552                 tok = end;
04553             } else
04554                 tok = tok->tokAt(3);
04555         }
04556     }
04557 }
04558 
04559 void Tokenizer::simplifyCasts()
04560 {
04561     for (Token *tok = list.front(); tok; tok = tok->next()) {
04562         // #2897 : don't remove cast in such cases:
04563         // *((char *)a + 1) = 0;
04564         // #3596 : remove cast when casting a function pointer:
04565         // (*(void (*)(char *))fp)(x);
04566         if (!tok->isName() &&
04567             Token::simpleMatch(tok->next(), "* (") &&
04568             !Token::Match(tok->linkAt(2), ") %var%") &&
04569             !Token::simpleMatch(tok->linkAt(2), ") &")) {
04570             tok = tok->linkAt(2);
04571             continue;
04572         }
04573         // #3935 : don't remove cast in such cases:
04574         // ((char *)a)[1] = 0;
04575         if (tok->str() == "(" && Token::simpleMatch(tok->link(), ") [")) {
04576             tok = tok->link();
04577             continue;
04578         }
04579         // #4164 : ((unsigned char)1) => (1)
04580         if (Token::Match(tok->next(), "( unsigned| %type% ) %num%") && tok->next()->link()->previous()->isStandardType()) {
04581             const MathLib::bigint value = MathLib::toLongNumber(tok->next()->link()->next()->str());
04582             unsigned int bits = 8 * _typeSize[tok->next()->link()->previous()->str()];
04583             if (!tok->tokAt(2)->isUnsigned())
04584                 bits--;
04585             if (bits < 31 && value >= 0 && value < (1LL << bits)) {
04586                 Token::eraseTokens(tok, tok->next()->link()->next());
04587             }
04588             continue;
04589         }
04590 
04591         while ((Token::Match(tok->next(), "( %type% *| *| *| ) *|&| %var%") && (tok->str() != ")" || tok->tokAt(2)->isStandardType())) ||
04592                Token::Match(tok->next(), "( %type% %type% *| *| *| ) *|&| %var%") ||
04593                (!tok->isName() && (Token::Match(tok->next(), "( %type% * *| *| ) (") ||
04594                                    Token::Match(tok->next(), "( %type% %type% * *| *| ) (")))) {
04595             if (tok->isName() && tok->str() != "return")
04596                 break;
04597 
04598             if (tok->strAt(-1) == "operator")
04599                 break;
04600 
04601             // Remove cast..
04602             Token::eraseTokens(tok, tok->next()->link()->next());
04603 
04604             // Remove '* &'
04605             if (Token::simpleMatch(tok, "* &")) {
04606                 tok->deleteNext();
04607                 tok->deleteThis();
04608             }
04609 
04610             if (tok->str() == ")" && tok->link()->previous()) {
04611                 // If there was another cast before this, go back
04612                 // there to check it also. e.g. "(int)(char)x"
04613                 tok = tok->link()->previous();
04614             }
04615         }
04616 
04617         // Replace pointer casts of 0.. "(char *)0" => "0"
04618         while (Token::Match(tok->next(), "( %type% * ) 0") ||
04619                Token::Match(tok->next(), "( %type% %type% * ) 0")) {
04620             Token::eraseTokens(tok, tok->next()->link()->next());
04621             if (tok->str() == ")" && tok->link()->previous()) {
04622                 // If there was another cast before this, go back
04623                 // there to check it also. e.g. "(char*)(char*)0"
04624                 tok = tok->link()->previous();
04625             }
04626         }
04627 
04628         while (Token::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <")) {
04629             Token *tok2 = tok->next();
04630             tok2->next()->findClosingBracket(tok2);
04631 
04632             if (Token::simpleMatch(tok2, "> (")) {
04633                 Token *closeBracket = tok2->next()->link();
04634                 if (closeBracket) {
04635                     Token::eraseTokens(tok, tok2->tokAt(2));
04636                     closeBracket->deleteThis();
04637                 } else {
04638                     break;
04639                 }
04640             } else {
04641                 break;
04642             }
04643         }
04644     }
04645 }
04646 
04647 
04648 bool Tokenizer::simplifyFunctionParameters()
04649 {
04650     for (Token *tok = list.front(); tok; tok = tok->next()) {
04651         if (tok->str() == "{" || tok->str() == "[" || tok->str() == "(") {
04652             tok = tok->link();
04653         }
04654 
04655         // Find the function e.g. foo( x ) or foo( x, y )
04656         else if (Token::Match(tok, "%var% ( %var% [,)]") &&
04657                  !(tok->strAt(-1) == ":" || tok->strAt(-1) == ",")) {
04658             // We have found old style function, now we need to change it
04659 
04660             // First step: Get list of argument names in parentheses
04661             std::map<std::string, Token *> argumentNames;
04662             bool bailOut = false;
04663             Token * tokparam = NULL;
04664 
04665             //take count of the function name..
04666             const std::string& funcName(tok->str());
04667 
04668             //floating token used to check for parameters
04669             Token *tok1 = tok;
04670 
04671             while (NULL != (tok1 = tok1->tokAt(2))) {
04672                 if (!Token::Match(tok1, "%var% [,)]")) {
04673                     bailOut = true;
04674                     break;
04675                 }
04676 
04677                 //same parameters: take note of the parameter
04678                 if (argumentNames.find(tok1->str()) != argumentNames.end())
04679                     tokparam = tok1;
04680                 else if (tok1->str() != funcName)
04681                     argumentNames[tok1->str()] = tok1;
04682                 else {
04683                     if (tok1->next()->str() == ")") {
04684                         if (tok1->previous()->str() == ",") {
04685                             tok1 = tok1->tokAt(-2);
04686                             tok1->deleteNext(2);
04687                         } else {
04688                             tok1 = tok1->previous();
04689                             tok1->deleteNext();
04690                             bailOut = true;
04691                             break;
04692                         }
04693                     } else {
04694                         tok1 = tok1->tokAt(-2);
04695                         tok1->next()->deleteNext(2);
04696                     }
04697                 }
04698 
04699                 if (tok1->next()->str() == ")") {
04700                     tok1 = tok1->tokAt(2);
04701                     //expect at least a type name after round brace..
04702                     if (!tok1 || !tok1->isName())
04703                         bailOut = true;
04704                     break;
04705                 }
04706             }
04707 
04708             //goto '('
04709             tok = tok->next();
04710 
04711             if (bailOut) {
04712                 tok = tok->link();
04713                 continue;
04714             }
04715 
04716             tok1 = tok->link()->next();
04717 
04718             // there should be the sequence '; {' after the round parentheses
04719             for (const Token* tok2 = tok1; tok2; tok2 = tok2->next()) {
04720                 if (Token::simpleMatch(tok2, "; {"))
04721                     break;
04722                 else if (tok2->str() == "{") {
04723                     bailOut = true;
04724                     break;
04725                 }
04726             }
04727 
04728             if (bailOut) {
04729                 tok = tok->link();
04730                 continue;
04731             }
04732 
04733             // Last step: check out if the declarations between ')' and '{' match the parameters list
04734             std::map<std::string, Token *> argumentNames2;
04735 
04736             while (tok1 && tok1->str() != "{") {
04737                 if (tok1->str() == "(" || tok1->str() == ")") {
04738                     bailOut = true;
04739                     break;
04740                 }
04741                 if (tok1->str() == ";") {
04742                     if (tokparam) {
04743                         syntaxError(tokparam);
04744                         return false;
04745                     }
04746                     Token *tok2 = tok1->previous();
04747                     while (tok2->str() == "]")
04748                         tok2 = tok2->link()->previous();
04749 
04750                     //it should be a name..
04751                     if (!tok2->isName()) {
04752                         bailOut = true;
04753                         break;
04754                     }
04755 
04756                     if (argumentNames2.find(tok2->str()) != argumentNames2.end()) {
04757                         //same parameter names...
04758                         syntaxError(tok1);
04759                         return false;
04760                     } else
04761                         argumentNames2[tok2->str()] = tok2;
04762 
04763                     if (argumentNames.find(tok2->str()) == argumentNames.end()) {
04764                         //non-matching parameter... bailout
04765                         bailOut = true;
04766                         break;
04767                     }
04768                 }
04769                 tok1 = tok1->next();
04770             }
04771 
04772             if (bailOut || !tok1) {
04773                 tok = tok->link();
04774                 continue;
04775             }
04776 
04777             //the two containers may not hold the same size...
04778             //in that case, the missing parameters are defined as 'int'
04779             if (argumentNames.size() != argumentNames2.size()) {
04780                 //move back 'tok1' to the last ';'
04781                 tok1 = tok1->previous();
04782                 std::map<std::string, Token *>::iterator it;
04783                 for (it = argumentNames.begin(); it != argumentNames.end(); ++it) {
04784                     if (argumentNames2.find(it->first) == argumentNames2.end()) {
04785                         //add the missing parameter argument declaration
04786                         tok1->insertToken(";");
04787                         tok1->insertToken(it->first);
04788                         //register the change inside argumentNames2
04789                         argumentNames2[it->first] = tok1->next();
04790                         tok1->insertToken("int");
04791                     }
04792                 }
04793             }
04794 
04795             while (tok->str() != ")") {
04796                 //initialize start and end tokens to be moved
04797                 Token *declStart = argumentNames2[tok->next()->str()];
04798                 Token *declEnd = declStart;
04799                 while (declStart->previous()->str() != ";" && declStart->previous()->str() != ")")
04800                     declStart = declStart->previous();
04801                 while (declEnd->next()->str() != ";" && declEnd->next()->str() != "{")
04802                     declEnd = declEnd->next();
04803 
04804                 //remove ';' after declaration
04805                 declEnd->deleteNext();
04806 
04807                 //replace the parameter name in the parentheses with all the declaration
04808                 Token::replace(tok->next(), declStart, declEnd);
04809 
04810                 //since there are changes to tokens, put tok where tok1 is
04811                 tok = declEnd->next();
04812             }
04813             //goto forward and continue
04814             tok = tok->next()->link();
04815         }
04816     }
04817     return true;
04818 }
04819 
04820 void Tokenizer::simplifyPointerToStandardType()
04821 {
04822     if (!isC())
04823         return;
04824 
04825     for (Token *tok = list.front(); tok; tok = tok->next()) {
04826         if (!Token::Match(tok, "& %var% [ 0 ]"))
04827             continue;
04828 
04829         // Remove '[ 0 ]' suffix
04830         tok->next()->eraseTokens(tok->next(), tok->tokAt(5));
04831         // Remove '&' prefix
04832         tok = tok->previous();
04833         tok->deleteNext();
04834     }
04835 }
04836 
04837 void Tokenizer:: simplifyFunctionPointers()
04838 {
04839     for (Token *tok = list.front(); tok; tok = tok->next()) {
04840         // #2873 - dont simplify function pointer usage here:
04841         // (void)(xy(*p)(0));
04842         if (Token::simpleMatch(tok, ") (")) {
04843             tok = tok->next()->link();
04844             continue;
04845         }
04846 
04847         // check for function pointer cast
04848         if (Token::Match(tok, "( %type% *| *| ( * ) (") ||
04849             Token::Match(tok, "( %type% %type% *| *| ( * ) (") ||
04850             Token::Match(tok, "static_cast < %type% *| *| ( * ) (") ||
04851             Token::Match(tok, "static_cast < %type% %type% *| *| ( * ) (")) {
04852             Token *tok1 = tok;
04853 
04854             if (tok1->str() == "static_cast")
04855                 tok1 = tok1->next();
04856 
04857             tok1 = tok1->next();
04858 
04859             if (Token::Match(tok1->next(), "%type%"))
04860                 tok1 = tok1->next();
04861 
04862             while (tok1->next()->str() == "*")
04863                 tok1 = tok1->next();
04864 
04865             // check that the cast ends
04866             if (!Token::Match(tok1->linkAt(4), ") )|>"))
04867                 continue;
04868 
04869             // ok simplify this function pointer cast to an ordinary pointer cast
04870             tok1->deleteNext();
04871             tok1->next()->deleteNext();
04872             Token::eraseTokens(tok1->next(), tok1->linkAt(2)->next());
04873             continue;
04874         }
04875 
04876         // check for start of statement
04877         else if (tok->previous() && !Token::Match(tok->previous(), "{|}|;|(|public:|protected:|private:"))
04878             continue;
04879 
04880         if (Token::Match(tok, "%type% *| *| ( * %var% [| ]| ) ("))
04881             ;
04882         else if (Token::Match(tok, "%type% %type% *| *| ( * %var% [| ]| ) ("))
04883             tok = tok->next();
04884         else
04885             continue;
04886 
04887         while (tok->next()->str() == "*")
04888             tok = tok->next();
04889 
04890         // check that the declaration ends
04891         const Token *endTok = tok->next()->link()->next()->link();
04892         if (!Token::Match(endTok, ") ;|,|)|=|["))
04893             continue;
04894 
04895         // ok simplify this function pointer to an ordinary pointer
04896         Token::eraseTokens(tok->next()->link(), endTok->next());
04897         tok->next()->link()->deleteThis();
04898         tok->deleteNext();
04899     }
04900 }
04901 
04902 
04903 bool Tokenizer::simplifyFunctionReturn()
04904 {
04905     bool ret = false;
04906     for (const Token *tok = tokens(); tok; tok = tok->next()) {
04907         if (tok->str() == "{")
04908             tok = tok->link();
04909 
04910         else if (Token::Match(tok, "%var% ( ) { return %bool%|%char%|%num%|%str% ; }")) {
04911             const Token* const any = tok->tokAt(5);
04912 
04913             const std::string pattern("(|[|=|%cop% " + tok->str() + " ( ) ;|]|)|%cop%");
04914             for (Token *tok2 = list.front(); tok2; tok2 = tok2->next()) {
04915                 if (Token::Match(tok2, pattern.c_str())) {
04916                     tok2 = tok2->next();
04917                     tok2->str(any->str());
04918                     tok2->deleteNext(2);
04919                     ret = true;
04920                 }
04921             }
04922         }
04923     }
04924 
04925     return ret;
04926 }
04927 
04928 
04929 static void incdec(std::string &value, const std::string &op)
04930 {
04931     int ivalue = 0;
04932     std::istringstream istr(value);
04933     istr >> ivalue;
04934     if (op == "++")
04935         ++ivalue;
04936     else if (op == "--")
04937         --ivalue;
04938     std::ostringstream ostr;
04939     ostr << ivalue;
04940     value = ostr.str();
04941 }
04942 
04943 
04944 
04945 void Tokenizer::simplifyVarDecl(bool only_k_r_fpar)
04946 {
04947     // Split up variable declarations..
04948     // "int a=4;" => "int a; a=4;"
04949     bool finishedwithkr = true;
04950     for (Token *tok = list.front(); tok; tok = tok->next()) {
04951         if (Token::simpleMatch(tok, "= {")) {
04952             tok = tok->next()->link();
04953         }
04954 
04955         if (only_k_r_fpar && finishedwithkr) {
04956             if (tok->str() == "(" || tok->str() == "[" || tok->str() == "{") {
04957                 tok = tok->link();
04958                 if (tok->next() && Token::Match(tok, ") !!{"))
04959                     tok = tok->next();
04960                 else
04961                     continue;
04962             } else
04963                 continue;
04964         } else if (tok->str() == "(") {
04965             tok = tok->link();
04966 
04967             // TestTokenizer::vardecl24 - lambda functions..
04968             if (isCPP() && tok->previous()->str() == "}")
04969                 tok = tok->previous()->link();
04970         }
04971 
04972         if (tok->previous() && !Token::Match(tok->previous(), "{|}|;|)|public:|protected:|private:"))
04973             continue;
04974 
04975         Token *type0 = tok;
04976         if (!Token::Match(type0, "::| %type%"))
04977             continue;
04978         if (Token::Match(type0, "else|return|public:|protected:|private:"))
04979             continue;
04980 
04981         bool isconst = false;
04982         bool isstatic = false;
04983         Token *tok2 = type0;
04984         unsigned int typelen = 1;
04985 
04986         if (tok2->str() == "::") {
04987             tok2 = tok2->next();
04988             typelen++;
04989         }
04990 
04991         //check if variable is declared 'const' or 'static' or both
04992         while (tok2) {
04993             if (!Token::Match(tok2, "const|static") && Token::Match(tok2, "%type% const|static")) {
04994                 tok2 = tok2->next();
04995                 ++typelen;
04996             }
04997 
04998             if (tok2->str() == "const")
04999                 isconst = true;
05000 
05001             else if (tok2->str() == "static")
05002                 isstatic = true;
05003 
05004             else if (Token::Match(tok2, "%type% :: %type%")) {
05005                 tok2 = tok2->next();
05006                 ++typelen;
05007             }
05008 
05009             else
05010                 break;
05011 
05012             if (tok2->strAt(1) == "*")
05013                 break;
05014 
05015             tok2 = tok2->next();
05016             ++typelen;
05017         }
05018 
05019         // strange looking variable declaration => don't split up.
05020         if (Token::Match(tok2, "%type% *| %var% , %type% *| %var%"))
05021             continue;
05022 
05023         if (Token::Match(tok2, "struct|union|class %type%")) {
05024             tok2 = tok2->next();
05025             ++typelen;
05026         }
05027 
05028         // check for qualification..
05029         if (Token::Match(tok2,  ":: %type%")) {
05030             ++typelen;
05031             tok2 = tok2->next();
05032         }
05033 
05034         //skip combinations of templates and namespaces
05035         while (Token::Match(tok2, "%type% <") || Token::Match(tok2, "%type% ::")) {
05036             if (tok2->next()->str() == "<" && !TemplateSimplifier::templateParameters(tok2->next())) {
05037                 tok2 = NULL;
05038                 break;
05039             }
05040             typelen += 2;
05041             tok2 = tok2->tokAt(2);
05042             if (tok2 && tok2->previous()->str() == "::")
05043                 continue;
05044             unsigned int indentlevel = 0;
05045             unsigned int parens = 0;
05046 
05047             for (Token *tok3 = tok2; tok3; tok3 = tok3->next()) {
05048                 ++typelen;
05049 
05050                 if (tok3->str() == "<" && !parens) {
05051                     ++indentlevel;
05052                 } else if (tok3->str() == ">" && !parens) {
05053                     if (indentlevel == 0) {
05054                         tok2 = tok3->next();
05055                         break;
05056                     }
05057                     --indentlevel;
05058                 } else if (tok3->str() == ">>" && !parens) {
05059                     if (indentlevel <= 1U) {
05060                         tok2 = tok3->next();
05061                         break;
05062                     }
05063                     indentlevel -= 2;
05064                 } else if (tok3->str() == "(") {
05065                     ++parens;
05066                 } else if (tok3->str() == ")") {
05067                     if (!parens) {
05068                         tok2 = NULL;
05069                         break;
05070                     }
05071                     --parens;
05072                 } else if (tok3->str() == ";") {
05073                     break;
05074                 }
05075             }
05076 
05077             if (Token::Match(tok2,  ":: %type%")) {
05078                 ++typelen;
05079                 tok2 = tok2->next();
05080             }
05081         }
05082 
05083         //pattern: "%type% *| ... *| const| %var% ,|="
05084         if (Token::Match(tok2, "%type%") ||
05085             (tok2 && tok2->previous() && tok2->previous()->str() == ">")) {
05086             bool ispointer = false;
05087             Token *varName = tok2;
05088             if (!tok2->previous() || tok2->previous()->str() != ">")
05089                 varName = varName->next();
05090             else
05091                 --typelen;
05092             //skip all the pointer part
05093             while (varName && varName->str() == "*") {
05094                 ispointer = true;
05095                 varName = varName->next();
05096             }
05097 
05098             while (Token::Match(varName, "%type% %type%")) {
05099                 if (varName->str() != "const") {
05100                     ++typelen;
05101                 }
05102                 varName = varName->next();
05103             }
05104             //non-VLA case
05105             if (Token::Match(varName, "%var% ,|=")) {
05106                 if (varName->str() != "operator") {
05107                     tok2 = varName->next(); // The ',' or '=' token
05108 
05109                     if (tok2->str() == "=") {
05110                         if (isstatic) {
05111                             if (Token::Match(tok2->next(), "%num% ,"))
05112                                 tok2 = tok2->tokAt(2);
05113                             else
05114                                 tok2 = NULL;
05115                         } else if (isconst && !ispointer) {
05116                             //do not split const non-pointer variables..
05117                             while (tok2 && tok2->str() != "," && tok2->str() != ";") {
05118                                 if (tok2->str() == "{" || tok2->str() == "(" || tok2->str() == "[")
05119                                     tok2 = tok2->link();
05120                                 if (tok2->str() == "<" && TemplateSimplifier::templateParameters(tok2) > 0)
05121                                     tok2->findClosingBracket(tok2);
05122                                 tok2 = tok2->next();
05123                             }
05124                             if (tok2 && tok2->str() == ";")
05125                                 tok2 = NULL;
05126                         }
05127                     }
05128                 } else
05129                     tok2 = NULL;
05130             }
05131 
05132             //VLA case
05133             else if (Token::Match(varName, "%var% [")) {
05134                 tok2 = varName->next();
05135 
05136                 while (Token::Match(tok2->link(), "] ,|=|["))
05137                     tok2 = tok2->link()->next();
05138                 if (!Token::Match(tok2, "=|,"))
05139                     tok2 = NULL;
05140                 if (tok2 && tok2->str() == "=") {
05141                     while (tok2 && tok2->str() != "," && tok2->str() != ";") {
05142                         if (tok2->str() == "{" || tok2->str() == "(" || tok2->str() == "[")
05143                             tok2 = tok2->link();
05144                         tok2 = tok2->next();
05145                     }
05146                     if (tok2 && tok2->str() == ";")
05147                         tok2 = NULL;
05148                 }
05149             } else
05150                 tok2 = NULL;
05151         } else {
05152             tok2 = NULL;
05153         }
05154 
05155         if (!tok2) {
05156             if (only_k_r_fpar)
05157                 finishedwithkr = false;
05158             continue;
05159         }
05160 
05161         if (tok2->str() == ",") {
05162             tok2->str(";");
05163             //TODO: should we have to add also template '<>' links?
05164             list.insertTokens(tok2, type0, typelen);
05165         }
05166 
05167         else {
05168             Token *eq = tok2;
05169 
05170             while (tok2) {
05171                 if (tok2->str() == "{" || tok2->str() == "(")
05172                     tok2 = tok2->link();
05173 
05174                 else if (tok2->str() == "<" && tok2->previous()->isName() && !tok2->previous()->varId())
05175                     tok2->findClosingBracket(tok2);
05176 
05177                 else if (std::strchr(";,", tok2->str()[0])) {
05178                     // "type var ="   =>   "type var; var ="
05179                     const Token *VarTok = type0->tokAt((int)typelen);
05180                     while (Token::Match(VarTok, "*|&|const"))
05181                         VarTok = VarTok->next();
05182                     list.insertTokens(eq, VarTok, 2);
05183                     eq->str(";");
05184 
05185                     // "= x, "   =>   "= x; type "
05186                     if (tok2->str() == ",") {
05187                         tok2->str(";");
05188                         list.insertTokens(tok2, type0, typelen);
05189                     }
05190                     break;
05191                 }
05192 
05193                 tok2 = tok2->next();
05194             }
05195         }
05196         finishedwithkr = (only_k_r_fpar && tok2 && tok2->strAt(1) == "{");
05197     }
05198 }
05199 
05200 void Tokenizer::simplifyPlatformTypes()
05201 {
05202     enum { isLongLong, isLong, isInt } type;
05203 
05204     /** @todo This assumes a flat address space. Not true for segmented address space (FAR *). */
05205     if (_settings->sizeof_size_t == 8)
05206         type = isLongLong;
05207     else if (_settings->sizeof_size_t == 4 && _settings->sizeof_long == 4)
05208         type = isLong;
05209     else if (_settings->sizeof_size_t == 4)
05210         type = isInt;
05211     else
05212         return;
05213 
05214     for (Token *tok = list.front(); tok; tok = tok->next()) {
05215         if (Token::Match(tok, "std :: size_t|ssize_t|ptrdiff_t|intptr_t|uintptr_t")) {
05216             tok->deleteNext();
05217             tok->deleteThis();
05218         } else if (Token::Match(tok, ":: size_t|ssize_t|ptrdiff_t|intptr_t|uintptr_t")) {
05219             tok->deleteThis();
05220         }
05221 
05222         if (Token::Match(tok, "size_t|uintptr_t")) {
05223             tok->str("unsigned");
05224 
05225             switch (type) {
05226             case isLongLong:
05227                 tok->insertToken("long");
05228                 tok->insertToken("long");
05229                 break;
05230             case isLong :
05231                 tok->insertToken("long");
05232                 break;
05233             case isInt:
05234                 tok->insertToken("int");
05235                 break;
05236             }
05237         } else if (Token::Match(tok, "ssize_t|ptrdiff_t|intptr_t")) {
05238             switch (type) {
05239             case isLongLong:
05240                 tok->str("long");
05241                 tok->insertToken("long");
05242                 break;
05243             case isLong :
05244                 tok->str("long");
05245                 break;
05246             case isInt:
05247                 tok->str("int");
05248                 break;
05249             }
05250         }
05251     }
05252 
05253     if (_settings->platformType == Settings::Win32A ||
05254         _settings->platformType == Settings::Win32W ||
05255         _settings->platformType == Settings::Win64) {
05256         for (Token *tok = list.front(); tok; tok = tok->next()) {
05257             if (Token::Match(tok, "BOOL|INT|INT32|HFILE|LONG32"))
05258                 tok->str("int");
05259             else if (Token::Match(tok, "BOOLEAN|BYTE|UCHAR")) {
05260                 tok->str("unsigned");
05261                 tok->insertToken("char");
05262             } else if (tok->str() == "CHAR")
05263                 tok->str("char");
05264             else if (Token::Match(tok, "DWORD|ULONG|COLORREF|LCID|LCTYPE|LGRPID")) {
05265                 tok->str("unsigned");
05266                 tok->insertToken("long");
05267             } else if (Token::Match(tok, "DWORD_PTR|ULONG_PTR|SIZE_T")) {
05268                 tok->str("unsigned");
05269                 tok->insertToken("long");
05270                 if (_settings->platformType == Settings::Win64)
05271                     tok->insertToken("long");
05272             } else if (tok->str() == "FLOAT")
05273                 tok->str("float");
05274             else if (Token::Match(tok, "HRESULT|LONG"))
05275                 tok->str("long");
05276             else if (Token::Match(tok, "INT64|LONG64")) {
05277                 tok->str("long");
05278                 tok->insertToken("long");
05279             } else if (Token::Match(tok, "LONG_PTR|LPARAM|LRESULT|SSIZE_T")) {
05280                 tok->str("long");
05281                 if (_settings->platformType == Settings::Win64)
05282                     tok->insertToken("long");
05283             } else if (Token::Match(tok, "LPBOOL|PBOOL")) {
05284                 tok->str("int");
05285                 tok->insertToken("*");
05286             } else if (Token::Match(tok, "LPBYTE|PBOOLEAN|PBYTE|PUCHAR")) {
05287                 tok->str("unsigned");
05288                 tok->insertToken("*");
05289                 tok->insertToken("char");
05290             } else if (Token::Match(tok, "LPCSTR|PCSTR")) {
05291                 tok->str("const");
05292                 tok->insertToken("*");
05293                 tok->insertToken("char");
05294             } else if (tok->str() == "LPCVOID") {
05295                 tok->str("const");
05296                 tok->insertToken("*");
05297                 tok->insertToken("void");
05298             } else if (Token::Match(tok, "LPDWORD|LPCOLORREF|PDWORD|PULONG")) {
05299                 tok->str("unsigned");
05300                 tok->insertToken("*");
05301                 tok->insertToken("long");
05302             } else if (Token::Match(tok, "LPINT|PINT")) {
05303                 tok->str("int");
05304                 tok->insertToken("*");
05305             } else if (Token::Match(tok, "LPLONG|PLONG")) {
05306                 tok->str("long");
05307                 tok->insertToken("*");
05308             } else if (Token::Match(tok, "LPSTR|PSTR|PCHAR")) {
05309                 tok->str("char");
05310                 tok->insertToken("*");
05311             } else if (Token::Match(tok, "PWSTR|PWCHAR")) {
05312                 tok->str("wchar_t");
05313                 tok->insertToken("*");
05314             } else if (Token::Match(tok, "LPVOID|PVOID|HANDLE|HBITMAP|HBRUSH|HCOLORSPACE|HCURSOR|HDC|HFONT|HGDIOBJ|HGLOBAL|HICON|HINSTANCE|HKEY|HLOCAL|HMENU|HMETAFILE|HMODULE|HPALETTE|HPEN|HRGN|HRSRC|HWND|SERVICE_STATUS_HANDLE|SC_LOCK|SC_HANDLE|HACCEL|HCONV|HCONVLIST|HDDEDATA|HDESK|HDROP|HDWP|HENHMETAFILE|HHOOK|HKL|HMONITOR|HSZ|HWINSTA")) {
05315                 tok->str("void");
05316                 tok->insertToken("*");
05317             } else if ((tok->str() == "PHANDLE")) {
05318                 tok->str("void");
05319                 tok->insertToken("*");
05320                 tok->insertToken("*");
05321             } else if (Token::Match(tok, "LPWORD|PWORD|PUSHORT")) {
05322                 tok->str("unsigned");
05323                 tok->insertToken("*");
05324                 tok->insertToken("short");
05325             } else if (tok->str() == "SHORT")
05326                 tok->str("short");
05327             else if (Token::Match(tok, "UINT|MMRESULT|SOCKET|ULONG32|UINT32|DWORD32")) {
05328                 tok->str("unsigned");
05329                 tok->insertToken("int");
05330             } else if (Token::Match(tok, "UINT_PTR|WPARAM")) {
05331                 tok->str("unsigned");
05332                 if (_settings->platformType == Settings::Win64) {
05333                     tok->insertToken("long");
05334                     tok->insertToken("long");
05335                 } else {
05336                     tok->insertToken("int");
05337                 }
05338             } else if (Token::Match(tok, "USHORT|WORD|ATOM|LANGID")) {
05339                 tok->str("unsigned");
05340                 tok->insertToken("short");
05341             } else if (tok->str() == "VOID")
05342                 tok->str("void");
05343             else if (tok->str() == "TCHAR") {
05344                 if (_settings->platformType == Settings::Win32A)
05345                     tok->str("char");
05346                 else {
05347                     tok->str("wchar_t");
05348                 }
05349             } else if (tok->str() == "TBYTE") {
05350                 tok->str("unsigned");
05351                 if (_settings->platformType == Settings::Win32A)
05352                     tok->insertToken("short");
05353                 else
05354                     tok->insertToken("char");
05355             } else if (Token::Match(tok, "PTSTR|LPTSTR")) {
05356                 if (_settings->platformType == Settings::Win32A) {
05357                     tok->str("char");
05358                     tok->insertToken("*");
05359                 } else {
05360                     tok->str("wchar_t");
05361                     tok->insertToken("*");
05362                 }
05363             } else if (Token::Match(tok, "PCTSTR|LPCTSTR")) {
05364                 tok->str("const");
05365                 if (_settings->platformType == Settings::Win32A) {
05366                     tok->insertToken("*");
05367                     tok->insertToken("char");
05368                 } else {
05369                     tok->insertToken("*");
05370                     tok->insertToken("wchar_t");
05371                 }
05372             } else if (Token::Match(tok, "ULONG64|DWORD64")) {
05373                 tok->str("unsigned");
05374                 tok->insertToken("long");
05375             } else if (tok->str() == "HALF_PTR") {
05376                 if (_settings->platformType == Settings::Win64)
05377                     tok->str("int");
05378                 else
05379                     tok->str("short");
05380             } else if (tok->str() == "INT_PTR") {
05381                 if (_settings->platformType == Settings::Win64) {
05382                     tok->str("long");
05383                     tok->insertToken("long");
05384                 } else {
05385                     tok->str("int");
05386                 }
05387             } else if (tok->str() == "LPWSTR") {
05388                 tok->str("wchar_t");
05389                 tok->insertToken("*");
05390             } else if (tok->str() == "LPCWSTR") {
05391                 tok->str("const");
05392                 tok->insertToken("*");
05393                 tok->insertToken("wchar_t");
05394             }
05395         }
05396     }
05397 }
05398 
05399 void Tokenizer::simplifyStdType()
05400 {
05401     for (Token *tok = list.front(); tok; tok = tok->next()) {
05402         // long unsigned => unsigned long
05403         if (Token::Match(tok, "char|short|int|long|__int8|__int16|__int32|__int64 unsigned|signed")) {
05404             bool isUnsigned = tok->next()->str() == "unsigned";
05405             tok->deleteNext();
05406             tok->isUnsigned(isUnsigned);
05407             tok->isSigned(!isUnsigned);
05408         }
05409 
05410         else if (!Token::Match(tok, "unsigned|signed|char|short|int|long|__int8|__int16|__int32|__int64"))
05411             continue;
05412 
05413         // check if signed or unsigned specified
05414         if (Token::Match(tok, "unsigned|signed")) {
05415             bool isUnsigned = tok->str() == "unsigned";
05416 
05417             // unsigned i => unsigned int i
05418             if (!Token::Match(tok->next(), "char|short|int|long|__int8|__int16|__int32|__int64"))
05419                 tok->str("int");
05420             else
05421                 tok->deleteThis();
05422             tok->isUnsigned(isUnsigned);
05423             tok->isSigned(!isUnsigned);
05424         }
05425 
05426         if (tok->str() == "__int8")
05427             tok->str("char");
05428         else if (tok->str() == "__int16")
05429             tok->str("short");
05430         else if (tok->str() == "__int32")
05431             tok->str("int");
05432         else if (tok->str() == "__int64") {
05433             tok->str("long");
05434             tok->isLong(true);
05435         } else if (tok->str() == "long") {
05436             if (tok->strAt(1) == "long") {
05437                 tok->isLong(true);
05438                 tok->deleteNext();
05439             }
05440 
05441             if (tok->strAt(1) == "int")
05442                 tok->deleteNext();
05443             else if (tok->strAt(1) == "double") {
05444                 tok->str("double");
05445                 tok->isLong(true);
05446                 tok->deleteNext();
05447             }
05448         } else if (tok->str() == "short") {
05449             if (tok->strAt(1) == "int")
05450                 tok->deleteNext();
05451         }
05452     }
05453 }
05454 
05455 void Tokenizer::simplifyIfAssign()
05456 {
05457     // See also simplifyFunctionAssign
05458 
05459     for (Token *tok = list.front(); tok; tok = tok->next()) {
05460         if (!Token::Match(tok->next(), "if|while ( !| (| %var% =") &&
05461             !Token::Match(tok->next(), "if|while ( !| (| %var% . %var% ="))
05462             continue;
05463 
05464         // simplifying a "while" condition ?
05465         const bool iswhile(tok->next()->str() == "while");
05466 
05467         // delete the "if"
05468         tok->deleteNext();
05469 
05470         // Remember if there is a "!" or not. And delete it if there are.
05471         const bool isNot(tok->strAt(2) == "!");
05472         if (isNot)
05473             tok->next()->deleteNext();
05474 
05475         // Delete parentheses.. and remember how many there are with
05476         // their links.
05477         std::stack<Token *> braces;
05478         while (tok->next()->str() == "(") {
05479             braces.push(tok->next()->link());
05480             tok->deleteNext();
05481         }
05482 
05483         // Skip the "%var% = ..."
05484         Token *tok2;
05485         for (tok2 = tok->next(); tok2; tok2 = tok2->next()) {
05486             if (tok2->str() == "(")
05487                 tok2 = tok2->link();
05488             else if (tok2->str() == ")")
05489                 break;
05490         }
05491 
05492         // Insert "; if|while ( .."
05493         tok2 = tok2->previous();
05494         if (tok->strAt(2) == ".") {
05495             tok2->insertToken(tok->strAt(3));
05496             tok2->next()->varId(tok->tokAt(3)->varId());
05497             tok2->insertToken(".");
05498         }
05499         tok2->insertToken(tok->next()->str());
05500         tok2->next()->varId(tok->next()->varId());
05501 
05502         while (! braces.empty()) {
05503             tok2->insertToken("(");
05504             Token::createMutualLinks(tok2->next(), braces.top());
05505             braces.pop();
05506         }
05507 
05508         if (isNot)
05509             tok2->next()->insertToken("!");
05510         tok2->insertToken(iswhile ? "while" : "if");
05511         tok2->insertToken(";");
05512 
05513         // If it's a while loop.. insert the assignment in the loop
05514         if (iswhile) {
05515             unsigned int indentlevel = 0;
05516             Token *tok3 = tok2;
05517             for (; tok3; tok3 = tok3->next()) {
05518                 if (tok3->str() == "{")
05519                     ++indentlevel;
05520                 else if (tok3->str() == "}") {
05521                     if (indentlevel <= 1)
05522                         break;
05523                     --indentlevel;
05524                 }
05525             }
05526 
05527             if (tok3 && indentlevel == 1) {
05528                 tok3 = tok3->previous();
05529                 std::stack<Token *> braces2;
05530 
05531                 for (tok2 = tok2->next(); tok2 && tok2 != tok; tok2 = tok2->previous()) {
05532                     tok3->insertToken(tok2->str());
05533                     tok3->next()->varId(tok2->varId());
05534 
05535                     Token *newTok = tok3->next();
05536                     newTok->fileIndex(tok2->fileIndex());
05537                     newTok->linenr(tok2->linenr());
05538 
05539                     // link() newly tokens manually
05540                     if (Token::Match(newTok, "}|)|]")) {
05541                         braces2.push(newTok);
05542                     } else if (Token::Match(newTok, "{|(|[")) {
05543                         Token::createMutualLinks(newTok, braces2.top());
05544                         braces2.pop();
05545                     }
05546                 }
05547             }
05548         }
05549     }
05550 }
05551 
05552 
05553 void Tokenizer::simplifyVariableMultipleAssign()
05554 {
05555     for (Token *tok = list.front(); tok; tok = tok->next()) {
05556         if (Token::Match(tok, "%var% = %var% = %num%|%var% ;")) {
05557             // skip intermediate assignments
05558             Token *tok2 = tok->previous();
05559             while (tok2 &&
05560                    tok2->str() == "=" &&
05561                    Token::Match(tok2->previous(), "%var%")) {
05562                 tok2 = tok2->tokAt(-2);
05563             }
05564 
05565             if (!tok2 || tok2->str() != ";") {
05566                 continue;
05567             }
05568 
05569             Token *stopAt = tok->tokAt(2);
05570             const Token *valueTok = tok->tokAt(4);
05571             const std::string value(valueTok->str());
05572             tok2 = tok2->next();
05573 
05574             while (tok2 != stopAt) {
05575                 tok2->next()->insertToken(";");
05576                 tok2->next()->insertToken(value);
05577                 tok2 = tok2->tokAt(4);
05578             }
05579         }
05580     }
05581 }
05582 
05583 
05584 void Tokenizer::simplifyIfNot()
05585 {
05586     for (Token *tok = list.front(); tok; tok = tok->next()) {
05587         if (Token::Match(tok, "(|&&|%oror%")) {
05588             tok = tok->next();
05589             while (tok && tok->str() == "(")
05590                 tok = tok->next();
05591 
05592             if (!tok)
05593                 break;
05594 
05595             if (Token::Match(tok, "0|false == (") ||
05596                 Token::Match(tok, "0|false == %var%")) {
05597                 tok->deleteNext();
05598                 tok->str("!");
05599             }
05600 
05601             else if (Token::Match(tok, "%var% == 0|false")) {
05602                 tok->deleteNext(2);
05603                 tok = tok->previous();
05604                 tok->insertToken("!");
05605                 tok = tok->next();
05606             }
05607 
05608             else if (Token::Match(tok, "%var% .|:: %var% == 0|false")) {
05609                 tok = tok->previous();
05610                 tok->insertToken("!");
05611                 tok = tok->tokAt(4);
05612                 tok->deleteNext(2);
05613             }
05614 
05615             else if (Token::Match(tok, "* %var% == 0|false")) {
05616                 tok = tok->previous();
05617                 tok->insertToken("!");
05618                 tok = tok->tokAt(3);
05619                 tok->deleteNext(2);
05620             }
05621         }
05622 
05623         else if (tok->link() && Token::Match(tok, ") == 0|false")) {
05624             // if( foo(x) == 0 )
05625             if (Token::Match(tok->link()->tokAt(-2), "( %var%")) {
05626                 tok->deleteNext(2);
05627                 tok->link()->previous()->insertToken(tok->link()->previous()->str());
05628                 tok->link()->tokAt(-2)->str("!");
05629             }
05630 
05631             // if( (x) == 0 )
05632             else if (tok->link()->strAt(-1) == "(") {
05633                 tok->deleteNext(2);
05634                 tok->link()->insertToken("(");
05635                 tok->link()->str("!");
05636                 Token *temp = tok->link();
05637                 Token::createMutualLinks(tok->link()->next(), tok);
05638                 temp->link(0);
05639             }
05640         }
05641     }
05642 }
05643 
05644 
05645 void Tokenizer::simplifyIfNotNull()
05646 {
05647     for (Token *tok = list.front(); tok; tok = tok->next()) {
05648         Token *deleteFrom = NULL;
05649 
05650         // Remove 'x = (x != 0)'
05651         if (Token::simpleMatch(tok, "= (")) {
05652             if (Token::Match(tok->tokAt(-2), "[;{}] %var%")) {
05653                 const std::string varname(tok->previous()->str());
05654 
05655                 if (Token::simpleMatch(tok->tokAt(2), (varname + " != 0 ) ;").c_str()) ||
05656                     Token::simpleMatch(tok->tokAt(2), ("0 != " + varname + " ) ;").c_str())) {
05657                     tok = tok->tokAt(-2);
05658                     tok->deleteNext(8);
05659                 }
05660             }
05661             continue;
05662         }
05663 
05664         if (Token::Match(tok, "(|&&|%oror%")) {
05665             tok = tok->next();
05666 
05667             if (!tok)
05668                 break;
05669 
05670             if (Token::simpleMatch(tok, "0 != (") ||
05671                 Token::Match(tok, "0 != %var%")) {
05672                 deleteFrom = tok->previous();
05673                 if (tok->tokAt(2))
05674                     tok->tokAt(2)->isPointerCompare(true);
05675             }
05676 
05677             else if (Token::Match(tok, "%var% != 0")) {
05678                 deleteFrom = tok;
05679                 tok->isPointerCompare(true);
05680             }
05681 
05682             else if (Token::Match(tok, "%var% .|:: %var% != 0")) {
05683                 tok = tok->tokAt(2);
05684                 deleteFrom = tok;
05685                 tok->isPointerCompare(true);
05686             }
05687         }
05688 
05689         else if (tok->link() && Token::simpleMatch(tok, ") != 0")) {
05690             deleteFrom = tok;
05691         }
05692 
05693         if (deleteFrom) {
05694             Token::eraseTokens(deleteFrom, deleteFrom->tokAt(3));
05695             tok = deleteFrom;
05696         }
05697     }
05698 }
05699 
05700 
05701 void Tokenizer::simplifyIfSameInnerCondition()
05702 {
05703     // same inner condition
05704     for (Token *tok = list.front(); tok; tok = tok->next()) {
05705         if (Token::Match(tok, "if ( %var% ) {")) {
05706             const unsigned int varid(tok->tokAt(2)->varId());
05707             if (!varid)
05708                 continue;
05709 
05710             for (Token *tok2 = tok->tokAt(5); tok2; tok2 = tok2->next()) {
05711                 if (tok2->str() == "{" || tok2->str() == "}")
05712                     break;
05713                 if (Token::simpleMatch(tok2, "if (")) {
05714                     tok2 = tok2->tokAt(2);
05715                     if (Token::Match(tok2, "%varid% )", varid))
05716                         tok2->str("true");
05717                     else if (Token::Match(tok2, "! %varid% )", varid))
05718                         tok2->next()->varId(varid);
05719                     break;
05720                 }
05721             }
05722         }
05723     }
05724 }
05725 
05726 
05727 bool Tokenizer::simplifyLogicalOperators()
05728 {
05729     bool ret = false;
05730 
05731     // "if (not p)" => "if (!p)"
05732     // "if (p and q)" => "if (p && q)"
05733     // "if (p or q)" => "if (p || q)"
05734     for (Token *tok = list.front(); tok; tok = tok->next()) {
05735         if (Token::Match(tok, "if|while ( not|compl %var%")) {
05736             tok->tokAt(2)->str(tok->strAt(2) == "not" ? "!" : "~");
05737             ret = true;
05738         } else if (Token::Match(tok, "&& not|compl %var%")) {
05739             tok->next()->str(tok->next()->str() == "not" ? "!" : "~");
05740             ret = true;
05741         } else if (Token::Match(tok, "|| not|compl %var%")) {
05742             tok->next()->str(tok->next()->str() == "not" ? "!" : "~");
05743             ret = true;
05744         }
05745         // "%var%|) and %var%|("
05746         else if (Token::Match(tok, "%var% %any%")) {
05747             if (!Token::Match(tok, "and|or|bitand|bitor|xor|not_eq"))
05748                 continue;
05749 
05750             const Token *tok2 = tok;
05751             while (NULL != (tok2 = tok2->previous())) {
05752                 if (tok2->str() == ")")
05753                     tok2 = tok2->link();
05754                 else if (Token::Match(tok2, "(|;|{|}"))
05755                     break;
05756             }
05757             if (tok2 && Token::Match(tok2->previous(), "if|while (")) {
05758                 if (tok->str() == "and")
05759                     tok->str("&&");
05760                 else if (tok->str() == "or")
05761                     tok->str("||");
05762                 else if (tok->str() == "bitand")
05763                     tok->str("&");
05764                 else if (tok->str() == "bitor")
05765                     tok->str("|");
05766                 else if (tok->str() == "xor")
05767                     tok->str("^");
05768                 else if (tok->str() == "not_eq")
05769                     tok->str("!=");
05770                 ret = true;
05771             }
05772         }
05773     }
05774     return ret;
05775 }
05776 
05777 // int i(0); => int i; i = 0;
05778 // int i(0), j; => int i; i = 0; int j;
05779 void Tokenizer::simplifyInitVar()
05780 {
05781     for (Token *tok = list.front(); tok; tok = tok->next()) {
05782         if (!tok->isName() || (tok->previous() && !Token::Match(tok->previous(), "[;{}]")))
05783             continue;
05784 
05785         if (tok->str() == "return")
05786             continue;
05787 
05788         if (Token::Match(tok, "class|struct|union| %type% *| %var% ( &| %any% ) ;") ||
05789             Token::Match(tok, "%type% *| %var% ( %type% (")) {
05790             tok = initVar(tok);
05791         } else if (Token::Match(tok, "class|struct|union| %type% *| %var% ( &| %any% ) ,")) {
05792             Token *tok1 = tok;
05793             while (tok1->str() != ",")
05794                 tok1 = tok1->next();
05795             tok1->str(";");
05796             Token *tok2 = tok;
05797             if (Token::Match(tok2, "class|struct|union")) {
05798                 tok1->insertToken(tok2->str());
05799                 tok1 = tok1->next();
05800                 tok2 = tok2->next();
05801             }
05802             tok1->insertToken(tok2->str());
05803             tok1 = tok1->next();
05804             tok2 = tok2->next();
05805             if (tok2->str() == "*") {
05806                 tok1->insertToken("*");
05807             }
05808             tok = initVar(tok);
05809         }
05810     }
05811 }
05812 
05813 Token * Tokenizer::initVar(Token * tok)
05814 {
05815     // call constructor of class => no simplification
05816     if (Token::Match(tok, "class|struct|union")) {
05817         if (tok->strAt(2) != "*")
05818             return tok;
05819 
05820         tok = tok->next();
05821     } else if (!tok->isStandardType() && tok->next()->str() != "*")
05822         return tok;
05823 
05824     // goto variable name..
05825     tok = tok->next();
05826     if (tok->str() == "*")
05827         tok = tok->next();
05828 
05829     // sizeof is not a variable name..
05830     if (tok->str() == "sizeof")
05831         return tok;
05832 
05833     // check initializer..
05834     if (tok->tokAt(2)->isStandardType() || tok->strAt(2) == "void")
05835         return tok;
05836     else if (!tok->tokAt(2)->isNumber() && !Token::Match(tok->tokAt(2), "%type% (") && tok->strAt(2) != "&" && tok->tokAt(2)->varId() == 0)
05837         return tok;
05838 
05839     // insert '; var ='
05840     tok->insertToken(";");
05841     tok->next()->insertToken(tok->str());
05842     tok->tokAt(2)->varId(tok->varId());
05843     tok = tok->tokAt(2);
05844     tok->insertToken("=");
05845 
05846     // goto '('..
05847     tok = tok->tokAt(2);
05848 
05849     // delete ')'
05850     tok->link()->deleteThis();
05851 
05852     // delete this
05853     tok->deleteThis();
05854 
05855     return tok;
05856 }
05857 
05858 
05859 bool Tokenizer::simplifyKnownVariables()
05860 {
05861     // return value for function. Set to true if any simplifications are made
05862     bool ret = false;
05863 
05864     // constants..
05865     {
05866         std::map<unsigned int, std::string> constantValues;
05867         bool goback = false;
05868         for (Token *tok = list.front(); tok; tok = tok->next()) {
05869             if (goback) {
05870                 tok = tok->previous();
05871                 goback = false;
05872             }
05873             if (tok->isName() && Token::Match(tok, "static| const| static| %type% const| %var% = %any% ;")) {
05874                 bool isconst = false;
05875                 for (const Token *tok2 = tok; tok2->str() != "="; tok2 = tok2->next()) {
05876                     if (tok2->str() == "const") {
05877                         isconst = true;
05878                         break;
05879                     }
05880                 }
05881                 if (!isconst)
05882                     continue;
05883 
05884                 Token *tok1 = tok;
05885 
05886                 // start of statement
05887                 if (tok != list.front() && !Token::Match(tok->previous(),";|{|}|private:|protected:|public:"))
05888                     continue;
05889                 // skip "const" and "static"
05890                 while (tok->str() == "const" || tok->str() == "static")
05891                     tok = tok->next();
05892                 // pod type
05893                 if (!tok->isStandardType())
05894                     continue;
05895 
05896                 const Token * const vartok = (tok->next() && tok->next()->str() == "const") ? tok->tokAt(2) : tok->next();
05897                 const Token * const valuetok = vartok->tokAt(2);
05898                 if (Token::Match(valuetok, "%bool%|%char%|%num%|%str% ;")) {
05899                     //check if there's not a reference usage inside the code
05900                     bool withreference = false;
05901                     for (const Token *tok2 = valuetok->tokAt(2); tok2; tok2 = tok2->next()) {
05902                         if (Token::Match(tok2,"(|[|,|{|return|%op% & %varid%", vartok->varId())) {
05903                             withreference = true;
05904                             break;
05905                         }
05906                     }
05907                     //don't simplify 'f(&x)' to 'f(&100)'
05908                     if (withreference)
05909                         continue;
05910 
05911                     constantValues[vartok->varId()] = valuetok->str();
05912 
05913                     // remove statement
05914                     while (tok1->next()->str() != ";")
05915                         tok1->deleteNext();
05916                     tok1->deleteNext();
05917                     tok1->deleteThis();
05918                     tok = tok1;
05919                     goback = true;
05920                 }
05921             }
05922 
05923             else if (tok->varId() && constantValues.find(tok->varId()) != constantValues.end()) {
05924                 tok->str(constantValues[tok->varId()]);
05925             }
05926         }
05927     }
05928 
05929     // variable id for float/double variables
05930     std::set<unsigned int> floatvars;
05931 
05932     // auto variables..
05933     for (Token *tok = list.front(); tok; tok = tok->next()) {
05934         // Search for a block of code
05935         if (! Token::Match(tok, ") const| {"))
05936             continue;
05937 
05938         // parse the block of code..
05939         int indentlevel = 0;
05940         Token *tok2 = tok;
05941         for (; tok2; tok2 = tok2->next()) {
05942             if (Token::Match(tok2, "[;{}] float|double %var% ;")) {
05943                 floatvars.insert(tok2->tokAt(2)->varId());
05944             }
05945 
05946             if (tok2->str() == "{")
05947                 ++indentlevel;
05948 
05949             else if (tok2->str() == "}") {
05950                 --indentlevel;
05951                 if (indentlevel <= 0)
05952                     break;
05953             }
05954 
05955             else if (tok2->previous()->str() != "*" &&
05956                      (Token::Match(tok2, "%var% = %bool%|%char%|%num%|%str%|%var% ;") ||
05957                       Token::Match(tok2, "%var% [ ] = %str% ;") ||
05958                       Token::Match(tok2, "%var% [ %num% ] = %str% ;") ||
05959                       Token::Match(tok2, "%var% = & %var% ;") ||
05960                       Token::Match(tok2, "%var% = & %var% [ 0 ] ;"))) {
05961                 const unsigned int varid = tok2->varId();
05962                 if (varid == 0)
05963                     continue;
05964 
05965                 // initialization of static variable => the value is not *known*
05966                 {
05967                     bool isstatic = false;
05968                     const Token *decl = tok2->previous();
05969                     while (decl && (decl->isName() || decl->str() == "*")) {
05970                         if (decl->str() == "static") {
05971                             isstatic = true;
05972                             break;
05973                         }
05974                         decl = decl->previous();
05975                     }
05976                     if (isstatic)
05977                         continue;
05978                 }
05979 
05980                 // skip loop variable
05981                 if (Token::Match(tok2->tokAt(-2), "(|:: %type%")) {
05982                     const Token *tok3 = tok2->previous();
05983                     while (Token::Match(tok3->previous(), ":: %type%"))
05984                         tok3 = tok3->tokAt(-2);
05985                     if (Token::Match(tok3->tokAt(-2), "for ( %type%"))
05986                         continue;
05987                 }
05988 
05989                 // struct name..
05990                 const std::string structname = Token::Match(tok2->tokAt(-3), "[;{}] %var% .") ?
05991                                                std::string(tok2->strAt(-2) + " .") :
05992                                                std::string("");
05993 
05994                 if (tok2->str() == tok2->strAt(2))
05995                     continue;
05996 
05997                 const Token * const valueToken = tok2->tokAt(2);
05998 
05999                 std::string value;
06000                 unsigned int valueVarId = 0;
06001 
06002                 Token *tok3 = NULL;
06003                 bool valueIsPointer = false;
06004 
06005                 // there could be a hang here if tok2 is moved back by the function calls below for some reason
06006                 if (_settings->terminated())
06007                     return false;
06008 
06009                 if (!simplifyKnownVariablesGetData(varid, &tok2, &tok3, value, valueVarId, valueIsPointer, floatvars.find(tok2->varId()) != floatvars.end()))
06010                     continue;
06011 
06012                 ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, valueToken, indentlevel);
06013             }
06014 
06015             else if (Token::Match(tok2, "( %var% == %num% ) {")) {
06016                 const unsigned int varid = tok2->next()->varId();
06017                 if (varid == 0)
06018                     continue;
06019 
06020                 const std::string structname;
06021 
06022                 const Token *valueToken = tok2->tokAt(3);
06023                 std::string value(tok2->strAt(3));
06024                 const unsigned int valueVarId = 0;
06025                 const bool valueIsPointer = false;
06026 
06027                 Token *scopeStart = tok2->tokAt(6);
06028                 ret |= simplifyKnownVariablesSimplify(&scopeStart, scopeStart, varid, structname, value, valueIsPointer, valueVarId, valueToken, -1);
06029             }
06030 
06031             else if (Token::Match(tok2, "strcpy|sprintf ( %var% , %str% ) ;")) {
06032                 const unsigned int varid(tok2->tokAt(2)->varId());
06033                 std::string::size_type n = std::string::npos;
06034                 if (varid == 0)
06035                     continue;
06036                 const std::string structname;
06037                 const Token * const valueToken = tok2->tokAt(4);
06038                 std::string value(valueToken->str());
06039                 if (tok2->str() == "sprintf") {
06040                     while ((n = value.find("%%",n+1)) != std::string::npos) {
06041                         value.replace(n,2,"%");
06042                     }
06043                 }
06044                 const unsigned int valueVarId(0);
06045                 const bool valueIsPointer(false);
06046                 Token *tok3 = tok2->tokAt(6);
06047                 ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, valueToken, indentlevel);
06048 
06049                 // there could be a hang here if tok2 was moved back by the function call above for some reason
06050                 if (_settings->terminated())
06051                     return false;
06052             }
06053         }
06054 
06055         if (tok2)
06056             tok = tok2->previous();
06057     }
06058 
06059     return ret;
06060 }
06061 
06062 bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2, Token **_tok3, std::string &value, unsigned int &valueVarId, bool &valueIsPointer, bool floatvar)
06063 {
06064     Token *tok2 = *_tok2;
06065     Token *tok3 = NULL;
06066 
06067     if (Token::simpleMatch(tok2->tokAt(-2), "for (")) {
06068         // only specific for loops is handled
06069         if (!Token::Match(tok2, "%varid% = %num% ; %varid% <|<= %num% ; ++| %varid% ++| ) {", varid))
06070             return false;
06071 
06072         // is there a "break" in the for loop?
06073         bool hasbreak = false;
06074         const Token* end4 = tok2->linkAt(-1)->linkAt(1);
06075         for (const Token *tok4 = tok2->previous()->link(); tok4 != end4; tok4 = tok4->next()) {
06076             if (tok4->str() == "break") {
06077                 hasbreak = true;
06078                 break;
06079             }
06080         }
06081         if (hasbreak)
06082             return false;
06083 
06084         // no break => the value of the counter value is known after the for loop..
06085         const std::string& compareop = tok2->strAt(5);
06086         if (compareop == "<") {
06087             value = tok2->strAt(6);
06088             valueVarId = tok2->tokAt(6)->varId();
06089         } else
06090             value = MathLib::longToString(MathLib::toLongNumber(tok2->strAt(6)) + 1);
06091 
06092         // Skip for-body..
06093         tok3 = tok2->previous()->link()->next()->link()->next();
06094     } else {
06095         value = tok2->strAt(2);
06096         valueVarId = tok2->tokAt(2)->varId();
06097         if (tok2->strAt(1) == "[") {
06098             value = tok2->next()->link()->strAt(2);
06099             valueVarId = 0;
06100         } else if (value == "&") {
06101             value = tok2->strAt(3);
06102             valueVarId = tok2->tokAt(3)->varId();
06103 
06104             // *ptr = &var; *ptr = 5;
06105             // equals
06106             // var = 5; not *var = 5;
06107             if (tok2->strAt(4) == ";")
06108                 valueIsPointer = true;
06109         }
06110 
06111         // float value should contain a "."
06112         else if (tok2->tokAt(2)->isNumber() &&
06113                  floatvar &&
06114                  value.find(".") == std::string::npos) {
06115             value += ".0";
06116         }
06117 
06118         // float variable: convert true/false to 1.0 / 0.0
06119         else if (tok2->tokAt(2)->isBoolean() && floatvar) {
06120             value = (value == "true") ? "1.0" : "0.0";
06121         }
06122 
06123         if (Token::simpleMatch(tok2->next(), "= &"))
06124             tok2 = tok2->tokAt(3);
06125 
06126         tok3 = tok2->next();
06127     }
06128     *_tok2 = tok2;
06129     *_tok3 = tok3;
06130     return true;
06131 }
06132 
06133 bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, const Token * const valueToken, int indentlevel) const
06134 {
06135     const bool pointeralias(valueToken->isName() || Token::Match(valueToken, "& %var% ["));
06136 
06137     if (_errorLogger && !list.getFiles().empty())
06138         _errorLogger->reportProgress(list.getFiles()[0], "Tokenize (simplifyKnownVariables)", tok3->progressValue());
06139 
06140     bool ret = false;
06141 
06142     // skip increments and decrements if the given indentlevel is -1
06143     const bool skipincdec = (indentlevel == -1);
06144 
06145     Token* bailOutFromLoop = 0;
06146     int indentlevel3 = indentlevel;
06147     bool ret3 = false;
06148     for (; tok3; tok3 = tok3->next()) {
06149         if (tok3->str() == "{") {
06150             ++indentlevel3;
06151         } else if (tok3->str() == "}") {
06152             --indentlevel3;
06153             if (indentlevel3 < indentlevel) {
06154                 if (Token::Match((*tok2)->tokAt(-7), "%type% * %var% ; %var% = & %var% ;") &&
06155                     (*tok2)->strAt(-5) == (*tok2)->strAt(-3)) {
06156                     (*tok2) = (*tok2)->tokAt(-4);
06157                     Token::eraseTokens((*tok2), (*tok2)->tokAt(6));
06158                 }
06159                 break;
06160             }
06161         }
06162 
06163         // Stop if there is a pointer alias and a shadow variable is
06164         // declared in an inner scope (#3058)
06165         if (valueIsPointer && tok3->varId() > 0 &&
06166             tok3->previous() && (tok3->previous()->isName() || tok3->previous()->str() == "*") &&
06167             valueToken->str() == "&" &&
06168             valueToken->next() &&
06169             valueToken->next()->isName() &&
06170             tok3->str() == valueToken->next()->str() &&
06171             tok3->varId() > valueToken->next()->varId()) {
06172             // more checking if this is a variable declaration
06173             bool decl = true;
06174             for (const Token *tok4 = tok3->previous(); tok4; tok4 = tok4->previous()) {
06175                 if (Token::Match(tok4, "[;{}]"))
06176                     break;
06177 
06178                 else if (tok4->isName()) {
06179                     if (tok4->varId() > 0) {
06180                         decl = false;
06181                         break;
06182                     }
06183                 }
06184 
06185                 else if (!Token::Match(tok4, "[&*]")) {
06186                     decl = false;
06187                     break;
06188                 }
06189             }
06190             if (decl)
06191                 break;
06192         }
06193 
06194         // Stop if label is found
06195         if (Token::Match(tok3, "; %type% : ;"))
06196             break;
06197 
06198         // Stop if break/continue is found ..
06199         if (tok3->str() == "break" || tok3->str() == "continue")
06200             break;
06201         if ((indentlevel3 > 1 || !Token::simpleMatch(Token::findsimplematch(tok3,";"), "; }")) && tok3->str() == "return")
06202             ret3 = true;
06203         if (ret3 && tok3->str() == ";")
06204             break;
06205 
06206         if (pointeralias && Token::Match(tok3, ("!!= " + value).c_str()))
06207             break;
06208 
06209         // Stop if do is found
06210         if (tok3->str() == "do")
06211             break;
06212 
06213         // Stop if unknown function call is seen
06214         // If the variable is a global or a member variable it might be
06215         // changed by the function call
06216         // TODO: don't bail out if the variable is a local variable,
06217         //       then it can't be changed by the function call.
06218         if (tok3->str() == ")" && tok3->link() &&
06219             Token::Match(tok3->link()->tokAt(-2), "[;{}] %var% (") &&
06220             !Token::Match(tok3->link()->previous(), "if|for|while|switch|BOOST_FOREACH"))
06221             break;
06222 
06223         // Stop if something like 'while (--var)' is found
06224         if (tok3->str() == "for" || tok3->str() == "while" || tok3->str() == "do") {
06225             const Token *endpar = tok3->next()->link();
06226             if (Token::simpleMatch(endpar, ") {"))
06227                 endpar = endpar->next()->link();
06228             bool bailout = false;
06229             for (const Token *tok4 = tok3; tok4 && tok4 != endpar; tok4 = tok4->next()) {
06230                 if (Token::Match(tok4, "++|-- %varid%", varid) ||
06231                     Token::Match(tok4, "%varid% ++|--|=", varid)) {
06232                     bailout = true;
06233                     break;
06234                 }
06235             }
06236             if (bailout)
06237                 break;
06238         }
06239 
06240         if (bailOutFromLoop) {
06241             // This could be a loop, skip it, but only if it doesn't contain
06242             // the variable we are checking for. If it contains the variable
06243             // we will bail out.
06244             if (tok3->varId() == varid) {
06245                 // Continue
06246                 //tok2 = bailOutFromLoop;
06247                 break;
06248             } else if (tok3 == bailOutFromLoop) {
06249                 // We have skipped the loop
06250                 bailOutFromLoop = 0;
06251                 continue;
06252             }
06253 
06254             continue;
06255         } else if (tok3->str() == "{" && tok3->previous()->str() == ")") {
06256             // There is a possible loop after the assignment. Try to skip it.
06257             if (tok3->previous()->link() &&
06258                 tok3->previous()->link()->strAt(-1) != "if")
06259                 bailOutFromLoop = tok3->link();
06260             continue;
06261         }
06262 
06263         // Variable used in realloc (see Ticket #1649)
06264         if (Token::Match(tok3, "%var% = realloc ( %var% ,") &&
06265             tok3->varId() == varid &&
06266             tok3->tokAt(4)->varId() == varid) {
06267             tok3->tokAt(4)->str(value);
06268             ret = true;
06269         }
06270 
06271         // condition "(|&&|%OROR% %varid% )|&&|%OROR%
06272         if (!Token::Match(tok3->previous(), "( %var% )") &&
06273             Token::Match(tok3->previous(), "&&|(|%oror% %varid% &&|%oror%|)", varid)) {
06274             tok3->str(value);
06275             tok3->varId(valueVarId);
06276             ret = true;
06277         }
06278 
06279         // parameter in function call..
06280         if (tok3->varId() == varid && Token::Match(tok3->previous(), "[(,] %var% [,)]")) {
06281             // If the parameter is passed by value then simplify it
06282             if (isFunctionParameterPassedByValue(tok3)) {
06283                 tok3->str(value);
06284                 tok3->varId(valueVarId);
06285                 ret = true;
06286             }
06287         }
06288 
06289         // Variable is used somehow in a non-defined pattern => bail out
06290         if (tok3->varId() == varid) {
06291             // This is a really generic bailout so let's try to avoid this.
06292             // There might be lots of false negatives.
06293             if (_settings->debugwarnings) {
06294                 // FIXME: Fix all the debug warnings for values and then
06295                 // remove this bailout
06296                 if (pointeralias)
06297                     break;
06298 
06299                 // suppress debug-warning when calling member function
06300                 if (Token::Match(tok3->next(), ". %var% ("))
06301                     break;
06302 
06303                 // suppress debug-warning when assignment
06304                 if (tok3->strAt(1) == "=")
06305                     break;
06306 
06307                 // taking address of variable..
06308                 if (Token::Match(tok3->tokAt(-2), "return|= & %var% ;"))
06309                     break;
06310 
06311                 // parameter in function call..
06312                 if (Token::Match(tok3->tokAt(-2), "%var% ( %var% ,|)") ||
06313                     Token::Match(tok3->previous(), ", %var% ,|)"))
06314                     break;
06315 
06316                 // conditional increment
06317                 if (Token::Match(tok3->tokAt(-3), ") { ++|--") ||
06318                     Token::Match(tok3->tokAt(-2), ") { %var% ++|--"))
06319                     break;
06320 
06321                 reportError(tok3, Severity::debug, "debug",
06322                             "simplifyKnownVariables: bailing out (variable="+tok3->str()+", value="+value+")");
06323             }
06324 
06325             break;
06326         }
06327 
06328         // Using the variable in condition..
06329         if (Token::Match(tok3->previous(), ("if ( " + structname + " %varid% %comp%|)").c_str(), varid) ||
06330             Token::Match(tok3, ("( " + structname + " %varid% %comp%").c_str(), varid) ||
06331             Token::Match(tok3, ("%comp%|! " + structname + " %varid% %comp%|)|;").c_str(), varid) ||
06332             Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid)) {
06333             if (value[0] == '\"' && tok3->previous()->str() != "strlen") {
06334                 // bail out if value is a string unless if it's just given
06335                 // as parameter to strlen
06336                 break;
06337             }
06338             if (!structname.empty()) {
06339                 tok3->deleteNext(2);
06340             }
06341             if (Token::Match(valueToken, "& %var% ;")) {
06342                 tok3->insertToken("&");
06343                 tok3 = tok3->next();
06344             }
06345             tok3 = tok3->next();
06346             tok3->str(value);
06347             tok3->varId(valueVarId);
06348             ret = true;
06349         }
06350 
06351         // Delete pointer alias
06352         if (pointeralias && tok3->str() == "delete" &&
06353             (Token::Match(tok3, "delete %varid% ;", varid) ||
06354              Token::Match(tok3, "delete [ ] %varid%", varid))) {
06355             tok3 = (tok3->next() && tok3->next()->str() == "[") ? tok3->tokAt(3) : tok3->next();
06356             tok3->str(value);
06357             tok3->varId(valueVarId);
06358             ret = true;
06359         }
06360 
06361         // Variable is used in function call..
06362         if (Token::Match(tok3, ("%var% ( " + structname + " %varid% ,").c_str(), varid)) {
06363             static const char * const functionName[] = {
06364                 "memcmp","memcpy","memmove","memset",
06365                 "strcmp","strcpy","strncmp","strncpy","strdup"
06366             };
06367             for (unsigned int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i) {
06368                 if (tok3->str() == functionName[i]) {
06369                     Token *par1 = tok3->tokAt(2);
06370                     if (!structname.empty()) {
06371                         par1->deleteNext();
06372                         par1->deleteThis();
06373                     }
06374                     par1->str(value);
06375                     par1->varId(valueVarId);
06376                     break;
06377                 }
06378             }
06379         }
06380 
06381         // Variable is used as 2nd parameter in function call..
06382         if (Token::Match(tok3, ("%var% ( %any% , " + structname + " %varid% ,|)").c_str(), varid)) {
06383             static const char * const functionName[] = {
06384                 "memcmp","memcpy","memmove",
06385                 "strcmp","strcpy","strncmp","strncpy"
06386             };
06387             for (unsigned int i = 0; i < (sizeof(functionName) / sizeof(*functionName)); ++i) {
06388                 if (tok3->str() == functionName[i]) {
06389                     Token *par = tok3->tokAt(4);
06390                     if (!structname.empty()) {
06391                         par->deleteNext();
06392                         par->deleteThis();
06393                     }
06394                     par->str(value);
06395                     par->varId(valueVarId);
06396                     break;
06397                 }
06398             }
06399         }
06400 
06401         // array usage
06402         if (value[0] != '\"' && Token::Match(tok3, ("[(,] " + structname + " %varid% [|%cop%").c_str(), varid)) {
06403             if (!structname.empty()) {
06404                 tok3->deleteNext(2);
06405             }
06406             tok3 = tok3->next();
06407             tok3->str(value);
06408             tok3->varId(valueVarId);
06409             ret = true;
06410         }
06411 
06412         // The >> operator is sometimes used to assign a variable in C++
06413         if (isCPP() && Token::Match(tok3, (">> " + structname + " %varid%").c_str(), varid)) {
06414             // bailout for such code:   ; std :: cin >> i ;
06415             const Token *prev = tok3->previous();
06416             while (prev && prev->str() != "return" && (prev->isName() || prev->str() == "::"))
06417                 prev = prev->previous();
06418             if (Token::Match(prev, ";|{|}|>>"))
06419                 break;
06420         }
06421 
06422         // Variable is used in calculation..
06423         if (((tok3->previous()->varId() > 0) && Token::Match(tok3, ("& " + structname + " %varid%").c_str(), varid)) ||
06424             (Token::Match(tok3, ("[=+-*/%^|[] " + structname + " %varid% [=?+-*/%^|;])]").c_str(), varid) && !Token::Match(tok3, ("= " + structname + " %var% =").c_str())) ||
06425             Token::Match(tok3, ("[(=+-*/%^|[] " + structname + " %varid% <<|>>").c_str(), varid) ||
06426             Token::Match(tok3, ("<<|>> " + structname + " %varid% %cop%|;|]|)").c_str(), varid) ||
06427             Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid% !!=").c_str(), varid)) {
06428             if (value[0] == '\"')
06429                 break;
06430             if (!structname.empty()) {
06431                 tok3->deleteNext(2);
06432                 ret = true;
06433             }
06434             tok3 = tok3->next();
06435             if (tok3->str() != value)
06436                 ret = true;
06437             tok3->str(value);
06438             tok3->varId(valueVarId);
06439             if (tok3->previous()->str() == "*" && valueIsPointer) {
06440                 tok3 = tok3->previous();
06441                 tok3->deleteThis();
06442                 ret = true;
06443             }
06444         }
06445 
06446         if (Token::simpleMatch(tok3, "= {")) {
06447             const Token* const end4 = tok3->linkAt(1);
06448             for (const Token *tok4 = tok3; tok4 != end4; tok4 = tok4->next()) {
06449                 if (Token::Match(tok4, "{|, %varid% ,|}", varid)) {
06450                     tok4->next()->str(value);
06451                     tok4->next()->varId(valueVarId);
06452                     ret = true;
06453                 }
06454             }
06455         }
06456 
06457         // Using the variable in for-condition..
06458         if (Token::simpleMatch(tok3, "for (")) {
06459             for (Token *tok4 = tok3->tokAt(2); tok4; tok4 = tok4->next()) {
06460                 if (tok4->str() == "(" || tok4->str() == ")")
06461                     break;
06462 
06463                 // Replace variable used in condition..
06464                 if (Token::Match(tok4, "; %var% <|<=|!= %var% ; ++| %var% ++| )")) {
06465                     const Token *inctok = tok4->tokAt(5);
06466                     if (inctok->str() == "++")
06467                         inctok = inctok->next();
06468                     if (inctok->varId() == varid)
06469                         break;
06470 
06471                     if (tok4->next()->varId() == varid) {
06472                         tok4->next()->str(value);
06473                         tok4->next()->varId(valueVarId);
06474                         ret = true;
06475                     }
06476                     if (tok4->tokAt(3)->varId() == varid) {
06477                         tok4->tokAt(3)->str(value);
06478                         tok4->tokAt(3)->varId(valueVarId);
06479                         ret = true;
06480                     }
06481                 }
06482             }
06483         }
06484 
06485         if (!skipincdec && indentlevel == indentlevel3 && Token::Match(tok3->next(), "%varid% ++|--", varid) && MathLib::isInt(value)) {
06486             const std::string op(tok3->strAt(2));
06487             if (Token::Match(tok3, "[{};] %any% %any% ;")) {
06488                 tok3->deleteNext(3);
06489             } else {
06490                 tok3 = tok3->next();
06491                 tok3->str(value);
06492                 tok3->varId(valueVarId);
06493                 tok3->deleteNext();
06494             }
06495             incdec(value, op);
06496             if (!Token::simpleMatch((*tok2)->tokAt(-2), "for (")) {
06497                 (*tok2)->tokAt(2)->str(value);
06498                 (*tok2)->tokAt(2)->varId(valueVarId);
06499             }
06500             ret = true;
06501         }
06502 
06503         if (indentlevel == indentlevel3 && Token::Match(tok3->next(), "++|-- %varid%", varid) && MathLib::isInt(value) &&
06504             !Token::Match(tok3->tokAt(3), "[.[]")) {
06505             incdec(value, tok3->next()->str());
06506             (*tok2)->tokAt(2)->str(value);
06507             (*tok2)->tokAt(2)->varId(valueVarId);
06508             if (Token::Match(tok3, "[;{}] %any% %any% ;")) {
06509                 tok3->deleteNext(3);
06510             } else {
06511                 tok3->deleteNext();
06512                 tok3->next()->str(value);
06513                 tok3->next()->varId(valueVarId);
06514             }
06515             tok3 = tok3->next();
06516             ret = true;
06517         }
06518 
06519         // return variable..
06520         if (Token::Match(tok3, "return %varid% %any%", varid) &&
06521             (tok3->tokAt(2)->isExtendedOp() || tok3->strAt(2) == ";") &&
06522             value[0] != '\"') {
06523             tok3->next()->str(value);
06524             tok3->next()->varId(valueVarId);
06525         }
06526 
06527         else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid) && value[0] != '\"') {
06528             tok3->deleteNext();
06529             tok3->next()->str(value);
06530             tok3->next()->varId(valueVarId);
06531         }
06532     }
06533     return ret;
06534 }
06535 
06536 
06537 void Tokenizer::elseif()
06538 {
06539     for (Token *tok = list.front(); tok; tok = tok->next()) {
06540         if (tok->str() == "(" || tok->str() == "[" ||
06541             (tok->str() == "{" && tok->previous() && tok->previous()->str() == "="))
06542             tok = tok->link();
06543 
06544         if (!Token::simpleMatch(tok, "else if"))
06545             continue;
06546         for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
06547             if (Token::Match(tok2, "(|{|["))
06548                 tok2 = tok2->link();
06549 
06550             if (Token::Match(tok2, "}|;")) {
06551                 if (tok2->next() && tok2->next()->str() != "else") {
06552                     tok->insertToken("{");
06553                     tok2->insertToken("}");
06554                     Token::createMutualLinks(tok->next(), tok2->next());
06555                     break;
06556                 }
06557             }
06558         }
06559     }
06560 }
06561 
06562 
06563 bool Tokenizer::simplifyRedundantParentheses()
06564 {
06565     bool ret = false;
06566     for (Token *tok = list.front(); tok; tok = tok->next()) {
06567         if (tok->str() != "(")
06568             continue;
06569 
06570         // !!operator = ( x ) ;
06571         if (tok->strAt(-2) != "operator" &&
06572             tok->previous() && tok->previous()->str() == "=" &&
06573             tok->next() && tok->next()->str() != "{" &&
06574             Token::simpleMatch(tok->link(), ") ;")) {
06575             tok->link()->deleteThis();
06576             tok->deleteThis();
06577             continue;
06578         }
06579 
06580         while (Token::simpleMatch(tok, "( (") &&
06581                tok->link()->previous() == tok->next()->link()) {
06582             // We have "(( *something* ))", remove the inner
06583             // parentheses
06584             tok->deleteNext();
06585             tok->link()->tokAt(-2)->deleteNext();
06586             ret = true;
06587         }
06588 
06589         if (Token::Match(tok->previous(), "! ( %var% )")) {
06590             // Remove the parentheses
06591             tok->deleteThis();
06592             tok->deleteNext();
06593             ret = true;
06594         }
06595 
06596         if (Token::Match(tok->previous(), "[(,;{}] ( %var% (") &&
06597             tok->link()->previous() == tok->linkAt(2)) {
06598             // We have "( func ( *something* ))", remove the outer
06599             // parentheses
06600             tok->link()->deleteThis();
06601             tok->deleteThis();
06602             ret = true;
06603         }
06604 
06605         if (Token::Match(tok->previous(), "[,;{}] ( delete [| ]| %var% ) ;")) {
06606             // We have "( delete [| ]| var )", remove the outer
06607             // parentheses
06608             tok->link()->deleteThis();
06609             tok->deleteThis();
06610             ret = true;
06611         }
06612 
06613         if (!Token::simpleMatch(tok->tokAt(-2), "operator delete") &&
06614             Token::Match(tok->previous(), "delete|; (") &&
06615             (tok->previous()->str() != "delete" || tok->next()->varId() > 0) &&
06616             Token::Match(tok->link(), ") ;|,")) {
06617             tok->link()->deleteThis();
06618             tok->deleteThis();
06619             ret = true;
06620         }
06621 
06622         if (Token::Match(tok->previous(), "[(!*;{}] ( %var% )") &&
06623             (tok->next()->varId() != 0 || Token::Match(tok->tokAt(3), "[+-/=]"))) {
06624             // We have "( var )", remove the parentheses
06625             tok->deleteThis();
06626             tok->deleteNext();
06627             ret = true;
06628         }
06629 
06630         while (Token::Match(tok->previous(), "[;{}[]().,!*] ( %var% .")) {
06631             Token *tok2 = tok->tokAt(2);
06632             while (Token::Match(tok2, ". %var%")) {
06633                 tok2 = tok2->tokAt(2);
06634             }
06635             if (tok2 != tok->link())
06636                 break;
06637             // We have "( var . var . ... . var )", remove the parentheses
06638             tok = tok->previous();
06639             tok->deleteNext();
06640             tok2->deleteThis();
06641             ret = true;
06642             continue;
06643         }
06644 
06645         if (Token::simpleMatch(tok->previous(), "? (") && Token::simpleMatch(tok->link(), ") :")) {
06646             const Token *tok2 = tok->next();
06647             while (tok2 && (Token::Match(tok2,"%bool%|%num%|%var%") || tok2->isArithmeticalOp()))
06648                 tok2 = tok2->next();
06649             if (tok2 && tok2->str() == ")") {
06650                 tok->link()->deleteThis();
06651                 tok->deleteThis();
06652                 ret = true;
06653                 continue;
06654             }
06655         }
06656 
06657         while (Token::Match(tok->previous(), "[{([,:] ( !!{") &&
06658                Token::Match(tok->link(), ") [;,])]") &&
06659                !Token::findsimplematch(tok, ",", tok->link())) {
06660             // We have "( ... )", remove the parentheses
06661             tok->link()->deleteThis();
06662             tok->deleteThis();
06663             ret = true;
06664         }
06665 
06666         if (Token::simpleMatch(tok->previous(), ", (") &&
06667             Token::simpleMatch(tok->link(), ") =")) {
06668             tok->link()->deleteThis();
06669             tok->deleteThis();
06670             ret = true;
06671         }
06672 
06673         // Simplify "!!operator !!(%var%|)) ( %num%|%bool% ) %op%|;|,|)"
06674         if (Token::Match(tok, "( %bool%|%num% ) %cop%|;|,|)") &&
06675             tok->strAt(-2) != "operator" &&
06676             tok->previous() &&
06677             !tok->previous()->isName() &&
06678             tok->previous()->str() != ")" &&
06679             (!isCPP() || tok->previous()->str() != ">")) {
06680             tok->link()->deleteThis();
06681             tok->deleteThis();
06682             ret = true;
06683         }
06684     }
06685     return ret;
06686 }
06687 
06688 void Tokenizer::simplifyCharAt()
06689 {
06690     // Replace "string"[0] with 's'
06691     for (Token *tok = list.front(); tok; tok = tok->next()) {
06692         if (Token::Match(tok, "%str% [ %num% ]")) {
06693             const MathLib::bigint index = MathLib::toLongNumber(tok->strAt(2));
06694             // Check within range
06695             if (index >= 0 && index <= (MathLib::bigint)Token::getStrLength(tok)) {
06696                 tok->str(std::string("'" + Token::getCharAt(tok, (size_t)index) + "'"));
06697                 tok->deleteNext(3);
06698             }
06699         }
06700     }
06701 }
06702 
06703 void Tokenizer::simplifyReference()
06704 {
06705     if (isC())
06706         return;
06707 
06708     for (Token *tok = list.front(); tok; tok = tok->next()) {
06709         // starting executable scope..
06710         if (Token::Match(tok, ") const| {")) {
06711             // replace references in this scope..
06712             if (tok->next()->str() != "{")
06713                 tok = tok->next();
06714             Token * const end = tok->next()->link();
06715             for (Token *tok2 = tok; tok2 && tok2 != end; tok2 = tok2->next()) {
06716                 // found a reference..
06717                 if (Token::Match(tok2, "[;{}] %type% & %var% (|= %var% )| ;")) {
06718                     const unsigned int ref_id = tok2->tokAt(3)->varId();
06719                     if (!ref_id)
06720                         continue;
06721 
06722                     // replace reference in the code..
06723                     for (Token *tok3 = tok2->tokAt(7); tok3 && tok3 != end; tok3 = tok3->next()) {
06724                         if (tok3->varId() == ref_id) {
06725                             tok3->str(tok2->strAt(5));
06726                             tok3->varId(tok2->tokAt(5)->varId());
06727                         }
06728                     }
06729 
06730                     tok2->deleteNext(6+(tok->strAt(6)==")" ? 1 : 0));
06731                 }
06732             }
06733         }
06734     }
06735 }
06736 
06737 bool Tokenizer::simplifyCalculations()
06738 {
06739     return TemplateSimplifier::simplifyCalculations(list.front());
06740 }
06741 
06742 
06743 
06744 
06745 void Tokenizer::simplifyGoto()
06746 {
06747     std::list<Token *> gotos;
06748     unsigned int indentlevel = 0;
06749     unsigned int indentspecial = 0;
06750     Token *beginfunction = 0;
06751     for (Token *tok = list.front(); tok; tok = tok->next()) {
06752         if (tok->str() == "(" || tok->str() == "[")
06753             tok = tok->link();
06754 
06755         else if (Token::Match(tok, "class|namespace|struct|union %type% :|{")) {
06756             tok = tok->tokAt(2);
06757             while (tok && !Token::Match(tok, "[;{=]"))
06758                 tok = tok->next();
06759             if (tok && tok->str() == "{")
06760                 ++indentspecial;
06761             else if (!tok)
06762                 break;
06763             else
06764                 continue;
06765         }
06766 
06767         else if (Token::Match(tok, "namespace|struct|union {")) {
06768             tok = tok->next();
06769             ++indentspecial;
06770         }
06771 
06772         else if (tok->str() == "{") {
06773             if ((!beginfunction && !indentlevel) ||
06774                 (tok->previous() && tok->previous()->str() == "="))
06775                 tok = tok->link();
06776             else
06777                 ++indentlevel;
06778         }
06779 
06780         else if (tok->str() == "}") {
06781             if (indentlevel == 0) {
06782                 if (indentspecial)
06783                     --indentspecial;
06784             } else {
06785                 --indentlevel;
06786                 if (indentlevel == 0) {
06787                     gotos.clear();
06788                     beginfunction = 0;
06789                 }
06790             }
06791         }
06792 
06793         if (!indentlevel && Token::Match(tok, ") const| {"))
06794             beginfunction = tok;
06795 
06796         else if (indentlevel && Token::Match(tok, "[{};] goto %var% ;"))
06797             gotos.push_back(tok->next());
06798 
06799         else if (indentlevel == 1 && Token::Match(tok, "[{};] %var% : ;") && tok->next()->str() != "default") {
06800             // Is this label at the end..
06801             bool end = false;
06802             unsigned int level = 0;
06803             for (const Token *tok2 = tok->tokAt(3); tok2; tok2 = tok2->next()) {
06804                 if (tok2->str() == "(" || tok2->str() == "[")
06805                     tok2 = tok2->link();
06806 
06807                 else if (tok2->str() == "{") {
06808                     ++level;
06809                 }
06810 
06811                 else if (tok2->str() == "}") {
06812                     if (!level) {
06813                         end = true;
06814                         break;
06815                     }
06816                     --level;
06817                 }
06818 
06819                 if ((Token::Match(tok2, "[{};] %var% : ;") && tok2->next()->str() != "default") ||
06820                     Token::Match(tok2, "[{};] goto %var% ;")) {
06821                     break;
06822                 }
06823             }
06824             if (!end)
06825                 continue;
06826 
06827             const std::string name(tok->next()->str());
06828 
06829             tok->deleteNext(3);
06830 
06831             // This label is at the end of the function.. replace all matching goto statements..
06832             for (std::list<Token *>::iterator it = gotos.begin(); it != gotos.end(); ++it) {
06833                 Token *token = *it;
06834                 if (token->next()->str() == name) {
06835                     // Delete the "goto name;"
06836                     token = token->previous();
06837                     // change 'tok' before 'goto' if it coincides with the ';' token after 'name'
06838                     if (token->tokAt(3) == tok)
06839                         tok = token;
06840                     token->deleteNext(3);
06841 
06842                     // Insert the statements..
06843                     bool ret = false;   // is there return
06844                     bool ret2 = false;  // is there return in indentlevel 0
06845                     std::list<Token*> links;
06846                     std::list<Token*> links2;
06847                     std::list<Token*> links3;
06848                     unsigned int lev = 0;
06849                     unsigned int roundbraces = 0;
06850                     for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
06851                         if (tok2->str() == ")") {
06852                             if (!roundbraces)
06853                                 break;
06854                             --roundbraces;
06855                         }
06856                         if (tok2->str() == "(")
06857                             ++roundbraces;
06858 
06859                         if (!roundbraces && tok2->str() == "}") {
06860                             if (!lev)
06861                                 break;
06862                             --lev;
06863                         } else if (!roundbraces && tok2->str() == "{") {
06864                             ++lev;
06865                         } else if (!roundbraces && tok2->str() == "return") {
06866                             ret = true;
06867                             if (indentlevel == 1 && lev == 0)
06868                                 ret2 = true;
06869                         }
06870                         token->insertToken(tok2->str());
06871                         token = token->next();
06872                         token->linenr(tok2->linenr());
06873                         token->varId(tok2->varId());
06874                         if (ret2 && roundbraces == 0 && tok2->str() == ";") {
06875                             break;
06876                         }
06877                         if (token->str() == "(") {
06878                             links.push_back(token);
06879                         } else if (token->str() == ")") {
06880                             if (links.empty()) {
06881                                 // This should never happen at this point
06882                                 syntaxError(token, ')');
06883                                 return;
06884                             }
06885 
06886                             Token::createMutualLinks(links.back(), token);
06887                             links.pop_back();
06888                         } else if (token->str() == "{") {
06889                             links2.push_back(token);
06890                         } else if (token->str() == "}") {
06891                             if (links2.empty()) {
06892                                 // This should never happen at this point
06893                                 syntaxError(token, '}');
06894                                 return;
06895                             }
06896 
06897                             Token::createMutualLinks(links2.back(), token);
06898                             links2.pop_back();
06899                         } else if (token->str() == "[") {
06900                             links3.push_back(token);
06901                         } else if (token->str() == "]") {
06902                             if (links3.empty()) {
06903                                 // This should never happen at this point
06904                                 syntaxError(token, ']');
06905                                 return;
06906                             }
06907 
06908                             Token::createMutualLinks(links3.back(), token);
06909                             links3.pop_back();
06910                         }
06911                     }
06912 
06913                     if (!ret) {
06914                         token->insertToken(";");
06915                         token->insertToken("return");
06916                     }
06917                 }
06918             }
06919 
06920             // goto the end of the function
06921             if (tok->str() == "{")
06922                 tok = tok->link();
06923             else {
06924                 while (tok) {
06925                     if (tok->str() == "{")
06926                         tok = tok->link();
06927                     else if (tok->str() == "}")
06928                         break;
06929                     tok = tok->next();
06930                 }
06931             }
06932             if (!tok)
06933                 break;
06934             gotos.clear();
06935             beginfunction = 0;
06936             indentlevel = 0;
06937             continue;
06938         }
06939     }
06940 }
06941 
06942 void Tokenizer::simplifyNestedStrcat()
06943 {
06944     for (Token *tok = list.front(); tok; tok = tok->next()) {
06945         if (! Token::Match(tok, "[;{}] strcat ( strcat (")) {
06946             continue;
06947         }
06948 
06949         // find inner strcat call
06950         Token *tok2 = tok->tokAt(3);
06951         while (Token::simpleMatch(tok2, "strcat ( strcat")) {
06952             tok2 = tok2->tokAt(2);
06953         }
06954 
06955         // If we have this code:
06956         //   strcat(strcat(dst, foo), bar);
06957         // We move this part of code before all strcat() calls: strcat(dst, foo)
06958         // And place "dst" token where the code was.
06959         Token *prevTok = tok2->previous();
06960 
06961         // Move tokens to new place
06962         Token::move(tok2, tok2->next()->link(), tok);
06963         tok = tok2->next()->link();
06964 
06965         // Insert the "dst" token
06966         prevTok->insertToken(tok2->strAt(2));
06967         prevTok->next()->varId(tok2->tokAt(2)->varId());
06968 
06969         // Insert semicolon after the moved strcat()
06970         tok->insertToken(";");
06971     }
06972 
06973 }
06974 
06975 void Tokenizer::duplicateEnumError(const Token * tok1, const Token * tok2, const std::string & type) const
06976 {
06977     if (tok1 && !(_settings->isEnabled("style")))
06978         return;
06979 
06980     std::list<const Token*> locationList;
06981     locationList.push_back(tok1);
06982     locationList.push_back(tok2);
06983     const std::string tok2_str = tok2 ? tok2->str() : std::string("name");
06984 
06985     reportError(locationList, Severity::style, "variableHidingEnum",
06986                 std::string(type + " '" + tok2_str + "' hides enumerator with same name"));
06987 }
06988 
06989 // Check if this statement is a duplicate definition.  A duplicate
06990 // definition will hide the enumerator within it's scope so just
06991 // skip the entire scope of the duplicate.
06992 bool Tokenizer::duplicateDefinition(Token ** tokPtr, const Token * name) const
06993 {
06994     // check for an end of definition
06995     const Token * tok = *tokPtr;
06996     if (tok && Token::Match(tok->next(), ";|,|[|=|)|>")) {
06997         const Token * end = tok->next();
06998 
06999         if (end->str() == "[") {
07000             end = end->link()->next();
07001         } else if (end->str() == ",") {
07002             // check for function argument
07003             if (Token::Match(tok->previous(), "(|,"))
07004                 return false;
07005 
07006             // find end of definition
07007             int level = 0;
07008             while (end->next() && (!Token::Match(end->next(), ";|)|>") ||
07009                                    (end->next()->str() == ")" && level == 0))) {
07010                 if (end->next()->str() == "(")
07011                     ++level;
07012                 else if (end->next()->str() == ")")
07013                     --level;
07014 
07015                 end = end->next();
07016             }
07017         } else if (end->str() == ")") {
07018             // check for function argument
07019             if (tok->previous()->str() == ",")
07020                 return false;
07021         }
07022 
07023         if (end) {
07024             if (Token::simpleMatch(end, ") {")) { // function parameter ?
07025                 // make sure it's not a conditional
07026                 if (Token::Match(end->link()->previous(), "if|for|while|switch|BOOST_FOREACH"))
07027                     return false;
07028 
07029                 // look backwards
07030                 if (tok->previous()->str() == "enum" ||
07031                     (Token::Match(tok->previous(), "%type%") &&
07032                      tok->previous()->str() != "return") ||
07033                     Token::Match(tok->tokAt(-2), "%type% &|*")) {
07034                     duplicateEnumError(*tokPtr, name, "Function parameter");
07035                     // duplicate definition so skip entire function
07036                     *tokPtr = end->next()->link();
07037                     return true;
07038                 }
07039             } else if (end->str() == ">") { // template parameter ?
07040                 // look backwards
07041                 if (tok->previous()->str() == "enum" ||
07042                     (Token::Match(tok->previous(), "%type%") &&
07043                      tok->previous()->str() != "return")) {
07044                     // duplicate definition so skip entire template
07045                     while (end && end->str() != "{")
07046                         end = end->next();
07047                     if (end) {
07048                         duplicateEnumError(*tokPtr, name, "Template parameter");
07049                         *tokPtr = end->link();
07050                         return true;
07051                     }
07052                 }
07053             } else {
07054                 if (Token::Match(tok->previous(), "enum|,")) {
07055                     duplicateEnumError(*tokPtr, name, "Variable");
07056                     return true;
07057                 } else if (Token::Match(tok->previous(), "%type%")) {
07058                     // look backwards
07059                     const Token *back = tok;
07060                     while (back && back->isName())
07061                         back = back->previous();
07062                     if (!back || Token::Match(back, "[(,;{}] !!return")) {
07063                         duplicateEnumError(*tokPtr, name, "Variable");
07064                         return true;
07065                     }
07066                 }
07067             }
07068         }
07069     }
07070     return false;
07071 }
07072 
07073 class EnumValue {
07074 public:
07075     EnumValue() {
07076         name  = 0;
07077         value = 0;
07078         start = 0;
07079         end   = 0;
07080     }
07081     EnumValue(const EnumValue &ev) {
07082         name  = ev.name;
07083         value = ev.value;
07084         start = ev.start;
07085         end   = ev.end;
07086     }
07087     EnumValue(Token *name_, Token *value_, Token *start_, Token *end_) {
07088         name  = name_;
07089         value = value_;
07090         start = start_;
07091         end   = end_;
07092     }
07093 
07094     void simplify(const std::map<std::string, EnumValue> &enumValues) {
07095         for (Token *tok = start; tok; tok = tok->next()) {
07096             if (enumValues.find(tok->str()) != enumValues.end()) {
07097                 const EnumValue &other = enumValues.find(tok->str())->second;
07098                 if (other.value != NULL)
07099                     tok->str(other.value->str());
07100                 else {
07101                     bool islast = (tok == end);
07102                     Token *last = Tokenizer::copyTokens(tok, other.start, other.end);
07103                     if (last == tok->next())  // tok->deleteThis() invalidates a pointer that points at the next token
07104                         last = tok;
07105                     tok->deleteThis();
07106                     if (islast) {
07107                         end = last;
07108                     }
07109                     tok = last;
07110                 }
07111             }
07112             if (tok == end)
07113                 break;
07114         }
07115 
07116         // Simplify calculations..
07117         while (start && start->previous() && TemplateSimplifier::simplifyNumericCalculations(start->previous())) { }
07118 
07119         if (Token::Match(start, "%num% [,}]")) {
07120             value = start;
07121             start = end = NULL;
07122         }
07123     }
07124 
07125     Token *name;
07126     Token *value;
07127     Token *start;
07128     Token *end;
07129 };
07130 
07131 void Tokenizer::simplifyEnum()
07132 {
07133     std::string className;
07134     int classLevel = 0;
07135     bool goback = false;
07136     for (Token *tok = list.front(); tok; tok = tok->next()) {
07137 
07138         if (goback) {
07139             //jump back once, see the comment at the end of the function
07140             goback = false;
07141             tok = tok->previous();
07142         }
07143 
07144         if (Token::Match(tok, "class|struct|namespace") && tok->next() &&
07145             (!tok->previous() || (tok->previous() && tok->previous()->str() != "enum"))) {
07146             className = tok->next()->str();
07147             classLevel = 0;
07148         } else if (tok->str() == "}") {
07149             --classLevel;
07150             if (classLevel < 0)
07151                 className = "";
07152         } else if (tok->str() == "{") {
07153             ++classLevel;
07154         } else if (tok->str() == "enum") {
07155             Token *temp = tok->next();
07156             if (!temp)
07157                 break;
07158             if (Token::Match(temp, "class|struct"))
07159                 temp = temp->next();
07160             if (!Token::Match(temp, "[{:]") &&
07161                 (!temp->isName() || !Token::Match(temp->next(), "[{:;]")))
07162                 continue;
07163             Token *start = tok;
07164             Token *enumType = 0;
07165             Token *typeTokenStart = 0;
07166             Token *typeTokenEnd = 0;
07167 
07168             // check for C++0x enum class
07169             if (Token::Match(tok->next(), "class|struct"))
07170                 tok->deleteNext();
07171 
07172             // check for name
07173             if (tok->next()->isName()) {
07174                 enumType = tok->next();
07175                 tok = tok->next();
07176             }
07177 
07178             // check for C++0x typed enumeration
07179             if (tok->next()->str() == ":") {
07180                 tok = tok->next();
07181 
07182                 if (!tok->next()) {
07183                     syntaxError(tok);
07184                     return; // can't recover
07185                 }
07186 
07187                 typeTokenStart = tok->next();
07188                 tok = tok->next();
07189                 typeTokenEnd = typeTokenStart;
07190 
07191                 while (typeTokenEnd->next() && (typeTokenEnd->next()->str() == "::" ||
07192                                                 Token::Match(typeTokenEnd->next(), "%type%"))) {
07193                     typeTokenEnd = typeTokenEnd->next();
07194                     tok = tok->next();
07195                 }
07196 
07197                 if (!tok->next()) {
07198                     syntaxError(tok);
07199                     return; // can't recover
07200                 }
07201             }
07202 
07203             // check for forward declaration
07204             if (tok->next()->str() == ";") {
07205                 tok = tok->next();
07206 
07207                 /** @todo start substitution check at forward declaration */
07208                 // delete forward declaration
07209                 Token::eraseTokens(start, tok);
07210                 start->deleteThis();
07211                 tok = start;
07212                 continue;
07213             } else if (tok->next()->str() != "{") {
07214                 syntaxError(tok->next());
07215                 return;
07216             }
07217 
07218             Token *tok1 = tok->next();
07219             Token *end = tok1->link();
07220             tok1 = tok1->next();
07221 
07222             MathLib::bigint lastValue = -1;
07223             Token * lastEnumValueStart = 0;
07224             Token * lastEnumValueEnd = 0;
07225 
07226             // iterate over all enumerators between { and }
07227             // Give each enumerator the const value specified or if not specified, 1 + the
07228             // previous value or 0 if it is the first one.
07229             std::map<std::string,EnumValue> enumValues;
07230             for (; tok1 && tok1 != end; tok1 = tok1->next()) {
07231                 Token * enumName = 0;
07232                 Token * enumValue = 0;
07233                 Token * enumValueStart = 0;
07234                 Token * enumValueEnd = 0;
07235 
07236                 if (tok1->str() == "(") {
07237                     tok1 = tok1->link();
07238                     continue;
07239                 }
07240 
07241                 if (Token::Match(tok1->previous(), ",|{ %type% ,|}")) {
07242                     // no value specified
07243                     enumName = tok1;
07244                     ++lastValue;
07245                     tok1->insertToken("=");
07246                     tok1 = tok1->next();
07247 
07248                     if (lastEnumValueStart && lastEnumValueEnd) {
07249                         // previous value was an expression
07250                         Token *valueStart = tok1;
07251                         tok1 = copyTokens(tok1, lastEnumValueStart, lastEnumValueEnd);
07252 
07253                         // value is previous expression + 1
07254                         tok1->insertToken("+");
07255                         tok1 = tok1->next();
07256                         tok1->insertToken("1");
07257                         enumValue = 0;
07258                         enumValueStart = valueStart->next();
07259                         enumValueEnd = tok1->next();
07260                     } else {
07261                         // value is previous numeric value + 1
07262                         tok1->insertToken(MathLib::longToString(lastValue));
07263                         enumValue = tok1->next();
07264                     }
07265                 } else if (Token::Match(tok1->previous(), ",|{ %type% = %num% ,|}")) {
07266                     // value is specified numeric value
07267                     enumName = tok1;
07268                     lastValue = MathLib::toLongNumber(tok1->strAt(2));
07269                     enumValue = tok1->tokAt(2);
07270                     lastEnumValueStart = 0;
07271                     lastEnumValueEnd = 0;
07272                 } else if (Token::Match(tok1->previous(), ",|{ %type% =")) {
07273                     // value is specified expression
07274                     enumName = tok1;
07275                     lastValue = 0;
07276                     tok1 = tok1->tokAt(2);
07277                     enumValueStart = tok1;
07278                     enumValueEnd = tok1;
07279                     int level = 0;
07280                     while (enumValueEnd->next() && (!Token::Match(enumValueEnd->next(), "[},]") || level)) {
07281                         if (Token::Match(enumValueEnd, "(|["))
07282                             ++level;
07283                         else if (Token::Match(enumValueEnd->next(), "]|)"))
07284                             --level;
07285 
07286                         enumValueEnd = enumValueEnd->next();
07287                     }
07288                     // remember this expression in case it needs to be incremented
07289                     lastEnumValueStart = enumValueStart;
07290                     lastEnumValueEnd = enumValueEnd;
07291                     // skip over expression
07292                     tok1 = enumValueEnd;
07293                 }
07294 
07295                 // add enumerator constant..
07296                 if (enumName && (enumValue || (enumValueStart && enumValueEnd))) {
07297                     EnumValue ev(enumName, enumValue, enumValueStart, enumValueEnd);
07298                     ev.simplify(enumValues);
07299                     enumValues[enumName->str()] = ev;
07300                     lastEnumValueStart = ev.start;
07301                     lastEnumValueEnd = ev.end;
07302                     if (ev.start == NULL)
07303                         lastValue = MathLib::toLongNumber(ev.value->str());
07304                     tok1 = ev.end ? ev.end : ev.value;
07305                 }
07306             }
07307 
07308             // Substitute enum values
07309             {
07310                 const std::string pattern = className.empty() ?
07311                                             std::string("") :
07312                                             std::string(className + " :: ");
07313                 int level = 0;
07314                 bool inScope = true;
07315 
07316                 std::stack<std::set<std::string> > shadowId;  // duplicate ids in inner scope
07317                 bool simplify = false;
07318                 bool hasClass = false;
07319                 EnumValue *ev = NULL;
07320 
07321                 if (!tok1)
07322                     return;
07323                 for (Token *tok2 = tok1->next(); tok2; tok2 = tok2->next()) {
07324                     if (tok2->str() == "}") {
07325                         --level;
07326                         if (level < 0)
07327                             inScope = false;
07328 
07329                         if (!shadowId.empty())
07330                             shadowId.pop();
07331                     } else if (tok2->str() == "{") {
07332                         // Is the same enum redefined?
07333                         const Token *begin = end->link();
07334                         if (tok2->fileIndex() == begin->fileIndex() &&
07335                             tok2->linenr() == begin->linenr() &&
07336                             Token::Match(begin->tokAt(-2), "enum %type% {") &&
07337                             Token::Match(tok2->tokAt(-2), "enum %type% {") &&
07338                             begin->previous()->str() == tok2->previous()->str()) {
07339                             // remove duplicate enum
07340                             Token * startToken = tok2->tokAt(-3);
07341                             tok2 = tok2->link()->next();
07342                             Token::eraseTokens(startToken, tok2);
07343                             if (!tok2)
07344