Cppcheck
symboldatabase.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 #include "symboldatabase.h"
00021 
00022 #include "tokenize.h"
00023 #include "token.h"
00024 #include "settings.h"
00025 #include "errorlogger.h"
00026 #include "check.h"
00027 
00028 #include <string>
00029 #include <sstream>
00030 #include <climits>
00031 
00032 // Define ULLONG_MAX and LLONG_MAX for Borland
00033 #ifdef __BORLANDC__
00034 #define ULLONG_MAX ULONG_MAX
00035 #define LLONG_MAX LONG_MAX
00036 #endif
00037 
00038 // Define ULLONG_MAX and LLONG_MAX for SunCC on non-Solaris systems
00039 #if (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) && \
00040   !(defined (__sun) || defined (__sun__))
00041 #define ULLONG_MAX ULONG_MAX
00042 #define LLONG_MAX LONG_MAX
00043 #endif
00044 
00045 //---------------------------------------------------------------------------
00046 
00047 SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
00048     : _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger)
00049 {
00050     // create global scope
00051     scopeList.push_back(Scope(this, NULL, NULL));
00052 
00053     // pointer to current scope
00054     Scope *scope = &scopeList.back();
00055 
00056     // Store current access in each scope (depends on evaluation progress)
00057     std::map<const Scope*, AccessControl> access;
00058 
00059     std::map<const Token *, Scope *> back;
00060 
00061     // find all scopes
00062     for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
00063         // Locate next class
00064         if (Token::Match(tok, "class|struct|union|namespace ::| %var% {|:|::") &&
00065             tok->strAt(-1) != "friend") {
00066             const Token *tok2 = tok->tokAt(2);
00067 
00068             if (tok->strAt(1) == "::")
00069                 tok2 = tok2->next();
00070 
00071             while (tok2 && tok2->str() == "::")
00072                 tok2 = tok2->tokAt(2);
00073 
00074             // make sure we have valid code
00075             if (!tok2 || !Token::Match(tok2, "{|:")) {
00076                 // check for qualified variable
00077                 if (tok2 && tok2->next()) {
00078                     if (tok2->next()->str() == ";")
00079                         tok = tok2->next();
00080                     else if (Token::Match(tok2->next(), "= {") &&
00081                              tok2->linkAt(2)->next()->str() == ";")
00082                         tok = tok2->linkAt(2)->next();
00083                     else if (Token::Match(tok2->next(), "(|{")  &&
00084                              tok2->next()->link()->next()->str() == ";")
00085                         tok = tok2->next()->link()->next();
00086                     else
00087                         break; // bail
00088                     continue;
00089                 }
00090                 break; // bail
00091             }
00092 
00093             Scope *new_scope = findScope(tok->next(), scope);
00094 
00095             if (new_scope) {
00096                 // only create base list for classes and structures
00097                 if (new_scope->isClassOrStruct()) {
00098                     // goto initial '{'
00099                     tok2 = new_scope->definedType->initBaseInfo(tok, tok2);
00100 
00101                     // make sure we have valid code
00102                     if (!tok2) {
00103                         break;
00104                     }
00105                 }
00106 
00107                 // definition may be different than declaration
00108                 if (tok->str() == "class") {
00109                     access[new_scope] = Private;
00110                     new_scope->type = Scope::eClass;
00111                 } else if (tok->str() == "struct") {
00112                     access[new_scope] = Public;
00113                     new_scope->type = Scope::eStruct;
00114                 }
00115 
00116                 back[tok2->link()] = scope;
00117                 new_scope->classDef = tok;
00118                 new_scope->classStart = tok2;
00119                 new_scope->classEnd = tok2->link();
00120                 scope = new_scope;
00121                 tok = tok2;
00122             } else {
00123                 scopeList.push_back(Scope(this, tok, scope));
00124                 new_scope = &scopeList.back();
00125 
00126                 if (tok->str() == "class")
00127                     access[new_scope] = Private;
00128                 else if (tok->str() == "struct")
00129                     access[new_scope] = Public;
00130 
00131                 // fill typeList...
00132                 if (new_scope->isClassOrStruct() || new_scope->type == Scope::eUnion) {
00133                     Type* new_type = findType(tok->next(), scope);
00134                     if (!new_type) {
00135                         typeList.push_back(Type(new_scope->classDef, new_scope, scope));
00136                         new_type = &typeList.back();
00137                         scope->definedTypes.push_back(new_type);
00138                     } else
00139                         new_type->classScope = new_scope;
00140                     new_scope->definedType = new_type;
00141                 }
00142 
00143                 // only create base list for classes and structures
00144                 if (new_scope->isClassOrStruct()) {
00145                     // goto initial '{'
00146                     tok2 = new_scope->definedType->initBaseInfo(tok, tok2);
00147 
00148                     // make sure we have valid code
00149                     if (!tok2) {
00150                         scopeList.pop_back();
00151                         break;
00152                     }
00153                 }
00154 
00155                 new_scope->classStart = tok2;
00156                 new_scope->classEnd = tok2->link();
00157 
00158                 // make sure we have valid code
00159                 if (!new_scope->classEnd) {
00160                     scopeList.pop_back();
00161                     break;
00162                 }
00163 
00164                 // make the new scope the current scope
00165                 scope->nestedList.push_back(new_scope);
00166                 scope = new_scope;
00167 
00168                 tok = tok2;
00169             }
00170         }
00171 
00172         // Namespace and unknown macro (#3854)
00173         else if (Token::Match(tok, "namespace %var% %type% (") &&
00174                  _tokenizer->isCPP() &&
00175                  tok->tokAt(2)->isUpperCaseName() &&
00176                  Token::simpleMatch(tok->linkAt(3), ") {")) {
00177             scopeList.push_back(Scope(this, tok, scope));
00178 
00179             Scope *new_scope = &scopeList.back();
00180             access[new_scope] = Public;
00181 
00182             const Token *tok2 = tok->linkAt(3)->next();
00183 
00184             new_scope->classStart = tok2;
00185             new_scope->classEnd = tok2->link();
00186 
00187             // make sure we have valid code
00188             if (!new_scope->classEnd) {
00189                 scopeList.pop_back();
00190                 break;
00191             }
00192 
00193             // make the new scope the current scope
00194             scope->nestedList.push_back(new_scope);
00195             scope = &scopeList.back();
00196 
00197             tok = tok2;
00198         }
00199 
00200         // forward declaration
00201         else if (Token::Match(tok, "class|struct|union %var% ;") &&
00202                  tok->strAt(-1) != "friend") {
00203             if (!findType(tok->next(), scope)) {
00204                 // fill typeList..
00205                 typeList.push_back(Type(tok, 0, scope));
00206                 scope->definedTypes.push_back(&typeList.back());
00207             }
00208             tok = tok->tokAt(2);
00209         }
00210 
00211         // using namespace
00212         else if (Token::Match(tok, "using namespace ::| %type% ;|::")) {
00213             Scope::UsingInfo using_info;
00214 
00215             using_info.start = tok; // save location
00216             using_info.scope = 0; // fill in later
00217 
00218             scope->usingList.push_back(using_info);
00219 
00220             // check for global namespace
00221             if (tok->strAt(2) == "::")
00222                 tok = tok->tokAt(4);
00223             else
00224                 tok = tok->tokAt(3);
00225 
00226             // skip over qualification
00227             while (tok && Token::Match(tok, "%type% ::"))
00228                 tok = tok->tokAt(2);
00229         }
00230 
00231         // unnamed struct and union
00232         else if (Token::Match(tok, "struct|union {") &&
00233                  Token::Match(tok->next()->link(), "} *|&| %var% ;|[")) {
00234             scopeList.push_back(Scope(this, tok, scope));
00235 
00236             Scope *new_scope = &scopeList.back();
00237             access[new_scope] = Public;
00238 
00239             const Token* varNameTok = tok->next()->link()->next();
00240             if (varNameTok->str() == "*") {
00241                 varNameTok = varNameTok->next();
00242             } else if (varNameTok->str() == "&") {
00243                 varNameTok = varNameTok->next();
00244             }
00245 
00246             typeList.push_back(Type(tok, new_scope, scope));
00247             new_scope->definedType = &typeList.back();
00248             scope->definedTypes.push_back(&typeList.back());
00249 
00250             scope->addVariable(varNameTok, tok, tok, access[scope], new_scope->definedType, scope);
00251 
00252             const Token *tok2 = tok->next();
00253 
00254             new_scope->classStart = tok2;
00255             new_scope->classEnd = tok2->link();
00256 
00257             // make sure we have valid code
00258             if (!new_scope->classEnd) {
00259                 scopeList.pop_back();
00260                 break;
00261             }
00262 
00263             // make the new scope the current scope
00264             scope->nestedList.push_back(new_scope);
00265             scope = new_scope;
00266 
00267             tok = tok2;
00268         }
00269 
00270         // anonymous struct and union
00271         else if (Token::Match(tok, "struct|union {") &&
00272                  Token::simpleMatch(tok->next()->link(), "} ;")) {
00273             scopeList.push_back(Scope(this, tok, scope));
00274 
00275             Scope *new_scope = &scopeList.back();
00276             access[new_scope] = Public;
00277 
00278             const Token *tok2 = tok->next();
00279 
00280             new_scope->classStart = tok2;
00281             new_scope->classEnd = tok2->link();
00282 
00283             typeList.push_back(Type(tok, new_scope, scope));
00284             new_scope->definedType = &typeList.back();
00285             scope->definedTypes.push_back(&typeList.back());
00286 
00287             // make sure we have valid code
00288             if (!new_scope->classEnd) {
00289                 scopeList.pop_back();
00290                 break;
00291             }
00292 
00293             // make the new scope the current scope
00294             scope->nestedList.push_back(new_scope);
00295             scope = new_scope;
00296 
00297             tok = tok2;
00298         }
00299 
00300         else {
00301             // check for end of scope
00302             if (tok == scope->classEnd) {
00303                 if (back.find(tok) != back.end()) {
00304                     scope = back[tok];
00305                     back.erase(tok);
00306                 } else
00307                     scope = const_cast<Scope*>(scope->nestedIn);
00308                 continue;
00309             }
00310 
00311             // check if in class or structure
00312             else if (scope->type == Scope::eClass || scope->type == Scope::eStruct) {
00313                 const Token *funcStart = 0;
00314                 const Token *argStart = 0;
00315 
00316                 // What section are we in..
00317                 if (tok->str() == "private:")
00318                     access[scope] = Private;
00319                 else if (tok->str() == "protected:")
00320                     access[scope] = Protected;
00321                 else if (tok->str() == "public:" || tok->str() == "__published:")
00322                     access[scope] = Public;
00323                 else if (Token::Match(tok, "public|protected|private %var% :")) {
00324                     if (tok->str() == "private")
00325                         access[scope] = Private;
00326                     else if (tok->str() == "protected")
00327                         access[scope] = Protected;
00328                     else
00329                         access[scope] = Public;
00330 
00331                     tok = tok->tokAt(2);
00332                 }
00333 
00334                 // class function?
00335                 else if (tok->previous()->str() != "::" && isFunction(tok, scope, &funcStart, &argStart)) {
00336                     Function function;
00337 
00338                     // save the function definition argument start '('
00339                     function.argDef = argStart;
00340 
00341                     // save the access type
00342                     function.access = access[scope];
00343 
00344                     // save the function name location
00345                     function.tokenDef = funcStart;
00346 
00347                     // save the function parent scope
00348                     function.nestedIn = scope;
00349 
00350                     // operator function
00351                     if (function.tokenDef->str().find("operator") == 0) {
00352                         function.isOperator = true;
00353 
00354                         // 'operator =' is special
00355                         if (function.tokenDef->str() == "operator=")
00356                             function.type = Function::eOperatorEqual;
00357                     }
00358 
00359                     // class constructor/destructor
00360                     else if (function.tokenDef->str() == scope->className) {
00361                         // destructor
00362                         if (function.tokenDef->previous()->str() == "~")
00363                             function.type = Function::eDestructor;
00364 
00365                         // copy constructor
00366                         else if ((Token::Match(function.tokenDef, "%var% ( const %var% & %var%| )") ||
00367                                   (Token::Match(function.tokenDef, "%var% ( const %var% <") &&
00368                                    Token::Match(function.tokenDef->linkAt(4), "> & %var%| )"))) &&
00369                                  function.tokenDef->strAt(3) == scope->className)
00370                             function.type = Function::eCopyConstructor;
00371 
00372                         else if ((Token::Match(function.tokenDef, "%var% <") &&
00373                                   Token::Match(function.tokenDef->linkAt(1), "> (const %var% & %var%| )")) &&
00374                                  function.tokenDef->linkAt(1)->strAt(3) == scope->className)
00375                             function.type = Function::eCopyConstructor;
00376 
00377                         // copy constructor with non-const argument
00378                         else if ((Token::Match(function.tokenDef, "%var% ( %var% & %var%| )") ||
00379                                   (Token::Match(function.tokenDef, "%var% ( %var% <") &&
00380                                    Token::Match(function.tokenDef->linkAt(4), "> & %var%| )"))) &&
00381                                  function.tokenDef->strAt(2) == scope->className)
00382                             function.type = Function::eCopyConstructor;
00383 
00384                         else if ((Token::Match(function.tokenDef, "%var% <") &&
00385                                   Token::Match(function.tokenDef->linkAt(1), "> ( %var% & %var%| )")) &&
00386                                  function.tokenDef->strAt(2) == scope->className)
00387                             function.type = Function::eCopyConstructor;
00388 
00389                         // regular constructor
00390                         else
00391                             function.type = Function::eConstructor;
00392 
00393                         if (function.tokenDef->previous()->str() == "explicit")
00394                             function.isExplicit = true;
00395                     }
00396 
00397                     // function returning function pointer
00398                     else if (tok->str() == "(") {
00399                         function.retFuncPtr = true;
00400                     }
00401 
00402                     const Token *tok1 = tok;
00403 
00404                     // look for end of previous statement
00405                     while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) {
00406                         // virtual function
00407                         if (tok1->previous()->str() == "virtual") {
00408                             function.isVirtual = true;
00409                             break;
00410                         }
00411 
00412                         // static function
00413                         else if (tok1->previous()->str() == "static") {
00414                             function.isStatic = true;
00415                             break;
00416                         }
00417 
00418                         // friend function
00419                         else if (tok1->previous()->str() == "friend") {
00420                             function.isFriend = true;
00421                             break;
00422                         }
00423 
00424                         tok1 = tok1->previous();
00425                     }
00426 
00427                     const Token *end;
00428 
00429                     if (!function.retFuncPtr)
00430                         end = function.argDef->link();
00431                     else
00432                         end = tok->link()->next()->link();
00433 
00434                     // const function
00435                     if (end->next()->str() == "const")
00436                         function.isConst = true;
00437 
00438                     // count the number of constructors
00439                     if (function.type == Function::eConstructor)
00440                         scope->numConstructors++;
00441                     else if (function.type == Function::eCopyConstructor) {
00442                         scope->numConstructors++;
00443                         scope->numCopyConstructors++;
00444                     }
00445 
00446                     // assume implementation is inline (definition and implementation same)
00447                     function.token = function.tokenDef;
00448                     function.arg = function.argDef;
00449 
00450                     // out of line function
00451                     if (Token::Match(end, ") const| ;")) {
00452                         // find the function implementation later
00453                         tok = end->next();
00454                         if (tok->str() != ";")
00455                             tok = tok->next();
00456 
00457                         scope->functionList.push_back(function);
00458                     }
00459 
00460                     // default or delete
00461                     else if (Token::Match(end, ") = default|delete ;")) {
00462                         if (end->strAt(2) == "default")
00463                             function.isDefault = true;
00464                         else
00465                             function.isDelete = true;
00466 
00467                         tok = end->tokAt(3);
00468 
00469                         scope->functionList.push_back(function);
00470                     }
00471 
00472                     // pure virtual function
00473                     else if (Token::Match(end, ") const| = %any% ;")) {
00474                         function.isPure = true;
00475 
00476                         if (end->next()->str() == "const")
00477                             tok = end->tokAt(4);
00478                         else
00479                             tok = end->tokAt(3);
00480 
00481                         scope->functionList.push_back(function);
00482                     }
00483 
00484                     // inline function
00485                     else {
00486                         function.isInline = true;
00487                         function.hasBody = true;
00488 
00489                         // find start of function '{'
00490                         while (end && end->str() != "{")
00491                             end = end->next();
00492                         if (!end)
00493                             continue;
00494 
00495                         scope->functionList.push_back(function);
00496 
00497                         Function* funcptr = &scope->functionList.back();
00498                         const Token *tok2 = funcStart;
00499 
00500                         addNewFunction(&scope, &tok2);
00501                         if (scope) {
00502                             scope->functionOf = function.nestedIn;
00503                             scope->function = funcptr;
00504                             scope->function->functionScope = scope;
00505                         }
00506 
00507                         tok = tok2;
00508                     }
00509                 }
00510 
00511                 // nested class or friend function?
00512                 else if (tok->previous()->str() == "::" && isFunction(tok, scope, &funcStart, &argStart)) {
00513                     /** @todo check entire qualification for match */
00514                     Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2));
00515 
00516                     if (nested)
00517                         addClassFunction(&scope, &tok, argStart);
00518                     else {
00519                         /** @todo handle friend functions */
00520                     }
00521                 }
00522 
00523                 // friend class declaration?
00524                 else if (Token::Match(tok, "friend class| ::| %any% ;|::")) {
00525                     Type::FriendInfo friendInfo;
00526 
00527                     // save the name start
00528                     friendInfo.nameStart = tok->strAt(1) == "class" ? tok->tokAt(2) : tok->next();
00529                     friendInfo.nameEnd = friendInfo.nameStart;
00530 
00531                     // skip leading "::"
00532                     if (friendInfo.nameEnd->str() == "::")
00533                         friendInfo.nameEnd = friendInfo.nameEnd->next();
00534 
00535                     // skip qualification "name ::"
00536                     while (friendInfo.nameEnd && friendInfo.nameEnd->strAt(1) == "::")
00537                         friendInfo.nameEnd = friendInfo.nameEnd->tokAt(2);
00538 
00539                     // save the name
00540                     if (friendInfo.nameEnd)
00541                         friendInfo.name = friendInfo.nameEnd->str();
00542 
00543                     // fill this in after parsing is complete
00544                     friendInfo.type = 0;
00545 
00546                     scope->definedType->friendList.push_back(friendInfo);
00547                 }
00548             } else if (scope->type == Scope::eNamespace || scope->type == Scope::eGlobal) {
00549                 const Token *funcStart = 0;
00550                 const Token *argStart = 0;
00551 
00552                 // function?
00553                 if (isFunction(tok, scope, &funcStart, &argStart)) {
00554                     // has body?
00555                     if (Token::Match(argStart->link(), ") const| {|:")) {
00556                         Scope *old_scope = scope;
00557 
00558                         // class function
00559                         if (tok->previous() && tok->previous()->str() == "::")
00560                             addClassFunction(&scope, &tok, argStart);
00561 
00562                         // class destructor
00563                         else if (tok->previous() && tok->previous()->str() == "~" &&
00564                                  tok->tokAt(-2) && tok->strAt(-2) == "::")
00565                             addClassFunction(&scope, &tok, argStart);
00566 
00567                         // regular function
00568                         else
00569                             addGlobalFunction(scope, tok, argStart, funcStart);
00570 
00571                         // syntax error
00572                         if (!scope) {
00573                             scope = old_scope;
00574                             break;
00575                         }
00576                     }
00577 
00578                     // function returning function pointer with body
00579                     else if (Token::simpleMatch(argStart->link(), ") ) (") &&
00580                              Token::Match(argStart->link()->linkAt(2), ") const| {")) {
00581                         tok = funcStart;
00582                         Scope *old_scope = scope;
00583 
00584                         // class function
00585                         if (tok->previous()->str() == "::")
00586                             addClassFunction(&scope, &tok, argStart);
00587 
00588                         // regular function
00589                         else {
00590                             Function* function = addGlobalFunction(scope, tok, argStart, funcStart);
00591                             function->retFuncPtr = true;
00592                         }
00593 
00594                         // syntax error?
00595                         if (!scope) {
00596                             scope = old_scope;
00597                             break;
00598                         }
00599                     }
00600 
00601                     // function prototype
00602                     else if (Token::simpleMatch(argStart->link(), ") ;")) {
00603                         bool newFunc = true; // Is this function already in the database?
00604                         for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
00605                             if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) {
00606                                 newFunc = false;
00607                                 break;
00608                             }
00609                         }
00610                         // save function prototype in database
00611                         if (newFunc)
00612                             addGlobalFunctionDecl(scope, argStart, funcStart);
00613 
00614                         tok = argStart->link()->next();
00615                         continue;
00616                     }
00617 
00618                     // function returning function pointer prototype
00619                     else if (Token::simpleMatch(argStart->link(), ") ) (") &&
00620                              Token::simpleMatch(argStart->link()->linkAt(2), ") ;")) {
00621                         bool newFunc = true; // Is this function already in the database?
00622                         for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
00623                             if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef, argStart, "", 0))
00624                                 newFunc = false;
00625                         }
00626                         // save function prototype in database
00627                         if (newFunc) {
00628                             Function* func = addGlobalFunctionDecl(scope, argStart, funcStart);
00629                             func->retFuncPtr = true;
00630                         }
00631 
00632                         tok = argStart->link()->linkAt(2)->next();
00633                         continue;
00634                     }
00635                 }
00636             } else if (scope->isExecutable()) {
00637                 if (Token::Match(tok, "else|try|do {")) {
00638                     const Token* tok1 = tok->next();
00639                     if (tok->str() == "else")
00640                         scopeList.push_back(Scope(this, tok, scope, Scope::eElse, tok1));
00641                     if (tok->str() == "do")
00642                         scopeList.push_back(Scope(this, tok, scope, Scope::eDo, tok1));
00643                     else if (tok->str() == "try")
00644                         scopeList.push_back(Scope(this, tok, scope, Scope::eTry, tok1));
00645 
00646                     tok = tok1;
00647                     scope->nestedList.push_back(&scopeList.back());
00648                     scope = &scopeList.back();
00649                 } else if (Token::Match(tok, "if|for|while|catch|switch (") && Token::simpleMatch(tok->next()->link(), ") {")) {
00650                     const Token *tok1 = tok->next()->link()->next();
00651                     if (tok->str() == "if" && tok->strAt(-1) == "else")
00652                         scopeList.push_back(Scope(this, tok->previous(), scope, Scope::eElseIf, tok1));
00653                     else if (tok->str() == "if")
00654                         scopeList.push_back(Scope(this, tok, scope, Scope::eIf, tok1));
00655                     else if (tok->str() == "for") {
00656                         scopeList.push_back(Scope(this, tok, scope, Scope::eFor, tok1));
00657                     } else if (tok->str() == "while")
00658                         scopeList.push_back(Scope(this, tok, scope, Scope::eWhile, tok1));
00659                     else if (tok->str() == "catch") {
00660                         scopeList.push_back(Scope(this, tok, scope, Scope::eCatch, tok1));
00661                     } else if (tok->str() == "switch")
00662                         scopeList.push_back(Scope(this, tok, scope, Scope::eSwitch, tok1));
00663 
00664                     scope->nestedList.push_back(&scopeList.back());
00665                     scope = &scopeList.back();
00666                     if (scope->type == Scope::eFor)
00667                         scope->checkVariable(tok->tokAt(2), Local); // check for variable declaration and add it to new scope if found
00668                     else if (scope->type == Scope::eCatch)
00669                         scope->checkVariable(tok->tokAt(2), Throw); // check for variable declaration and add it to new scope if found
00670                     tok = tok1;
00671                 } else if (tok->str() == "{") {
00672                     if (!Token::Match(tok->previous(), "=|,")) {
00673                         scopeList.push_back(Scope(this, tok, scope, Scope::eUnconditional, tok));
00674                         scope->nestedList.push_back(&scopeList.back());
00675                         scope = &scopeList.back();
00676                     } else {
00677                         tok = tok->link();
00678                     }
00679                 }
00680             }
00681         }
00682     }
00683 
00684     // fill in base class info
00685     for (std::list<Type>::iterator it = typeList.begin(); it != typeList.end(); ++it) {
00686         // finish filling in base class info
00687         for (unsigned int i = 0; i < it->derivedFrom.size(); ++i)
00688             it->derivedFrom[i].type = findType(it->derivedFrom[i].nameTok, it->enclosingScope);
00689     }
00690 
00691     // fill in friend info
00692     for (std::list<Type>::iterator it = typeList.begin(); it != typeList.end(); ++it) {
00693         for (std::list<Type::FriendInfo>::iterator i = it->friendList.begin(); i != it->friendList.end(); ++i) {
00694             i->type = findType(i->nameStart, it->enclosingScope);
00695         }
00696     }
00697 
00698     // fill in using info
00699     for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00700         for (std::list<Scope::UsingInfo>::iterator i = it->usingList.begin(); i != it->usingList.end(); ++i) {
00701             // check scope for match
00702             scope = findScope(i->start->tokAt(2), &(*it));
00703             if (scope) {
00704                 // set found scope
00705                 i->scope = scope;
00706                 break;
00707             }
00708         }
00709     }
00710 
00711     // fill in variable info
00712     for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00713         // find variables
00714         it->getVariableList();
00715     }
00716 
00717     // fill in function arguments
00718     for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00719         std::list<Function>::iterator func;
00720 
00721         for (func = it->functionList.begin(); func != it->functionList.end(); ++func) {
00722             // add arguments
00723             func->addArguments(this, scope);
00724         }
00725     }
00726 
00727     // fill in function scopes
00728     for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00729         if (it->type == Scope::eFunction)
00730             functionScopes.push_back(&*it);
00731     }
00732 
00733     // fill in class and struct scopes
00734     for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00735         if (it->isClassOrStruct())
00736             classAndStructScopes.push_back(&*it);
00737     }
00738 
00739     // determine if user defined type needs initialization
00740     unsigned int unknowns = 0; // stop checking when there are no unknowns
00741     unsigned int retry = 0;    // bail if we don't resolve all the variable types for some reason
00742 
00743     do {
00744         unknowns = 0;
00745 
00746         for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00747             scope = &(*it);
00748 
00749             if (scope->isClassOrStruct() && scope->definedType->needInitialization == Type::Unknown) {
00750                 // check for default constructor
00751                 bool hasDefaultConstructor = false;
00752 
00753                 std::list<Function>::const_iterator func;
00754 
00755                 for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
00756                     if (func->type == Function::eConstructor) {
00757                         // check for no arguments: func ( )
00758                         if (func->argCount() == 0) {
00759                             hasDefaultConstructor = true;
00760                             break;
00761                         }
00762 
00763                         /** check for arguments with default values */
00764                         else if (func->argCount() == func->initializedArgCount()) {
00765                             hasDefaultConstructor = true;
00766                             break;
00767                         }
00768                     }
00769                 }
00770 
00771                 // User defined types with user defined default constructor doesn't need initialization.
00772                 // We assume the default constructor initializes everything.
00773                 // Another check will figure out if the constructor actually initializes everything.
00774                 if (hasDefaultConstructor)
00775                     scope->definedType->needInitialization = Type::False;
00776 
00777                 // check each member variable to see if it needs initialization
00778                 else {
00779                     bool needInitialization = false;
00780                     bool unknown = false;
00781 
00782                     std::list<Variable>::const_iterator var;
00783                     for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
00784                         if (var->isClass()) {
00785                             if (var->type()) {
00786                                 // does this type need initialization?
00787                                 if (var->type()->needInitialization == Type::True)
00788                                     needInitialization = true;
00789                                 else if (var->type()->needInitialization == Type::Unknown)
00790                                     unknown = true;
00791                             }
00792                         } else
00793                             needInitialization = true;
00794                     }
00795 
00796                     if (!unknown) {
00797                         if (needInitialization)
00798                             scope->definedType->needInitialization = Type::True;
00799                         else
00800                             scope->definedType->needInitialization = Type::False;
00801                     }
00802 
00803                     if (scope->definedType->needInitialization == Type::Unknown)
00804                         unknowns++;
00805                 }
00806             } else if (scope->type == Scope::eUnion && scope->definedType->needInitialization == Type::Unknown)
00807                 scope->definedType->needInitialization = Type::True;
00808         }
00809 
00810         retry++;
00811     } while (unknowns && retry < 100);
00812 
00813     // this shouldn't happen so output a debug warning
00814     if (retry == 100 && _settings->debugwarnings) {
00815         for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00816             scope = &(*it);
00817 
00818             if (scope->isClassOrStruct() && scope->definedType->needInitialization == Type::Unknown)
00819                 debugMessage(scope->classDef, "SymbolDatabase::SymbolDatabase couldn't resolve all user defined types.");
00820         }
00821     }
00822 
00823     // create variable symbol table
00824     _variableList.resize(_tokenizer->varIdCount() + 1);
00825     std::fill_n(_variableList.begin(), _variableList.size(), (const Variable*)NULL);
00826 
00827     // check all scopes for variables
00828     for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
00829         scope = &(*it);
00830 
00831         // add all variables
00832         std::list<Variable>::const_iterator var;
00833         for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
00834             unsigned int varId = var->varId();
00835             if (varId)
00836                 _variableList[varId] = &(*var);
00837         }
00838 
00839         // add all function parameters
00840         std::list<Function>::const_iterator func;
00841         for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
00842             // ignore function without implementations
00843             if (!func->hasBody)
00844                 continue;
00845 
00846             std::list<Variable>::const_iterator arg;
00847             for (arg = func->argumentList.begin(); arg != func->argumentList.end(); ++arg) {
00848                 // check for named parameters
00849                 if (arg->nameToken() && arg->varId()) {
00850                     unsigned int varId = arg->varId();
00851                     if (varId)
00852                         _variableList[varId] = &(*arg);
00853                 }
00854             }
00855         }
00856     }
00857 
00858     // fill in missing variables if possible
00859     const std::size_t functions = functionScopes.size();
00860     for (std::size_t i = 0; i < functions; ++i) {
00861         const Scope *func = functionScopes[i];
00862         for (const Token *tok = func->classStart->next(); tok != func->classEnd; tok = tok->next()) {
00863             // check for member variable
00864             if (tok && tok->varId() && tok->next() && tok->next()->str() == ".") {
00865                 const Token *tok1 = tok->tokAt(2);
00866                 if (tok1 && tok1->varId() && _variableList[tok1->varId()] == 0) {
00867                     const Variable *var = _variableList[tok->varId()];
00868                     if (var && var->typeScope()) {
00869                         // find the member variable of this variable
00870                         const Variable *var1 = var->typeScope()->getVariable(tok1->str());
00871                         if (var1) {
00872                             // add this variable to the look up table
00873                             _variableList[tok1->varId()] = var1;
00874                         }
00875                     }
00876                 }
00877             }
00878         }
00879     }
00880 
00881     /* set all unknown array dimensions that are set by a variable to the maximum size of that variable type */
00882     for (std::size_t i = 1; i <= _tokenizer->varIdCount(); i++) {
00883         // check each array variable
00884         if (_variableList[i] && _variableList[i]->isArray()) {
00885             // check each array dimension
00886             for (std::size_t j = 0; j < _variableList[i]->dimensions().size(); j++) {
00887                 Dimension &dimension = const_cast<Dimension &>(_variableList[i]->dimensions()[j]);
00888                 // check for a single token dimension that is a variable
00889                 if (dimension.num == 0) {
00890                     dimension.known = false;
00891                     if (!dimension.start || (dimension.start != dimension.end) || !dimension.start->varId())
00892                         continue;
00893 
00894                     // get maximum size from type
00895                     // find where this type is defined
00896                     const Variable *var = getVariableFromVarId(dimension.start->varId());
00897 
00898                     // make sure it is in the database
00899                     if (!var)
00900                         break;
00901 
00902                     // get type token
00903                     const Token *index_type = var->typeEndToken();
00904 
00905                     if (index_type->str() == "char") {
00906                         if (index_type->isUnsigned())
00907                             dimension.num = UCHAR_MAX + 1;
00908                         else if (index_type->isSigned())
00909                             dimension.num = SCHAR_MAX + 1;
00910                         else
00911                             dimension.num = CHAR_MAX + 1;
00912                     } else if (index_type->str() == "short") {
00913                         if (index_type->isUnsigned())
00914                             dimension.num = USHRT_MAX + 1;
00915                         else
00916                             dimension.num = SHRT_MAX + 1;
00917                     }
00918 
00919                     // checkScope assumes size is signed int so we limit the following sizes to INT_MAX
00920                     else if (index_type->str() == "int") {
00921                         if (index_type->isUnsigned())
00922                             dimension.num = UINT_MAX + 1ULL;
00923                         else
00924                             dimension.num = INT_MAX + 1ULL;
00925                     } else if (index_type->str() == "long") {
00926                         if (index_type->isUnsigned()) {
00927                             if (index_type->isLong())
00928                                 dimension.num = ULLONG_MAX; // should be ULLONG_MAX + 1ULL
00929                             else
00930                                 dimension.num = ULONG_MAX; // should be ULONG_MAX + 1ULL
00931                         } else {
00932                             if (index_type->isLong())
00933                                 dimension.num = LLONG_MAX; // should be LLONG_MAX + 1LL
00934                             else
00935                                 dimension.num = LONG_MAX;  // should be LONG_MAX + 1LL
00936                         }
00937                     }
00938                 }
00939             }
00940         }
00941     }
00942 }
00943 
00944 bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart)
00945 {
00946     // function returning function pointer? '... ( ... %var% ( ... ))( ... ) {'
00947     if (tok->str() == "(" &&
00948         tok->link()->previous()->str() == ")" &&
00949         tok->link()->next() &&
00950         tok->link()->next()->str() == "(" &&
00951         tok->link()->next()->link()->next() &&
00952         Token::Match(tok->link()->next()->link()->next(), "{|;|const|=")) {
00953         *funcStart = tok->link()->previous()->link()->previous();
00954         *argStart = tok->link()->previous()->link();
00955         return true;
00956     }
00957 
00958     // regular function?
00959     else if (Token::Match(tok, "%var% (") && tok->previous() &&
00960              (tok->previous()->isName() || tok->strAt(-1) == ">" || tok->strAt(-1) == "&" || tok->strAt(-1) == "*" || // Either a return type in front of tok
00961               tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok
00962               outerScope->isClassOrStruct()) && // or a ctor/dtor
00963              (Token::Match(tok->next()->link(), ") const| ;|{|=") ||
00964               Token::Match(tok->next()->link(), ") : ::| %var% (|::|<|{") ||
00965               Token::Match(tok->next()->link(), ") = delete|default ;"))) {
00966         *funcStart = tok;
00967         *argStart = tok->next();
00968         return true;
00969     }
00970 
00971     // template constructor?
00972     else if (Token::Match(tok, "%var% <") && Token::simpleMatch(tok->next()->link(), "> (") &&
00973              (Token::Match(tok->next()->link()->next()->link(), ") const| ;|{|=") ||
00974               Token::Match(tok->next()->link()->next()->link(), ") : ::| %var% (|::|<|{"))) {
00975         *funcStart = tok;
00976         *argStart = tok->next()->link()->next();
00977         return true;
00978     }
00979 
00980     return false;
00981 }
00982 
00983 void Variable::evaluate()
00984 {
00985     const Token* tok = _start;
00986     while (tok && tok->previous() && tok->previous()->isName())
00987         tok = tok->previous();
00988     for (const Token* const end = _name?_name:_end; tok != end;) {
00989         if (tok->str() == "static")
00990             setFlag(fIsStatic, true);
00991         else if (tok->str() == "extern")
00992             setFlag(fIsExtern, true);
00993         else if (tok->str() == "mutable")
00994             setFlag(fIsMutable, true);
00995         else if (tok->str() == "const")
00996             setFlag(fIsConst, true);
00997         else if (tok->str() == "*") {
00998             setFlag(fIsPointer, true);
00999             setFlag(fIsConst, false); // Points to const, isn't necessarily const itself
01000         } else if (tok->str() == "&")
01001             setFlag(fIsReference, true);
01002 
01003         if (tok->str() == "<")
01004             tok->findClosingBracket(tok);
01005         else
01006             tok = tok->next();
01007     }
01008 
01009     while (_start && _start->next() && (_start->str() == "static" || _start->str() == "const"))
01010         _start = _start->next();
01011     while (_end && _end->previous() && _end->str() == "const")
01012         _end = _end->previous();
01013 
01014     if (_name)
01015         setFlag(fIsArray, arrayDimensions(_dimensions, _name->next()));
01016     if (_start)
01017         setFlag(fIsClass, !_start->isStandardType() && !isPointer() && !isReference());
01018     if (_access == Argument) {
01019         tok = _name;
01020         if (!tok) {
01021             // Argument without name
01022             tok = _end;
01023             // back up to start of array dimensions
01024             while (tok && tok->str() == "]")
01025                 tok = tok->link()->previous();
01026             // add array dimensions if present
01027             if (tok && tok->next()->str() == "[")
01028                 setFlag(fIsArray, arrayDimensions(_dimensions, tok->next()));
01029         }
01030         if (!tok)
01031             return;
01032         tok = tok->next();
01033         while (tok->str() == "[")
01034             tok = tok->link();
01035         setFlag(fHasDefault, tok->str() == "=");
01036     }
01037     // check for C++11 member initialization
01038     if (_scope && _scope->isClassOrStruct()) {
01039         // type var = x; gets simplified to: type var ; var = x ;
01040         if (Token::Match(_name, "%var% ; %var% = %any% ;") && _name->strAt(2) == _name->str())
01041             setFlag(fHasDefault, true);
01042     }
01043 }
01044 
01045 bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int depth)
01046 {
01047     const bool isCPP = scope->check->isCPP();
01048 
01049     // skip "struct" if it is C++
01050     if (isCPP) {
01051         if (first->str() == "struct")
01052             first = first->next();
01053         if (second->str() == "struct")
01054             second = second->next();
01055     }
01056 
01057     // skip const on type passed by value
01058     if (Token::Match(first, "const %type% %var%|,|)"))
01059         first = first->next();
01060     if (Token::Match(second, "const %type% %var%|,|)"))
01061         second = second->next();
01062 
01063     while (first->str() == second->str() &&
01064            first->isLong() == second->isLong() &&
01065            first->isUnsigned() == second->isUnsigned()) {
01066         // at end of argument list
01067         if (first->str() == ")") {
01068             return true;
01069         }
01070 
01071         // skip default value assignment
01072         else if (first->next()->str() == "=") {
01073             first = first->nextArgument();
01074 
01075             if (second->next()->str() == "=") {
01076                 second = second->nextArgument();
01077                 if (!first || !second) { // End of argument list (first or second)
01078                     return !first && !second;
01079                 }
01080             } else if (!first) { // End of argument list (first)
01081                 return second->next() && second->next()->str() == ")";
01082             }
01083         }
01084 
01085         // definition missing variable name
01086         else if (first->next()->str() == "," && second->next()->str() != ",")
01087             second = second->next();
01088         else if (first->next()->str() == ")" && second->next()->str() != ")")
01089             second = second->next();
01090         else if (first->next()->str() == "[" && second->next()->str() != "[")
01091             second = second->next();
01092 
01093         // function missing variable name
01094         else if (second->next()->str() == "," && first->next()->str() != ",")
01095             first = first->next();
01096         else if (second->next()->str() == ")" && first->next()->str() != ")")
01097             first = first->next();
01098         else if (second->next()->str() == "[" && first->next()->str() != "[")
01099             first = first->next();
01100 
01101         // argument list has different number of arguments
01102         else if (second->str() == ")")
01103             break;
01104 
01105         // variable names are different
01106         else if ((Token::Match(first->next(), "%var% ,|)|=") &&
01107                   Token::Match(second->next(), "%var% ,|)")) &&
01108                  (first->next()->str() != second->next()->str())) {
01109             // skip variable names
01110             first = first->next();
01111             second = second->next();
01112         }
01113 
01114         // variable with class path
01115         else if (depth && Token::Match(first->next(), "%var%")) {
01116             std::string param = path + first->next()->str();
01117 
01118             if (Token::Match(second->next(), param.c_str())) {
01119                 second = second->tokAt(int(depth) * 2);
01120             } else if (depth > 1) {
01121                 std::string short_path = path;
01122 
01123                 // remove last " :: "
01124                 short_path.resize(short_path.size() - 4);
01125 
01126                 // remove last name
01127                 while (!short_path.empty() && short_path[short_path.size() - 1] != ' ')
01128                     short_path.resize(short_path.size() - 1);
01129 
01130                 param = short_path + first->next()->str();
01131                 if (Token::Match(second->next(), param.c_str())) {
01132                     second = second->tokAt((int(depth) - 1) * 2);
01133                 }
01134             }
01135         }
01136 
01137         // nested class variable
01138         else if (depth == 0 && Token::Match(first->next(), "%var%") &&
01139                  second->next()->str() == scope->className && second->strAt(2) == "::" &&
01140                  first->next()->str() == second->strAt(3)) {
01141             second = second->tokAt(2);
01142         }
01143 
01144         first = first->next();
01145         second = second->next();
01146 
01147         // skip "struct" if it is C++
01148         if (isCPP) {
01149             if (first->str() == "struct")
01150                 first = first->next();
01151             if (second->str() == "struct")
01152                 second = second->next();
01153         }
01154 
01155         // skip const on type passed by value
01156         if (Token::Match(first, "const %type% %var%|,|)"))
01157             first = first->next();
01158         if (Token::Match(second, "const %type% %var%|,|)"))
01159             second = second->next();
01160     }
01161 
01162     return false;
01163 }
01164 
01165 Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart)
01166 {
01167     Function* function = 0;
01168     for (std::list<Function>::iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
01169         if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0))
01170             function = &*i;
01171     }
01172 
01173     if (!function)
01174         function = addGlobalFunctionDecl(scope, argStart, funcStart);
01175 
01176     function->arg = argStart;
01177     function->token = funcStart;
01178     function->hasBody = true;
01179 
01180     addNewFunction(&scope, &tok);
01181 
01182     if (scope) {
01183         scope->function = function;
01184         function->functionScope = scope;
01185         return function;
01186     }
01187     return 0;
01188 }
01189 
01190 Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *argStart, const Token* funcStart)
01191 {
01192     Function function;
01193 
01194     // save the function definition argument start '('
01195     function.argDef = argStart;
01196 
01197     // save the access type
01198     function.access = Public;
01199 
01200     // save the function name location
01201     function.tokenDef = funcStart;
01202 
01203     function.isInline = false;
01204     function.hasBody = false;
01205     function.type = Function::eFunction;
01206     function.nestedIn = scope;
01207 
01208     scope->functionList.push_back(function);
01209     return &scope->functionList.back();
01210 }
01211 
01212 void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const Token *argStart)
01213 {
01214     int count = 0;
01215     std::string path;
01216     unsigned int path_length = 0;
01217     const Token *tok1;
01218 
01219     const bool destructor((*tok)->previous()->str() == "~");
01220 
01221     // skip class/struct name
01222     if (destructor)
01223         tok1 = (*tok)->tokAt(-3);
01224     else
01225         tok1 = (*tok)->tokAt(-2);
01226 
01227     // syntax error?
01228     if (!tok1)
01229         return;
01230 
01231     // back up to head of path
01232     while (tok1 && tok1->previous() && tok1->previous()->str() == "::" &&
01233            tok1->tokAt(-2) && tok1->tokAt(-2)->isName()) {
01234         path = tok1->str() + " :: " + path;
01235         tok1 = tok1->tokAt(-2);
01236         count++;
01237         path_length++;
01238     }
01239 
01240     if (tok1 && count) {
01241         path = tok1->str() + " :: " + path;
01242         path_length++;
01243     }
01244 
01245     std::list<Scope>::iterator it1;
01246 
01247     // search for match
01248     for (it1 = scopeList.begin(); it1 != scopeList.end(); ++it1) {
01249         Scope *scope1 = &(*it1);
01250 
01251         bool match = false;
01252         if (scope1->className == tok1->str() && (scope1->type != Scope::eFunction)) {
01253             // do the scopes match (same scope) or do their names match (multiple namespaces)
01254             if ((*scope == scope1->nestedIn) || (*scope && scope1 &&
01255                                                  (*scope)->className == scope1->nestedIn->className &&
01256                                                  !(*scope)->className.empty() &&
01257                                                  (*scope)->type == scope1->nestedIn->type)) {
01258 
01259                 // nested scopes => check that they match
01260                 {
01261                     const Scope *s1 = *scope;
01262                     const Scope *s2 = scope1->nestedIn;
01263                     while (s1 && s2) {
01264                         if (s1->className != s2->className)
01265                             break;
01266                         s1 = s1->nestedIn;
01267                         s2 = s2->nestedIn;
01268                     }
01269                     // Not matching scopes
01270                     if (s1 || s2)
01271                         continue;
01272                 }
01273 
01274                 Scope *scope2 = scope1;
01275 
01276                 while (scope2 && count > 0) {
01277                     count--;
01278                     tok1 = tok1->tokAt(2);
01279                     scope2 = scope2->findInNestedList(tok1->str());
01280                 }
01281 
01282                 if (count == 0 && scope2) {
01283                     match = true;
01284                     scope1 = scope2;
01285                 }
01286             }
01287         }
01288 
01289         if (match) {
01290             std::list<Function>::iterator func;
01291 
01292             for (func = scope1->functionList.begin(); func != scope1->functionList.end(); ++func) {
01293                 if (!func->hasBody && func->tokenDef->str() == (*tok)->str()) {
01294                     if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
01295                         if (func->type == Function::eDestructor && destructor) {
01296                             func->hasBody = true;
01297                         } else if (func->type != Function::eDestructor && !destructor) {
01298                             // normal function?
01299                             if (!func->retFuncPtr && (*tok)->next()->link()) {
01300                                 if ((func->isConst && (*tok)->next()->link()->next()->str() == "const") ||
01301                                     (!func->isConst && (*tok)->next()->link()->next()->str() != "const")) {
01302                                     func->hasBody = true;
01303                                 }
01304                             }
01305 
01306                             // function returning function pointer?
01307                             else if (func->retFuncPtr) {
01308                                 // todo check for const
01309                                 func->hasBody = true;
01310                             }
01311                         }
01312 
01313                         if (func->hasBody) {
01314                             func->token = *tok;
01315                             func->arg = argStart;
01316                             addNewFunction(scope, tok);
01317                             if (*scope) {
01318                                 (*scope)->functionOf = scope1;
01319                                 (*scope)->function = &*func;
01320                                 (*scope)->function->functionScope = *scope;
01321                             }
01322                             return;
01323                         }
01324                     }
01325                 }
01326             }
01327         }
01328     }
01329 
01330     // class function of unknown class
01331     addNewFunction(scope, tok);
01332 }
01333 
01334 void SymbolDatabase::addNewFunction(Scope **scope, const Token **tok)
01335 {
01336     const Token *tok1 = *tok;
01337     scopeList.push_back(Scope(this, tok1, *scope));
01338     Scope *new_scope = &scopeList.back();
01339 
01340     // skip to start of function
01341     while (tok1 && ((tok1->str() != "{") || (tok1->previous() && tok1->previous()->isName() && tok1->strAt(-1) != "const" && Token::Match(tok1->link()->next(), ",|{|%type%")))) {
01342         if (tok1->str() == "(" || tok1->str() == "{")
01343             tok1 = tok1->link();
01344         tok1 = tok1->next();
01345     }
01346 
01347     if (tok1) {
01348         new_scope->classStart = tok1;
01349         new_scope->classEnd = tok1->link();
01350 
01351         // syntax error?
01352         if (!new_scope->classEnd) {
01353             scopeList.pop_back();
01354             while (tok1->next())
01355                 tok1 = tok1->next();
01356             *scope = NULL;
01357             *tok = tok1;
01358             return;
01359         }
01360 
01361         (*scope)->nestedList.push_back(new_scope);
01362         *scope = new_scope;
01363         *tok = tok1;
01364     } else {
01365         scopeList.pop_back();
01366         *scope = NULL;
01367         *tok = NULL;
01368     }
01369 }
01370 
01371 const Token *Type::initBaseInfo(const Token *tok, const Token *tok1)
01372 {
01373     // goto initial '{'
01374     const Token *tok2 = tok1;
01375     while (tok2 && tok2->str() != "{") {
01376         // skip unsupported templates
01377         if (tok2->str() == "<")
01378             tok2->findClosingBracket(tok2);
01379 
01380         // check for base classes
01381         else if (Token::Match(tok2, ":|,")) {
01382             Type::BaseInfo base;
01383 
01384             base.isVirtual = false;
01385 
01386             tok2 = tok2->next();
01387 
01388             // check for invalid code
01389             if (!tok2 || !tok2->next())
01390                 return NULL;
01391 
01392             if (tok2->str() == "virtual") {
01393                 base.isVirtual = true;
01394                 tok2 = tok2->next();
01395             }
01396 
01397             if (tok2->str() == "public") {
01398                 base.access = Public;
01399                 tok2 = tok2->next();
01400             } else if (tok2->str() == "protected") {
01401                 base.access = Protected;
01402                 tok2 = tok2->next();
01403             } else if (tok2->str() == "private") {
01404                 base.access = Private;
01405                 tok2 = tok2->next();
01406             } else {
01407                 if (tok->str() == "class")
01408                     base.access = Private;
01409                 else if (tok->str() == "struct")
01410                     base.access = Public;
01411             }
01412 
01413             if (tok2->str() == "virtual") {
01414                 base.isVirtual = true;
01415                 tok2 = tok2->next();
01416             }
01417 
01418             base.nameTok = tok2;
01419 
01420             // handle global namespace
01421             if (tok2->str() == "::") {
01422                 tok2 = tok2->next();
01423             }
01424 
01425             // handle derived base classes
01426             while (Token::Match(tok2, "%var% ::")) {
01427                 tok2 = tok2->tokAt(2);
01428             }
01429 
01430             base.name = tok2->str();
01431             base.type = NULL;
01432 
01433             // add unhandled templates
01434             if (tok2->next() && tok2->next()->str() == "<") {
01435                 tok2 = tok2->next();
01436                 base.name += tok2->str();
01437 
01438                 int level1 = 1;
01439                 while (tok2->next()) {
01440                     base.name += tok2->next()->str();
01441 
01442                     if (tok2->next()->str() == ">") {
01443                         level1--;
01444                         if (level1 == 0)
01445                             break;
01446                     } else if (tok2->next()->str() == "<")
01447                         level1++;
01448 
01449                     tok2 = tok2->next();
01450                 }
01451             }
01452 
01453             // save pattern for base class name
01454             derivedFrom.push_back(base);
01455         }
01456         tok2 = tok2->next();
01457     }
01458 
01459     return tok2;
01460 }
01461 
01462 void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) const
01463 {
01464     if (tok && _settings->debugwarnings) {
01465         const std::list<const Token*> locationList(1, tok);
01466         const ErrorLogger::ErrorMessage errmsg(locationList, &_tokenizer->list,
01467                                                Severity::debug,
01468                                                "debug",
01469                                                msg,
01470                                                false);
01471         if (_errorLogger)
01472             _errorLogger->reportErr(errmsg);
01473     }
01474 }
01475 
01476 const Function* Type::getFunction(const std::string& funcName) const
01477 {
01478     if (classScope) {
01479         for (std::list<Function>::const_iterator i = classScope->functionList.begin(); i != classScope->functionList.end(); ++i)
01480             if (i->name() == funcName)
01481                 return &*i;
01482     }
01483 
01484     for (std::size_t i = 0; i < derivedFrom.size(); i++) {
01485         if (derivedFrom[i].type) {
01486             const Function* func = derivedFrom[i].type->getFunction(funcName);
01487             if (func)
01488                 return func;
01489         }
01490     }
01491     return 0;
01492 }
01493 
01494 bool Variable::arrayDimensions(std::vector<Dimension> &dimensions, const Token *tok)
01495 {
01496     bool isArray = false;
01497 
01498     const Token *dim = tok;
01499 
01500     while (dim && dim->next() && dim->str() == "[") {
01501         Dimension dimension;
01502         // check for empty array dimension []
01503         if (dim->next()->str() != "]") {
01504             dimension.start = dim->next();
01505             dimension.end = dim->link()->previous();
01506             if (dimension.start == dimension.end && dimension.start->isNumber())
01507                 dimension.num = MathLib::toLongNumber(dimension.start->str());
01508         }
01509         dimensions.push_back(dimension);
01510         dim = dim->link()->next();
01511         isArray = true;
01512     }
01513     return isArray;
01514 }
01515 
01516 static std::ostream & operator << (std::ostream & s, Scope::ScopeType type)
01517 {
01518     s << (type == Scope::eGlobal ? "Global" :
01519           type == Scope::eClass ? "Class" :
01520           type == Scope::eStruct ? "Struct" :
01521           type == Scope::eUnion ? "Union" :
01522           type == Scope::eNamespace ? "Namespace" :
01523           type == Scope::eFunction ? "Function" :
01524           type == Scope::eIf ? "If" :
01525           type == Scope::eElse ? "Else" :
01526           type == Scope::eElseIf ? "ElseIf" :
01527           type == Scope::eFor ? "For" :
01528           type == Scope::eWhile ? "While" :
01529           type == Scope::eDo ? "Do" :
01530           type == Scope::eSwitch ? "Switch" :
01531           type == Scope::eTry ? "Try" :
01532           type == Scope::eCatch ? "Catch" :
01533           type == Scope::eUnconditional ? "Unconditional" :
01534           "Unknown");
01535     return s;
01536 }
01537 
01538 void SymbolDatabase::printVariable(const Variable *var, const char *indent) const
01539 {
01540     std::cout << indent << "_name: " << var->nameToken();
01541     if (var->nameToken()) {
01542         std::cout << " " << var->name() << " " << _tokenizer->list.fileLine(var->nameToken()) << std::endl;
01543         std::cout << indent << "    varId: " << var->varId() << std::endl;
01544     } else
01545         std::cout << std::endl;
01546     std::cout << indent << "_start: " << var->typeStartToken() << " " << var->typeStartToken()->str()
01547               << " " << _tokenizer->list.fileLine(var->typeStartToken()) << std::endl;
01548     std::cout << indent << "_end: " << var->typeEndToken() << " " << var->typeEndToken()->str()
01549               << " " << _tokenizer->list.fileLine(var->typeEndToken()) << std::endl;
01550     std::cout << indent << "_index: " << var->index() << std::endl;
01551     std::cout << indent << "_access: " <<
01552               (var->isPublic() ? "Public" :
01553                var->isProtected() ? "Protected" :
01554                var->isPrivate() ? "Private" :
01555                var->isGlobal() ? "Global" :
01556                var->isNamespace() ? "Namespace" :
01557                var->isArgument() ? "Argument" :
01558                var->isLocal() ? "Local" :
01559                var->isThrow() ? "Throw" :
01560                "???")  << std::endl;
01561     std::cout << indent << "_flags: " << std::endl;
01562     std::cout << indent << "    isMutable: " << (var->isMutable() ? "true" : "false") << std::endl;
01563     std::cout << indent << "    isStatic: " << (var->isStatic() ? "true" : "false") << std::endl;
01564     std::cout << indent << "    isExtern: " << (var->isExtern() ? "true" : "false") << std::endl;
01565     std::cout << indent << "    isConst: " << (var->isConst() ? "true" : "false") << std::endl;
01566     std::cout << indent << "    isClass: " << (var->isClass() ? "true" : "false") << std::endl;
01567     std::cout << indent << "    isArray: " << (var->isArray() ? "true" : "false") << std::endl;
01568     std::cout << indent << "    isPointer: " << (var->isPointer() ? "true" : "false") << std::endl;
01569     std::cout << indent << "    isReference: " << (var->isReference() ? "true" : "false") << std::endl;
01570     std::cout << indent << "    hasDefault: " << (var->hasDefault() ? "true" : "false") << std::endl;
01571     std::cout << indent << "_type: ";
01572     if (var->type()) {
01573         std::cout << var->type()->name();
01574         if (var->typeScope())
01575             std::cout << " " << var->typeScope()->type;
01576         std::cout << " " << _tokenizer->list.fileLine(var->type()->classDef) << std::endl;
01577     } else
01578         std::cout << "none" << std::endl;
01579 
01580     std::cout << indent << "_scope: ";
01581     if (var->scope()) {
01582         std::cout << var->scope()->className << " " << var->scope()->type;
01583         if (var->scope()->classDef)
01584             std::cout << " " << _tokenizer->list.fileLine(var->scope()->classDef) << std::endl;
01585         else
01586             std::cout << std::endl;
01587     } else
01588         std::cout << "none" << std::endl;
01589 
01590     std::cout << indent << "_dimensions:";
01591     for (std::size_t i = 0; i < var->dimensions().size(); i++) {
01592         std::cout << " " << var->dimension(i);
01593         if (!var->dimensions()[i].known)
01594             std::cout << "?";
01595     }
01596     std::cout << std::endl;
01597 }
01598 
01599 void SymbolDatabase::printOut(const char *title) const
01600 {
01601     if (title)
01602         std::cout << "\n### " << title << " ###\n";
01603 
01604     for (std::list<Scope>::const_iterator scope = scopeList.begin(); scope != scopeList.end(); ++scope) {
01605         std::cout << "Scope: " << &*scope << std::endl;
01606         std::cout << "    type: " << scope->type << std::endl;
01607         std::cout << "    className: " << scope->className << std::endl;
01608         std::cout << "    classDef: " << scope->classDef;
01609         if (scope->classDef)
01610             std::cout << " " << scope->classDef->str() << " " << _tokenizer->list.fileLine(scope->classDef) << std::endl;
01611         else
01612             std::cout << std::endl;
01613 
01614         std::cout << "    classStart: " << scope->classStart;
01615         if (scope->classStart)
01616             std::cout << " " << scope->classStart->str() << " " << _tokenizer->list.fileLine(scope->classStart) << std::endl;
01617         else
01618             std::cout << std::endl;
01619 
01620         std::cout << "    classEnd: " << scope->classEnd;
01621         if (scope->classEnd)
01622             std::cout << " " << scope->classEnd->str() << " " <<  _tokenizer->list.fileLine(scope->classEnd) << std::endl;
01623         else
01624             std::cout << std::endl;
01625 
01626         std::list<Function>::const_iterator func;
01627 
01628         // find the function body if not implemented inline
01629         for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
01630             std::cout << "    Function: " << &*func << std::endl;
01631             std::cout << "        name: " << func->tokenDef->str() << " "
01632                       << _tokenizer->list.fileLine(func->tokenDef) << std::endl;
01633             std::cout << "        type: " << (func->type == Function::eConstructor? "Constructor" :
01634                                               func->type == Function::eCopyConstructor ? "CopyConstructor" :
01635                                               func->type == Function::eOperatorEqual ? "OperatorEqual" :
01636                                               func->type == Function::eDestructor ? "Destructor" :
01637                                               func->type == Function::eFunction ? "Function" :
01638                                               "???") << std::endl;
01639             std::cout << "        access: " << (func->access == Public ? "Public" :
01640                                                 func->access == Protected ? "Protected" :
01641                                                 func->access == Private ? "Private" :
01642                                                 "???")  << std::endl;
01643             std::cout << "        hasBody: " << (func->hasBody ? "true" : "false") << std::endl;
01644             std::cout << "        isInline: " << (func->isInline ? "true" : "false") << std::endl;
01645             std::cout << "        isConst: " << (func->isConst ? "true" : "false") << std::endl;
01646             std::cout << "        isVirtual: " << (func->isVirtual ? "true" : "false") << std::endl;
01647             std::cout << "        isPure: " << (func->isPure ? "true" : "false") << std::endl;
01648             std::cout << "        isStatic: " << (func->isStatic ? "true" : "false") << std::endl;
01649             std::cout << "        isFriend: " << (func->isFriend ? "true" : "false") << std::endl;
01650             std::cout << "        isExplicit: " << (func->isExplicit ? "true" : "false") << std::endl;
01651             std::cout << "        isDefault: " << (func->isDefault ? "true" : "false") << std::endl;
01652             std::cout << "        isDelete: " << (func->isDelete ? "true" : "false") << std::endl;
01653             std::cout << "        isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
01654             std::cout << "        retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl;
01655             std::cout << "        tokenDef: " << _tokenizer->list.fileLine(func->tokenDef) << std::endl;
01656             std::cout << "        argDef: " << _tokenizer->list.fileLine(func->argDef) << std::endl;
01657             if (func->hasBody) {
01658                 std::cout << "        token: " << _tokenizer->list.fileLine(func->token) << std::endl;
01659                 std::cout << "        arg: " << _tokenizer->list.fileLine(func->arg) << std::endl;
01660             }
01661             std::cout << "        nestedIn: ";
01662             if (func->nestedIn) {
01663                 std::cout << func->nestedIn->className << " " << func->nestedIn->type;
01664                 if (func->nestedIn->classDef)
01665                     std::cout << " " << _tokenizer->list.fileLine(func->nestedIn->classDef) << std::endl;
01666                 else
01667                     std::cout << std::endl;
01668             } else
01669                 std::cout << "Unknown" << std::endl;
01670             std::cout << "        functionScope: ";
01671             if (func->functionScope) {
01672                 std::cout << func->functionScope->className << " "
01673                           <<  _tokenizer->list.fileLine(func->functionScope->classDef) << std::endl;
01674             } else
01675                 std::cout << "Unknown" << std::endl;
01676 
01677             std::list<Variable>::const_iterator var;
01678 
01679             for (var = func->argumentList.begin(); var != func->argumentList.end(); ++var) {
01680                 std::cout << "        Variable: " << &*var << std::endl;
01681                 printVariable(&*var, "            ");
01682             }
01683         }
01684 
01685         std::list<Variable>::const_iterator var;
01686 
01687         for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
01688             std::cout << "    Variable: " << &*var << std::endl;
01689             printVariable(&*var, "        ");
01690         }
01691 
01692         std::cout << "    nestedIn: " << scope->nestedIn;
01693         if (scope->nestedIn) {
01694             std::cout << " " << scope->nestedIn->type << " "
01695                       << scope->nestedIn->className;
01696         }
01697         std::cout << std::endl;
01698 
01699         std::cout << "    definedType: " << scope->definedType << std::endl;
01700 
01701         std::cout << "    nestedList[" << scope->nestedList.size() << "] = (";
01702 
01703         std::list<Scope *>::const_iterator nsi;
01704 
01705         std::size_t count = scope->nestedList.size();
01706         for (nsi = scope->nestedList.begin(); nsi != scope->nestedList.end(); ++nsi) {
01707             std::cout << " " << (*nsi) << " " << (*nsi)->type << " " << (*nsi)->className;
01708             if (count-- > 1)
01709                 std::cout << ",";
01710         }
01711 
01712         std::cout << " )" << std::endl;
01713 
01714         std::list<Scope::UsingInfo>::const_iterator use;
01715 
01716         for (use = scope->usingList.begin(); use != scope->usingList.end(); ++use) {
01717             std::cout << "    using: " << use->scope << " " << use->start->strAt(2);
01718             const Token *tok1 = use->start->tokAt(3);
01719             while (tok1 && tok1->str() == "::") {
01720                 std::cout << "::" << tok1->strAt(1);
01721                 tok1 = tok1->tokAt(2);
01722             }
01723             std::cout << " " << _tokenizer->list.fileLine(use->start) << std::endl;
01724         }
01725 
01726         std::cout << "    functionOf: " << scope->functionOf;
01727         if (scope->functionOf) {
01728             std::cout << " " << scope->functionOf->type << " " << scope->functionOf->className;
01729             if (scope->functionOf->classDef)
01730                 std::cout << " " << _tokenizer->list.fileLine(scope->functionOf->classDef);
01731         }
01732         std::cout << std::endl;
01733 
01734         std::cout << "    function: " << scope->function;
01735         if (scope->function) {
01736             std::cout << " " << scope->function->tokenDef->str() << " "
01737                       << _tokenizer->list.fileLine(scope->function->tokenDef);
01738         }
01739         std::cout << std::endl;
01740     }
01741 
01742     for (std::list<Type>::const_iterator type = typeList.begin(); type != typeList.end(); ++type) {
01743         std::cout << "Type: " << type->name() << std::endl;
01744         std::cout << "    classDef: " << _tokenizer->list.fileLine(type->classDef) << std::endl;
01745         std::cout << "    classScope: " << type->classScope << std::endl;
01746         std::cout << "    enclosingScope: " << type->enclosingScope << std::endl;
01747         std::cout << "    needInitialization: " << (type->needInitialization == Type::Unknown ? "Unknown" :
01748                   type->needInitialization == Type::True ? "True" :
01749                   type->needInitialization == Type::False ? "False" :
01750                   "Invalid") << std::endl;
01751 
01752         std::cout << "    derivedFrom[" << type->derivedFrom.size() << "] = (";
01753         std::size_t count = type->derivedFrom.size();
01754         for (std::size_t i = 0; i < type->derivedFrom.size(); ++i) {
01755             if (type->derivedFrom[i].isVirtual)
01756                 std::cout << "Virtual ";
01757 
01758             std::cout << (type->derivedFrom[i].access == Public    ? " Public " :
01759                           type->derivedFrom[i].access == Protected ? " Protected " :
01760                           type->derivedFrom[i].access == Private   ? " Private " :
01761                           " Unknown");
01762 
01763             if (type->derivedFrom[i].type)
01764                 std::cout << type->derivedFrom[i].type;
01765             else
01766                 std::cout << " Unknown";
01767 
01768             std::cout << " " << type->derivedFrom[i].name;
01769             if (count-- > 1)
01770                 std::cout << ",";
01771         }
01772 
01773         std::cout << " )" << std::endl;
01774 
01775         std::cout << "    friendList[" << type->friendList.size() << "] = (";
01776 
01777         std::list<Type::FriendInfo>::const_iterator fii;
01778 
01779         count = type->friendList.size();
01780         for (fii = type->friendList.begin(); fii != type->friendList.end(); ++fii) {
01781             if (fii->type)
01782                 std::cout << fii->type;
01783             else
01784                 std::cout << " Unknown";
01785 
01786             std::cout << " " << fii->name;
01787             if (count-- > 1)
01788                 std::cout << ",";
01789         }
01790 
01791         std::cout << " )" << std::endl;
01792     }
01793 
01794     for (std::size_t i = 1; i < _variableList.size(); i++) {
01795         std::cout << "_variableList[" << i << "]: " << _variableList[i];
01796         if (_variableList[i]) {
01797             std::cout << " " << _variableList[i]->name() << " "
01798                       << _tokenizer->list.fileLine(_variableList[i]->nameToken());
01799         }
01800         std::cout << std::endl;
01801     }
01802 }
01803 
01804 //---------------------------------------------------------------------------
01805 
01806 void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *scope)
01807 {
01808     // check for non-empty argument list "( ... )"
01809     const Token * start = arg ? arg : argDef;
01810     if (start && start->link() != start->next() && !Token::simpleMatch(start, "( void )")) {
01811         unsigned int count = 0;
01812 
01813         for (const Token* tok = start->next(); tok; tok = tok->next()) {
01814             const Token* startTok = tok;
01815             const Token* endTok   = NULL;
01816             const Token* nameTok  = NULL;
01817 
01818             if (tok->str() == "," || tok->str() == ")")
01819                 return; // Syntax error
01820 
01821             do {
01822                 if (tok->varId() != 0) {
01823                     nameTok = tok;
01824                     endTok = tok->previous();
01825                 } else if (tok->str() == "[") {
01826                     // skip array dimension(s)
01827                     tok = tok->link();
01828                     while (tok->next()->str() == "[")
01829                         tok = tok->next()->link();
01830                 } else if (tok->str() == "<") {
01831                     bool success = tok->findClosingBracket(tok);
01832                     if (!tok || !success) // something is wrong so just bail out
01833                         return;
01834                 }
01835 
01836                 tok = tok->next();
01837 
01838                 if (!tok) // something is wrong so just bail
01839                     return;
01840             } while (tok->str() != "," && tok->str() != ")" && tok->str() != "=");
01841 
01842             const Token *typeTok = startTok->tokAt(startTok->str() == "const" ? 1 : 0);
01843             if (typeTok->str() == "struct")
01844                 typeTok = typeTok->next();
01845 
01846             // check for argument with no name or missing varid
01847             if (!endTok) {
01848                 if (tok->previous()->isName()) {
01849                     if (tok->previous() != typeTok) {
01850                         nameTok = tok->previous();
01851                         endTok = nameTok->previous();
01852 
01853                         if (hasBody)
01854                             symbolDatabase->debugMessage(nameTok, "Function::addArguments found argument \'" + nameTok->str() + "\' with varid 0.");
01855                     } else
01856                         endTok = startTok;
01857                 } else
01858                     endTok = tok->previous();
01859             }
01860 
01861             const ::Type *argType = NULL;
01862             if (!typeTok->isStandardType()) {
01863                 argType = symbolDatabase->findVariableType(scope, typeTok);
01864                 if (!argType) {
01865                     // look for variable type in any using namespace in this scope or above
01866                     const Scope *parent = scope;
01867                     while (parent) {
01868                         for (std::list<Scope::UsingInfo>::const_iterator ui = scope->usingList.begin();
01869                              ui != scope->usingList.end(); ++ui) {
01870                             if (ui->scope) {
01871                                 argType = symbolDatabase->findVariableType(ui->scope, typeTok);
01872                                 if (argType)
01873                                     break;
01874                             }
01875                         }
01876                         parent = parent->nestedIn;
01877                     }
01878                 }
01879             }
01880 
01881             // skip default values
01882             if (tok->str() == "=") {
01883                 while (tok->str() != "," && tok->str() != ")") {
01884                     if (tok->link() && Token::Match(tok, "[{[(<]"))
01885                         tok = tok->link();
01886                     tok = tok->next();
01887                 }
01888             }
01889 
01890             argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, argType, functionScope));
01891 
01892             if (tok->str() == ")")
01893                 break;
01894         }
01895 
01896         // count deafult arguments
01897         for (const Token* tok = argDef->next(); tok && tok != argDef->link(); tok = tok->next()) {
01898             if (tok->str() == "=")
01899                 initArgCount++;
01900         }
01901     }
01902 }
01903 
01904 bool Function::isImplicitlyVirtual(bool defaultVal) const
01905 {
01906     if (isVirtual)
01907         return true;
01908     else if (access == Private || access == Public || access == Protected) {
01909         bool safe = true;
01910         bool hasVirt = isImplicitlyVirtual_rec(nestedIn->definedType, safe);
01911         if (hasVirt)
01912             return true;
01913         else if (safe)
01914             return false;
01915         else
01916             return defaultVal;
01917     } else
01918         return false;
01919 }
01920 
01921 bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const
01922 {
01923     // check each base class
01924     for (unsigned int i = 0; i < baseType->derivedFrom.size(); ++i) {
01925         // check if base class exists in database
01926         if (baseType->derivedFrom[i].type && baseType->derivedFrom[i].type->classScope) {
01927             const Scope *parent = baseType->derivedFrom[i].type->classScope;
01928 
01929             std::list<Function>::const_iterator func;
01930 
01931             // check if function defined in base class
01932             for (func = parent->functionList.begin(); func != parent->functionList.end(); ++func) {
01933                 if (func->isVirtual && func->tokenDef->str() == tokenDef->str()) { // Base is virtual and of same name
01934                     const Token *temp1 = func->tokenDef->previous();
01935                     const Token *temp2 = tokenDef->previous();
01936                     bool returnMatch = true;
01937 
01938                     // check for matching return parameters
01939                     while (temp1->str() != "virtual") {
01940                         if (temp1->str() != temp2->str()) {
01941                             returnMatch = false;
01942                             break;
01943                         }
01944 
01945                         temp1 = temp1->previous();
01946                         temp2 = temp2->previous();
01947                     }
01948 
01949                     // check for matching function parameters
01950                     if (returnMatch && argsMatch(baseType->classScope, func->argDef, argDef, "", 0)) {
01951                         return true;
01952                     }
01953                 }
01954             }
01955 
01956             if (!baseType->derivedFrom[i].type->derivedFrom.empty())
01957                 if (isImplicitlyVirtual_rec(baseType->derivedFrom[i].type, safe))
01958                     return true;
01959         } else {
01960             // unable to find base class so assume it has no virtual function
01961             safe = false;
01962             return false;
01963         }
01964     }
01965     return false;
01966 }
01967 
01968 const Variable* Function::getArgumentVar(unsigned int num) const
01969 {
01970     for (std::list<Variable>::const_iterator i = argumentList.begin(); i != argumentList.end(); ++i) {
01971         if (i->index() == num)
01972             return(&*i);
01973         else if (i->index() > num)
01974             return 0;
01975     }
01976     return 0;
01977 }
01978 
01979 
01980 //---------------------------------------------------------------------------
01981 
01982 Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_, ScopeType type_, const Token *start_) :
01983     check(check_),
01984     classDef(classDef_),
01985     classStart(start_),
01986     classEnd(start_->link()),
01987     nestedIn(nestedIn_),
01988     numConstructors(0),
01989     numCopyConstructors(0),
01990     type(type_),
01991     definedType(NULL),
01992     functionOf(NULL),
01993     function(NULL)
01994 {
01995 }
01996 
01997 Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_) :
01998     check(check_),
01999     classDef(classDef_),
02000     classStart(NULL),
02001     classEnd(NULL),
02002     nestedIn(nestedIn_),
02003     numConstructors(0),
02004     numCopyConstructors(0),
02005     definedType(NULL),
02006     functionOf(NULL),
02007     function(NULL)
02008 {
02009     const Token *nameTok = classDef;
02010     if (!classDef) {
02011         type = Scope::eGlobal;
02012     } else if (classDef->str() == "class") {
02013         type = Scope::eClass;
02014         nameTok = nameTok->next();
02015     } else if (classDef->str() == "struct") {
02016         type = Scope::eStruct;
02017         nameTok = nameTok->next();
02018     } else if (classDef->str() == "union") {
02019         type = Scope::eUnion;
02020         nameTok = nameTok->next();
02021     } else if (classDef->str() == "namespace") {
02022         type = Scope::eNamespace;
02023         nameTok = nameTok->next();
02024     } else {
02025         type = Scope::eFunction;
02026     }
02027     // skip over qualification if present
02028     if (nameTok && nameTok->str() == "::")
02029         nameTok = nameTok->next();
02030     while (nameTok && Token::Match(nameTok, "%type% ::"))
02031         nameTok = nameTok->tokAt(2);
02032     if (nameTok && nameTok->str() != "{") // anonymous and unnamed structs/unions don't have a name
02033         className = nameTok->str();
02034 }
02035 
02036 bool Scope::hasDefaultConstructor() const
02037 {
02038     if (numConstructors) {
02039         std::list<Function>::const_iterator func;
02040 
02041         for (func = functionList.begin(); func != functionList.end(); ++func) {
02042             if (func->type == Function::eConstructor && func->argCount() == 0)
02043                 return true;
02044         }
02045     }
02046     return false;
02047 }
02048 
02049 AccessControl Scope::defaultAccess() const
02050 {
02051     switch (type) {
02052     case eGlobal:
02053         return Global;
02054     case eClass:
02055         return Private;
02056     case eStruct:
02057         return Public;
02058     case eUnion:
02059         return Public;
02060     case eNamespace:
02061         return Namespace;
02062     default:
02063         return Local;
02064     }
02065 }
02066 
02067 // Get variable list..
02068 void Scope::getVariableList()
02069 {
02070     AccessControl varaccess = defaultAccess();
02071     const Token *start;
02072     unsigned int level = 1;
02073 
02074     if (classStart)
02075         start = classStart->next();
02076 
02077     // global scope
02078     else if (className.empty())
02079         start = check->_tokenizer->tokens();
02080 
02081     // forward declaration
02082     else
02083         return;
02084 
02085     for (const Token *tok = start; tok; tok = tok->next()) {
02086         // end of scope?
02087         if (tok->str() == "}") {
02088             level--;
02089             if (level == 0)
02090                 break;
02091         }
02092 
02093         // syntax error?
02094         else if (tok->next() == NULL)
02095             break;
02096 
02097         // Is it a function?
02098         else if (tok->str() == "{") {
02099             tok = tok->link();
02100             // syntax error?
02101             if (!tok)
02102                 return;
02103             continue;
02104         }
02105 
02106         // Is it a nested class or structure?
02107         else if (Token::Match(tok, "class|struct|union|namespace %type% :|{")) {
02108             tok = tok->tokAt(2);
02109             while (tok && tok->str() != "{")
02110                 tok = tok->next();
02111             if (tok) {
02112                 // skip implementation
02113                 tok = tok->link();
02114                 continue;
02115             } else
02116                 break;
02117         } else if (Token::Match(tok, "struct|union {") && Token::Match(tok->next()->link(), "} %var% ;|[")) {
02118             tok = tok->next()->link()->tokAt(2);
02119             continue;
02120         } else if (Token::Match(tok, "struct|union {") && Token::simpleMatch(tok->next()->link(), "} ;")) {
02121             level++;
02122             tok = tok->next();
02123             continue;
02124         }
02125 
02126         // Borland C++: Skip all variables in the __published section.
02127         // These are automatically initialized.
02128         else if (tok->str() == "__published:") {
02129             for (; tok; tok = tok->next()) {
02130                 if (tok->str() == "{")
02131                     tok = tok->link();
02132                 if (Token::Match(tok->next(), "private:|protected:|public:"))
02133                     break;
02134             }
02135             if (tok)
02136                 continue;
02137             else
02138                 break;
02139         }
02140 
02141         // "private:" "public:" "protected:" etc
02142         else if (tok->str() == "public:") {
02143             varaccess = Public;
02144             continue;
02145         } else if (tok->str() == "protected:") {
02146             varaccess = Protected;
02147             continue;
02148         } else if (tok->str() == "private:") {
02149             varaccess = Private;
02150             continue;
02151         }
02152 
02153         // Is it a forward declaration?
02154         else if (Token::Match(tok, "class|struct|union %var% ;")) {
02155             tok = tok->tokAt(2);
02156             continue;
02157         }
02158 
02159         // Borland C++: Ignore properties..
02160         else if (tok->str() == "__property")
02161             continue;
02162 
02163         // skip return and delete
02164         else if (Token::Match(tok, "return|delete")) {
02165             while (tok->next() && tok->next()->str() != ";")
02166                 tok = tok->next();
02167             continue;
02168         }
02169 
02170         // Search for start of statement..
02171         else if (tok->previous() && !Token::Match(tok->previous(), ";|{|}|public:|protected:|private:"))
02172             continue;
02173         else if (Token::Match(tok, ";|{|}"))
02174             continue;
02175         else if (Token::Match(tok, "goto %var% ;")) {
02176             tok = tok->tokAt(2);
02177             continue;
02178         }
02179 
02180         tok = checkVariable(tok, varaccess);
02181 
02182         if (!tok)
02183             break;
02184     }
02185 }
02186 
02187 const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess)
02188 {
02189     // This is the start of a statement
02190     const Token *vartok = NULL;
02191     const Token *typetok = NULL;
02192 
02193     // Is it a throw..?
02194     if (Token::Match(tok, "throw %any% (") &&
02195         Token::simpleMatch(tok->linkAt(2), ") ;")) {
02196         return tok->linkAt(2);
02197     } else if ((Token::Match(tok, "throw %any% :: %any% (") &&
02198                 Token::simpleMatch(tok->linkAt(4), ") ;"))) {
02199         return tok->linkAt(4);
02200     }
02201 
02202     // friend?
02203     if (Token::Match(tok, "friend %type%") && tok->next()->varId() == 0) {
02204         const Token *next = Token::findmatch(tok->tokAt(2), ";|{");
02205         if (next && next->str() == "{")
02206             next = next->link();
02207         return next;
02208     }
02209 
02210     // skip const|static|mutable|extern
02211     while (Token::Match(tok, "const|static|mutable|extern")) {
02212         tok = tok->next();
02213     }
02214 
02215     // the start of the type tokens does not include the above modifiers
02216     const Token *typestart = tok;
02217 
02218     if (Token::Match(tok, "struct|union")) {
02219         tok = tok->next();
02220     }
02221 
02222     if (tok && isVariableDeclaration(tok, vartok, typetok)) {
02223         // If the vartok was set in the if-blocks above, create a entry for this variable..
02224         tok = vartok->next();
02225         while (tok && tok->str() == "[")
02226             tok = tok->link()->next();
02227 
02228         if (vartok->varId() == 0 && !vartok->isBoolean())
02229             check->debugMessage(vartok, "Scope::checkVariable found variable \'" + vartok->str() + "\' with varid 0.");
02230 
02231         const Type *vType = NULL;
02232 
02233         if (typetok) {
02234             vType = check->findVariableType(this, typetok);
02235             if (!vType) {
02236                 // look for variable type in any using namespace in this scope or above
02237                 const Scope *parent = this;
02238                 while (parent) {
02239                     for (std::list<Scope::UsingInfo>::const_iterator ui = parent->usingList.begin();
02240                          ui != parent->usingList.end(); ++ui) {
02241                         if (ui->scope) {
02242                             vType = check->findVariableType(ui->scope, typetok);
02243                             if (vType)
02244                                 break;
02245                         }
02246                     }
02247                     parent = parent->nestedIn;
02248                 }
02249             }
02250         }
02251 
02252         addVariable(vartok, typestart, vartok->previous(), varaccess, vType, this);
02253     }
02254 
02255     return tok;
02256 }
02257 
02258 const Variable *Scope::getVariable(const std::string &varname) const
02259 {
02260     std::list<Variable>::const_iterator iter;
02261 
02262     for (iter = varlist.begin(); iter != varlist.end(); ++iter) {
02263         if (iter->name() == varname)
02264             return &*iter;
02265     }
02266 
02267     return NULL;
02268 }
02269 
02270 static const Token* skipScopeIdentifiers(const Token* tok)
02271 {
02272     if (tok && tok->str() == "::") {
02273         tok = tok->next();
02274     }
02275     while (Token::Match(tok, "%type% ::")) {
02276         tok = tok->tokAt(2);
02277     }
02278 
02279     return tok;
02280 }
02281 
02282 static const Token* skipPointers(const Token* tok)
02283 {
02284     while (Token::Match(tok, "*|&")) {
02285         tok = tok->next();
02286     }
02287 
02288     return tok;
02289 }
02290 
02291 bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const
02292 {
02293     if (tok && tok->str() == "throw" && check->_tokenizer->isCPP())
02294         return false;
02295 
02296     const Token* localTypeTok = skipScopeIdentifiers(tok);
02297     const Token* localVarTok = NULL;
02298 
02299     if (Token::Match(localTypeTok, "%type% <")) {
02300         const Token* closeTok = NULL;
02301         bool found = localTypeTok->next()->findClosingBracket(closeTok);
02302         if (found) {
02303             localVarTok = skipPointers(closeTok->next());
02304 
02305             if (Token::Match(localVarTok, ":: %type% %var% ;|=")) {
02306                 localTypeTok = localVarTok->next();
02307                 localVarTok = localVarTok->tokAt(2);
02308             }
02309         }
02310     } else if (Token::Match(localTypeTok, "%type%")) {
02311         localVarTok = skipPointers(localTypeTok->strAt(1)=="const"?localTypeTok->tokAt(2):localTypeTok->next());
02312     }
02313 
02314     if (localVarTok && localVarTok->str() == "const")
02315         localVarTok = localVarTok->next();
02316 
02317     if (Token::Match(localVarTok, "%var% ;|=")) {
02318         vartok = localVarTok;
02319         typetok = localTypeTok;
02320     } else if (Token::Match(localVarTok, "%var% [") && localVarTok->str() != "operator") {
02321         vartok = localVarTok;
02322         typetok = localTypeTok;
02323     } else if ((isLocal() || type == Scope::eFunction) &&
02324                Token::Match(localVarTok, "%var% (") &&
02325                Token::simpleMatch(localVarTok->next()->link(), ") ;")) {
02326         vartok = localVarTok;
02327         typetok = localTypeTok;
02328     } else if (type == eCatch &&
02329                (Token::Match(localTypeTok, "%var% )") ||
02330                 Token::Match(localTypeTok, "%var% &| %var% )"))) {
02331         vartok = localVarTok;
02332         typetok = localTypeTok;
02333     }
02334 
02335     return NULL != vartok;
02336 }
02337 
02338 
02339 
02340 //---------------------------------------------------------------------------
02341 
02342 const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *typeTok) const
02343 {
02344     std::list<Type>::const_iterator type;
02345 
02346     for (type = typeList.begin(); type != typeList.end(); ++type) {
02347         // do the names match?
02348         if (type->name() == typeTok->str()) {
02349             // check if type does not have a namespace
02350             if (typeTok->strAt(-1) != "::") {
02351                 const Scope *parent = start;
02352 
02353                 // check if in same namespace
02354                 while (parent) {
02355                     // out of line class function belongs to class
02356                     if (parent->type == Scope::eFunction && parent->functionOf)
02357                         parent = parent->functionOf;
02358                     else if (parent != type->enclosingScope)
02359                         parent = parent->nestedIn;
02360                     else
02361                         break;
02362                 }
02363 
02364                 if (type->enclosingScope == parent)
02365                     return &(*type);
02366             }
02367 
02368             // type has a namespace
02369             else {
02370                 // FIXME check if namespace path matches supplied path
02371                 return &(*type);
02372             }
02373         }
02374     }
02375 
02376     return NULL;
02377 }
02378 
02379 //---------------------------------------------------------------------------
02380 
02381 /** @todo This function only counts the number of arguments in the function call.
02382     It does not take into account function constantness.
02383     It does not take into account argument types.  This can be difficult because of promotion and conversion operators and casts and because the argument can also be a function call.
02384  */
02385 const Function* Scope::findFunction(const Token *tok) const
02386 {
02387     for (std::list<Function>::const_iterator i = functionList.begin(); i != functionList.end(); ++i) {
02388         if (i->tokenDef->str() == tok->str()) {
02389             const Function *func = &*i;
02390             if (tok->strAt(1) == "(" && tok->tokAt(2)) {
02391                 // check if function has no arguments
02392                 if (tok->strAt(2) == ")" && (func->argCount() == 0 || func->minArgCount() == 0))
02393                     return func;
02394 
02395                 // check the arguments
02396                 unsigned int args = 0;
02397                 const Token *arg = tok->tokAt(2);
02398                 while (arg && arg->str() != ")") {
02399                     /** @todo check argument type for match */
02400                     args++;
02401                     arg = arg->nextArgument();
02402                 }
02403 
02404                 // check for argument count match or default arguments
02405                 if (args == func->argCount() ||
02406                     (args < func->argCount() && args >= func->minArgCount()))
02407                     return func;
02408             }
02409         }
02410     }
02411 
02412     return 0;
02413 }
02414 
02415 //---------------------------------------------------------------------------
02416 
02417 const Function* SymbolDatabase::findFunction(const Token *tok) const
02418 {
02419     // find the scope this function is in
02420     const Scope *currScope = tok->scope();
02421     while (currScope && currScope->isExecutable()) {
02422         if (currScope->functionOf)
02423             currScope = currScope->functionOf;
02424         else
02425             currScope = currScope->nestedIn;
02426     }
02427 
02428     // check for a qualified name and use it when given
02429     if (tok->strAt(-1) == "::") {
02430         // find start of qualified function name
02431         const Token *tok1 = tok;
02432 
02433         while (Token::Match(tok1->tokAt(-2), "%type% ::"))
02434             tok1 = tok1->tokAt(-2);
02435 
02436         // check for global scope
02437         if (tok1->strAt(-1) == "::") {
02438             currScope = &scopeList.front();
02439 
02440             currScope = currScope->findRecordInNestedList(tok1->str());
02441         }
02442 
02443         // find start of qualification
02444         else {
02445             while (currScope) {
02446                 if (currScope->className == tok1->str())
02447                     break;
02448                 else {
02449                     const Scope *scope = currScope->findRecordInNestedList(tok1->str());
02450 
02451                     if (scope) {
02452                         currScope = scope;
02453                         break;
02454                     } else
02455                         currScope = currScope->nestedIn;
02456                 }
02457             }
02458         }
02459 
02460         if (currScope) {
02461             while (currScope && !Token::Match(tok1, "%type% :: %any% (")) {
02462                 currScope = currScope->findRecordInNestedList(tok1->strAt(2));
02463                 tok1 = tok1->tokAt(2);
02464             }
02465 
02466             tok1 = tok1->tokAt(2);
02467 
02468             if (currScope && tok1)
02469                 return currScope->findFunction(tok1);
02470         }
02471     }
02472 
02473     // check for member function
02474     else if (tok->strAt(-1) == ".") {
02475         if (Token::Match(tok->tokAt(-2), "%var% .")) {
02476             const Token *tok1 = tok->tokAt(-2);
02477 
02478             if (tok1->varId()) {
02479                 const Variable *var = getVariableFromVarId(tok1->varId());
02480                 if (var && var->typeScope())
02481                     return var->typeScope()->findFunction(tok);
02482             }
02483         }
02484     }
02485 
02486     // check in enclosing scopes
02487     else {
02488         while (currScope) {
02489             const Function *func = currScope->findFunction(tok);
02490             if (func)
02491                 return func;
02492             currScope = currScope->nestedIn;
02493         }
02494     }
02495     return 0;
02496 }
02497 
02498 //---------------------------------------------------------------------------
02499 
02500 const Scope *SymbolDatabase::findScopeByName(const std::string& name) const
02501 {
02502     for (std::list<Scope>::const_iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
02503         if (it->className == name)
02504             return &*it;
02505     }
02506     return 0;
02507 }
02508 
02509 //---------------------------------------------------------------------------
02510 
02511 Scope *Scope::findInNestedList(const std::string & name)
02512 {
02513     std::list<Scope *>::iterator it;
02514 
02515     for (it = nestedList.begin(); it != nestedList.end(); ++it) {
02516         if ((*it)->className == name)
02517             return (*it);
02518     }
02519     return 0;
02520 }
02521 
02522 //---------------------------------------------------------------------------
02523 
02524 const Scope *Scope::findRecordInNestedList(const std::string & name) const
02525 {
02526     std::list<Scope *>::const_iterator it;
02527 
02528     for (it = nestedList.begin(); it != nestedList.end(); ++it) {
02529         if ((*it)->className == name && (*it)->type != eFunction)
02530             return (*it);
02531     }
02532     return 0;
02533 }
02534 
02535 //---------------------------------------------------------------------------
02536 
02537 const Type* Scope::findType(const std::string & name) const
02538 {
02539     std::list<Type*>::const_iterator it;
02540 
02541     for (it = definedTypes.begin(); it != definedTypes.end(); ++it) {
02542         if ((*it)->name() == name)
02543             return (*it);
02544     }
02545     return 0;
02546 }
02547 
02548 //---------------------------------------------------------------------------
02549 
02550 Scope *Scope::findInNestedListRecursive(const std::string & name)
02551 {
02552     std::list<Scope *>::iterator it;
02553 
02554     for (it = nestedList.begin(); it != nestedList.end(); ++it) {
02555         if ((*it)->className == name)
02556             return (*it);
02557     }
02558 
02559     for (it = nestedList.begin(); it != nestedList.end(); ++it) {
02560         Scope *child = (*it)->findInNestedListRecursive(name);
02561         if (child)
02562             return child;
02563     }
02564     return 0;
02565 }
02566 
02567 //---------------------------------------------------------------------------
02568 
02569 const Function *Scope::getDestructor() const
02570 {
02571     std::list<Function>::const_iterator it;
02572     for (it = functionList.begin(); it != functionList.end(); ++it) {
02573         if (it->type == Function::eDestructor)
02574             return &(*it);
02575     }
02576     return 0;
02577 }
02578 
02579 //---------------------------------------------------------------------------
02580 
02581 unsigned int Scope::getNestedNonFunctions() const
02582 {
02583     unsigned int nested = 0;
02584     std::list<Scope *>::const_iterator ni;
02585     for (ni = nestedList.begin(); ni != nestedList.end(); ++ni) {
02586         if ((*ni)->type != Scope::eFunction)
02587             nested++;
02588     }
02589     return nested;
02590 }
02591 
02592 //---------------------------------------------------------------------------
02593 
02594 bool SymbolDatabase::isCPP() const
02595 {
02596     return _tokenizer->isCPP();
02597 }
02598 
02599 //---------------------------------------------------------------------------
02600 
02601 const Scope *SymbolDatabase::findScope(const Token *tok, const Scope *startScope) const
02602 {
02603     const Scope *scope = 0;
02604     // absolute path
02605     if (tok->str() == "::") {
02606         tok = tok->next();
02607         scope = &scopeList.front();
02608     }
02609     // relative path
02610     else if (tok->isName()) {
02611         scope = startScope;
02612     }
02613 
02614     while (scope && tok && tok->isName()) {
02615         if (tok->strAt(1) == "::") {
02616             scope = scope->findRecordInNestedList(tok->str());
02617             tok = tok->tokAt(2);
02618         } else
02619             return scope->findRecordInNestedList(tok->str());
02620     }
02621 
02622 
02623     // not a valid path
02624     return 0;
02625 }
02626 
02627 const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startScope) const
02628 {
02629     // absolute path - directly start in global scope
02630     if (startTok->str() == "::") {
02631         startTok = startTok->next();
02632         startScope = &scopeList.front();
02633     }
02634 
02635     const Token* tok = startTok;
02636     const Scope* scope = startScope;
02637 
02638     while (scope && tok && tok->isName()) {
02639         if (tok->strAt(1) == "::") {
02640             scope = scope->findRecordInNestedList(tok->str());
02641             if (scope) {
02642                 tok = tok->tokAt(2);
02643             } else {
02644                 startScope = startScope->nestedIn;
02645                 if (!startScope)
02646                     break;
02647                 scope = startScope;
02648                 tok = startTok;
02649             }
02650         } else
02651             return scope->findType(tok->str());
02652     }
02653 
02654 
02655     // not a valid path
02656     return 0;
02657 }