LCOV - code coverage report
Current view: top level - lib - checkmemoryleak.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 1464 1559 93.9 %
Date: 2013-03-30 Functions: 44 44 100.0 %
Branches: 2302 3450 66.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Cppcheck - A tool for static C/C++ code analysis
       3                 :            :  * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
       4                 :            :  *
       5                 :            :  * This program is free software: you can redistribute it and/or modify
       6                 :            :  * it under the terms of the GNU General Public License as published by
       7                 :            :  * the Free Software Foundation, either version 3 of the License, or
       8                 :            :  * (at your option) any later version.
       9                 :            :  *
      10                 :            :  * This program is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13                 :            :  * GNU General Public License for more details.
      14                 :            :  *
      15                 :            :  * You should have received a copy of the GNU General Public License
      16                 :            :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17                 :            :  */
      18                 :            : 
      19                 :            : 
      20                 :            : #include "checkmemoryleak.h"
      21                 :            : #include "symboldatabase.h"
      22                 :            : #include "mathlib.h"
      23                 :            : #include "tokenize.h"
      24                 :            : 
      25                 :            : #include <algorithm>
      26                 :            : #include <cstring>
      27                 :            : #include <cstdlib>
      28                 :            : #include <sstream>
      29                 :            : #include <set>
      30                 :            : #include <stack>
      31                 :            : 
      32                 :            : //---------------------------------------------------------------------------
      33                 :            : 
      34                 :            : // Register this check class (by creating a static instance of it)
      35                 :            : namespace {
      36                 :         45 :     CheckMemoryLeakInFunction instance1;
      37                 :         45 :     CheckMemoryLeakInClass instance2;
      38                 :         45 :     CheckMemoryLeakStructMember instance3;
      39                 :         45 :     CheckMemoryLeakNoVar instance4;
      40                 :            : }
      41                 :            : 
      42                 :            : /**
      43                 :            :  * Count function parameters
      44                 :            :  * \param tok Function name token before the '('
      45                 :            :  */
      46                 :       5580 : static unsigned int countParameters(const Token *tok)
      47                 :            : {
      48                 :       5580 :     tok = tok->tokAt(2);
      49         [ +  + ]:       5580 :     if (tok->str() == ")")
      50                 :       1485 :         return 0;
      51                 :            : 
      52                 :       4095 :     unsigned int numpar = 1;
      53         [ +  + ]:       5760 :     while (NULL != (tok = tok->nextArgument()))
      54                 :       1665 :         numpar++;
      55                 :            : 
      56                 :       5580 :     return numpar;
      57                 :            : }
      58                 :            : 
      59                 :            : 
      60                 :            : /** List of functions that can be ignored when searching for memory leaks.
      61                 :            :  * These functions don't take the address of the given pointer
      62                 :            :  * This list needs to be alphabetically sorted so we can run bsearch on it.
      63                 :            :  * This list contains function names with const parameters e.g.: atof(const char *)
      64                 :            :  * Reference: http://www.aquaphoenix.com/ref/gnu_c_library/libc_492.html#SEC492
      65                 :            :  */
      66                 :            : static const char * const call_func_white_list[] = {
      67                 :            :     "_open", "_wopen", "access", "adjtime", "asctime", "asctime_r", "asprintf", "assert"
      68                 :            :     , "atof", "atoi", "atol", "chdir", "chmod", "chown"
      69                 :            :     , "clearerr", "creat", "ctime", "ctime_r", "delete", "execl", "execle"
      70                 :            :     , "execlp", "execv", "execve", "fchmod", "fclose", "fcntl"
      71                 :            :     , "fdatasync", "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets"
      72                 :            :     , "flock", "fmemopen", "fnmatch", "fopen", "fopencookie", "for", "fprintf", "fputc", "fputs", "fread", "free"
      73                 :            :     , "freopen", "fscanf", "fseek", "fseeko", "fsetpos", "fstat", "fsync", "ftell", "ftello"
      74                 :            :     , "ftruncate", "fwrite", "getc", "getenv","getgrnam", "gethostbyaddr", "gethostbyname", "getnetbyname"
      75                 :            :     , "getopt", "getopt_long", "getprotobyname", "getpwnam", "gets", "getservbyname", "getservbyport"
      76                 :            :     , "glob", "gmtime", "gmtime_r", "if", "index", "inet_addr", "inet_aton", "inet_network", "initgroups", "ioctl"
      77                 :            :     , "link", "localtime", "localtime_r"
      78                 :            :     , "lockf", "lseek", "lstat", "mblen", "mbstowcs", "mbtowc", "memchr", "memcmp", "memcpy", "memmove", "memset"
      79                 :            :     , "mkdir", "mkfifo", "mknod", "mkstemp"
      80                 :            :     , "obstack_printf", "obstack_vprintf", "open", "opendir", "parse_printf_format", "pathconf"
      81                 :            :     , "perror", "popen" ,"posix_fadvise", "posix_fallocate", "pread"
      82                 :            :     , "printf", "psignal", "puts", "pwrite", "qsort", "read", "readahead", "readdir", "readdir_r"
      83                 :            :     , "readlink", "readv"
      84                 :            :     , "realloc", "regcomp", "remove", "rename", "return", "rewind", "rewinddir", "rindex"
      85                 :            :     , "rmdir" ,"scandir", "scanf", "seekdir"
      86                 :            :     , "setbuf", "setbuffer", "sethostname", "setlinebuf", "setlocale" ,"setvbuf", "sizeof" ,"snprintf", "sprintf", "sscanf"
      87                 :            :     , "stat", "stpcpy", "strcasecmp", "strcat", "strchr", "strcmp", "strcoll"
      88                 :            :     , "strcpy", "strcspn", "strdup", "stricmp", "strlen", "strncasecmp", "strncat", "strncmp"
      89                 :            :     , "strncpy", "strpbrk","strrchr", "strspn", "strstr", "strtod", "strtok", "strtol", "strtoul", "strxfrm", "switch"
      90                 :            :     , "symlink", "sync_file_range", "system", "telldir", "tempnam", "time", "typeid", "unlink"
      91                 :            :     , "utime", "utimes", "vasprintf", "vfprintf", "vfscanf", "vprintf"
      92                 :            :     , "vscanf", "vsnprintf", "vsprintf", "vsscanf", "while", "wordexp","write", "writev"
      93                 :            : };
      94                 :            : 
      95                 :            : extern "C"
      96                 :            : {
      97                 :            :     int call_func_white_list_compare(const void *a, const void *b);
      98                 :            : 
      99                 :     340308 :     int call_func_white_list_compare(const void *a, const void *b)
     100                 :            :     {
     101                 :     340308 :         return std::strcmp((const char *)a, *(const char * const *)b);
     102                 :            :     }
     103                 :            : }
     104                 :            : 
     105                 :            : //---------------------------------------------------------------------------
     106                 :            : 
     107                 :        765 : bool CheckMemoryLeak::isclass(const Token *tok, unsigned int varid) const
     108                 :            : {
     109         [ +  + ]:        765 :     if (tok->isStandardType())
     110                 :        270 :         return false;
     111                 :            : 
     112                 :        495 :     const Variable * var = tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
     113                 :            : 
     114                 :            :     // return false if the type is a simple record type without side effects
     115                 :            :     // a type that has no side effects (no constructors and no members with constructors)
     116                 :            :     /** @todo false negative: check base class for side effects */
     117                 :            :     /** @todo false negative: check constructors for side effects */
     118 [ +  - ][ +  + ]:        990 :     if (var && var->typeScope() && var->typeScope()->numConstructors == 0 &&
           [ +  +  +  +  
             +  -  +  - ]
                 [ +  + ]
     119                 :        270 :         (var->typeScope()->varlist.empty() || var->type()->needInitialization == Type::True) &&
     120                 :        225 :         var->type()->derivedFrom.empty())
     121                 :        225 :         return false;
     122                 :            : 
     123                 :        765 :     return true;
     124                 :            : }
     125                 :            : //---------------------------------------------------------------------------
     126                 :            : 
     127                 :      27621 : CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, unsigned int varid, std::list<const Function*> *callstack) const
     128                 :            : {
     129                 :            :     // What we may have...
     130                 :            :     //     * var = (char *)malloc(10);
     131                 :            :     //     * var = new char[10];
     132                 :            :     //     * var = strdup("hello");
     133                 :            :     //     * var = strndup("hello", 3);
     134 [ +  - ][ -  + ]:      27621 :     if (tok2 && tok2->str() == "(") {
                 [ -  + ]
     135                 :          0 :         tok2 = tok2->link();
     136         [ #  # ]:          0 :         tok2 = tok2 ? tok2->next() : NULL;
     137                 :            :     }
     138         [ -  + ]:      27621 :     if (! tok2)
     139                 :          0 :         return No;
     140         [ +  + ]:      27621 :     if (! tok2->isName())
     141                 :       1620 :         return No;
     142                 :            : 
     143         [ +  + ]:      26001 :     if (!Token::Match(tok2, "%type%|%var% ::|. %type%")) {
     144                 :            :         // Does tok2 point on "malloc", "strdup" or "kmalloc"..
     145                 :            :         static const char * const mallocfunc[] = {
     146                 :            :             "malloc",
     147                 :            :             "calloc",
     148                 :            :             "strdup",
     149                 :            :             "strndup",
     150                 :            :             "kmalloc",
     151                 :            :             "kzalloc",
     152                 :            :             "kcalloc"
     153                 :            :         };
     154         [ +  + ]:     164016 :         for (unsigned int i = 0; i < sizeof(mallocfunc)/sizeof(*mallocfunc); i++) {
     155         [ +  + ]:     144486 :             if (tok2->str() == mallocfunc[i])
     156                 :       6381 :                 return Malloc;
     157                 :            :         }
     158                 :            : 
     159                 :            :         // Using realloc..
     160 [ +  + ][ +  + ]:      19530 :         if (varid && Token::Match(tok2, "realloc ( %any% ,") && tok2->tokAt(2)->varId() != varid)
         [ +  + ][ +  + ]
     161                 :        360 :             return Malloc;
     162                 :            : 
     163                 :            :         // Does tok2 point on "g_malloc", "g_strdup", ..
     164                 :            :         static const char * const gmallocfunc[] = {
     165                 :            :             "g_new",
     166                 :            :             "g_new0",
     167                 :            :             "g_try_new",
     168                 :            :             "g_try_new0",
     169                 :            :             "g_malloc",
     170                 :            :             "g_malloc0",
     171                 :            :             "g_try_malloc",
     172                 :            :             "g_try_malloc0",
     173                 :            :             "g_strdup",
     174                 :            :             "g_strndup",
     175                 :            :             "g_strdup_printf"
     176                 :            :         };
     177         [ +  + ]:     229860 :         for (unsigned int i = 0; i < sizeof(gmallocfunc)/sizeof(*gmallocfunc); i++) {
     178         [ +  + ]:     210780 :             if (tok2->str() == gmallocfunc[i])
     179                 :         90 :                 return gMalloc;
     180                 :            :         }
     181                 :            : 
     182   [ +  +  +  +  :      53370 :         if (Token::Match(tok2, "new struct| %type% [;()]") ||
           +  + ][ +  + ]
     183                 :      17235 :             Token::Match(tok2, "new ( std :: nothrow ) struct| %type% [;()]") ||
     184                 :      17055 :             Token::Match(tok2, "new ( nothrow ) struct| %type% [;()]"))
     185                 :       2160 :             return New;
     186                 :            : 
     187   [ +  +  +  +  :      38970 :         if (Token::Match(tok2, "new struct| %type% [") ||
           +  + ][ +  + ]
     188                 :      11115 :             Token::Match(tok2, "new ( std :: nothrow ) struct| %type% [") ||
     189                 :      10935 :             Token::Match(tok2, "new ( nothrow ) struct| %type% ["))
     190                 :       6030 :             return NewArray;
     191                 :            : 
     192         [ +  + ]:      10890 :         if (Token::Match(tok2, "fopen|tmpfile|g_fopen ("))
     193                 :        900 :             return File;
     194                 :            : 
     195         [ +  + ]:       9990 :         if (standards.posix) {
     196         [ +  + ]:       9855 :             if (Token::Match(tok2, "open|openat|creat|mkstemp|mkostemp (")) {
     197                 :            :                 // simple sanity check of function parameters..
     198                 :            :                 // TODO: Make such check for all these functions
     199                 :       1080 :                 unsigned int num = countParameters(tok2);
     200 [ +  + ][ +  + ]:       1080 :                 if (tok2->str() == "open" && num != 2 && num != 3)
         [ +  - ][ +  + ]
     201                 :        135 :                     return No;
     202                 :            : 
     203                 :            :                 // is there a user function with this name?
     204 [ +  - ][ +  - ]:        945 :                 if (tokenizer && Token::findmatch(tokenizer->tokens(), ("%type% *|&| " + tok2->str()).c_str()))
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ -  + ][ #  # ]
     205                 :          0 :                     return No;
     206                 :        945 :                 return Fd;
     207                 :            :             }
     208                 :            : 
     209         [ +  + ]:       8775 :             if (Token::simpleMatch(tok2, "popen ("))
     210                 :        135 :                 return Pipe;
     211                 :            : 
     212         [ +  + ]:       8640 :             if (Token::Match(tok2, "opendir|fdopendir ("))
     213                 :        360 :                 return Dir;
     214                 :            :         }
     215                 :            : 
     216                 :            :     }
     217                 :            : 
     218         [ +  + ]:       8595 :     while (Token::Match(tok2,"%type%|%var% ::|. %type%"))
     219                 :         90 :         tok2 = tok2->tokAt(2);
     220                 :            : 
     221                 :            :     // User function
     222                 :       8505 :     const Function* func = tok2->function();
     223         [ +  + ]:       8505 :     if (func == NULL)
     224                 :       5355 :         return No;
     225                 :            : 
     226                 :            :     // Prevent recursion
     227 [ +  + ][ +  + ]:       3150 :     if (callstack && std::find(callstack->begin(), callstack->end(), func) != callstack->end())
                 [ +  + ]
     228                 :        360 :         return No;
     229                 :            : 
     230                 :       2790 :     std::list<const Function*> cs;
     231         [ +  + ]:       2790 :     if (!callstack)
     232                 :       2700 :         callstack = &cs;
     233                 :            : 
     234         [ +  - ]:       2790 :     callstack->push_back(func);
     235         [ +  - ]:      27621 :     return functionReturnType(func, callstack);
     236                 :            : }
     237                 :            : 
     238                 :            : 
     239                 :            : 
     240                 :            : 
     241                 :      14490 : CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok2, unsigned int varid) const
     242                 :            : {
     243                 :            :     // What we may have...
     244                 :            :     //     * var = (char *)realloc(..;
     245 [ +  - ][ -  + ]:      14490 :     if (tok2 && tok2->str() == "(") {
                 [ -  + ]
     246                 :          0 :         tok2 = tok2->link();
     247         [ #  # ]:          0 :         tok2 = tok2 ? tok2->next() : NULL;
     248                 :            :     }
     249         [ -  + ]:      14490 :     if (! tok2)
     250                 :          0 :         return No;
     251                 :            : 
     252 [ +  - ][ +  + ]:      14490 :     if (varid > 0 && ! Token::Match(tok2, "%var% ( %varid% [,)]", varid))
                 [ +  + ]
     253                 :      12060 :         return No;
     254                 :            : 
     255         [ +  + ]:       2430 :     if (tok2->str() == "realloc")
     256                 :        675 :         return Malloc;
     257                 :            : 
     258                 :            :     // GTK memory reallocation..
     259         [ -  + ]:       1755 :     if (Token::Match(tok2, "g_realloc|g_try_realloc|g_renew|g_try_renew"))
     260                 :          0 :         return gMalloc;
     261                 :            : 
     262                 :      14490 :     return No;
     263                 :            : }
     264                 :            : 
     265                 :            : 
     266                 :      63940 : CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok, unsigned int varid) const
     267                 :            : {
     268         [ +  + ]:      63940 :     if (Token::Match(tok, "delete %varid% ;", varid))
     269                 :        765 :         return New;
     270                 :            : 
     271         [ +  + ]:      63175 :     if (Token::Match(tok, "delete [ ] %varid% ;", varid))
     272                 :       3060 :         return NewArray;
     273                 :            : 
     274         [ -  + ]:      60115 :     if (Token::Match(tok, "delete ( %varid% ) ;", varid))
     275                 :          0 :         return New;
     276                 :            : 
     277         [ +  + ]:      60115 :     if (Token::Match(tok, "delete [ ] ( %varid% ) ;", varid))
     278                 :         45 :         return NewArray;
     279                 :            : 
     280 [ +  - ][ +  + ]:      60070 :     if (tok && tok->str() == "::")
                 [ +  + ]
     281                 :         45 :         tok = tok->next();
     282                 :            : 
     283   [ +  +  +  +  :     175530 :     if (Token::Match(tok, "free|kfree ( %varid% ) [;:]", varid) ||
           +  + ][ +  + ]
     284                 :      57775 :         Token::Match(tok, "free|kfree ( %varid% -", varid) ||
     285                 :      57685 :         Token::Match(tok, "realloc ( %varid% , 0 ) ;", varid))
     286                 :       2475 :         return Malloc;
     287                 :            : 
     288   [ +  +  -  + ]:     115145 :     if (Token::Match(tok, "g_free ( %varid% ) ;", varid) ||
                 [ +  + ]
     289                 :      57550 :         Token::Match(tok, "g_free ( %varid% -", varid))
     290                 :         45 :         return gMalloc;
     291                 :            : 
     292   [ +  +  +  + ]:     114560 :     if (Token::Match(tok, "fclose ( %varid% )", varid) ||
                 [ +  + ]
     293                 :      57010 :         Token::simpleMatch(tok, "fcloseall ( )"))
     294                 :        765 :         return File;
     295                 :            : 
     296         [ +  + ]:      56785 :     if (Token::Match(tok, "close ( %varid% )", varid))
     297                 :        585 :         return Fd;
     298                 :            : 
     299         [ +  + ]:      56200 :     if (Token::Match(tok, "pclose ( %varid% )", varid))
     300                 :        135 :         return Pipe;
     301                 :            : 
     302         [ +  + ]:      56065 :     if (Token::Match(tok, "closedir ( %varid% )", varid))
     303                 :         90 :         return Dir;
     304                 :            : 
     305                 :      63940 :     return No;
     306                 :            : }
     307                 :            : 
     308                 :     108900 : CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok, const std::string &varname) const
     309                 :            : {
     310 [ +  - ][ +  - ]:     108900 :     if (Token::Match(tok, std::string("delete " + varname + " [,;]").c_str()))
         [ +  - ][ +  - ]
                 [ +  + ]
     311                 :        450 :         return New;
     312                 :            : 
     313 [ +  - ][ +  - ]:     108450 :     if (Token::Match(tok, std::string("delete [ ] " + varname + " [,;]").c_str()))
         [ +  - ][ +  - ]
                 [ +  + ]
     314                 :        810 :         return NewArray;
     315                 :            : 
     316 [ +  - ][ +  - ]:     107640 :     if (Token::Match(tok, std::string("delete ( " + varname + " ) [,;]").c_str()))
         [ +  - ][ +  - ]
                 [ +  + ]
     317                 :         45 :         return New;
     318                 :            : 
     319 [ +  - ][ +  - ]:     107595 :     if (Token::Match(tok, std::string("delete [ ] ( " + varname + " ) [,;]").c_str()))
         [ +  - ][ +  - ]
                 [ -  + ]
     320                 :          0 :         return NewArray;
     321                 :            : 
     322 [ +  - ][ +  - ]:     429750 :     if (Token::simpleMatch(tok, std::string("free ( " + varname + " ) ;").c_str()) ||
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ #  # ]
                 [ #  # ]
     323 [ +  - ][ +  - ]:     214875 :         Token::simpleMatch(tok, std::string("kfree ( " + varname + " ) ;").c_str()) ||
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ #  # ][ #  # ]
     324 [ +  - ][ +  - ]:     214875 :         Token::simpleMatch(tok, std::string("realloc ( " + varname + " , 0 ) ;").c_str()))
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ #  # ][ #  # ]
     325                 :        315 :         return Malloc;
     326                 :            : 
     327 [ +  - ][ +  - ]:     107280 :     if (Token::simpleMatch(tok, std::string("g_free ( " + varname + " ) ;").c_str()))
         [ +  - ][ +  - ]
                 [ -  + ]
     328                 :          0 :         return gMalloc;
     329                 :            : 
     330 [ +  - ][ +  - ]:     214560 :     if (Token::simpleMatch(tok, std::string("fclose ( " + varname + " )").c_str()) ||
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
     331         [ +  - ]:     107280 :         Token::simpleMatch(tok, "fcloseall ( )"))
     332                 :          0 :         return File;
     333                 :            : 
     334 [ +  - ][ +  - ]:     107280 :     if (Token::simpleMatch(tok, std::string("close ( " + varname + " )").c_str()))
         [ +  - ][ +  - ]
                 [ -  + ]
     335                 :          0 :         return Fd;
     336                 :            : 
     337 [ +  - ][ +  - ]:     107280 :     if (Token::simpleMatch(tok, std::string("pclose ( " + varname + " )").c_str()))
         [ +  - ][ +  - ]
                 [ -  + ]
     338                 :          0 :         return Pipe;
     339                 :            : 
     340 [ +  - ][ +  - ]:     107280 :     if (Token::simpleMatch(tok, std::string("closedir ( " + varname + " )").c_str()))
         [ +  - ][ +  - ]
                 [ -  + ]
     341                 :          0 :         return Dir;
     342                 :            : 
     343                 :     108900 :     return No;
     344                 :            : }
     345                 :            : 
     346                 :            : //--------------------------------------------------------------------------
     347                 :            : 
     348                 :            : 
     349                 :            : //--------------------------------------------------------------------------
     350                 :            : 
     351                 :       5391 : void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype)
     352                 :            : {
     353 [ +  + ][ +  - ]:       5391 :     if (alloctype == CheckMemoryLeak::File ||
         [ +  + ][ +  + ]
     354                 :            :         alloctype == CheckMemoryLeak::Pipe ||
     355                 :            :         alloctype == CheckMemoryLeak::Fd   ||
     356                 :            :         alloctype == CheckMemoryLeak::Dir)
     357                 :        630 :         resourceLeakError(tok, varname);
     358                 :            :     else
     359                 :       4761 :         memleakError(tok, varname);
     360                 :       5391 : }
     361                 :            : //---------------------------------------------------------------------------
     362                 :            : 
     363                 :            : 
     364                 :       8262 : void CheckMemoryLeak::reportErr(const Token *tok, Severity::SeverityType severity, const std::string &id, const std::string &msg) const
     365                 :            : {
     366                 :       8262 :     std::list<const Token *> callstack;
     367                 :            : 
     368         [ +  + ]:       8262 :     if (tok)
     369         [ +  - ]:       7992 :         callstack.push_back(tok);
     370                 :            : 
     371         [ +  - ]:       8262 :     reportErr(callstack, severity, id, msg);
     372                 :       8262 : }
     373                 :            : 
     374                 :       8982 : void CheckMemoryLeak::reportErr(const std::list<const Token *> &callstack, Severity::SeverityType severity, const std::string &id, const std::string &msg) const
     375                 :            : {
     376         [ +  + ]:       8982 :     const ErrorLogger::ErrorMessage errmsg(callstack, tokenizer?&tokenizer->list:0, severity, id, msg, false);
     377                 :            : 
     378         [ +  - ]:       8982 :     if (errorLogger)
     379         [ +  - ]:       8982 :         errorLogger->reportErr(errmsg);
     380                 :            :     else
     381         [ #  # ]:       8982 :         Check::reportError(errmsg);
     382                 :       8982 : }
     383                 :            : 
     384                 :       6552 : void CheckMemoryLeak::memleakError(const Token *tok, const std::string &varname) const
     385                 :            : {
     386 [ +  - ][ +  - ]:       6552 :     reportErr(tok, Severity::error, "memleak", "Memory leak: " + varname);
                 [ +  - ]
     387                 :       6552 : }
     388                 :            : 
     389                 :        450 : void CheckMemoryLeak::memleakUponReallocFailureError(const Token *tok, const std::string &varname) const
     390                 :            : {
     391 [ +  - ][ +  - ]:        450 :     reportErr(tok, Severity::error, "memleakOnRealloc", "Common realloc mistake: \'" + varname + "\' nulled but not freed upon failure");
         [ +  - ][ +  - ]
                 [ +  - ]
     392                 :        450 : }
     393                 :            : 
     394                 :        675 : void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname) const
     395                 :            : {
     396         [ +  - ]:        675 :     std::string errmsg("Resource leak");
     397 [ +  - ][ +  - ]:        675 :     if (!varname.empty())
     398 [ +  - ][ +  - ]:        675 :         errmsg += ": " + varname;
                 [ +  - ]
     399 [ +  - ][ +  - ]:        675 :     reportErr(tok, Severity::error, "resourceLeak", errmsg);
                 [ +  - ]
     400                 :        675 : }
     401                 :            : 
     402                 :         90 : void CheckMemoryLeak::deallocDeallocError(const Token *tok, const std::string &varname) const
     403                 :            : {
     404 [ +  - ][ +  - ]:         90 :     reportErr(tok, Severity::error, "deallocDealloc", "Deallocating a deallocated pointer: " + varname);
                 [ +  - ]
     405                 :         90 : }
     406                 :            : 
     407                 :        405 : void CheckMemoryLeak::deallocuseError(const Token *tok, const std::string &varname) const
     408                 :            : {
     409 [ +  - ][ +  - ]:        405 :     reportErr(tok, Severity::error, "deallocuse", "Dereferencing '" + varname + "' after it is deallocated / released");
         [ +  - ][ +  - ]
                 [ +  - ]
     410                 :        405 : }
     411                 :            : 
     412                 :         90 : void CheckMemoryLeak::mismatchSizeError(const Token *tok, const std::string &sz) const
     413                 :            : {
     414 [ +  - ][ +  - ]:         90 :     reportErr(tok, Severity::error, "mismatchSize", "The given size " + sz + " is mismatching");
         [ +  - ][ +  - ]
                 [ +  - ]
     415                 :         90 : }
     416                 :            : 
     417                 :        720 : void CheckMemoryLeak::mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname) const
     418                 :            : {
     419 [ +  - ][ +  - ]:        720 :     reportErr(callstack, Severity::error, "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname);
                 [ +  - ]
     420                 :        720 : }
     421                 :            : 
     422                 :       2970 : CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* func, std::list<const Function*> *callstack) const
     423                 :            : {
     424 [ +  - ][ -  + ]:       2970 :     if (!func || !func->hasBody)
     425                 :          0 :         return No;
     426                 :            : 
     427                 :            :     // Get return pointer..
     428                 :       2970 :     unsigned int varid = 0;
     429                 :       2970 :     unsigned int indentlevel = 0;
     430         [ +  + ]:      32805 :     for (const Token *tok2 = func->functionScope->classStart; tok2 != func->functionScope->classEnd; tok2 = tok2->next()) {
     431         [ +  + ]:      31410 :         if (tok2->str() == "{")
     432                 :       3510 :             ++indentlevel;
     433         [ +  + ]:      27900 :         else if (tok2->str() == "}") {
     434         [ -  + ]:        450 :             if (indentlevel <= 1)
     435                 :          0 :                 return No;
     436                 :        450 :             --indentlevel;
     437                 :            :         }
     438         [ +  + ]:      31410 :         if (Token::Match(tok2, "return %var% ;")) {
     439         [ +  + ]:        900 :             if (indentlevel != 1)
     440                 :         90 :                 return No;
     441                 :        810 :             varid = tok2->next()->varId();
     442                 :        810 :             break;
     443         [ +  + ]:      30510 :         } else if (tok2->str() == "return") {
     444                 :       1260 :             AllocType allocType = getAllocationType(tok2->next(), 0, callstack);
     445         [ +  + ]:       1260 :             if (allocType != No)
     446                 :        675 :                 return allocType;
     447                 :            :         }
     448                 :            :     }
     449                 :            : 
     450                 :            :     // Not returning pointer value..
     451         [ +  + ]:       2205 :     if (varid == 0)
     452                 :       1395 :         return No;
     453                 :            : 
     454         [ +  + ]:        810 :     if (this != NULL) {
     455                 :            :         // If variable is not local then alloctype shall be "No"
     456                 :            :         // Todo: there can be false negatives about mismatching allocation/deallocation.
     457                 :            :         //       => Generate "alloc ; use ;" if variable is not local?
     458                 :        765 :         const Variable *var = tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
     459 [ +  - ][ +  + ]:        765 :         if (!var || !var->isLocal() || var->isStatic())
         [ +  + ][ +  + ]
     460                 :        180 :             return No;
     461                 :            :     }
     462                 :            : 
     463                 :            :     // Check if return pointer is allocated..
     464                 :        630 :     AllocType allocType = No;
     465         [ +  - ]:       9045 :     for (const Token* tok = func->functionScope->classStart; tok != func->functionScope->classEnd; tok = tok->next()) {
     466         [ +  + ]:       9045 :         if (Token::Match(tok, "%varid% =", varid)) {
     467                 :        720 :             allocType = getAllocationType(tok->tokAt(2), varid, callstack);
     468                 :            :         }
     469         [ +  + ]:       9045 :         if (Token::Match(tok, "= %varid% ;", varid)) {
     470                 :         90 :             return No;
     471                 :            :         }
     472         [ -  + ]:       8955 :         if (Token::Match(tok, "static %type% * %varid% [;{}=]", varid)) {
     473                 :          0 :             return No;
     474                 :            :         }
     475         [ +  + ]:       8955 :         if (Token::Match(tok, "[(,] %varid% [,)]", varid)) {
     476                 :         90 :             return No;
     477                 :            :         }
     478         [ +  + ]:       8865 :         if (tok->str() == "return")
     479                 :        450 :             return allocType;
     480                 :            :     }
     481                 :            : 
     482                 :       2970 :     return allocType;
     483                 :            : }
     484                 :            : 
     485                 :            : 
     486                 :        405 : const char *CheckMemoryLeak::functionArgAlloc(const Function *func, unsigned int targetpar, AllocType &allocType) const
     487                 :            : {
     488                 :        405 :     allocType = No;
     489                 :            : 
     490 [ +  - ][ -  + ]:        405 :     if (!func || !func->functionScope)
     491                 :          0 :         return "";
     492                 :            : 
     493                 :        405 :     std::list<Variable>::const_iterator arg = func->argumentList.begin();
     494         [ +  - ]:        450 :     for (; arg != func->argumentList.end(); ++arg) {
     495         [ +  + ]:        450 :         if (arg->index() == targetpar-1)
     496                 :        405 :             break;
     497                 :            :     }
     498         [ -  + ]:        405 :     if (arg == func->argumentList.end())
     499                 :          0 :         return "";
     500                 :            : 
     501                 :            :     // Is **
     502         [ -  + ]:        405 :     if (!arg->isPointer())
     503                 :          0 :         return "";
     504                 :        405 :     const Token* tok = arg->typeEndToken();
     505                 :        405 :     tok = tok->previous();
     506         [ -  + ]:        405 :     if (tok->str() != "*")
     507                 :          0 :         return "";
     508                 :            : 
     509                 :            :     // Check if pointer is allocated.
     510                 :        405 :     int realloc = 0;
     511 [ +  - ][ +  + ]:       3015 :     for (tok = func->functionScope->classStart; tok && tok != func->functionScope->classEnd; tok = tok->next()) {
                 [ +  + ]
     512         [ +  + ]:       2925 :         if (tok->varId() == arg->varId()) {
     513         [ +  + ]:        450 :             if (Token::Match(tok->tokAt(-3), "free ( * %var% )")) {
     514                 :         90 :                 realloc = 1;
     515                 :         90 :                 allocType = No;
     516         [ +  + ]:        360 :             } else if (Token::Match(tok->previous(), "* %var% =")) {
     517                 :        270 :                 allocType = getAllocationType(tok->tokAt(2), arg->varId());
     518         [ +  + ]:        270 :                 if (allocType == No) {
     519                 :         45 :                     allocType = getReallocationType(tok->tokAt(2), arg->varId());
     520                 :            :                 }
     521         [ +  + ]:        270 :                 if (allocType != No) {
     522         [ +  + ]:        225 :                     if (realloc)
     523                 :         90 :                         return "realloc";
     524                 :        135 :                     return "alloc";
     525                 :            :                 }
     526                 :            :             } else {
     527                 :            :                 // unhandled variable usage: bailout
     528                 :         90 :                 return "";
     529                 :            :             }
     530                 :            :         }
     531                 :            :     }
     532                 :            : 
     533                 :        405 :     return "";
     534                 :            : }
     535                 :            : 
     536                 :            : 
     537                 :      16666 : void CheckMemoryLeakInFunction::parse_noreturn()
     538                 :            : {
     539         [ +  - ]:      16666 :     if (noreturn.empty()) {
     540 [ +  - ][ +  - ]:      16666 :         noreturn.insert("exit");
                 [ +  - ]
     541 [ +  - ][ +  - ]:      16666 :         noreturn.insert("_exit");
                 [ +  - ]
     542 [ +  - ][ +  - ]:      16666 :         noreturn.insert("_Exit");
                 [ +  - ]
     543 [ +  - ][ +  - ]:      16666 :         noreturn.insert("abort");
                 [ +  - ]
     544 [ +  - ][ +  - ]:      16666 :         noreturn.insert("err");
                 [ +  - ]
     545 [ +  - ][ +  - ]:      16666 :         noreturn.insert("verr");
                 [ +  - ]
     546 [ +  - ][ +  - ]:      16666 :         noreturn.insert("errx");
                 [ +  - ]
     547 [ +  - ][ +  - ]:      16666 :         noreturn.insert("verrx");
                 [ +  - ]
     548 [ +  - ][ +  - ]:      16666 :         noreturn.insert("ExitProcess");
                 [ +  - ]
     549 [ +  - ][ +  - ]:      16666 :         noreturn.insert("ExitThread");
                 [ +  - ]
     550 [ +  - ][ +  - ]:      16666 :         noreturn.insert("pthread_exit");
                 [ +  - ]
     551                 :            :     }
     552                 :            : 
     553                 :            :     // only check functions
     554                 :      16666 :     const std::size_t functions = symbolDatabase->functionScopes.size();
     555         [ +  + ]:      30542 :     for (std::size_t i = 0; i < functions; ++i) {
     556                 :      13876 :         const Scope * scope = symbolDatabase->functionScopes[i];
     557                 :            : 
     558                 :            :         // parse this function to check if it contains an "exit" call..
     559                 :      13876 :         bool isNoreturn = false;
     560         [ +  + ]:     342919 :         for (const Token *tok2 = scope->classStart->next(); tok2 != scope->classEnd; tok2 = tok2->next()) {
     561         [ +  + ]:     329538 :             if (Token::Match(tok2->previous(), "[;{}] exit (")) {
     562                 :        495 :                 isNoreturn = true;
     563                 :        495 :                 break;
     564                 :            :             }
     565                 :            :         }
     566                 :            : 
     567                 :            :         // This function is not a noreturn function
     568         [ +  + ]:      13876 :         if (isNoreturn)
     569                 :        495 :             noreturn.insert(scope->className);
     570                 :            :         else
     571                 :      13381 :             notnoreturn.insert(scope->className);
     572                 :            :     }
     573                 :      16666 : }
     574                 :            : 
     575                 :            : 
     576                 :      14040 : bool CheckMemoryLeakInFunction::notvar(const Token *tok, unsigned int varid, bool endpar)
     577                 :            : {
     578 [ +  + ][ +  - ]:      14040 :     const std::string end(endpar ? " &&|)" : " [;)&|]");
     579 [ +  - ][ +  - ]:      28080 :     return bool(Token::Match(tok, ("! %varid%" + end).c_str(), varid) ||
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
     580 [ +  + ][ +  - ]:      28080 :                 Token::Match(tok, ("! ( %varid% )" + end).c_str(), varid));
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
         [ +  - ][ #  # ]
     581                 :            : }
     582                 :            : 
     583                 :            : 
     584                 :            : 
     585                 :      48141 : bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname)
     586                 :            : {
     587                 :      48141 :     return (std::bsearch(funcname.c_str(), call_func_white_list,
     588                 :            :                          sizeof(call_func_white_list) / sizeof(call_func_white_list[0]),
     589                 :      48141 :                          sizeof(call_func_white_list[0]), call_func_white_list_compare) != NULL);
     590                 :            : }
     591                 :            : 
     592                 :      37026 : const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &allocpar, unsigned int sz)
     593                 :            : {
     594         [ +  + ]:      37026 :     if (test_white_list(tok->str())) {
     595   [ +  +  +  +  :     162000 :         if (tok->str() == "asprintf" ||
          +  +  +  -  +  
          +  +  -  +  +  
          +  -  +  -  -  
              + ][ +  + ]
     596                 :      19260 :             tok->str() == "delete" ||
     597                 :      19215 :             tok->str() == "fclose" ||
     598                 :      18225 :             tok->str() == "for" ||
     599                 :      18225 :             tok->str() == "free" ||
     600                 :      14715 :             tok->str() == "if" ||
     601                 :      14715 :             tok->str() == "realloc" ||
     602                 :      12780 :             tok->str() == "return" ||
     603                 :      12780 :             tok->str() == "switch" ||
     604                 :      12780 :             tok->str() == "while") {
     605                 :       6525 :             return 0;
     606                 :            :         }
     607                 :            : 
     608                 :            :         // is the varid a parameter?
     609         [ +  + ]:      25245 :         for (const Token *tok2 = tok->tokAt(2); tok2 != tok->linkAt(1); tok2 = tok2->next()) {
     610         [ +  + ]:      21960 :             if (tok2->str() == "(") {
     611                 :         90 :                 tok2 = tok2->nextArgument();
     612         [ +  + ]:         90 :                 if (!tok2)
     613                 :         45 :                     break;
     614                 :            :             }
     615         [ +  + ]:      21915 :             if (tok2->varId() == varid) {
     616         [ +  + ]:       9450 :                 if (tok->strAt(-1) == ".")
     617                 :         45 :                     return "use";
     618         [ +  + ]:       9405 :                 else if (tok2->strAt(1) == "=")
     619                 :         45 :                     return "assign";
     620                 :            :                 else
     621                 :       9360 :                     return "use_";
     622                 :            :             }
     623                 :            :         }
     624                 :            : 
     625                 :       3330 :         return 0;
     626                 :            :     }
     627                 :            : 
     628 [ +  + ][ +  + ]:      17721 :     if (noreturn.find(tok->str()) != noreturn.end() && tok->strAt(-1) != "=")
                 [ +  + ]
     629                 :       1620 :         return "exit";
     630                 :            : 
     631 [ +  + ][ +  + ]:      16101 :     if (varid > 0 && (getAllocationType(tok, varid) != No || getReallocationType(tok, varid) != No || getDeallocationType(tok, varid) != No))
         [ +  - ][ +  + ]
                 [ +  + ]
     632                 :        720 :         return 0;
     633                 :            : 
     634         [ -  + ]:      15381 :     if (callstack.size() > 2)
     635                 :          0 :         return "dealloc_";
     636                 :            : 
     637                 :      15381 :     const std::string& funcname(tok->str());
     638         [ +  + ]:      16686 :     for (std::list<const Token *>::const_iterator it = callstack.begin(); it != callstack.end(); ++it) {
     639 [ +  + ][ +  + ]:       1395 :         if ((*it) && (*it)->str() == funcname)
                 [ +  + ]
     640                 :         90 :             return "recursive";
     641                 :            :     }
     642                 :      15291 :     callstack.push_back(tok);
     643                 :            : 
     644                 :            :     // lock/unlock..
     645         [ +  + ]:      15291 :     if (varid == 0) {
     646                 :      10791 :         const Function* func = tok->function();
     647 [ +  + ][ -  + ]:      10791 :         if (!func || !func->hasBody)
     648                 :       8811 :             return 0;
     649                 :            : 
     650         [ +  - ]:       1980 :         Token *ftok = getcode(func->functionScope->classStart->next(), callstack, 0, alloctype, dealloctype, false, 1);
     651                 :       1980 :         simplifycode(ftok);
     652                 :       1980 :         const char *ret = 0;
     653         [ -  + ]:       1980 :         if (Token::simpleMatch(ftok, "; alloc ; }"))
     654                 :          0 :             ret = "alloc";
     655         [ -  + ]:       1980 :         else if (Token::simpleMatch(ftok, "; dealloc ; }"))
     656                 :          0 :             ret = "dealloc";
     657                 :       1980 :         TokenList::deleteTokens(ftok);
     658                 :       1980 :         return ret;
     659                 :            :     }
     660                 :            : 
     661                 :            :     // how many parameters is there in the function call?
     662                 :       4500 :     unsigned int numpar = countParameters(tok);
     663         [ +  + ]:       4500 :     if (numpar == 0) {
     664                 :            :         // Taking return value => it is not a noreturn function
     665         [ +  + ]:       1395 :         if (tok->strAt(-1) == "=")
     666                 :        450 :             return NULL;
     667                 :            : 
     668                 :            :         // Function is not noreturn
     669         [ +  + ]:        945 :         if (notnoreturn.find(funcname) != notnoreturn.end())
     670                 :         45 :             return NULL;
     671                 :            : 
     672                 :        900 :         return "callfunc";
     673                 :            :     }
     674                 :            : 
     675                 :       3105 :     unsigned int par = 0;
     676                 :            : 
     677                 :       3105 :     const bool dot(tok->previous()->str() == ".");
     678                 :       3105 :     const bool eq(tok->previous()->str() == "=");
     679                 :            : 
     680                 :       3105 :     const Token *functok = tok;
     681                 :            : 
     682                 :       3105 :     tok = Token::findsimplematch(tok, "(");
     683         [ +  - ]:       3105 :     if (tok)
     684                 :       3105 :         tok = tok->next();
     685                 :            : 
     686         [ +  + ]:       5175 :     for (; tok; tok = tok->nextArgument()) {
     687                 :       3645 :         ++par;
     688 [ +  - ][ +  + ]:       3645 :         if (varid > 0 && Token::Match(tok, "%varid% [,()]", varid)) {
                 [ +  + ]
     689         [ +  + ]:       1305 :             if (dot)
     690                 :        180 :                 return "use";
     691                 :            : 
     692                 :       1125 :             const Function* function = functok->function();
     693         [ +  + ]:       1125 :             if (!function)
     694                 :        585 :                 return "use";
     695                 :            : 
     696                 :            :             // how many parameters does the function want?
     697         [ -  + ]:        540 :             if (numpar != function->argCount()) // TODO: Handle default parameters
     698                 :          0 :                 return "recursive";
     699                 :            : 
     700                 :        540 :             const Variable* param = function->getArgumentVar(par-1);
     701 [ +  - ][ +  + ]:        540 :             if (!param || !param->nameToken())
                 [ +  + ]
     702                 :         45 :                 return "use";
     703         [ -  + ]:        495 :             if (!function->functionScope)
     704                 :          0 :                 return "use";
     705         [ +  - ]:        495 :             Token *func = getcode(function->functionScope->classStart->next(), callstack, param->varId(), alloctype, dealloctype, false, sz);
     706                 :            :             //simplifycode(func);
     707                 :        495 :             const Token *func_ = func;
     708 [ +  - ][ +  + ]:        990 :             while (func_ && func_->str() == ";")
                 [ +  + ]
     709                 :        495 :                 func_ = func_->next();
     710                 :            : 
     711                 :        495 :             const char *ret = 0;
     712                 :            :             /** @todo handle "goto" */
     713         [ +  + ]:        495 :             if (Token::findsimplematch(func_, "dealloc"))
     714                 :        135 :                 ret = "dealloc";
     715         [ +  + ]:        360 :             else if (Token::findsimplematch(func_, "use"))
     716                 :         45 :                 ret = "use";
     717         [ +  + ]:        315 :             else if (Token::findsimplematch(func_, "&use"))
     718                 :         45 :                 ret = "&use";
     719                 :            : 
     720                 :        495 :             TokenList::deleteTokens(func);
     721                 :        495 :             return ret;
     722                 :            :         }
     723 [ +  - ][ +  + ]:       2340 :         if (varid > 0 && Token::Match(tok, "& %varid% [,()]", varid)) {
                 [ +  + ]
     724                 :        675 :             const Function *func = functok->function();
     725         [ +  + ]:        675 :             if (func == 0)
     726                 :        270 :                 continue;
     727                 :            :             AllocType a;
     728                 :        405 :             const char *ret = functionArgAlloc(func, par, a);
     729                 :            : 
     730         [ +  + ]:        405 :             if (a != No) {
     731         [ +  + ]:        225 :                 if (alloctype == No)
     732                 :        135 :                     alloctype = a;
     733         [ -  + ]:         90 :                 else if (alloctype != a)
     734                 :          0 :                     alloctype = Many;
     735                 :        225 :                 allocpar = true;
     736                 :        225 :                 return ret;
     737                 :            :             }
     738                 :            :         }
     739 [ +  - ][ +  + ]:       1845 :         if (varid > 0 && Token::Match(tok, "%varid% . %var% [,)]", varid))
                 [ +  + ]
     740                 :         45 :             return "use";
     741                 :            :     }
     742 [ +  + ][ +  + ]:      37026 :     return (eq || _settings->experimental) ? 0 : "callfunc";
     743                 :            : }
     744                 :            : 
     745                 :            : 
     746                 :     275879 : static void addtoken(Token **rettail, const Token *tok, const std::string &str)
     747                 :            : {
     748                 :     275879 :     (*rettail)->insertToken(str);
     749                 :     275879 :     (*rettail) = (*rettail)->next();
     750                 :     275879 :     (*rettail)->linenr(tok->linenr());
     751                 :     275879 :     (*rettail)->fileIndex(tok->fileIndex());
     752                 :     275879 : }
     753                 :            : 
     754                 :            : 
     755                 :      37892 : Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, CheckMemoryLeak::AllocType &alloctype, CheckMemoryLeak::AllocType &dealloctype, bool classmember, unsigned int sz)
     756                 :            : {
     757                 :            :     // variables whose value depends on if(!var). If one of these variables
     758                 :            :     // is used in a if-condition then generate "ifv" instead of "if".
     759                 :      37892 :     std::set<unsigned int> extravar;
     760                 :            : 
     761                 :            :     // The first token should be ";"
     762 [ +  - ][ +  - ]:      37892 :     Token* rethead = new Token(0);
     763 [ +  - ][ +  - ]:      37892 :     rethead->str(";");
                 [ +  - ]
     764                 :      37892 :     rethead->linenr(tok->linenr());
     765                 :      37892 :     rethead->fileIndex(tok->fileIndex());
     766                 :      37892 :     Token* rettail = rethead;
     767                 :            : 
     768                 :      37892 :     int indentlevel = 0;
     769                 :      37892 :     int parlevel = 0;
     770         [ +  + ]:     665524 :     for (; tok; tok = tok->next()) {
     771 [ +  - ][ +  + ]:     660529 :         if (tok->str() == "{") {
     772 [ +  - ][ +  - ]:      17856 :             addtoken(&rettail, tok, "{");
                 [ +  - ]
     773                 :      17856 :             ++indentlevel;
     774 [ +  - ][ +  + ]:     642673 :         } else if (tok->str() == "}") {
     775 [ +  - ][ +  - ]:      50483 :             addtoken(&rettail, tok, "}");
                 [ +  - ]
     776         [ +  + ]:      50483 :             if (indentlevel <= 0)
     777                 :      32627 :                 break;
     778                 :      17856 :             --indentlevel;
     779                 :            :         }
     780                 :            : 
     781 [ +  - ][ +  + ]:     592190 :         else if (tok->str() == "(")
     782                 :      42876 :             ++parlevel;
     783 [ +  - ][ +  + ]:     549314 :         else if (tok->str() == ")")
     784                 :      43101 :             --parlevel;
     785                 :            : 
     786 [ +  + ][ +  - ]:     627902 :         if (parlevel == 0 && tok->str() == ";")
         [ +  + ][ +  + ]
     787 [ +  - ][ +  - ]:     113709 :             addtoken(&rettail, tok, ";");
                 [ +  - ]
     788                 :            : 
     789                 :            :         // Start of new statement.. check if the statement has anything interesting
     790 [ +  + ][ +  + ]:     627902 :         if (varid > 0 && parlevel == 0 && Token::Match(tok, "[;{}]")) {
         [ +  - ][ +  + ]
                 [ +  + ]
     791 [ +  - ][ +  + ]:      84527 :             if (Token::Match(tok->next(), "[{};]"))
     792                 :      20011 :                 continue;
     793                 :            : 
     794                 :            :             // function calls are interesting..
     795                 :      64516 :             const Token *tok2 = tok;
     796 [ +  - ][ +  + ]:      65056 :             while (Token::Match(tok2->next(), "%var% ."))
     797         [ +  - ]:        540 :                 tok2 = tok2->tokAt(2);
     798 [ +  - ][ +  + ]:      64516 :             if (Token::Match(tok2->next(), "%var% ("))
     799                 :            :                 ;
     800                 :            : 
     801 [ +  - ][ +  + ]:      42016 :             else if (Token::Match(tok->next(), "continue|break|return|throw|goto|do|else"))
     802                 :            :                 ;
     803                 :            : 
     804                 :            :             else {
     805                 :      33421 :                 const Token *skipToToken = 0;
     806                 :            : 
     807                 :            :                 // scan statement for interesting keywords / varid
     808         [ +  + ]:      73336 :                 for (tok2 = tok->next(); tok2; tok2 = tok2->next()) {
     809 [ +  - ][ +  + ]:      68971 :                     if (tok2->str() == ";") {
     810                 :            :                         // nothing interesting found => skip this statement
     811                 :       4320 :                         skipToToken = tok2->previous();
     812                 :       4320 :                         break;
     813                 :            :                     }
     814                 :            : 
     815 [ +  + ][ +  + ]:     184936 :                     if (tok2->varId() == varid ||
         [ +  + ][ -  + ]
                 [ +  + ]
     816 [ +  - ][ +  - ]:     120285 :                         tok2->str() == ":" || tok2->str() == "{" || tok2->str() == "}") {
                 [ +  - ]
     817                 :      24736 :                         break;
     818                 :            :                     }
     819                 :            :                 }
     820                 :            : 
     821         [ +  + ]:      33421 :                 if (skipToToken) {
     822                 :       4320 :                     tok = skipToToken;
     823                 :       4320 :                     continue;
     824                 :            :                 }
     825                 :            :             }
     826                 :            :         }
     827                 :            : 
     828         [ +  + ]:     603571 :         if (varid == 0) {
     829 [ +  + ][ +  - ]:     311163 :             if (!callstack.empty() && Token::Match(tok, "[;{}] __cppcheck_lock|__cppcheck_unlock ( ) ;")) {
         [ +  + ][ +  + ]
     830                 :            :                 // Type of leak = Resource leak
     831                 :         90 :                 alloctype = dealloctype = CheckMemoryLeak::File;
     832                 :            : 
     833 [ +  - ][ +  + ]:         90 :                 if (tok->next()->str() == "__cppcheck_lock") {
     834 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, "alloc");
                 [ +  - ]
     835                 :            :                 } else {
     836 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
     837                 :            :                 }
     838                 :            : 
     839         [ +  - ]:         90 :                 tok = tok->tokAt(3);
     840                 :         90 :                 continue;
     841                 :            :             }
     842                 :            : 
     843 [ +  - ][ +  + ]:     311073 :             if (Token::simpleMatch(tok, "if (")) {
     844 [ +  - ][ +  - ]:       4815 :                 addtoken(&rettail, tok, "if");
                 [ +  - ]
     845                 :       4815 :                 tok = tok->next()->link();
     846                 :       4815 :                 continue;
     847                 :            :             }
     848                 :            :         } else {
     849                 :            : 
     850 [ +  - ][ +  + ]:     292408 :             if (Token::Match(tok, "%varid% = close ( %varid% )", varid)) {
     851 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
     852 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, ";");
                 [ +  - ]
     853 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, "assign");
                 [ +  - ]
     854 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, ";");
                 [ +  - ]
     855         [ +  - ]:         45 :                 tok = tok->tokAt(5);
     856                 :         45 :                 continue;
     857                 :            :             }
     858                 :            : 
     859                 :            :             // var = strcpy|.. ( var ,
     860 [ +  - ][ +  + ]:     292363 :             if (Token::Match(tok, "[;{}] %varid% = memcpy|memmove|memset|strcpy|strncpy|strcat|strncat ( %varid% ,", varid)) {
     861         [ +  - ]:         90 :                 tok = tok->linkAt(4);
     862                 :         90 :                 continue;
     863                 :            :             }
     864                 :            : 
     865 [ +  - ][ +  + ]:     568535 :             if (Token::Match(tok->previous(), "[(;{}] %varid% =", varid) ||
         [ +  + ][ +  + ]
     866         [ +  - ]:     276262 :                 Token::Match(tok, "asprintf|vasprintf ( & %varid% ,", varid)) {
     867                 :            :                 CheckMemoryLeak::AllocType alloc;
     868                 :            : 
     869 [ +  - ][ +  + ]:      16191 :                 if (Token::Match(tok, "asprintf|vasprintf (")) {
     870                 :            :                     // todo: check how the return value is used.
     871 [ +  - ][ +  + ]:        180 :                     if (!Token::Match(tok->previous(), "[;{}]")) {
     872         [ +  - ]:         90 :                         TokenList::deleteTokens(rethead);
     873                 :         90 :                         return 0;
     874                 :            :                     }
     875                 :         90 :                     alloc = Malloc;
     876                 :         90 :                     tok = tok->next()->link();
     877                 :            :                 } else {
     878 [ +  - ][ +  - ]:      16011 :                     alloc = getAllocationType(tok->tokAt(2), varid);
     879                 :            :                 }
     880                 :            :                 //bool realloc = false;
     881                 :            : 
     882 [ +  + ][ +  + ]:      18666 :                 if (sz > 1 &&
         [ +  + ][ +  + ]
     883 [ +  - ][ +  - ]:       2385 :                     Token::Match(tok->tokAt(2), "malloc ( %num% )") &&
     884 [ +  - ][ +  - ]:        180 :                     (MathLib::toLongNumber(tok->strAt(4)) % long(sz)) != 0) {
     885 [ +  - ][ +  - ]:         45 :                     mismatchSizeError(tok->tokAt(4), tok->strAt(4));
                 [ +  - ]
     886                 :            :                 }
     887                 :            : 
     888         [ +  + ]:      16101 :                 if (alloc == CheckMemoryLeak::No) {
     889 [ +  - ][ +  - ]:       3555 :                     alloc = getReallocationType(tok->tokAt(2), varid);
     890         [ +  + ]:       3555 :                     if (alloc != CheckMemoryLeak::No) {
     891 [ +  - ][ +  - ]:        540 :                         addtoken(&rettail, tok, "realloc");
                 [ +  - ]
     892 [ +  - ][ +  - ]:        540 :                         addtoken(&rettail, tok, ";");
                 [ +  - ]
     893                 :            :                         //TODO: this assignment is redundant, should be fixed
     894                 :            :                         //realloc = true;
     895         [ +  - ]:        540 :                         tok = tok->tokAt(2);
     896 [ +  - ][ +  - ]:        540 :                         if (Token::Match(tok, "%var% ("))
     897                 :        540 :                             tok = tok->next()->link();
     898                 :        540 :                         continue;
     899                 :            :                     }
     900                 :            :                 }
     901                 :            : 
     902                 :            :                 // don't check classes..
     903         [ +  + ]:      15561 :                 if (alloc == CheckMemoryLeak::New) {
     904 [ +  - ][ +  - ]:        810 :                     if (Token::Match(tok->tokAt(2), "new struct| %type% [(;]")) {
                 [ +  + ]
     905 [ +  - ][ +  - ]:        540 :                         const int offset = tok->strAt(3) == "struct" ? 1 : 0;
                 [ -  + ]
     906 [ +  - ][ +  - ]:        540 :                         if (isclass(tok->tokAt(3 + offset), varid)) {
                 [ +  + ]
     907                 :        180 :                             alloc = No;
     908                 :            :                         }
     909 [ +  - ][ +  - ]:        270 :                     } else if (Token::Match(tok->tokAt(2), "new ( nothrow ) struct| %type%")) {
                 [ +  + ]
     910 [ +  - ][ +  - ]:         90 :                         const int offset = tok->strAt(6) == "struct" ? 1 : 0;
                 [ -  + ]
     911 [ +  - ][ +  - ]:         90 :                         if (isclass(tok->tokAt(6 + offset), varid)) {
                 [ +  + ]
     912                 :         45 :                             alloc = No;
     913                 :            :                         }
     914 [ +  - ][ +  - ]:        180 :                     } else if (Token::Match(tok->tokAt(2), "new ( std :: nothrow ) struct| %type%")) {
                 [ +  + ]
     915 [ +  - ][ +  - ]:        135 :                         const int offset = tok->strAt(8) == "struct" ? 1 : 0;
                 [ -  + ]
     916 [ +  - ][ +  - ]:        135 :                         if (isclass(tok->tokAt(8 + offset), varid)) {
                 [ +  + ]
     917                 :         45 :                             alloc = No;
     918                 :            :                         }
     919                 :            :                     }
     920                 :            : 
     921 [ +  + ][ +  - ]:        810 :                     if (alloc == No && alloctype == No)
     922                 :        270 :                         alloctype = CheckMemoryLeak::New;
     923                 :            :                 }
     924                 :            : 
     925         [ +  + ]:      15561 :                 if (alloc != No) {
     926                 :            :                     //if (! realloc)
     927 [ +  - ][ +  - ]:      12276 :                     addtoken(&rettail, tok, "alloc");
                 [ +  - ]
     928                 :            : 
     929 [ +  + ][ +  + ]:      12276 :                     if (alloctype != No && alloctype != alloc)
     930                 :        135 :                         alloc = Many;
     931                 :            : 
     932 [ +  + ][ +  + ]:      12276 :                     if (alloc != Many && dealloctype != No && dealloctype != Many && dealloctype != alloc) {
         [ +  - ][ +  + ]
     933         [ +  - ]:         45 :                         callstack.push_back(tok);
     934 [ +  - ][ +  - ]:         45 :                         mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str());
     935         [ +  - ]:         45 :                         callstack.pop_back();
     936                 :            :                     }
     937                 :            : 
     938                 :      12276 :                     alloctype = alloc;
     939                 :            : 
     940 [ +  - ][ +  + ]:      12276 :                     if (Token::Match(tok, "%var% = %type% (")) {
     941         [ +  - ]:       7866 :                         tok = tok->linkAt(3);
     942                 :       7866 :                         continue;
     943                 :            :                     }
     944                 :            :                 }
     945                 :            : 
     946                 :            :                 // assignment..
     947                 :            :                 else {
     948                 :            :                     // is the pointer in rhs?
     949                 :       3285 :                     bool rhs = false;
     950                 :       3285 :                     bool trailingSemicolon = false;
     951                 :       3285 :                     bool used = false;
     952         [ +  - ]:      15750 :                     for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
     953 [ +  - ][ +  + ]:      15750 :                         if (tok2->str() == ";") {
     954                 :       3285 :                             trailingSemicolon = true;
     955         [ +  + ]:       3285 :                             if (rhs)
     956                 :        225 :                                 tok = tok2;
     957                 :       3285 :                             break;
     958                 :            :                         }
     959                 :            : 
     960         [ +  + ]:      12465 :                         if (!used) {
     961 [ +  - ][ +  + ]:      12285 :                             if (Token::Match(tok2, "[=+(,] %varid%", varid)) {
     962 [ +  - ][ +  - ]:        225 :                                 if (!rhs && Token::Match(tok2, "[(,]")) {
         [ +  + ][ +  + ]
     963                 :         90 :                                     used = true;
     964 [ +  - ][ +  - ]:         90 :                                     addtoken(&rettail, tok, "use");
                 [ +  - ]
     965 [ +  - ][ +  - ]:         90 :                                     addtoken(&rettail, tok, ";");
                 [ +  - ]
     966                 :            :                                 }
     967                 :        225 :                                 rhs = true;
     968                 :            :                             }
     969                 :            :                         }
     970                 :            :                     }
     971                 :            : 
     972         [ +  + ]:       3285 :                     if (!used) {
     973         [ +  + ]:       3195 :                         if (!rhs)
     974 [ +  - ][ +  - ]:       3060 :                             addtoken(&rettail, tok, "assign");
                 [ +  - ]
     975                 :            :                         else {
     976 [ +  - ][ +  - ]:        135 :                             addtoken(&rettail, tok, "use_");
                 [ +  - ]
     977         [ +  - ]:        135 :                             if (trailingSemicolon)
     978 [ +  - ][ +  - ]:        135 :                                 addtoken(&rettail, tok, ";");
                 [ +  - ]
     979                 :            :                         }
     980                 :            :                     }
     981                 :       3285 :                     continue;
     982                 :            :                 }
     983                 :            :             }
     984                 :            : 
     985 [ +  - ][ +  + ]:     280492 :             if (Token::Match(tok->previous(), "[;{})=|] ::| %var%")) {
     986 [ +  - ][ +  + ]:      57865 :                 if (Token::Match(tok, "%varid% ?", varid))
     987         [ +  - ]:         45 :                     tok = tok->tokAt(2);
     988                 :            : 
     989         [ +  - ]:      57865 :                 AllocType dealloc = getDeallocationType(tok, varid);
     990                 :            : 
     991 [ +  + ][ +  - ]:      57865 :                 if (dealloc != No && tok->str() == "fcloseall" && alloctype != dealloc)
         [ +  + ][ +  + ]
                 [ +  + ]
     992                 :            :                     //TODO: this assignment is redundant, should be fixed
     993                 :            :                     /*dealloc = No*/;
     994                 :            : 
     995         [ +  + ]:      57820 :                 else if (dealloc != No) {
     996 [ +  - ][ +  - ]:       7740 :                     addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
     997                 :            : 
     998 [ +  + ][ +  + ]:       7740 :                     if (dealloctype != No && dealloctype != dealloc)
     999                 :        180 :                         dealloc = Many;
    1000                 :            : 
    1001 [ +  + ][ +  + ]:       7740 :                     if (dealloc != Many && alloctype != No && alloctype != Many && alloctype != dealloc) {
         [ +  + ][ +  + ]
    1002         [ +  - ]:        450 :                         callstack.push_back(tok);
    1003 [ +  - ][ +  - ]:        450 :                         mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str());
    1004         [ +  - ]:        450 :                         callstack.pop_back();
    1005                 :            :                     }
    1006                 :       7740 :                     dealloctype = dealloc;
    1007                 :            : 
    1008 [ +  - ][ +  - ]:       7740 :                     if (tok->strAt(2) == "(")
                 [ +  + ]
    1009         [ +  - ]:         45 :                         tok = tok->linkAt(2);
    1010                 :       7740 :                     continue;
    1011                 :            :                 }
    1012                 :            :             }
    1013                 :            : 
    1014                 :            :             // if else switch
    1015 [ +  - ][ +  + ]:     272752 :             if (Token::simpleMatch(tok, "if (")) {
    1016         [ +  + ]:       6975 :                 if (alloctype == Fd) {
    1017 [ +  - ][ +  + ]:       1035 :                     if (Token::Match(tok, "if ( 0|-1 <=|< %varid% )", varid) ||
         [ -  + ][ +  + ]
    1018         [ +  - ]:        450 :                         Token::Match(tok, "if ( %varid% != -1 )", varid)) {
    1019 [ +  - ][ +  - ]:        135 :                         addtoken(&rettail, tok, "if(var)");
                 [ +  - ]
    1020                 :        135 :                         tok = tok->next()->link();
    1021                 :        135 :                         continue;
    1022 [ +  - ][ +  + ]:        810 :                     } else if (Token::Match(tok, "if ( %varid% == -1 )", varid) ||
         [ +  + ][ +  + ]
    1023         [ +  - ]:        360 :                                Token::Match(tok, "if ( %varid% < 0 )", varid)) {
    1024 [ +  - ][ +  - ]:        180 :                         addtoken(&rettail, tok, "if(!var)");
                 [ +  - ]
    1025                 :        180 :                         tok = tok->next()->link();
    1026                 :        180 :                         continue;
    1027                 :            :                     }
    1028                 :            :                 }
    1029                 :            : 
    1030 [ +  - ][ +  + ]:       6660 :                 if (Token::Match(tok, "if ( %varid% )", varid)) {
    1031 [ +  - ][ +  - ]:        405 :                     addtoken(&rettail, tok, "if(var)");
                 [ +  - ]
    1032                 :            : 
    1033                 :            :                     // Make sure the "use" will not be added
    1034                 :        405 :                     tok = tok->next()->link();
    1035                 :        405 :                     continue;
    1036 [ +  - ][ +  - ]:       6255 :                 } else if (Token::simpleMatch(tok, "if (") && notvar(tok->tokAt(2), varid, true)) {
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
    1037 [ +  - ][ +  - ]:        855 :                     addtoken(&rettail, tok, "if(!var)");
                 [ +  - ]
    1038                 :            : 
    1039                 :            :                     // parse the if-body.
    1040                 :            :                     // if a variable is assigned then add variable to "extravar".
    1041 [ +  - ][ +  - ]:       3780 :                     for (const Token *tok2 = tok->next()->link()->tokAt(2); tok2; tok2 = tok2->next()) {
    1042 [ +  - ][ -  + ]:       3780 :                         if (tok2->str() == "{")
    1043                 :          0 :                             tok2 = tok2->link();
    1044 [ +  - ][ +  + ]:       3780 :                         else if (tok2->str() == "}")
    1045                 :        855 :                             break;
    1046 [ +  - ][ +  + ]:       2925 :                         else if (Token::Match(tok2, "%var% ="))
    1047         [ +  - ]:         90 :                             extravar.insert(tok2->varId());
    1048                 :            :                     }
    1049                 :            : 
    1050                 :        855 :                     tok = tok->next()->link();
    1051                 :        855 :                     continue;
    1052                 :            :                 } else {
    1053                 :            :                     // Check if the condition depends on var or extravar somehow..
    1054                 :       5400 :                     bool dep = false;
    1055         [ +  - ]:       5400 :                     const Token* const end = tok->linkAt(1);
    1056         [ +  + ]:      27360 :                     for (const Token *tok2 = tok->next(); tok2 != end; tok2 = tok2->next()) {
    1057 [ +  - ][ +  + ]:      22500 :                         if (Token::Match(tok2, "close|pclose|fclose|closedir ( %varid% )", varid)) {
    1058 [ +  - ][ +  - ]:        135 :                             addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
    1059 [ +  - ][ +  - ]:        135 :                             addtoken(&rettail, tok, ";");
                 [ +  - ]
    1060                 :        135 :                             dep = true;
    1061                 :        135 :                             break;
    1062 [ +  + ][ +  - ]:      22365 :                         } else if (alloctype == Fd && Token::Match(tok2, "%varid% !=|>=", varid)) {
         [ +  + ][ +  + ]
    1063                 :         45 :                             dep = true;
    1064 [ +  - ][ +  + ]:      22320 :                         } else if (Token::Match(tok2, "! %varid%", varid)) {
    1065                 :        225 :                             dep = true;
    1066 [ +  - ][ +  + ]:      22095 :                         } else if (Token::Match(tok2, "%var% (") && !test_white_list(tok2->str())) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1067                 :        855 :                             bool use = false;
    1068 [ +  - ][ +  - ]:       1305 :                             for (const Token *tok3 = tok2->tokAt(2); tok3; tok3 = tok3->nextArgument()) {
                 [ +  + ]
    1069 [ +  - ][ +  + ]:        855 :                                 if (Token::Match(tok3->previous(), "(|, &| %varid% ,|)", varid)) {
    1070                 :        405 :                                     use = true;
    1071                 :        405 :                                     break;
    1072                 :            :                                 }
    1073                 :            :                             }
    1074         [ +  + ]:        855 :                             if (use) {
    1075 [ +  - ][ +  - ]:        405 :                                 addtoken(&rettail, tok, "use");
                 [ +  - ]
    1076 [ +  - ][ +  - ]:        405 :                                 addtoken(&rettail, tok, ";");
                 [ +  - ]
    1077                 :        405 :                                 dep = false;
    1078                 :        405 :                                 break;
    1079                 :            :                             }
    1080 [ +  + ][ +  - ]:      21240 :                         } else if (tok2->varId() && extravar.find(tok2->varId()) != extravar.end()) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1081                 :         45 :                             dep = true;
    1082 [ +  + ][ +  - ]:      21195 :                         } else if (tok2->varId() == varid && tok2->next()->isConstOp())
         [ +  + ][ +  + ]
    1083                 :        540 :                             dep = true;
    1084                 :            :                     }
    1085                 :            : 
    1086 [ +  - ][ -  + ]:       5400 :                     if (Token::Match(tok, "if ( ! %varid% &&", varid)) {
    1087 [ #  # ][ #  # ]:          0 :                         addtoken(&rettail, tok, "if(!var)");
                 [ #  # ]
    1088   [ +  -  +  - ]:      16200 :                     } else if (tok->next() &&
         [ +  + ][ +  + ]
    1089                 :       5400 :                                tok->next()->link() &&
    1090 [ +  - ][ +  - ]:       5400 :                                Token::Match(tok->next()->link()->tokAt(-3), "&& ! %varid%", varid)) {
    1091 [ +  - ][ +  - ]:         90 :                         addtoken(&rettail, tok, "if(!var)");
                 [ +  - ]
    1092                 :            :                     } else {
    1093 [ +  + ][ +  - ]:       5310 :                         addtoken(&rettail, tok, (dep ? "ifv" : "if"));
         [ +  - ][ +  - ]
    1094                 :            :                     }
    1095                 :            : 
    1096                 :       5400 :                     tok = tok->next()->link();
    1097                 :       5400 :                     continue;
    1098                 :            :                 }
    1099                 :            :             }
    1100                 :            :         }
    1101                 :            : 
    1102 [ +  - ][ +  + ]:     572035 :         if ((tok->str() == "else") || (tok->str() == "switch")) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1103         [ +  - ]:       1395 :             addtoken(&rettail, tok, tok->str());
    1104 [ +  - ][ +  + ]:       1395 :             if (Token::simpleMatch(tok, "switch ("))
    1105                 :        225 :                 tok = tok->next()->link();
    1106                 :       1395 :             continue;
    1107                 :            :         }
    1108                 :            : 
    1109 [ +  - ][ +  + ]:     570640 :         if ((tok->str() == "case")) {
    1110 [ +  - ][ +  - ]:        180 :             addtoken(&rettail, tok, "case");
                 [ +  - ]
    1111 [ +  - ][ +  - ]:        180 :             addtoken(&rettail, tok, ";");
                 [ +  - ]
    1112 [ +  - ][ +  - ]:        180 :             if (Token::Match(tok, "case %any% :"))
    1113         [ +  - ]:        180 :                 tok = tok->tokAt(2);
    1114                 :        180 :             continue;
    1115                 :            :         }
    1116                 :            : 
    1117 [ +  - ][ +  + ]:     570460 :         if ((tok->str() == "default")) {
    1118 [ +  - ][ +  - ]:        180 :             addtoken(&rettail, tok, "default");
                 [ +  - ]
    1119 [ +  - ][ +  - ]:        180 :             addtoken(&rettail, tok, ";");
                 [ +  - ]
    1120                 :        180 :             continue;
    1121                 :            :         }
    1122                 :            : 
    1123                 :            :         // Loops..
    1124 [ +  - ][ +  + ]:     570280 :         else if ((tok->str() == "for") || (tok->str() == "while")) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1125         [ +  - ]:       2160 :             const Token* const end = tok->linkAt(1);
    1126                 :            : 
    1127 [ +  - ][ +  + ]:       4275 :             if (Token::simpleMatch(tok, "while ( true )") ||
         [ +  + ][ +  + ]
    1128         [ +  - ]:       2115 :                 Token::simpleMatch(tok, "for ( ; ; )")) {
    1129 [ +  - ][ +  - ]:        225 :                 addtoken(&rettail, tok, "while1");
                 [ +  - ]
    1130                 :        225 :                 tok = end;
    1131                 :        225 :                 continue;
    1132                 :            :             }
    1133                 :            : 
    1134 [ +  + ][ +  - ]:       1935 :             else if (varid && getDeallocationType(tok->tokAt(2), varid) != No) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1135 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
    1136 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, ";");
                 [ +  - ]
    1137                 :            :             }
    1138                 :            : 
    1139 [ +  + ][ +  - ]:       1890 :             else if (alloctype == Fd && varid) {
    1140 [ +  - ][ +  + ]:        270 :                 if (Token::Match(tok, "while ( 0 <= %varid% )", varid) ||
         [ -  + ][ +  + ]
    1141         [ +  - ]:         90 :                     Token::Match(tok, "while ( %varid% != -1 )", varid)) {
    1142 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, "while(var)");
                 [ +  - ]
    1143                 :         45 :                     tok = end;
    1144                 :         45 :                     continue;
    1145 [ +  - ][ +  - ]:        180 :                 } else if (Token::Match(tok, "while ( %varid% == -1 )", varid) ||
         [ +  + ][ +  + ]
    1146         [ +  - ]:         90 :                            Token::Match(tok, "while ( %varid% < 0 )", varid)) {
    1147 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, "while(!var)");
                 [ +  - ]
    1148                 :         45 :                     tok = end;
    1149                 :         45 :                     continue;
    1150                 :            :                 }
    1151                 :            :             }
    1152                 :            : 
    1153 [ +  + ][ +  - ]:       1755 :             else if (varid && Token::Match(tok, "while ( %varid% )", varid)) {
         [ +  + ][ +  + ]
    1154 [ +  - ][ +  - ]:         45 :                 addtoken(&rettail, tok, "while(var)");
                 [ +  - ]
    1155                 :         45 :                 tok = end;
    1156                 :         45 :                 continue;
    1157 [ +  + ][ +  - ]:       1710 :             } else if (varid && Token::simpleMatch(tok, "while (") && notvar(tok->tokAt(2), varid, true)) {
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
    1158 [ +  - ][ +  - ]:         90 :                 addtoken(&rettail, tok, "while(!var)");
                 [ +  - ]
    1159                 :         90 :                 tok = end;
    1160                 :         90 :                 continue;
    1161                 :            :             }
    1162                 :            : 
    1163 [ +  - ][ +  - ]:       1710 :             addtoken(&rettail, tok, "loop");
                 [ +  - ]
    1164                 :            : 
    1165         [ +  + ]:       1710 :             if (varid > 0) {
    1166 [ +  - ][ +  - ]:       8460 :                 for (const Token *tok2 = tok->tokAt(2); tok2 && tok2 != end; tok2 = tok2->next()) {
         [ +  + ][ +  + ]
    1167 [ +  - ][ +  + ]:       7380 :                     if (notvar(tok2, varid)) {
    1168 [ +  - ][ +  - ]:         90 :                         addtoken(&rettail, tok2, "!var");
                 [ +  - ]
    1169                 :         90 :                         break;
    1170                 :            :                     }
    1171                 :            :                 }
    1172                 :            :             }
    1173                 :            : 
    1174                 :       1710 :             continue;
    1175                 :            :         }
    1176 [ +  - ][ +  + ]:     568120 :         if ((tok->str() == "do")) {
    1177 [ +  - ][ +  - ]:         45 :             addtoken(&rettail, tok, "do");
                 [ +  - ]
    1178                 :         45 :             continue;
    1179                 :            :         }
    1180                 :            : 
    1181                 :            :         // continue / break..
    1182 [ +  - ][ +  + ]:     568075 :         else if (tok->str() == "continue") {
    1183 [ +  - ][ +  - ]:        405 :             addtoken(&rettail, tok, "continue");
                 [ +  - ]
    1184 [ +  - ][ +  + ]:     567670 :         } else if (tok->str() == "break") {
    1185 [ +  - ][ +  - ]:        540 :             addtoken(&rettail, tok, "break");
                 [ +  - ]
    1186 [ +  - ][ +  + ]:     567130 :         } else if (tok->str() == "goto") {
    1187 [ +  - ][ +  - ]:        180 :             addtoken(&rettail, tok, "goto");
                 [ +  - ]
    1188                 :            :         }
    1189                 :            : 
    1190                 :            :         // Return..
    1191 [ +  - ][ +  + ]:     566950 :         else if (tok->str() == "return") {
    1192 [ +  - ][ +  - ]:      14880 :             addtoken(&rettail, tok, "return");
                 [ +  - ]
    1193         [ +  + ]:      14880 :             if (varid == 0) {
    1194 [ +  - ][ +  - ]:       7410 :                 addtoken(&rettail, tok, ";");
                 [ +  - ]
    1195 [ +  - ][ +  - ]:      26010 :                 while (tok && tok->str() != ";")
         [ +  + ][ +  + ]
    1196                 :      18600 :                     tok = tok->next();
    1197         [ -  + ]:       7410 :                 if (!tok)
    1198                 :          0 :                     break;
    1199                 :       7410 :                 continue;
    1200                 :            :             }
    1201                 :            : 
    1202                 :            :             // Returning a auto_ptr of this allocated variable..
    1203 [ +  - ][ +  + ]:       7470 :             if (Token::simpleMatch(tok->next(), "std :: auto_ptr <")) {
    1204         [ +  - ]:         45 :                 const Token *tok2 = tok->linkAt(4);
    1205 [ +  - ][ +  - ]:         45 :                 if (Token::Match(tok2, "> ( %varid% )", varid)) {
    1206 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, "use");
                 [ +  - ]
    1207         [ +  - ]:         45 :                     tok = tok2->tokAt(3);
    1208                 :            :                 }
    1209                 :            :             }
    1210                 :            : 
    1211 [ +  - ][ +  - ]:       7425 :             else if (varid && Token::Match(tok, "return strcpy|strncpy|memcpy ( %varid%", varid)) {
         [ +  + ][ +  + ]
    1212 [ +  - ][ +  - ]:         90 :                 addtoken(&rettail, tok, "use");
                 [ +  - ]
    1213         [ +  - ]:         90 :                 tok = tok->tokAt(2);
    1214                 :            :             }
    1215                 :            : 
    1216                 :            :             else {
    1217                 :       7335 :                 bool use = false;
    1218                 :            : 
    1219 [ +  - ][ +  - ]:       7335 :                 std::stack<const Token *> f;
                 [ +  - ]
    1220                 :            : 
    1221         [ +  - ]:      13815 :                 for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) {
    1222 [ +  - ][ +  + ]:      13815 :                     if (tok2->str() == ";") {
    1223                 :       7335 :                         tok = tok2;
    1224                 :       7335 :                         break;
    1225                 :            :                     }
    1226                 :            : 
    1227 [ +  - ][ +  + ]:       6480 :                     if (tok2->str() == "(")
    1228         [ +  - ]:        180 :                         f.push(tok2->previous());
    1229 [ +  - ][ +  + ]:       6300 :                     else if (!f.empty() && tok2->str() == ")")
         [ +  - ][ +  + ]
                 [ +  + ]
    1230         [ +  - ]:        180 :                         f.pop();
    1231                 :            : 
    1232         [ +  + ]:       6480 :                     if (tok2->varId() == varid) {
    1233                 :            :                         // Read data..
    1234 [ +  - ][ +  + ]:       3510 :                         if (!Token::Match(tok2->previous(), "&|(") &&
         [ +  + ][ +  + ]
    1235 [ +  - ][ +  - ]:       1665 :                             tok2->strAt(1) == "[") {
    1236 [ +  - ][ +  + ]:       2115 :                         } else if (f.empty() ||
         [ +  - ][ +  + ]
                 [ +  + ]
    1237 [ +  - ][ +  - ]:        180 :                                    !test_white_list(f.top()->str()) ||
    1238 [ +  - ][ +  - ]:        180 :                                    getDeallocationType(f.top(),varid)) {
    1239                 :       1620 :                             use = true;
    1240                 :            :                         }
    1241                 :            :                     }
    1242                 :            :                 }
    1243         [ +  + ]:       7335 :                 if (use)
    1244 [ +  - ][ +  - ]:       1575 :                     addtoken(&rettail, tok, "use");
                 [ +  - ]
    1245 [ +  - ][ +  - ]:       7335 :                 addtoken(&rettail, tok, ";");
         [ +  - ][ +  - ]
    1246                 :            :             }
    1247                 :            :         }
    1248                 :            : 
    1249                 :            :         // throw..
    1250 [ +  - ][ +  + ]:     552070 :         else if (Token::Match(tok, "try|throw|catch")) {
    1251         [ +  - ]:        585 :             addtoken(&rettail, tok, tok->str());
    1252 [ +  - ][ +  - ]:        585 :             if (tok->strAt(1) == "(")
                 [ +  + ]
    1253                 :        225 :                 tok = tok->next()->link();
    1254                 :            :         }
    1255                 :            : 
    1256                 :            :         // Assignment..
    1257         [ +  + ]:     560665 :         if (varid) {
    1258 [ +  - ][ +  + ]:     263347 :             if (Token::simpleMatch(tok, "= {")) {
    1259         [ +  - ]:         45 :                 const Token* const end2 = tok->linkAt(1);
    1260                 :         45 :                 bool use = false;
    1261         [ +  - ]:        225 :                 for (const Token *tok2 = tok; tok2 != end2; tok2 = tok2->next()) {
    1262         [ +  + ]:        225 :                     if (tok2->varId() == varid) {
    1263                 :         45 :                         use = true;
    1264                 :         45 :                         break;
    1265                 :            :                     }
    1266                 :            :                 }
    1267                 :            : 
    1268         [ +  - ]:         45 :                 if (use) {
    1269 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, "use");
                 [ +  - ]
    1270 [ +  - ][ +  - ]:         45 :                     addtoken(&rettail, tok, ";");
                 [ +  - ]
    1271                 :         45 :                     tok = tok->next()->link();
    1272                 :         45 :                     continue;
    1273                 :            :                 }
    1274                 :            :             }
    1275                 :            : 
    1276 [ +  - ][ +  + ]:     263302 :             if (Token::Match(tok, "& %var% = %varid% ;", varid)) {
    1277         [ +  + ]:         90 :                 while (rethead->next())
    1278         [ +  - ]:         45 :                     rethead->deleteNext();
    1279                 :         45 :                 return rethead;
    1280                 :            :             }
    1281 [ +  - ][ +  + ]:    1313225 :             if (Token::Match(tok, "[)=] %varid% [+;)]", varid) ||
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
                 [ +  + ]
    1282         [ +  - ]:     262492 :                 (Token::Match(tok, "%var% + %varid%", varid) &&
    1283 [ +  - ][ +  - ]:        180 :                  tok->strAt(3) != "[" &&
    1284 [ +  - ][ +  - ]:        135 :                  tok->strAt(3) != ".") ||
    1285         [ +  - ]:     262402 :                 Token::Match(tok, "<< %varid% ;", varid) ||
    1286         [ +  - ]:     262402 :                 Token::Match(tok, "= strcpy|strcat|memmove|memcpy ( %varid% ,", varid) ||
    1287         [ +  - ]:     262357 :                 Token::Match(tok, "[;{}] %var% [ %varid% ]", varid)) {
    1288 [ +  - ][ +  - ]:        990 :                 addtoken(&rettail, tok, "use");
                 [ +  - ]
    1289 [ +  - ][ +  + ]:     523994 :             } else if (Token::Match(tok->previous(), ";|{|}|=|(|,|%cop% %varid% [", varid) ||
         [ +  + ][ +  + ]
    1290         [ +  - ]:     261727 :                        Token::Match(tok->previous(), ";|{|}|=|(|,|%cop% %varid% .", varid)) {
    1291                 :            :                 // warning is written for "dealloc ; use_ ;".
    1292                 :            :                 // but this use doesn't affect the leak-checking
    1293 [ +  - ][ +  - ]:       1170 :                 addtoken(&rettail, tok, "use_");
                 [ +  - ]
    1294                 :            :             }
    1295                 :            :         }
    1296                 :            : 
    1297                 :            :         // Investigate function calls..
    1298 [ +  - ][ +  + ]:     560575 :         if (Token::Match(tok, "%var% (")) {
    1299                 :            :             // A function call should normally be followed by ";"
    1300 [ +  - ][ +  + ]:      37746 :             if (Token::simpleMatch(tok->next()->link(), ") {")) {
    1301 [ +  - ][ +  - ]:         90 :                 if (!Token::Match(tok, "if|for|while|switch")) {
    1302 [ +  - ][ +  - ]:         90 :                     addtoken(&rettail, tok, "exit");
                 [ +  - ]
    1303 [ +  - ][ +  - ]:         90 :                     addtoken(&rettail, tok, ";");
                 [ +  - ]
    1304                 :         90 :                     tok = tok->next()->link();
    1305                 :         90 :                     continue;
    1306                 :            :                 }
    1307                 :            :             }
    1308                 :            : 
    1309                 :            :             // Calling setjmp / longjmp => bail out
    1310 [ +  - ][ +  + ]:      37656 :             else if (Token::Match(tok, "setjmp|longjmp")) {
    1311         [ +  + ]:        945 :                 while (rethead->next())
    1312         [ +  - ]:        810 :                     rethead->deleteNext();
    1313                 :        135 :                 return rethead;
    1314                 :            :             }
    1315                 :            : 
    1316                 :            :             // Inside class function.. if the var is passed as a parameter then
    1317                 :            :             // just add a "::use"
    1318                 :            :             // The "::use" means that a member function was probably called but it wasn't analysed further
    1319         [ +  + ]:      37521 :             else if (classmember) {
    1320 [ +  - ][ +  - ]:        405 :                 if (noreturn.find(tok->str()) != noreturn.end())
                 [ +  + ]
    1321 [ +  - ][ +  - ]:        135 :                     addtoken(&rettail, tok, "exit");
                 [ +  - ]
    1322                 :            : 
    1323 [ +  - ][ +  + ]:        270 :                 else if (!test_white_list(tok->str())) {
    1324         [ +  - ]:        225 :                     const Token* const end2 = tok->linkAt(1);
    1325 [ +  - ][ +  + ]:        495 :                     for (const Token *tok2 = tok->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
    1326         [ +  + ]:        270 :                         if (tok2->varId() == varid) {
    1327 [ +  - ][ +  - ]:         90 :                             addtoken(&rettail, tok, "::use");
                 [ +  - ]
    1328                 :         90 :                             break;
    1329                 :            :                         }
    1330                 :            :                     }
    1331                 :            :                 }
    1332                 :            :             }
    1333                 :            : 
    1334                 :            :             else {
    1335 [ +  + ][ +  - ]:      37116 :                 if (varid > 0 && Token::Match(tok, "%var% ( close|fclose|pclose ( %varid% ) ) ;", varid)) {
         [ +  + ][ +  + ]
    1336 [ +  - ][ +  - ]:         90 :                     addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
    1337                 :         90 :                     tok = tok->next()->link();
    1338                 :         90 :                     continue;
    1339                 :            :                 }
    1340                 :            : 
    1341                 :      37026 :                 bool allocpar = false;
    1342 [ +  - ][ +  - ]:      37026 :                 const char *str = call_func(tok, callstack, varid, alloctype, dealloctype, allocpar, sz);
                 [ +  - ]
    1343         [ +  + ]:      37026 :                 if (str) {
    1344         [ +  + ]:      14490 :                     if (allocpar) {
    1345 [ +  - ][ +  - ]:        225 :                         addtoken(&rettail, tok, str);
                 [ +  - ]
    1346                 :        225 :                         tok = tok->next()->link();
    1347 [ +  + ][ +  - ]:      14265 :                     } else if (varid == 0 || str != std::string("alloc")) {
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ #  # ][ #  # ]
    1348 [ +  - ][ +  - ]:      14265 :                         addtoken(&rettail, tok, str);
                 [ +  - ]
    1349 [ #  # ][ #  # ]:          0 :                     } else if (Token::Match(tok->tokAt(-2), "%varid% =", varid)) {
                 [ #  # ]
    1350 [ #  # ][ #  # ]:          0 :                         addtoken(&rettail, tok, str);
                 [ #  # ]
    1351                 :            :                     }
    1352         [ +  + ]:      28971 :                 } else if (varid > 0 &&
           [ +  +  +  - ]
                 [ +  + ]
    1353         [ +  - ]:       6300 :                            getReallocationType(tok, varid) != No &&
    1354         [ +  - ]:        135 :                            tok->tokAt(2)->varId() == varid) {
    1355 [ +  - ][ +  - ]:        135 :                     addtoken(&rettail, tok, "if");
                 [ +  - ]
    1356 [ +  - ][ +  - ]:        135 :                     addtoken(&rettail, tok, "{");
                 [ +  - ]
    1357 [ +  - ][ +  - ]:        135 :                     addtoken(&rettail, tok, "dealloc");
                 [ +  - ]
    1358 [ +  - ][ +  - ]:        135 :                     addtoken(&rettail, tok, ";");
                 [ +  - ]
    1359 [ +  - ][ +  - ]:        135 :                     addtoken(&rettail, tok, "}");
                 [ +  - ]
    1360                 :        135 :                     tok = tok->next()->link();
    1361                 :        135 :                     continue;
    1362                 :            :                 }
    1363                 :            :             }
    1364                 :            :         }
    1365                 :            : 
    1366                 :            :         // Callback..
    1367 [ +  - ][ +  + ]:     560125 :         if (Token::Match(tok, "( *| %var%") && Token::simpleMatch(tok->link(),") (")) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1368                 :         90 :             const Token *tok2 = tok->next();
    1369 [ +  - ][ +  + ]:         90 :             if (tok2->str() == "*")
    1370                 :         45 :                 tok2 = tok2->next();
    1371                 :         90 :             tok2 = tok2->next();
    1372                 :            : 
    1373 [ +  - ][ -  + ]:         90 :             while (Token::Match(tok2, ". %var%"))
    1374         [ #  # ]:          0 :                 tok2 = tok2->tokAt(2);
    1375                 :            : 
    1376 [ +  - ][ +  + ]:         90 :             if (Token::simpleMatch(tok2, ") (")) {
    1377         [ +  - ]:        180 :                 for (; tok2; tok2 = tok2->next()) {
    1378 [ +  - ][ -  + ]:        135 :                     if (Token::Match(tok2, "[;{]"))
    1379                 :          0 :                         break;
    1380         [ +  + ]:        135 :                     else if (tok2->varId() == varid) {
    1381 [ +  - ][ +  - ]:         45 :                         addtoken(&rettail, tok, "use");
                 [ +  - ]
    1382                 :         45 :                         break;
    1383                 :            :                     }
    1384                 :            :                 }
    1385                 :            :             }
    1386                 :            :         }
    1387                 :            : 
    1388                 :            :         // Linux lists..
    1389 [ +  + ][ +  - ]:     560125 :         if (varid > 0 && Token::Match(tok, "[=(,] & %varid% [.[,)]", varid)) {
         [ +  + ][ +  + ]
    1390 [ +  - ][ +  - ]:        585 :             addtoken(&rettail, tok, "&use");
                 [ +  - ]
    1391                 :            :         }
    1392                 :            :     }
    1393                 :            : 
    1394         [ +  + ]:     350133 :     for (Token *tok1 = rethead; tok1; tok1 = tok1->next()) {
    1395 [ +  - ][ +  + ]:     312511 :         if (Token::simpleMatch(tok1, "callfunc alloc ;")) {
    1396         [ +  - ]:         45 :             tok1->deleteThis();
    1397 [ +  - ][ +  - ]:         45 :             tok1->insertToken("use");
                 [ +  - ]
    1398 [ +  - ][ +  - ]:         45 :             tok1->insertToken(";");
                 [ +  - ]
    1399                 :            :         }
    1400                 :            :     }
    1401                 :            : 
    1402                 :      37892 :     return rethead;
    1403                 :            : }
    1404                 :            : 
    1405                 :            : 
    1406                 :            : 
    1407                 :            : 
    1408                 :            : 
    1409                 :            : 
    1410                 :      16956 : void CheckMemoryLeakInFunction::simplifycode(Token *tok) const
    1411                 :            : {
    1412                 :            :     {
    1413                 :            :         // Replace "throw" that is not in a try block with "return"
    1414                 :      16956 :         int indentlevel = 0;
    1415                 :      16956 :         int trylevel = -1;
    1416         [ +  + ]:     167535 :         for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    1417         [ +  + ]:     150579 :             if (tok2->str() == "{")
    1418                 :       9765 :                 ++indentlevel;
    1419         [ +  + ]:     140814 :             else if (tok2->str() == "}") {
    1420                 :      24066 :                 --indentlevel;
    1421         [ +  + ]:      24066 :                 if (indentlevel <= trylevel)
    1422                 :      14391 :                     trylevel = -1;
    1423 [ +  + ][ +  + ]:     116748 :             } else if (trylevel == -1 && tok2->str() == "try")
                 [ +  + ]
    1424                 :        135 :                 trylevel = indentlevel;
    1425 [ +  + ][ +  + ]:     116613 :             else if (trylevel == -1 && tok2->str() == "throw")
                 [ +  + ]
    1426 [ +  - ][ +  - ]:         45 :                 tok2->str("return");
                 [ +  - ]
    1427                 :            :         }
    1428                 :            :     }
    1429                 :            : 
    1430                 :            :     // Insert extra ";"
    1431         [ +  + ]:     167895 :     for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    1432 [ +  + ][ +  + ]:     150939 :         if (!tok2->previous() || Token::Match(tok2->previous(), "[;{}]")) {
                 [ +  + ]
    1433         [ +  + ]:      99018 :             if (Token::Match(tok2, "assign|callfunc|use assign|callfunc|use|}")) {
    1434 [ +  - ][ +  - ]:        360 :                 tok2->insertToken(";");
                 [ +  - ]
    1435                 :            :             }
    1436                 :            :         }
    1437                 :            :     }
    1438                 :            : 
    1439                 :            :     // remove redundant braces..
    1440         [ +  + ]:     167625 :     for (Token *start = tok; start; start = start->next()) {
    1441         [ +  + ]:     150669 :         if (Token::simpleMatch(start, "; {")) {
    1442                 :            :             // the "link" doesn't work here. Find the end brace..
    1443                 :        135 :             unsigned int indent = 0;
    1444         [ +  - ]:        855 :             for (Token *end = start; end; end = end->next()) {
    1445         [ +  + ]:        720 :                 if (end->str() == "{")
    1446                 :        135 :                     ++indent;
    1447         [ +  + ]:        585 :                 else if (end->str() == "}") {
    1448         [ +  - ]:        135 :                     if (indent <= 1) {
    1449                 :            :                         // If the start/end braces are redundant, delete them
    1450 [ +  - ][ +  - ]:        135 :                         if (indent == 1 && Token::Match(end->previous(), "[;{}] } %any%")) {
                 [ +  - ]
    1451                 :        135 :                             start->deleteNext();
    1452                 :        135 :                             end->deleteThis();
    1453                 :            :                         }
    1454                 :        135 :                         break;
    1455                 :            :                     }
    1456                 :          0 :                     --indent;
    1457                 :            :                 }
    1458                 :            :             }
    1459                 :            :         }
    1460                 :            :     }
    1461                 :            : 
    1462                 :            :     // reduce the code..
    1463                 :            :     // it will be reduced in N passes. When a pass completes without any
    1464                 :            :     // simplifications the loop is done.
    1465                 :      16956 :     bool done = false;
    1466         [ +  + ]:      53442 :     while (! done) {
    1467                 :            :         //tok->printOut("simplifycode loop..");
    1468                 :      36486 :         done = true;
    1469                 :            : 
    1470                 :            :         // reduce callfunc
    1471         [ +  + ]:     327240 :         for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    1472         [ +  + ]:     290754 :             if (tok2->str() == "callfunc") {
    1473         [ +  + ]:       1575 :                 if (!Token::Match(tok2->previous(), "[;{}] callfunc ; }"))
    1474                 :        990 :                     tok2->deleteThis();
    1475                 :            :             }
    1476                 :            :         }
    1477                 :            : 
    1478                 :            :         // If the code starts with "if return ;" then remove it
    1479         [ +  + ]:      36486 :         if (Token::Match(tok, ";| if return ;")) {
    1480                 :        225 :             tok->deleteNext();
    1481                 :        225 :             tok->deleteThis();
    1482         [ +  - ]:        225 :             if (tok->str() == "return")
    1483                 :        225 :                 tok->deleteThis();
    1484         [ +  + ]:        225 :             if (tok->strAt(1) == "else")
    1485                 :         90 :                 tok->deleteNext();
    1486                 :            :         }
    1487                 :            : 
    1488                 :            :         // simplify "while1" contents..
    1489         [ +  + ]:     325350 :         for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    1490         [ +  + ]:     288864 :             if (Token::simpleMatch(tok2, "while1 {")) {
    1491                 :       1035 :                 unsigned int innerIndentlevel = 0;
    1492         [ +  - ]:       8595 :                 for (Token *tok3 = tok2->tokAt(2); tok3; tok3 = tok3->next()) {
    1493         [ +  + ]:       8595 :                     if (tok3->str() == "{")
    1494                 :        900 :                         ++innerIndentlevel;
    1495         [ +  + ]:       7695 :                     else if (tok3->str() == "}") {
    1496         [ +  + ]:       1935 :                         if (innerIndentlevel == 0)
    1497                 :       1035 :                             break;
    1498                 :        900 :                         --innerIndentlevel;
    1499                 :            :                     }
    1500 [ +  + ][ +  + ]:       7650 :                     while (innerIndentlevel == 0 && Token::Match(tok3, "[{};] if|ifv|else { continue ; }")) {
                 [ +  + ]
    1501                 :         90 :                         tok3->deleteNext(5);
    1502         [ -  + ]:         90 :                         if (tok3->strAt(1) == "else")
    1503                 :          0 :                             tok3->deleteNext();
    1504                 :            :                     }
    1505                 :            :                 }
    1506                 :            : 
    1507         [ +  + ]:       1035 :                 if (Token::simpleMatch(tok2, "while1 { if { dealloc ; return ; } }")) {
    1508 [ +  - ][ +  - ]:        135 :                     tok2->str(";");
                 [ +  - ]
    1509                 :        135 :                     tok2->deleteNext(3);
    1510                 :        135 :                     tok2->tokAt(4)->deleteNext(2);
    1511                 :            :                 }
    1512                 :            :             }
    1513                 :            :         }
    1514                 :            : 
    1515                 :            :         // Main inner simplification loop
    1516 [ +  - ][ +  + ]:     266445 :         for (Token *tok2 = tok; tok2; tok2 = tok2 ? tok2->next() : NULL) {
    1517                 :            :             // Delete extra ";"
    1518         [ +  + ]:     245394 :             while (Token::Match(tok2, "[;{}] ;")) {
    1519                 :      15435 :                 tok2->deleteNext();
    1520                 :      15435 :                 done = false;
    1521                 :            :             }
    1522                 :            : 
    1523                 :            :             // Replace "{ }" with ";"
    1524         [ +  + ]:     229959 :             if (Token::simpleMatch(tok2->next(), "{ }")) {
    1525                 :       1260 :                 tok2->deleteNext(2);
    1526 [ +  - ][ +  - ]:       1260 :                 tok2->insertToken(";");
                 [ +  - ]
    1527                 :       1260 :                 done = false;
    1528                 :            :             }
    1529                 :            : 
    1530                 :            :             // Delete braces around a single instruction..
    1531         [ +  + ]:     229959 :             if (Token::Match(tok2->next(), "{ %var% ; }")) {
    1532                 :       4950 :                 tok2->deleteNext();
    1533                 :       4950 :                 tok2->tokAt(2)->deleteNext();
    1534                 :       4950 :                 done = false;
    1535                 :            :             }
    1536         [ +  + ]:     229959 :             if (Token::Match(tok2->next(), "{ %var% %var% ; }")) {
    1537                 :       1170 :                 tok2->deleteNext();
    1538                 :       1170 :                 tok2->tokAt(3)->deleteNext();
    1539                 :       1170 :                 done = false;
    1540                 :            :             }
    1541                 :            : 
    1542                 :            :             // Reduce "if if|callfunc" => "if"
    1543         [ +  + ]:     228789 :             else if (Token::Match(tok2, "if if|callfunc")) {
    1544                 :         90 :                 tok2->deleteNext();
    1545                 :         90 :                 done = false;
    1546                 :            :             }
    1547                 :            : 
    1548                 :            :             // outer/inner if blocks. Remove outer condition..
    1549         [ +  + ]:     228699 :             else if (Token::Match(tok2->next(), "if|if(var) { if return use ; }")) {
    1550                 :         90 :                 tok2->deleteNext(2);
    1551                 :         90 :                 tok2->tokAt(4)->deleteNext();
    1552                 :         90 :                 done = false;
    1553                 :            :             }
    1554                 :            : 
    1555 [ +  + ][ +  + ]:     228609 :             else if (tok2->next() && tok2->next()->str() == "if") {
                 [ +  + ]
    1556                 :            :                 // Delete empty if that is not followed by an else
    1557         [ +  + ]:      10080 :                 if (Token::Match(tok2->next(), "if ; !!else")) {
    1558                 :        360 :                     tok2->deleteNext();
    1559                 :        360 :                     done = false;
    1560                 :            :                 }
    1561                 :            : 
    1562                 :            :                 // Reduce "if X ; else X ;" => "X ;"
    1563   [ +  +  +  + ]:      10035 :                 else if (Token::Match(tok2->next(), "if %var% ; else %var% ;") &&
                 [ +  + ]
    1564                 :        315 :                          tok2->strAt(2) == tok2->strAt(5)) {
    1565                 :        180 :                     tok2->deleteNext(4);
    1566                 :        180 :                     done = false;
    1567                 :            :                 }
    1568                 :            : 
    1569                 :            :                 // Reduce "if continue ; if continue ;" => "if continue ;"
    1570         [ +  + ]:       9540 :                 else if (Token::simpleMatch(tok2->next(), "if continue ; if continue ;")) {
    1571                 :         45 :                     tok2->deleteNext(3);
    1572                 :         45 :                     done = false;
    1573                 :            :                 }
    1574                 :            : 
    1575                 :            :                 // Reduce "if return ; alloc ;" => "alloc ;"
    1576         [ +  + ]:       9495 :                 else if (Token::Match(tok2, "[;{}] if return ; alloc|return ;")) {
    1577                 :        180 :                     tok2->deleteNext(3);
    1578                 :        180 :                     done = false;
    1579                 :            :                 }
    1580                 :            : 
    1581                 :            :                 // "[;{}] if alloc ; else return ;" => "[;{}] alloc ;"
    1582         [ +  + ]:       9315 :                 else if (Token::Match(tok2, "[;{}] if alloc ; else return ;")) {
    1583                 :            :                     // Remove "if"
    1584                 :         45 :                     tok2->deleteNext();
    1585                 :            :                     // Remove "; else return"
    1586                 :         45 :                     tok2->next()->deleteNext(3);
    1587                 :         45 :                     done = false;
    1588                 :            :                 }
    1589                 :            : 
    1590                 :            :                 // Reduce "if ; else %var% ;" => "if %var% ;"
    1591         [ +  + ]:       9270 :                 else if (Token::Match(tok2->next(), "if ; else %var% ;")) {
    1592                 :         45 :                     tok2->next()->deleteNext(2);
    1593                 :         45 :                     done = false;
    1594                 :            :                 }
    1595                 :            : 
    1596                 :            :                 // Reduce "if ; else" => "if"
    1597         [ +  + ]:       9225 :                 else if (Token::simpleMatch(tok2->next(), "if ; else")) {
    1598                 :        180 :                     tok2->next()->deleteNext(2);
    1599                 :        180 :                     done = false;
    1600                 :            :                 }
    1601                 :            : 
    1602                 :            :                 // Reduce "if return ; else|if return|continue ;" => "if return ;"
    1603         [ +  + ]:       9045 :                 else if (Token::Match(tok2->next(), "if return ; else|if return|continue|break ;")) {
    1604                 :         45 :                     tok2->tokAt(3)->deleteNext(3);
    1605                 :         45 :                     done = false;
    1606                 :            :                 }
    1607                 :            : 
    1608                 :            :                 // Reduce "if continue|break ; else|if return ;" => "if return ;"
    1609         [ +  + ]:       9000 :                 else if (Token::Match(tok2->next(), "if continue|break ; if|else return ;")) {
    1610                 :         45 :                     tok2->next()->deleteNext(3);
    1611                 :         45 :                     done = false;
    1612                 :            :                 }
    1613                 :            : 
    1614                 :            :                 // Remove "else" after "if continue|break|return"
    1615         [ +  + ]:       8955 :                 else if (Token::Match(tok2->next(), "if continue|break|return ; else")) {
    1616                 :         45 :                     tok2->tokAt(3)->deleteNext();
    1617                 :         45 :                     done = false;
    1618                 :            :                 }
    1619                 :            : 
    1620                 :            :                 // Delete "if { dealloc|assign|use ; return ; }"
    1621   [ +  +  +  + ]:      10350 :                 else if (Token::Match(tok2, "[;{}] if { dealloc|assign|use ; return ; }") &&
                 [ +  + ]
    1622                 :       1440 :                          !Token::findmatch(tok, "if {| alloc ;")) {
    1623                 :       1125 :                     tok2->deleteNext(7);
    1624         [ +  + ]:       1125 :                     if (tok2->strAt(1) == "else")
    1625                 :         90 :                         tok2->deleteNext();
    1626                 :       1125 :                     done = false;
    1627                 :            :                 }
    1628                 :            : 
    1629                 :            :                 // Remove "if { dealloc ; callfunc ; } !!else|return"
    1630   [ +  +  +  + ]:       7965 :                 else if (Token::Match(tok2->next(), "if { dealloc|assign ; callfunc ; }") &&
                 [ +  + ]
    1631                 :        180 :                          !Token::Match(tok2->tokAt(8), "else|return")) {
    1632                 :        135 :                     tok2->deleteNext(7);
    1633                 :        135 :                     done = false;
    1634                 :            :                 }
    1635                 :            : 
    1636                 :      10080 :                 continue;
    1637                 :            :             }
    1638                 :            : 
    1639                 :            :             // Reduce "alloc while(!var) alloc ;" => "alloc ;"
    1640         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] alloc ; while(!var) alloc ;")) {
    1641                 :         90 :                 tok2->deleteNext(3);
    1642                 :         90 :                 done = false;
    1643                 :            :             }
    1644                 :            : 
    1645                 :            :             // Reduce "ifv return;" => "if return use;"
    1646         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "ifv return ;")) {
    1647 [ +  - ][ +  - ]:         90 :                 tok2->str("if");
                 [ +  - ]
    1648 [ +  - ][ +  - ]:         90 :                 tok2->next()->insertToken("use");
                 [ +  - ]
    1649                 :         90 :                 done = false;
    1650                 :            :             }
    1651                 :            : 
    1652                 :            :             // Reduce "if(var) dealloc ;" and "if(var) use ;" that is not followed by an else..
    1653         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] if(var) assign|dealloc|use ; !!else")) {
    1654                 :        135 :                 tok2->deleteNext();
    1655                 :        135 :                 done = false;
    1656                 :            :             }
    1657                 :            : 
    1658                 :            :             // Reduce "; if(!var) alloc ; !!else" => "; dealloc ; alloc ;"
    1659         [ +  + ]:     219879 :             if (Token::Match(tok2, "; if(!var) alloc ; !!else")) {
    1660                 :            :                 // Remove the "if(!var)"
    1661                 :         90 :                 tok2->deleteNext();
    1662                 :            : 
    1663                 :            :                 // Insert "dealloc ;" before the "alloc ;"
    1664 [ +  - ][ +  - ]:         90 :                 tok2->insertToken(";");
                 [ +  - ]
    1665 [ +  - ][ +  - ]:         90 :                 tok2->insertToken("dealloc");
                 [ +  - ]
    1666                 :            : 
    1667                 :         90 :                 done = false;
    1668                 :            :             }
    1669                 :            : 
    1670                 :            :             // Reduce "if(!var) exit ;" => ";"
    1671         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "; if(!var) exit ;")) {
    1672                 :         90 :                 tok2->deleteNext(2);
    1673                 :         90 :                 done = false;
    1674                 :            :             }
    1675                 :            : 
    1676                 :            :             // Reduce "if* ;"..
    1677         [ +  + ]:     219879 :             if (Token::Match(tok2->next(), "if(var)|if(!var)|ifv ;")) {
    1678                 :            :                 // Followed by else..
    1679         [ +  + ]:        675 :                 if (tok2->strAt(3) == "else") {
    1680                 :        180 :                     tok2 = tok2->next();
    1681         [ +  + ]:        180 :                     if (tok2->str() == "if(var)")
    1682 [ +  - ][ +  - ]:         45 :                         tok2->str("if(!var)");
                 [ +  - ]
    1683         [ +  + ]:        135 :                     else if (tok2->str() == "if(!var)")
    1684 [ +  - ][ +  - ]:         90 :                         tok2->str("if(var)");
                 [ +  - ]
    1685                 :            : 
    1686                 :            :                     // remove the "; else"
    1687                 :        180 :                     tok2->deleteNext(2);
    1688                 :            :                 } else {
    1689                 :            :                     // remove the "if*"
    1690                 :        495 :                     tok2->deleteNext();
    1691                 :            :                 }
    1692                 :        675 :                 done = false;
    1693                 :            :             }
    1694                 :            : 
    1695                 :            :             // Reduce "else ;" => ";"
    1696         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2->next(), "else ;")) {
    1697                 :        225 :                 tok2->deleteNext();
    1698                 :        225 :                 done = false;
    1699                 :            :             }
    1700                 :            : 
    1701                 :            :             // Reduce "while1 continue| ;" => "use ;"
    1702         [ +  + ]:     219879 :             if (Token::Match(tok2, "while1 if| continue| ;")) {
    1703 [ +  - ][ +  - ]:        135 :                 tok2->str("use");
                 [ +  - ]
    1704         [ +  + ]:        270 :                 while (tok2->strAt(1) != ";")
    1705                 :        135 :                     tok2->deleteNext();
    1706                 :        135 :                 done = false;
    1707                 :            :             }
    1708                 :            : 
    1709                 :            :             // Reduce "while1 if break ;" => ";"
    1710         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "while1 if break ;")) {
    1711 [ +  - ][ +  - ]:         45 :                 tok2->str(";");
                 [ +  - ]
    1712                 :         45 :                 tok2->deleteNext(2);
    1713                 :         45 :                 done = false;
    1714                 :            :             }
    1715                 :            : 
    1716                 :            :             // Delete if block: "alloc; if return use ;"
    1717         [ +  + ]:     219879 :             if (Token::Match(tok2, "alloc ; if return use ; !!else")) {
    1718                 :        360 :                 tok2->deleteNext(4);
    1719                 :        360 :                 done = false;
    1720                 :            :             }
    1721                 :            : 
    1722                 :            :             // Reduce "alloc|dealloc|use|callfunc ; exit ;" => "; exit ;"
    1723         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] alloc|dealloc|use|callfunc ; exit ;")) {
    1724                 :        630 :                 tok2->deleteNext();
    1725                 :        630 :                 done = false;
    1726                 :            :             }
    1727                 :            : 
    1728                 :            :             // Reduce "alloc|dealloc|use ; if(var) exit ;"
    1729         [ +  + ]:     219879 :             if (Token::Match(tok2, "alloc|dealloc|use ; if(var) exit ;")) {
    1730                 :         90 :                 tok2->deleteThis();
    1731                 :         90 :                 done = false;
    1732                 :            :             }
    1733                 :            : 
    1734                 :            :             // Remove "if exit ;"
    1735         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "if exit ;")) {
    1736                 :        270 :                 tok2->deleteNext();
    1737                 :        270 :                 tok2->deleteThis();
    1738                 :        270 :                 done = false;
    1739                 :            :             }
    1740                 :            : 
    1741                 :            :             // Remove the "if break|continue ;" that follows "dealloc ; alloc ;"
    1742 [ +  + ][ +  + ]:     219879 :             if (! _settings->experimental && Token::Match(tok2, "dealloc ; alloc ; if break|continue ;")) {
                 [ +  + ]
    1743                 :         45 :                 tok2->tokAt(3)->deleteNext(2);
    1744                 :         45 :                 done = false;
    1745                 :            :             }
    1746                 :            : 
    1747                 :            :             // if break ; break ; => break ;
    1748         [ -  + ]:     219879 :             if (Token::Match(tok2->previous(), "[;{}] if break ; break ;")) {
    1749                 :          0 :                 tok2->deleteNext(3);
    1750                 :          0 :                 done = false;
    1751                 :            :             }
    1752                 :            : 
    1753                 :            :             // Reduce "do { dealloc ; alloc ; } while(var) ;" => ";"
    1754         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2->next(), "do { dealloc ; alloc ; } while(var) ;")) {
    1755                 :         45 :                 tok2->deleteNext(8);
    1756                 :         45 :                 done = false;
    1757                 :            :             }
    1758                 :            : 
    1759                 :            :             // Reduce "do { alloc ; } " => "alloc ;"
    1760                 :            :             /** @todo If the loop "do { alloc ; }" can be executed twice, reduce it to "loop alloc ;" */
    1761         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2->next(), "do { alloc ; }")) {
    1762                 :         45 :                 tok2->deleteNext(2);
    1763                 :         45 :                 tok2->tokAt(2)->deleteNext();
    1764                 :         45 :                 done = false;
    1765                 :            :             }
    1766                 :            : 
    1767                 :            :             // Reduce "loop break ; => ";"
    1768         [ +  + ]:     219879 :             if (Token::Match(tok2->next(), "loop break|continue ;")) {
    1769                 :         90 :                 tok2->deleteNext(2);
    1770                 :         90 :                 done = false;
    1771                 :            :             }
    1772                 :            : 
    1773                 :            :             // Reduce "loop|do ;" => ";"
    1774         [ +  + ]:     219879 :             if (Token::Match(tok2, "loop|do ;")) {
    1775                 :        360 :                 tok2->deleteThis();
    1776                 :        360 :                 done = false;
    1777                 :            :             }
    1778                 :            : 
    1779                 :            :             // Reduce "loop if break|continue ; !!else" => ";"
    1780         [ +  + ]:     219879 :             if (Token::Match(tok2->next(), "loop if break|continue ; !!else")) {
    1781                 :        180 :                 tok2->deleteNext(3);
    1782                 :        180 :                 done = false;
    1783                 :            :             }
    1784                 :            : 
    1785                 :            :             // Reduce "loop { if break|continue ; !!else" => "loop {"
    1786         [ +  + ]:     219879 :             if (Token::Match(tok2, "loop { if break|continue ; !!else")) {
    1787                 :        270 :                 tok2->next()->deleteNext(3);
    1788                 :        270 :                 done = false;
    1789                 :            :             }
    1790                 :            : 
    1791                 :            :             // Replace "do ; loop ;" with ";"
    1792         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "; loop ;")) {
    1793                 :         90 :                 tok2->deleteNext(2);
    1794                 :         90 :                 done = false;
    1795                 :            :             }
    1796                 :            : 
    1797                 :            :             // Replace "loop loop .." with "loop .."
    1798         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "loop loop")) {
    1799                 :         90 :                 tok2->deleteThis();
    1800                 :         90 :                 done = false;
    1801                 :            :             }
    1802                 :            : 
    1803                 :            :             // Replace "loop if return ;" with "if return ;"
    1804         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2->next(), "loop if return")) {
    1805                 :        180 :                 tok2->deleteNext();
    1806                 :        180 :                 done = false;
    1807                 :            :             }
    1808                 :            : 
    1809                 :            :             // Reduce "loop|while1 { dealloc ; alloc ; }"
    1810         [ +  + ]:     219879 :             if (Token::Match(tok2, "loop|while1 { dealloc ; alloc ; }")) {
    1811                 :            :                 // delete "{"
    1812                 :        225 :                 tok2->deleteNext();
    1813                 :            :                 // delete "loop|while1"
    1814                 :        225 :                 tok2->deleteThis();
    1815                 :            : 
    1816                 :            :                 // delete "}"
    1817                 :        225 :                 tok2->tokAt(3)->deleteNext();
    1818                 :            : 
    1819                 :        225 :                 done = false;
    1820                 :            :             }
    1821                 :            : 
    1822                 :            :             // loop { use ; callfunc ; }  =>  use ;
    1823                 :            :             // assume that the "callfunc" is not noreturn
    1824         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "loop { use ; callfunc ; }")) {
    1825                 :         45 :                 tok2->deleteNext(6);
    1826 [ +  - ][ +  - ]:         45 :                 tok2->str("use");
                 [ +  - ]
    1827 [ +  - ][ +  - ]:         45 :                 tok2->insertToken(";");
                 [ +  - ]
    1828                 :         45 :                 done = false;
    1829                 :            :             }
    1830                 :            : 
    1831                 :            :             // Delete if block in "alloc ; if(!var) return ;"
    1832         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "alloc ; if(!var) return ;")) {
    1833                 :        855 :                 tok2->deleteNext(3);
    1834                 :        855 :                 done = false;
    1835                 :            :             }
    1836                 :            : 
    1837                 :            :             // Reduce "[;{}] return use ; %var%" => "[;{}] return use ;"
    1838         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] return use ; %var%")) {
    1839                 :         45 :                 tok2->tokAt(3)->deleteNext();
    1840                 :         45 :                 done = false;
    1841                 :            :             }
    1842                 :            : 
    1843                 :            :             // Reduce "if(var) return use ;" => "return use ;"
    1844         [ +  + ]:     219879 :             if (Token::Match(tok2->next(), "if(var) return use ; !!else")) {
    1845                 :         90 :                 tok2->deleteNext();
    1846                 :         90 :                 done = false;
    1847                 :            :             }
    1848                 :            : 
    1849                 :            :             // malloc - realloc => alloc ; dealloc ; alloc ;
    1850                 :            :             // Reduce "[;{}] alloc ; dealloc ; alloc ;" => "[;{}] alloc ;"
    1851         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] alloc ; dealloc ; alloc ;")) {
    1852                 :        315 :                 tok2->deleteNext(4);
    1853                 :        315 :                 done = false;
    1854                 :            :             }
    1855                 :            : 
    1856                 :            :             // use; dealloc; => dealloc;
    1857         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] use ; dealloc ;")) {
    1858                 :        315 :                 tok2->deleteNext(2);
    1859                 :        315 :                 done = false;
    1860                 :            :             }
    1861                 :            : 
    1862                 :            :             // use use => use
    1863         [ -  + ]:     219879 :             while (Token::simpleMatch(tok2, "use use")) {
    1864                 :          0 :                 tok2->deleteNext();
    1865                 :          0 :                 done = false;
    1866                 :            :             }
    1867                 :            : 
    1868                 :            :             // use use_ => use
    1869         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "use use_")) {
    1870                 :         45 :                 tok2->deleteNext();
    1871                 :         45 :                 done = false;
    1872                 :            :             }
    1873                 :            : 
    1874                 :            :             // use_ use => use
    1875         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "use_ use")) {
    1876                 :         45 :                 tok2->deleteThis();
    1877                 :         45 :                 done = false;
    1878                 :            :             }
    1879                 :            : 
    1880                 :            :             // use & use => use
    1881         [ +  + ]:     219924 :             while (Token::simpleMatch(tok2, "use & use")) {
    1882                 :         45 :                 tok2->deleteNext(2);
    1883                 :         45 :                 done = false;
    1884                 :            :             }
    1885                 :            : 
    1886                 :            :             // & use use => use
    1887         [ +  + ]:     219924 :             while (Token::simpleMatch(tok2, "& use use")) {
    1888                 :         45 :                 tok2->deleteThis();
    1889                 :         45 :                 tok2->deleteThis();
    1890                 :         45 :                 done = false;
    1891                 :            :             }
    1892                 :            : 
    1893                 :            :             // use; if| use; => use;
    1894         [ +  + ]:     220059 :             while (Token::Match(tok2, "[;{}] use ; if| use ;")) {
    1895                 :        180 :                 Token *t = tok2->tokAt(2);
    1896         [ -  + ]:        180 :                 t->deleteNext(2+(t->str()=="if" ? 1 : 0));
    1897                 :        180 :                 done = false;
    1898                 :            :             }
    1899                 :            : 
    1900                 :            :             // Delete first part in "use ; return use ;"
    1901         [ +  + ]:     219879 :             if (Token::Match(tok2, "[;{}] use ; return use ;")) {
    1902                 :        135 :                 tok2->deleteNext(2);
    1903                 :        135 :                 done = false;
    1904                 :            :             }
    1905                 :            : 
    1906                 :            :             // try/catch
    1907         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "try ; catch exit ;")) {
    1908                 :         45 :                 tok2->deleteNext(3);
    1909                 :         45 :                 tok2->deleteThis();
    1910                 :         45 :                 done = false;
    1911                 :            :             }
    1912                 :            : 
    1913                 :            :             // Delete second case in "case ; case ;"
    1914         [ +  + ]:     219924 :             while (Token::simpleMatch(tok2, "case ; case ;")) {
    1915                 :         45 :                 tok2->deleteNext(2);
    1916                 :         45 :                 done = false;
    1917                 :            :             }
    1918                 :            : 
    1919                 :            :             // Replace switch with if (if not complicated)
    1920         [ +  + ]:     219879 :             if (Token::simpleMatch(tok2, "switch {")) {
    1921                 :            :                 // Right now, I just handle if there are a few case and perhaps a default.
    1922                 :        450 :                 bool valid = false;
    1923                 :        450 :                 bool incase = false;
    1924         [ +  - ]:       3690 :                 for (const Token * _tok = tok2->tokAt(2); _tok; _tok = _tok->next()) {
    1925         [ +  + ]:       3690 :                     if (_tok->str() == "{")
    1926                 :         45 :                         break;
    1927                 :            : 
    1928         [ +  + ]:       3645 :                     else if (_tok->str() == "}") {
    1929                 :        360 :                         valid = true;
    1930                 :        360 :                         break;
    1931                 :            :                     }
    1932                 :            : 
    1933         [ -  + ]:       3285 :                     else if (_tok->str() == "switch")
    1934                 :          0 :                         break;
    1935                 :            : 
    1936         [ -  + ]:       3285 :                     else if (_tok->str() == "loop")
    1937                 :          0 :                         break;
    1938                 :            : 
    1939 [ +  + ][ +  + ]:       3285 :                     else if (incase && _tok->str() == "case")
                 [ +  + ]
    1940                 :         45 :                         break;
    1941                 :            : 
    1942         [ -  + ]:       3240 :                     else if (Token::Match(_tok, "return !!;"))
    1943                 :          0 :                         break;
    1944                 :            : 
    1945         [ +  + ]:       3240 :                     if (Token::Match(_tok, "if return|break use| ;"))
    1946                 :         45 :                         _tok = _tok->tokAt(2);
    1947                 :            : 
    1948                 :       3240 :                     incase |= (_tok->str() == "case");
    1949 [ +  + ][ +  + ]:       3240 :                     incase &= (_tok->str() != "break" && _tok->str() != "return");
    1950                 :            :                 }
    1951                 :            : 
    1952 [ +  + ][ +  - ]:        450 :                 if (!incase && valid) {
    1953                 :        360 :                     done = false;
    1954 [ +  - ][ +  - ]:        360 :                     tok2->str(";");
                 [ +  - ]
    1955                 :        360 :                     tok2->deleteNext();
    1956                 :        360 :                     tok2 = tok2->next();
    1957                 :        360 :                     bool first = true;
    1958         [ +  + ]:        990 :                     while (Token::Match(tok2, "case|default")) {
    1959                 :        630 :                         const bool def(tok2->str() == "default");
    1960 [ +  + ][ +  - ]:        630 :                         tok2->str(first ? "if" : "}");
         [ +  - ][ +  - ]
    1961         [ +  + ]:        630 :                         if (first) {
    1962                 :        360 :                             first = false;
    1963 [ +  - ][ +  - ]:        360 :                             tok2->insertToken("{");
                 [ +  - ]
    1964                 :            :                         } else {
    1965                 :            :                             // Insert "else [if] {
    1966 [ +  - ][ +  - ]:        270 :                             tok2->insertToken("{");
                 [ +  - ]
    1967         [ -  + ]:        270 :                             if (! def)
    1968 [ #  # ][ #  # ]:          0 :                                 tok2->insertToken("if");
                 [ #  # ]
    1969 [ +  - ][ +  - ]:        270 :                             tok2->insertToken("else");
                 [ +  - ]
    1970                 :        270 :                             tok2 = tok2->next();
    1971                 :            :                         }
    1972         [ +  - ]:       3060 :                         while (tok2) {
    1973         [ -  + ]:       3060 :                             if (tok2->str() == "}")
    1974                 :          0 :                                 break;
    1975         [ +  + ]:       3060 :                             if (Token::Match(tok2, "break|return ;"))
    1976                 :        630 :                                 break;
    1977         [ +  + ]:       2430 :                             if (Token::Match(tok2, "if return|break use| ;"))
    1978                 :         45 :                                 tok2 = tok2->tokAt(2);
    1979                 :            :                             else
    1980                 :       2385 :                                 tok2 = tok2->next();
    1981                 :            :                         }
    1982         [ +  + ]:        630 :                         if (Token::simpleMatch(tok2, "break ;")) {
    1983 [ +  - ][ +  - ]:        360 :                             tok2->str(";");
                 [ +  - ]
    1984                 :        360 :                             tok2 = tok2->tokAt(2);
    1985 [ +  - ][ +  - ]:        270 :                         } else if (tok2 && tok2->str() == "return") {
                 [ +  - ]
    1986                 :        270 :                             tok2 = tok2->tokAt(2);
    1987                 :            :                         }
    1988                 :            :                     }
    1989                 :            :                 }
    1990                 :            :             }
    1991                 :            :         }
    1992                 :            : 
    1993                 :            :         // If "--all" is given, remove all "callfunc"..
    1994 [ +  + ][ +  + ]:      36486 :         if (done && _settings->experimental) {
    1995         [ +  + ]:       5445 :             for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    1996         [ -  + ]:       4770 :                 if (tok2->str() == "callfunc") {
    1997                 :          0 :                     tok2->deleteThis();
    1998                 :          0 :                     done = false;
    1999                 :            :                 }
    2000                 :            :             }
    2001                 :            :         }
    2002                 :            :     }
    2003                 :      16956 : }
    2004                 :            : 
    2005                 :            : 
    2006                 :            : 
    2007                 :            : 
    2008                 :            : 
    2009                 :      12456 : const Token *CheckMemoryLeakInFunction::findleak(const Token *tokens)
    2010                 :            : {
    2011                 :            :     const Token *result;
    2012                 :            : 
    2013         [ +  + ]:      12456 :     if ((result = Token::findsimplematch(tokens, "loop alloc ;")) != NULL) {
    2014                 :         90 :         return result;
    2015                 :            :     }
    2016                 :            : 
    2017         [ +  + ]:      12366 :     if (Token::Match(tokens, "alloc ; if|if(var)|ifv break|continue|return ;")) {
    2018                 :        180 :         return tokens->tokAt(3);
    2019                 :            :     }
    2020                 :            : 
    2021         [ +  + ]:      12186 :     if ((result = Token::findmatch(tokens, "alloc ; if|if(var)|ifv return ;")) != NULL) {
    2022                 :        585 :         return result->tokAt(3);
    2023                 :            :     }
    2024                 :            : 
    2025         [ +  + ]:      11601 :     if ((result = Token::findmatch(tokens, "alloc ; alloc|assign|return callfunc| ;")) != NULL) {
    2026                 :        990 :         return result->tokAt(2);
    2027                 :            :     }
    2028                 :            : 
    2029         [ +  + ]:      10611 :     if ((result = Token::findsimplematch(tokens, "; alloc ; if assign ;")) != NULL) {
    2030                 :         45 :         return result->tokAt(4);
    2031                 :            :     }
    2032                 :            : 
    2033   [ +  +  +  - ]:      10656 :     if (((result = Token::findsimplematch(tokens, "; alloc ; if dealloc ; }")) != NULL) &&
                 [ +  + ]
    2034                 :         90 :         !result->tokAt(7)) {
    2035                 :         90 :         return result->tokAt(6);
    2036                 :            :     }
    2037                 :            : 
    2038         [ +  + ]:      10476 :     if ((result = Token::findsimplematch(tokens, "alloc ; }")) != NULL) {
    2039         [ +  + ]:       3771 :         if (result->tokAt(3) == NULL)
    2040                 :       3681 :             return result->tokAt(2);
    2041                 :            :     }
    2042                 :            : 
    2043                 :            :     // No deallocation / usage => report leak at the last token
    2044         [ +  + ]:       6795 :     if (!Token::findmatch(tokens, "dealloc|use")) {
    2045                 :        225 :         const Token *last = tokens;
    2046         [ +  + ]:       1305 :         while (last->next())
    2047                 :       1080 :             last = last->next();
    2048                 :            : 
    2049                 :            :         // not a leak if exit is called before the end of the function
    2050         [ +  + ]:        225 :         if (!Token::Match(last->tokAt(-2), "exit|callfunc ; }"))
    2051                 :        135 :             return last;
    2052                 :            :     }
    2053                 :            : 
    2054                 :      12456 :     return NULL;
    2055                 :            : }
    2056                 :            : 
    2057                 :            : 
    2058                 :            : 
    2059                 :            : 
    2060                 :            : 
    2061                 :            : 
    2062                 :            : // Check for memory leaks for a function variable.
    2063                 :      30287 : void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string &varname, unsigned int varid, bool classmember, unsigned int sz)
    2064                 :            : {
    2065                 :      30287 :     std::list<const Token *> callstack;
    2066                 :            : 
    2067                 :      30287 :     AllocType alloctype = No;
    2068                 :      30287 :     AllocType dealloctype = No;
    2069                 :            : 
    2070                 :            :     const Token *result;
    2071                 :            : 
    2072 [ +  - ][ +  - ]:      30287 :     Token *tok = getcode(Tok1, callstack, varid, alloctype, dealloctype, classmember, sz);
                 [ +  - ]
    2073                 :            :     //tok->printOut((std::string("Checkmemoryleak: getcode result for: ") + varname).c_str());
    2074                 :            : 
    2075         [ +  - ]:      30287 :     const bool use_addr = bool(Token::findsimplematch(tok, "&use") != NULL);
    2076                 :            : 
    2077                 :            :     // Simplify the code and check if freed memory is used..
    2078         [ +  + ]:     238755 :     for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    2079 [ +  - ][ +  + ]:     272956 :         while (Token::Match(tok2, "[;{}] ;"))
    2080         [ +  - ]:      64488 :             tok2->deleteNext();
    2081                 :            :     }
    2082 [ +  - ][ +  + ]:      30287 :     if ((result = Token::findmatch(tok, "[;{}] dealloc ; use_ ;")) != NULL) {
    2083 [ +  - ][ +  - ]:        225 :         deallocuseError(result->tokAt(3), varname);
    2084                 :            :     }
    2085                 :            : 
    2086                 :            :     // Replace "&use" with "use". Replace "use_" with ";"
    2087         [ +  + ]:     239925 :     for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
    2088 [ +  - ][ +  + ]:     209638 :         if (tok2->str() == "&use")
    2089 [ +  - ][ +  - ]:        540 :             tok2->str("use");
                 [ +  - ]
    2090 [ +  - ][ +  + ]:     209098 :         else if (tok2->str() == "use_")
    2091 [ +  - ][ +  - ]:      10170 :             tok2->str(";");
                 [ +  - ]
    2092 [ +  - ][ -  + ]:     198928 :         else if (Token::simpleMatch(tok2, "loop use_ {"))
    2093         [ #  # ]:          0 :             tok2->deleteNext();
    2094 [ +  - ][ +  + ]:     198928 :         else if (tok2->str() == "::use")    // Some kind of member function usage. Not analyzed very well.
    2095 [ +  - ][ +  - ]:         90 :             tok2->str("use");
                 [ +  - ]
    2096 [ +  - ][ -  + ]:     198838 :         else if (tok2->str() == "recursive")
    2097 [ #  # ][ #  # ]:          0 :             tok2->str("use");
                 [ #  # ]
    2098 [ +  - ][ -  + ]:     198838 :         else if (tok2->str() == "dealloc_")
    2099 [ #  # ][ #  # ]:          0 :             tok2->str("dealloc");
                 [ #  # ]
    2100 [ +  - ][ +  + ]:     198838 :         else if (tok2->str() == "realloc") {
    2101 [ +  - ][ +  - ]:        585 :             tok2->str("dealloc");
                 [ +  - ]
    2102 [ +  - ][ +  - ]:        585 :             tok2->insertToken("alloc");
                 [ +  - ]
    2103 [ +  - ][ +  - ]:        585 :             tok2->insertToken(";");
                 [ +  - ]
    2104                 :            :         }
    2105                 :            :     }
    2106                 :            : 
    2107                 :            :     // If the variable is not allocated at all => no memory leak
    2108 [ +  - ][ +  + ]:      30287 :     if (Token::findsimplematch(tok, "alloc") == 0) {
    2109         [ +  - ]:      19091 :         TokenList::deleteTokens(tok);
    2110                 :            :         return;
    2111                 :            :     }
    2112                 :            : 
    2113         [ +  - ]:      11196 :     simplifycode(tok);
    2114                 :            : 
    2115 [ -  + ][ #  # ]:      11196 :     if (_settings->debug && _settings->_verbose) {
    2116 [ #  # ][ #  # ]:          0 :         tok->printOut(("Checkmemoryleak: simplifycode result for: " + varname).c_str());
         [ #  # ][ #  # ]
    2117                 :            :     }
    2118                 :            : 
    2119                 :            :     // If the variable is not allocated at all => no memory leak
    2120 [ +  - ][ +  + ]:      11196 :     if (Token::findsimplematch(tok, "alloc") == 0) {
    2121         [ +  - ]:        225 :         TokenList::deleteTokens(tok);
    2122                 :            :         return;
    2123                 :            :     }
    2124                 :            : 
    2125                 :            :     /** @todo handle "goto" */
    2126 [ +  - ][ -  + ]:      10971 :     if (Token::findsimplematch(tok, "goto")) {
    2127         [ #  # ]:          0 :         TokenList::deleteTokens(tok);
    2128                 :            :         return;
    2129                 :            :     }
    2130                 :            : 
    2131 [ +  - ][ +  + ]:      10971 :     if ((result = findleak(tok)) != NULL) {
    2132         [ +  - ]:       5166 :         memoryLeak(result, varname, alloctype);
    2133                 :            :     }
    2134                 :            : 
    2135 [ +  + ][ +  - ]:       5805 :     else if (!use_addr && (result = Token::findsimplematch(tok, "dealloc ; dealloc ;")) != NULL) {
         [ +  + ][ +  + ]
    2136 [ +  - ][ +  - ]:         45 :         deallocDeallocError(result->tokAt(2), varname);
    2137                 :            :     }
    2138                 :            : 
    2139                 :            :     // detect cases that "simplifycode" don't handle well..
    2140         [ -  + ]:       5760 :     else if (_settings->debugwarnings) {
    2141                 :          0 :         Token *first = tok;
    2142 [ #  # ][ #  # ]:          0 :         while (first && first->str() == ";")
         [ #  # ][ #  # ]
    2143                 :          0 :             first = first->next();
    2144                 :            : 
    2145                 :          0 :         bool noerr = false;
    2146         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; }");
    2147         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; dealloc ; }");
    2148         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; return use ; }");
    2149         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; use ; }");
    2150         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; use ; return ; }");
    2151         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; dealloc ; return ; }");
    2152         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "if alloc ; dealloc ; }");
    2153         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "if alloc ; return use ; }");
    2154         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "if alloc ; use ; }");
    2155         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; ifv return ; dealloc ; }");
    2156         [ #  # ]:          0 :         noerr |= Token::simpleMatch(first, "alloc ; if return ; dealloc; }");
    2157                 :            : 
    2158                 :            :         // Unhandled case..
    2159 [ #  # ][ #  # ]:          0 :         if (!noerr && tok) {
    2160         [ #  # ]:          0 :             std::ostringstream errmsg;
    2161 [ #  # ][ #  # ]:          0 :             errmsg << "inconclusive leak of " << varname << ": ";
                 [ #  # ]
    2162 [ #  # ][ #  # ]:          0 :             errmsg << tok->stringifyList(false, false, false, false, false, 0, 0);
                 [ #  # ]
    2163 [ #  # ][ #  # ]:          0 :             reportError(first, Severity::debug, "debug", errmsg.str());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2164                 :            :         }
    2165                 :            :     }
    2166                 :            : 
    2167         [ +  - ]:      30287 :     TokenList::deleteTokens(tok);
    2168                 :            : }
    2169                 :            : //---------------------------------------------------------------------------
    2170                 :            : 
    2171                 :            : 
    2172                 :            : 
    2173                 :            : 
    2174                 :            : 
    2175                 :            : //---------------------------------------------------------------------------
    2176                 :            : // Check for memory leaks due to improper realloc() usage.
    2177                 :            : //   Below, "a" may be set to null without being freed if realloc() cannot
    2178                 :            : //   allocate the requested memory:
    2179                 :            : //     a = malloc(10); a = realloc(a, 100);
    2180                 :            : //---------------------------------------------------------------------------
    2181                 :        630 : static bool isNoArgument(const SymbolDatabase* symbolDatabase, unsigned int varid)
    2182                 :            : {
    2183                 :        630 :     const Variable* var = symbolDatabase->getVariableFromVarId(varid);
    2184 [ +  - ][ +  + ]:        630 :     return var && !var->isArgument();
    2185                 :            : }
    2186                 :            : 
    2187                 :      11536 : void CheckMemoryLeakInFunction::checkReallocUsage()
    2188                 :            : {
    2189                 :            :     // only check functions
    2190                 :      11536 :     const std::size_t functions = symbolDatabase->functionScopes.size();
    2191         [ +  + ]:      25412 :     for (std::size_t i = 0; i < functions; ++i) {
    2192                 :      13876 :         const Scope * scope = symbolDatabase->functionScopes[i];
    2193                 :            : 
    2194                 :            :         // Search for the "var = realloc(var, 100" pattern within this function
    2195         [ +  + ]:     347284 :         for (const Token *tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
    2196   [ +  +  +  +  :     388100 :             if (tok->varId() > 0 &&
             +  +  +  + ]
                 [ +  + ]
    2197                 :      53522 :                 Token::Match(tok, "%var% = realloc|g_try_realloc ( %var% , %any%") &&
    2198                 :        630 :                 tok->varId() == tok->tokAt(4)->varId() &&
    2199                 :        540 :                 isNoArgument(symbolDatabase, tok->varId())) {
    2200                 :            :                 // Check that another copy of the pointer wasn't saved earlier in the function
    2201   [ +  -  +  + ]:        990 :                 if (Token::findmatch(scope->classStart, "%var% = %varid% ;", tok, tok->varId()) ||
                 [ +  + ]
    2202                 :        495 :                     Token::findmatch(scope->classStart, "[{};] %varid% = %var% [;=]", tok, tok->varId()))
    2203                 :         45 :                     continue;
    2204                 :            : 
    2205                 :        450 :                 const Token* tokEndRealloc = tok->linkAt(3);
    2206                 :            :                 // Check that the allocation isn't followed immediately by an 'if (!var) { error(); }' that might handle failure
    2207         [ +  + ]:        450 :                 if (Token::Match(tokEndRealloc->next(), "; if ( ! %varid% ) {", tok->varId())) {
    2208                 :        225 :                     const Token* tokEndBrace = tokEndRealloc->linkAt(7);
    2209         [ +  - ]:        315 :                     if (tokEndBrace && Token::simpleMatch(tokEndBrace->tokAt(-2), ") ;") &&
           [ +  +  +  - ]
                 [ +  + ]
    2210                 :         90 :                         Token::Match(tokEndBrace->linkAt(-2)->tokAt(-2), "{|}|; %var% ("))
    2211                 :         90 :                         continue;
    2212                 :            :                 }
    2213                 :            : 
    2214                 :        360 :                 memleakUponReallocFailureError(tok, tok->str());
    2215   [ +  +  +  +  :     386345 :             } else if (tok->next()->varId() > 0 &&
             +  -  +  + ]
                 [ +  + ]
    2216                 :      53252 :                        (Token::Match(tok, "* %var% = realloc|g_try_realloc ( * %var% , %any%") &&
    2217                 :         90 :                         tok->next()->varId() == tok->tokAt(6)->varId()) &&
    2218                 :         90 :                        isNoArgument(symbolDatabase, tok->next()->varId())) {
    2219                 :            :                 // Check that another copy of the pointer wasn't saved earlier in the function
    2220   [ +  -  -  + ]:         90 :                 if (Token::findmatch(scope->classStart, "%var% = * %varid% ;", tok, tok->next()->varId()) ||
                 [ -  + ]
    2221                 :         45 :                     Token::findmatch(scope->classStart, "[{};] * %varid% = %var% [;=]", tok, tok->next()->varId()))
    2222                 :          0 :                     continue;
    2223                 :            : 
    2224                 :         45 :                 const Token* tokEndRealloc = tok->linkAt(4);
    2225                 :            :                 // Check that the allocation isn't followed immediately by an 'if (!var) { error(); }' that might handle failure
    2226         [ -  + ]:         45 :                 if (Token::Match(tokEndRealloc->next(), "; if ( ! * %varid% ) {", tok->next()->varId())) {
    2227                 :          0 :                     const Token* tokEndBrace = tokEndRealloc->linkAt(8);
    2228         [ #  # ]:          0 :                     if (tokEndBrace && Token::simpleMatch(tokEndBrace->tokAt(-2), ") ;") &&
           [ #  #  #  # ]
                 [ #  # ]
    2229                 :          0 :                         Token::Match(tokEndBrace->linkAt(-2)->tokAt(-2), "{|}|; %var% ("))
    2230                 :          0 :                         continue;
    2231                 :            :                 }
    2232                 :         45 :                 memleakUponReallocFailureError(tok->next(), tok->strAt(1));
    2233                 :            :             }
    2234                 :            :         }
    2235                 :            :     }
    2236                 :      11536 : }
    2237                 :            : //---------------------------------------------------------------------------
    2238                 :            : 
    2239                 :            : 
    2240                 :            : 
    2241                 :            : 
    2242                 :            : 
    2243                 :            : 
    2244                 :            : //---------------------------------------------------------------------------
    2245                 :            : // Checks for memory leaks inside function..
    2246                 :            : //---------------------------------------------------------------------------
    2247                 :            : 
    2248                 :      16411 : static bool isInMemberFunc(const Scope* scope)
    2249                 :            : {
    2250 [ +  + ][ +  + ]:      34388 :     while (scope->nestedIn && !scope->functionOf)
                 [ +  + ]
    2251                 :      17977 :         scope = scope->nestedIn;
    2252                 :            : 
    2253                 :      16411 :     return (scope->functionOf != 0);
    2254                 :            : }
    2255                 :            : 
    2256                 :      11536 : void CheckMemoryLeakInFunction::check()
    2257                 :            : {
    2258                 :            :     // fill the "noreturn"
    2259                 :      11536 :     parse_noreturn();
    2260                 :            : 
    2261                 :            :     // Check locking/unlocking of global resources..
    2262                 :      11536 :     const std::size_t functions = symbolDatabase->functionScopes.size();
    2263         [ +  + ]:      25412 :     for (std::size_t i = 0; i < functions; ++i) {
    2264                 :      13876 :         const Scope * scope = symbolDatabase->functionScopes[i];
    2265                 :            : 
    2266 [ +  - ][ +  - ]:      13876 :         checkScope(scope->classStart->next(), "", 0, scope->functionOf != NULL, 1);
                 [ +  - ]
    2267                 :            :     }
    2268                 :            : 
    2269                 :            :     // Check variables..
    2270         [ +  + ]:      41603 :     for (unsigned int i = 0; i < symbolDatabase->getVariableListSize(); i++) {
    2271                 :      30067 :         const Variable* var = symbolDatabase->getVariableFromVarId(i);
    2272 [ +  + ][ +  + ]:      30067 :         if (!var || (!var->isLocal() && !var->isArgument()) || var->isStatic() || !var->scope())
         [ +  + ][ +  + ]
         [ -  + ][ +  + ]
    2273                 :      12576 :             continue;
    2274                 :            : 
    2275         [ +  + ]:      17491 :         if (var->isReference())
    2276                 :         90 :             continue;
    2277                 :            : 
    2278 [ +  + ][ +  + ]:      17401 :         if (!var->isPointer() && var->typeStartToken()->str() != "int")
                 [ +  + ]
    2279                 :        945 :             continue;
    2280                 :            : 
    2281                 :            :         // check for known class without implementation (forward declaration)
    2282 [ +  + ][ +  + ]:      16456 :         if (var->isPointer() && var->type() && !var->typeScope())
         [ +  + ][ +  + ]
    2283                 :         45 :             continue;
    2284                 :            : 
    2285                 :      16411 :         unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken());
    2286         [ +  + ]:      16411 :         if (sz < 1)
    2287                 :       2430 :             sz = 1;
    2288                 :            : 
    2289         [ +  + ]:      16411 :         if (var->isArgument())
    2290                 :       2655 :             checkScope(var->scope()->classStart->next(), var->name(), i, isInMemberFunc(var->scope()), sz);
    2291                 :            :         else
    2292                 :      13756 :             checkScope(var->nameToken(), var->name(), i, isInMemberFunc(var->scope()), sz);
    2293                 :            :     }
    2294                 :      11536 : }
    2295                 :            : //---------------------------------------------------------------------------
    2296                 :            : 
    2297                 :            : 
    2298                 :            : 
    2299                 :            : 
    2300                 :            : 
    2301                 :            : 
    2302                 :            : 
    2303                 :            : 
    2304                 :            : 
    2305                 :            : 
    2306                 :            : 
    2307                 :            : 
    2308                 :            : 
    2309                 :            : 
    2310                 :            : 
    2311                 :            : 
    2312                 :            : 
    2313                 :            : 
    2314                 :            : 
    2315                 :            : 
    2316                 :            : 
    2317                 :            : 
    2318                 :            : 
    2319                 :            : 
    2320                 :            : 
    2321                 :            : 
    2322                 :            : 
    2323                 :            : 
    2324                 :            : 
    2325                 :            : //---------------------------------------------------------------------------
    2326                 :            : // Checks for memory leaks in classes..
    2327                 :            : //---------------------------------------------------------------------------
    2328                 :            : 
    2329                 :            : 
    2330                 :            : 
    2331                 :       3571 : void CheckMemoryLeakInClass::check()
    2332                 :            : {
    2333                 :       3571 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
    2334                 :            : 
    2335                 :            :     // only check classes and structures
    2336                 :       3571 :     const std::size_t classes = symbolDatabase->classAndStructScopes.size();
    2337         [ +  + ]:       6721 :     for (std::size_t i = 0; i < classes; ++i) {
    2338                 :       3150 :         const Scope * scope = symbolDatabase->classAndStructScopes[i];
    2339                 :       3150 :         std::list<Variable>::const_iterator var;
    2340         [ +  + ]:       6435 :         for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) {
    2341 [ +  + ][ +  + ]:       3285 :             if (!var->isStatic() && var->isPointer()) {
                 [ +  + ]
    2342                 :            :                 // allocation but no deallocation of private variables in public function..
    2343                 :       3195 :                 const Token *tok = var->typeStartToken();
    2344         [ +  + ]:       3195 :                 if (tok->isStandardType()) {
    2345         [ +  + ]:       2520 :                     if (var->isPrivate())
    2346                 :       2160 :                         checkPublicFunctions(&(*scope), var->nameToken());
    2347                 :            : 
    2348                 :       2520 :                     variable(&(*scope), var->nameToken());
    2349                 :            :                 }
    2350                 :            : 
    2351                 :            :                 // known class?
    2352         [ +  + ]:        675 :                 else if (var->type()) {
    2353                 :            :                     // not derived?
    2354         [ +  - ]:        585 :                     if (var->type()->derivedFrom.empty()) {
    2355         [ +  + ]:        585 :                         if (var->isPrivate())
    2356                 :        495 :                             checkPublicFunctions(&(*scope), var->nameToken());
    2357                 :            : 
    2358                 :        585 :                         variable(&(*scope), var->nameToken());
    2359                 :            :                     }
    2360                 :            :                 }
    2361                 :            :             }
    2362                 :            :         }
    2363                 :            :     }
    2364                 :       3571 : }
    2365                 :            : 
    2366                 :            : 
    2367                 :       3105 : void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarname)
    2368                 :            : {
    2369                 :       3105 :     const std::string& varname = tokVarname->str();
    2370                 :       3105 :     const unsigned int varid = tokVarname->varId();
    2371                 :       3105 :     const std::string& classname = scope->className;
    2372                 :            : 
    2373                 :            :     // Check if member variable has been allocated and deallocated..
    2374                 :       3105 :     CheckMemoryLeak::AllocType Alloc = CheckMemoryLeak::No;
    2375                 :       3105 :     CheckMemoryLeak::AllocType Dealloc = CheckMemoryLeak::No;
    2376                 :            : 
    2377                 :       3105 :     bool allocInConstructor = false;
    2378                 :       3105 :     bool deallocInDestructor = false;
    2379                 :            : 
    2380                 :            :     // Inspect member functions
    2381                 :       3105 :     std::list<Function>::const_iterator func;
    2382         [ +  + ]:       8235 :     for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
    2383                 :       5445 :         const bool constructor = func->type == Function::eConstructor;
    2384                 :       5445 :         const bool destructor = func->type == Function::eDestructor;
    2385         [ +  + ]:       5445 :         if (!func->hasBody) {
    2386         [ +  - ]:         45 :             if (destructor) { // implementation for destructor is not seen => assume it deallocates all variables properly
    2387                 :         45 :                 deallocInDestructor = true;
    2388                 :         45 :                 Dealloc = CheckMemoryLeak::Many;
    2389                 :            :             }
    2390                 :         45 :             continue;
    2391                 :            :         }
    2392                 :       5400 :         bool body = false;
    2393                 :       5400 :         const Token *end = func->functionScope->classEnd;
    2394         [ +  + ]:      56385 :         for (const Token *tok = func->arg->link(); tok != end; tok = tok->next()) {
    2395         [ +  + ]:      51300 :             if (tok == func->functionScope->classStart)
    2396                 :       5400 :                 body = true;
    2397                 :            :             else {
    2398         [ +  + ]:      45900 :                 if (!body) {
    2399         [ +  + ]:       8550 :                     if (!Token::Match(tok, ":|, %varid% (", varid))
    2400                 :       8235 :                         continue;
    2401                 :            :                 }
    2402                 :            : 
    2403                 :            :                 // Allocate..
    2404 [ +  + ][ +  + ]:      37665 :                 if (!body || Token::Match(tok, "%varid% =", varid)) {
                 [ +  + ]
    2405                 :            :                     // var1 = var2 = ...
    2406                 :            :                     // bail out
    2407         [ +  + ]:       3285 :                     if (tok->strAt(-1) == "=")
    2408                 :         45 :                         return;
    2409                 :            : 
    2410                 :            :                     // Foo::var1 = ..
    2411                 :            :                     // bail out when not same class
    2412   [ +  +  -  + ]:       3285 :                     if (tok->strAt(-1) == "::" &&
                 [ -  + ]
    2413                 :         45 :                         tok->strAt(-2) != scope->className)
    2414                 :          0 :                         return;
    2415                 :            : 
    2416         [ +  + ]:       3240 :                     AllocType alloc = getAllocationType(tok->tokAt(body ? 2 : 3), 0);
    2417         [ +  + ]:       3240 :                     if (alloc != CheckMemoryLeak::No) {
    2418         [ +  + ]:       2880 :                         if (constructor)
    2419                 :       2205 :                             allocInConstructor = true;
    2420                 :            : 
    2421 [ -  + ][ #  # ]:       2880 :                         if (Alloc != No && Alloc != alloc)
    2422                 :          0 :                             alloc = CheckMemoryLeak::Many;
    2423                 :            : 
    2424                 :       2880 :                         std::list<const Token *> callstack;
    2425 [ +  - ][ +  + ]:       2880 :                         if (alloc != CheckMemoryLeak::Many && Dealloc != CheckMemoryLeak::No && Dealloc != CheckMemoryLeak::Many && Dealloc != alloc) {
         [ -  + ][ #  # ]
    2426         [ #  # ]:          0 :                             callstack.push_back(tok);
    2427 [ #  # ][ #  # ]:          0 :                             mismatchAllocDealloc(callstack, classname + "::" + varname);
         [ #  # ][ #  # ]
                 [ #  # ]
    2428                 :            :                         }
    2429                 :            : 
    2430                 :       2880 :                         Alloc = alloc;
    2431                 :            :                     }
    2432                 :            :                 }
    2433                 :            : 
    2434         [ +  + ]:      37620 :                 if (!body)
    2435                 :        315 :                     continue;
    2436                 :            : 
    2437                 :            :                 // Deallocate..
    2438                 :      37305 :                 AllocType dealloc = getDeallocationType(tok, varname);
    2439         [ +  + ]:      37305 :                 if (dealloc == No) {
    2440 [ +  - ][ +  - ]:      35820 :                     std::string temp = scope->className + " :: " + varname;
    2441         [ +  - ]:      35820 :                     dealloc = getDeallocationType(tok, temp);
    2442                 :            :                 }
    2443         [ +  + ]:      37305 :                 if (dealloc == No) {
    2444                 :      35775 :                     std::string temp = "this . " + varname;
    2445         [ +  - ]:      35775 :                     dealloc = getDeallocationType(tok, temp);
    2446                 :            :                 }
    2447                 :            :                 // some usage in the destructor => assume it's related
    2448                 :            :                 // to deallocation
    2449 [ +  + ][ +  + ]:      37305 :                 if (destructor && tok->str() == varname)
                 [ +  + ]
    2450                 :       1395 :                     dealloc = CheckMemoryLeak::Many;
    2451         [ +  + ]:      37305 :                 if (dealloc != CheckMemoryLeak::No) {
    2452         [ +  + ]:       3015 :                     if (destructor)
    2453                 :       2655 :                         deallocInDestructor = true;
    2454                 :            : 
    2455                 :            :                     // several types of allocation/deallocation?
    2456 [ +  + ][ +  + ]:       3015 :                     if (Dealloc != CheckMemoryLeak::No && Dealloc != dealloc)
    2457                 :       1260 :                         dealloc = CheckMemoryLeak::Many;
    2458                 :            : 
    2459                 :       3015 :                     std::list<const Token *> callstack;
    2460 [ +  + ][ +  + ]:       3015 :                     if (dealloc != CheckMemoryLeak::Many && Alloc != CheckMemoryLeak::No &&  Alloc != Many && Alloc != dealloc) {
         [ +  - ][ +  + ]
    2461         [ +  - ]:        135 :                         callstack.push_back(tok);
    2462 [ +  - ][ +  - ]:        135 :                         mismatchAllocDealloc(callstack, classname + "::" + varname);
         [ +  - ][ +  - ]
                 [ +  - ]
    2463                 :            :                     }
    2464                 :            : 
    2465                 :       3015 :                     Dealloc = dealloc;
    2466                 :            :                 }
    2467                 :            : 
    2468                 :            :                 // Function call .. possible deallocation
    2469         [ +  + ]:      34290 :                 else if (Token::Match(tok->previous(), "[{};] %var% (")) {
    2470         [ +  + ]:        360 :                     if (!CheckMemoryLeakInFunction::test_white_list(tok->str())) {
    2471                 :        270 :                         return;
    2472                 :            :                     }
    2473                 :            :                 }
    2474                 :            :             }
    2475                 :            :         }
    2476                 :            :     }
    2477                 :            : 
    2478 [ +  + ][ +  + ]:       2790 :     if (allocInConstructor && !deallocInDestructor) {
    2479 [ +  - ][ +  - ]:        855 :         unsafeClassError(tokVarname, classname, classname + "::" + varname /*, Alloc*/);
                 [ +  - ]
    2480 [ +  + ][ +  + ]:       1935 :     } else if (Alloc != CheckMemoryLeak::No && Dealloc == CheckMemoryLeak::No) {
    2481 [ +  - ][ +  - ]:       3105 :         unsafeClassError(tokVarname, classname, classname + "::" + varname /*, Alloc*/);
                 [ +  - ]
    2482                 :            :     }
    2483                 :            : }
    2484                 :            : 
    2485                 :       1170 : void CheckMemoryLeakInClass::unsafeClassError(const Token *tok, const std::string &classname, const std::string &varname)
    2486                 :            : {
    2487                 :            :     reportError(tok, Severity::style, "unsafeClassCanLeak",
    2488                 :            :                 "Class '" + classname + "' is unsafe, '" + varname + "' can leak by wrong usage.\n"
    2489 [ +  - ][ +  - ]:       1170 :                 "The class '" + classname + "' is unsafe, wrong usage can cause memory/resource leaks for '" + varname + "'. This can for instance be fixed by adding proper cleanup in the destructor.");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2490                 :       1170 : }
    2491                 :            : 
    2492                 :            : 
    2493                 :       2655 : void CheckMemoryLeakInClass::checkPublicFunctions(const Scope *scope, const Token *classtok)
    2494                 :            : {
    2495                 :            :     // Check that public functions deallocate the pointers that they allocate.
    2496                 :            :     // There is no checking how these functions are used and therefore it
    2497                 :            :     // isn't established if there is real leaks or not.
    2498 [ +  - ][ +  - ]:       2655 :     if (!_settings->isEnabled("warning"))
         [ +  - ][ -  + ]
    2499                 :          0 :         return;
    2500                 :            : 
    2501                 :       2655 :     const unsigned int varid = classtok->varId();
    2502         [ -  + ]:       2655 :     if (varid == 0) {
    2503 [ #  # ][ #  # ]:          0 :         _tokenizer->getSymbolDatabase()->debugMessage(classtok, "CheckMemoryInClass::checkPublicFunctions found variable \'" + classtok->str() + "\' with varid 0");
                 [ #  # ]
    2504                 :          0 :         return;
    2505                 :            :     }
    2506                 :            : 
    2507                 :            :     // Parse public functions..
    2508                 :            :     // If they allocate member variables, they should also deallocate
    2509                 :       2655 :     std::list<Function>::const_iterator func;
    2510                 :            : 
    2511         [ +  + ]:       7650 :     for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) {
    2512 [ +  + ][ +  +  :       6660 :         if ((func->type == Function::eFunction || func->type == Function::eOperatorEqual) &&
             +  +  +  - ]
                 [ +  + ]
    2513                 :       1665 :             func->access == Public && func->hasBody) {
    2514                 :        810 :             const Token *tok2 = func->token;
    2515         [ +  + ]:       3690 :             while (tok2->str() != "{")
    2516                 :       2880 :                 tok2 = tok2->next();
    2517         [ +  + ]:        810 :             if (Token::Match(tok2, "{|}|; %varid% =", varid)) {
    2518                 :        585 :                 const CheckMemoryLeak::AllocType alloc = getAllocationType(tok2->tokAt(3), varid);
    2519         [ +  - ]:        585 :                 if (alloc != CheckMemoryLeak::No)
    2520                 :        585 :                     publicAllocationError(tok2, tok2->strAt(1));
    2521   [ +  +  +  - ]:        270 :             } else if (Token::Match(tok2, "{|}|; %type% :: %varid% =", varid) &&
                 [ +  + ]
    2522                 :         45 :                        tok2->next()->str() == scope->className) {
    2523                 :         45 :                 const CheckMemoryLeak::AllocType alloc = getAllocationType(tok2->tokAt(5), varid);
    2524         [ +  - ]:         45 :                 if (alloc != CheckMemoryLeak::No)
    2525                 :         45 :                     publicAllocationError(tok2, tok2->strAt(3));
    2526                 :            :             }
    2527                 :            :         }
    2528                 :            :     }
    2529                 :            : }
    2530                 :            : 
    2531                 :        675 : void CheckMemoryLeakInClass::publicAllocationError(const Token *tok, const std::string &varname)
    2532                 :            : {
    2533 [ +  - ][ +  - ]:        675 :     reportError(tok, Severity::warning, "publicAllocationError", "Possible leak in public function. The pointer '" + varname + "' is not deallocated before it is allocated.");
         [ +  - ][ +  - ]
                 [ +  - ]
    2534                 :        675 : }
    2535                 :            : 
    2536                 :            : 
    2537                 :       1816 : void CheckMemoryLeakStructMember::check()
    2538                 :            : {
    2539                 :       1816 :     const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
    2540         [ +  + ]:       8438 :     for (unsigned int i = 0; i < symbolDatabase->getVariableListSize(); i++) {
    2541                 :       6622 :         const Variable* var = symbolDatabase->getVariableFromVarId(i);
    2542 [ +  + ][ +  + ]:       6622 :         if (!var || !var->isLocal() || var->isStatic())
         [ -  + ][ +  + ]
    2543                 :       3621 :             continue;
    2544         [ +  + ]:       3001 :         if (var->typeEndToken()->isStandardType())
    2545                 :        445 :             continue;
    2546                 :       2556 :         checkStructVariable(var);
    2547                 :            :     }
    2548                 :       1816 : }
    2549                 :            : 
    2550                 :       2331 : bool CheckMemoryLeakStructMember::isMalloc(const Variable *variable)
    2551                 :            : {
    2552                 :       2331 :     const unsigned int varid(variable->varId());
    2553                 :       2331 :     bool alloc = false;
    2554         [ +  + ]:      40725 :     for (const Token *tok2 = variable->nameToken(); tok2 != variable->scope()->classEnd; tok2 = tok2->next()) {
    2555         [ +  + ]:      38529 :         if (Token::Match(tok2, "= %varid% [;=]", varid)) {
    2556                 :        135 :             return false;
    2557         [ +  + ]:      38394 :         } else if (Token::Match(tok2, "%varid% = malloc|kmalloc (", varid)) {
    2558                 :       2196 :             alloc = true;
    2559                 :            :         }
    2560                 :            :     }
    2561                 :       2331 :     return alloc;
    2562                 :            : }
    2563                 :            : 
    2564                 :            : 
    2565                 :       2556 : void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const variable)
    2566                 :            : {
    2567                 :            :     // This should be in the CheckMemoryLeak base class
    2568 [ +  + ][ +  - ]:       2556 :     static std::set<std::string> ignoredFunctions;
         [ +  - ][ #  # ]
    2569         [ +  + ]:       2556 :     if (ignoredFunctions.empty()) {
    2570 [ +  - ][ +  - ]:         45 :         ignoredFunctions.insert("if");
                 [ +  - ]
    2571 [ +  - ][ +  - ]:         45 :         ignoredFunctions.insert("for");
                 [ +  - ]
    2572 [ +  - ][ +  - ]:         45 :         ignoredFunctions.insert("while");
                 [ +  - ]
    2573 [ +  - ][ +  - ]:         45 :         ignoredFunctions.insert("malloc");
                 [ +  - ]
    2574                 :            :     }
    2575                 :            : 
    2576                 :            :     // Is struct variable a pointer?
    2577         [ +  + ]:       2556 :     if (variable->isPointer()) {
    2578                 :            :         // Check that variable is allocated with malloc
    2579         [ +  + ]:       2331 :         if (!isMalloc(variable))
    2580                 :        180 :             return;
    2581         [ +  + ]:        225 :     } else if (!_tokenizer->isC()) {
    2582                 :            :         // For non-C code a destructor might cleanup members
    2583                 :         45 :         return;
    2584                 :            :     }
    2585                 :            : 
    2586                 :            :     // Check struct..
    2587                 :       2331 :     unsigned int indentlevel2 = 0;
    2588         [ +  + ]:      37800 :     for (const Token *tok2 = variable->nameToken(); tok2 != variable->scope()->classEnd; tok2 = tok2->next()) {
    2589         [ +  + ]:      35244 :         if (tok2->str() == "{")
    2590                 :        315 :             ++indentlevel2;
    2591                 :            : 
    2592         [ +  + ]:      34929 :         else if (tok2->str() == "}") {
    2593         [ -  + ]:        180 :             if (indentlevel2 == 0)
    2594                 :          0 :                 break;
    2595                 :        180 :             --indentlevel2;
    2596                 :            :         }
    2597                 :            : 
    2598                 :            :         // Unknown usage of struct
    2599                 :            :         /** @todo Check how the struct is used. Only bail out if necessary */
    2600         [ +  + ]:      34749 :         else if (Token::Match(tok2, "[(,] %varid% [,)]", variable->varId()))
    2601                 :        315 :             break;
    2602                 :            : 
    2603                 :            :         // Struct member is allocated => check if it is also properly deallocated..
    2604         [ +  + ]:      34434 :         else if (Token::Match(tok2->previous(), "[;{}] %varid% . %var% = malloc|strdup|kmalloc (", variable->varId())) {
    2605                 :        765 :             const unsigned int structid(variable->varId());
    2606                 :        765 :             const unsigned int structmemberid(tok2->tokAt(2)->varId());
    2607                 :            : 
    2608                 :            :             // This struct member is allocated.. check that it is deallocated
    2609                 :        765 :             unsigned int indentlevel3 = indentlevel2;
    2610         [ +  - ]:      10890 :             for (const Token *tok3 = tok2; tok3; tok3 = tok3->next()) {
    2611         [ +  + ]:      10125 :                 if (tok3->str() == "{")
    2612                 :        180 :                     ++indentlevel3;
    2613                 :            : 
    2614         [ +  + ]:       9945 :                 else if (tok3->str() == "}") {
    2615         [ +  + ]:        180 :                     if (indentlevel3 == 0) {
    2616 [ +  - ][ +  - ]:        135 :                         memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), Malloc);
                 [ +  - ]
    2617                 :        135 :                         break;
    2618                 :            :                     }
    2619                 :         45 :                     --indentlevel3;
    2620                 :            :                 }
    2621                 :            : 
    2622                 :            :                 // Deallocating the struct member..
    2623         [ +  + ]:       9765 :                 else if (Token::Match(tok3, "free|kfree ( %var% . %varid% )", structmemberid)) {
    2624                 :            :                     // If the deallocation happens at the base level, don't check this member anymore
    2625         [ -  + ]:         45 :                     if (indentlevel3 == 0)
    2626                 :          0 :                         break;
    2627                 :            : 
    2628                 :            :                     // deallocating and then returning from function in a conditional block =>
    2629                 :            :                     // skip ahead out of the block
    2630                 :         45 :                     bool ret = false;
    2631         [ +  - ]:        450 :                     while (tok3) {
    2632         [ +  + ]:        450 :                         if (tok3->str() == "return")
    2633                 :         45 :                             ret = true;
    2634 [ +  - ][ +  + ]:        405 :                         else if (tok3->str() == "{" || tok3->str() == "}")
                 [ +  + ]
    2635                 :         45 :                             break;
    2636                 :        405 :                         tok3 = tok3->next();
    2637                 :            :                     }
    2638 [ +  - ][ +  - ]:         45 :                     if (!ret || !tok3 || tok3->str() != "}")
         [ -  + ][ -  + ]
    2639                 :          0 :                         break;
    2640                 :         45 :                     --indentlevel3;
    2641                 :         45 :                     continue;
    2642                 :            :                 }
    2643                 :            : 
    2644                 :            :                 // Deallocating the struct..
    2645 [ +  + ][ +  + ]:       9720 :                 else if (indentlevel2 == 0 && Token::Match(tok3, "free|kfree ( %varid% )", structid)) {
                 [ +  + ]
    2646 [ +  - ][ +  - ]:         45 :                     memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), Malloc);
                 [ +  - ]
    2647                 :         45 :                     break;
    2648                 :            :                 }
    2649                 :            : 
    2650                 :            :                 // failed allocation => skip code..
    2651         [ +  + ]:       9675 :                 else if (Token::Match(tok3, "if ( ! %var% . %varid% )", structmemberid)) {
    2652                 :            :                     // Goto the ")"
    2653                 :         90 :                     tok3 = tok3->next()->link();
    2654                 :            : 
    2655                 :            :                     // make sure we have ") {".. it should be
    2656         [ -  + ]:         90 :                     if (!Token::simpleMatch(tok3, ") {"))
    2657                 :          0 :                         break;
    2658                 :            : 
    2659                 :            :                     // Goto the "}"
    2660                 :         90 :                     tok3 = tok3->next()->link();
    2661                 :            :                 }
    2662                 :            : 
    2663                 :            :                 // succeeded allocation
    2664         [ +  + ]:       9585 :                 else if (Token::Match(tok3, "if ( %var% . %varid% ) {", structmemberid)) {
    2665                 :            :                     // goto the ")"
    2666                 :         45 :                     tok3 = tok3->next()->link();
    2667                 :            : 
    2668                 :            :                     // check if the variable is deallocated or returned..
    2669                 :         45 :                     unsigned int indentlevel4 = 0;
    2670         [ +  - ]:        135 :                     for (const Token *tok4 = tok3; tok4; tok4 = tok4->next()) {
    2671         [ +  + ]:        135 :                         if (tok4->str() == "{")
    2672                 :         45 :                             ++indentlevel4;
    2673         [ -  + ]:         90 :                         else if (tok4->str() == "}") {
    2674                 :          0 :                             --indentlevel4;
    2675         [ #  # ]:          0 :                             if (indentlevel4 == 0)
    2676                 :          0 :                                 break;
    2677         [ +  + ]:         90 :                         } else if (Token::Match(tok4, "free|kfree ( %var% . %varid% )", structmemberid)) {
    2678                 :         45 :                             break;
    2679                 :            :                         }
    2680                 :            :                     }
    2681                 :            : 
    2682                 :            :                     // was there a proper deallocation?
    2683         [ +  - ]:         45 :                     if (indentlevel4 > 0)
    2684                 :         45 :                         break;
    2685                 :            :                 }
    2686                 :            : 
    2687                 :            :                 // Returning from function..
    2688         [ +  + ]:       9540 :                 else if (tok3->str() == "return") {
    2689                 :            :                     // Returning from function without deallocating struct member?
    2690   [ +  +  +  + ]:        315 :                     if (!Token::Match(tok3, "return %varid% ;", structid) &&
                 [ +  + ]
    2691                 :         90 :                         !Token::Match(tok3, "return & %varid% .", structid)) {
    2692 [ +  - ][ +  - ]:         45 :                         memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), Malloc);
                 [ +  - ]
    2693                 :            :                     }
    2694                 :        225 :                     break;
    2695                 :            :                 }
    2696                 :            : 
    2697                 :            :                 // struct assignment..
    2698         [ +  + ]:       9315 :                 else if (Token::Match(tok3, "= %varid% ;", structid)) {
    2699                 :         45 :                     break;
    2700         [ +  + ]:       9270 :                 } else if (Token::Match(tok3, "= %var% . %varid% ;", structmemberid)) {
    2701                 :         45 :                     break;
    2702                 :            :                 }
    2703                 :            : 
    2704                 :            :                 // goto isn't handled well.. bail out even though there might be leaks
    2705         [ -  + ]:       9225 :                 else if (tok3->str() == "goto")
    2706                 :          0 :                     break;
    2707                 :            : 
    2708                 :            :                 // using struct in a function call..
    2709         [ +  + ]:       9225 :                 else if (Token::Match(tok3, "%var% (")) {
    2710                 :            :                     // Calling non-function / function that doesn't deallocate?
    2711         [ +  + ]:       1215 :                     if (ignoredFunctions.find(tok3->str()) != ignoredFunctions.end())
    2712                 :        900 :                         continue;
    2713                 :            : 
    2714                 :            :                     // Check if the struct is used..
    2715                 :        315 :                     bool deallocated = false;
    2716                 :        315 :                     const Token* const end4 = tok3->linkAt(1);
    2717         [ +  + ]:        855 :                     for (const Token *tok4 = tok3; tok4 != end4; tok4 = tok4->next()) {
    2718         [ +  + ]:        765 :                         if (Token::Match(tok4, "[(,] &| %varid% [,)]", structid)) {
    2719                 :            :                             /** @todo check if the function deallocates the memory */
    2720                 :        135 :                             deallocated = true;
    2721                 :        135 :                             break;
    2722                 :            :                         }
    2723                 :            : 
    2724         [ +  + ]:        630 :                         if (Token::Match(tok4, "[(,] &| %varid% . %var% [,)]", structid)) {
    2725                 :            :                             /** @todo check if the function deallocates the memory */
    2726                 :         90 :                             deallocated = true;
    2727                 :         90 :                             break;
    2728                 :            :                         }
    2729                 :            :                     }
    2730                 :            : 
    2731         [ +  + ]:        315 :                     if (deallocated)
    2732                 :        225 :                         break;
    2733                 :            :                 }
    2734                 :            :             }
    2735                 :            :         }
    2736                 :            :     }
    2737                 :            : }
    2738                 :            : 
    2739                 :            : 
    2740                 :            : 
    2741                 :            : #include "checkuninitvar.h" // CheckUninitVar::analyse
    2742                 :            : 
    2743                 :       1051 : void CheckMemoryLeakNoVar::check()
    2744                 :            : {
    2745                 :       1051 :     std::set<std::string> uvarFunctions;
    2746                 :            :     {
    2747         [ +  - ]:       1051 :         const CheckUninitVar c(_tokenizer, _settings, _errorLogger);
    2748 [ +  - ][ +  - ]:       1051 :         c.analyse(_tokenizer->tokens(), uvarFunctions);
    2749                 :            :     }
    2750                 :            : 
    2751                 :       1051 :     const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
    2752                 :            : 
    2753                 :            :     // only check functions
    2754                 :       1051 :     const std::size_t functions = symbolDatabase->functionScopes.size();
    2755         [ +  + ]:       2192 :     for (std::size_t i = 0; i < functions; ++i) {
    2756                 :       1141 :         const Scope * scope = symbolDatabase->functionScopes[i];
    2757                 :            : 
    2758                 :            :         // goto the "}" that ends the executable scope..
    2759                 :       1141 :         const Token *tok = scope->classEnd;
    2760                 :            : 
    2761                 :            :         // parse the executable scope until tok is reached...
    2762 [ +  - ][ +  + ]:      29015 :         for (const Token *tok2 = tok->link(); tok2 && tok2 != tok; tok2 = tok2->next()) {
                 [ +  + ]
    2763                 :            :             // allocating memory in parameter for function call..
    2764 [ +  - ][ +  + ]:      27874 :             if (Token::Match(tok2, "[(,] %var% (") && Token::Match(tok2->linkAt(2), ") [,)]")) {
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
    2765         [ +  - ]:        225 :                 const AllocType allocType = getAllocationType(tok2->next(), 0);
    2766         [ +  - ]:        225 :                 if (allocType != No) {
    2767                 :            :                     // locate outer function call..
    2768         [ +  - ]:        540 :                     for (const Token *tok3 = tok2; tok3; tok3 = tok3->previous()) {
    2769 [ +  - ][ +  + ]:        315 :                         if (tok3->str() == "(") {
    2770                 :            :                             // Is it a function call..
    2771 [ +  - ][ +  - ]:        225 :                             if (Token::Match(tok3->tokAt(-2), "[;{}] %var% (")) {
                 [ +  + ]
    2772         [ +  - ]:        135 :                                 const std::string& functionName = tok3->strAt(-1);
    2773 [ +  - ][ +  - ]:        450 :                                 if (functionName == "delete" ||
         [ +  + ][ +  - ]
         [ -  + ][ +  + ]
    2774         [ +  - ]:        135 :                                     functionName == "free" ||
    2775         [ +  - ]:         90 :                                     functionName == "fclose" ||
    2776         [ +  - ]:         90 :                                     functionName == "realloc")
    2777                 :         45 :                                     break;
    2778 [ +  - ][ +  + ]:         90 :                                 if (CheckMemoryLeakInFunction::test_white_list(functionName)) {
    2779 [ +  - ][ +  - ]:         45 :                                     functionCallLeak(tok2, tok2->strAt(1), functionName);
    2780                 :         45 :                                     break;
    2781                 :            :                                 }
    2782 [ +  - ][ +  - ]:         45 :                                 if (uvarFunctions.find(functionName) != uvarFunctions.end()) {
                 [ +  - ]
    2783 [ +  - ][ +  - ]:         45 :                                     functionCallLeak(tok2, tok2->strAt(1), functionName);
    2784                 :         45 :                                     break;
    2785                 :            :                                 }
    2786                 :            :                             }
    2787                 :         90 :                             break;
    2788 [ +  - ][ -  + ]:         90 :                         } else if (tok3->str() == ")")
    2789                 :          0 :                             tok3 = tok3->link();
    2790 [ +  - ][ -  + ]:         90 :                         else if (Token::Match(tok3, "[;{}]"))
    2791                 :          0 :                             break;
    2792                 :            :                     }
    2793                 :            :                 }
    2794                 :            :             }
    2795                 :            :         }
    2796                 :       1051 :     }
    2797                 :       1051 : }
    2798                 :            : 
    2799                 :        135 : void CheckMemoryLeakNoVar::functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall)
    2800                 :            : {
    2801 [ +  - ][ +  - ]:        135 :     reportError(loc, Severity::error, "leakNoVarFunctionCall", "Allocation with " + alloc + ", " + functionCall + " doesn't release it.");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2802 [ +  - ][ +  - ]:        270 : }

Generated by: LCOV version 1.9