⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 checkclass.cpp

📁 cppcheck is a static C/C++ code analyzer that checks for memory leaks, mismatching allocation-deallo
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2009 Daniel Marjamäki, Reijo Tomperi, Nicolas Le Cam, * Leandro Penz, Kimmo Varis, Vesa Pikki * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program.  If not, see <http://www.gnu.org/licenses/ *///---------------------------------------------------------------------------#include "checkclass.h"#include <locale>#include <cstring>#include <string>#include <sstream>#include <algorithm>//---------------------------------------------------------------------------CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger){    _tokenizer = tokenizer;    _settings = settings;    _errorLogger = errorLogger;}CheckClass::~CheckClass(){}//---------------------------------------------------------------------------struct CheckClass::VAR *CheckClass::ClassChecking_GetVarList(const Token *tok1){    // Get variable list..    struct VAR *varlist = NULL;    unsigned int indentlevel = 0;    for (const Token *tok = tok1; tok; tok = tok->next())    {        if (!tok->next())            break;        if (tok->str() == "{")            ++indentlevel;        else if (tok->str() == "}")        {            if (indentlevel <= 1)                break;            --indentlevel;        }        if (indentlevel != 1)            continue;        // "private:" "public:" "protected:" etc        bool b = bool((*tok->strAt(0) != ':') && strchr(tok->strAt(0), ':') != 0);        // Search for start of statement..        if (! Token::Match(tok, "[;{}]") && ! b)            continue;        // This is the start of a statement        const Token *next = tok->next();        const char *varname = 0;        // If next token contains a ":".. it is not part of a variable declaration        if (next->str().find(":") != std::string::npos)        {        }        // Is it a variable declaration?        else if (Token::Match(next, "%type% %var% ;"))        {            if (next->isStandardType())                varname = next->strAt(1);            else if (Token::findmatch(_tokenizer->tokens(), ("enum " + next->str()).c_str()))                varname = next->strAt(1);        }        // Pointer?        else if (Token::Match(next, "%type% * %var% ;"))        {            varname = next->strAt(2);        }        // If the varname was set in one of the two if-block above, create a entry for this variable..        if (varname)        {            struct VAR *var = new VAR(varname, false, varlist);            varlist   = var;        }    }    return varlist;}//---------------------------------------------------------------------------const Token * CheckClass::FindClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel){    if (indentlevel < 0 || tok == NULL)        return NULL;    std::ostringstream classPattern;    classPattern << "class " << classname << " :|{";    std::ostringstream internalPattern;    internalPattern << funcname << " (";    std::ostringstream externalPattern;    externalPattern << classname << " :: " << funcname << " (";    for (;tok; tok = tok->next())    {        if (indentlevel == 0 && Token::Match(tok, classPattern.str().c_str()))        {            while (tok && tok->str() != "{")                tok = tok->next();            if (tok)                tok = tok->next();            if (! tok)                break;            indentlevel = 1;        }        if (tok->str() == "{")        {            // If indentlevel==0 don't go to indentlevel 1. Skip the block.            if (indentlevel > 0)                ++indentlevel;            else            {                for (; tok; tok = tok->next())                {                    if (tok->str() == "{")                        ++indentlevel;                    else if (tok->str() == "}")                    {                        --indentlevel;                        if (indentlevel <= 0)                            break;                    }                }                if (tok == NULL)                    return NULL;                continue;            }        }        if (tok->str() == "}")        {            --indentlevel;            if (indentlevel < 0)                return NULL;        }        if (indentlevel == 1)        {            // Member function implemented in the class declaration?            if (tok->str() != "~" && Token::Match(tok->next(), internalPattern.str().c_str()))            {                const Token *tok2 = tok->next();                while (tok2 && tok2->str() != "{" && tok2->str() != ";")                    tok2 = tok2->next();                if (tok2 && tok2->str() == "{")                    return tok->next();            }        }        else if (indentlevel == 0 && Token::Match(tok, externalPattern.str().c_str()))        {            return tok;        }    }    // Not found    return NULL;}//---------------------------------------------------------------------------void CheckClass::InitVar(struct VAR *varlist, const char varname[]){    for (struct VAR *var = varlist; var; var = var->next)    {        if (strcmp(var->name, varname) == 0)        {            var->init = true;            break;        }    }}//---------------------------------------------------------------------------void CheckClass::ClassChecking_VarList_Initialize(const Token *tok1, const Token *ftok, struct VAR *varlist, const char classname[], std::list<std::string> &callstack){    bool Assign = false;    unsigned int indentlevel = 0;    for (; ftok; ftok = ftok->next())    {        if (!ftok->next())            break;        // Class constructor.. initializing variables like this        // clKalle::clKalle() : var(value) { }        if (indentlevel == 0)        {            if (Assign && Token::Match(ftok, "%var% ("))            {                InitVar(varlist, ftok->aaaa());            }            Assign |= (ftok->str() == ":");        }        if (ftok->str() == "{")        {            ++indentlevel;            Assign = false;        }        if (ftok->str() == "}")        {            if (indentlevel <= 1)                break;            --indentlevel;        }        if (indentlevel < 1)            continue;        // Variable getting value from stream?        if (Token::Match(ftok, ">> %var%"))        {            InitVar(varlist, ftok->next()->aaaa());        }        // Before a new statement there is "[{};)=]" or "else"        if (! Token::Match(ftok, "[{};)=]") && ftok->str() != "else")            continue;        // Using the operator= function to initialize all variables..        if (Token::simpleMatch(ftok->next(), "* this = "))        {            for (struct VAR *var = varlist; var; var = var->next)                var->init = true;            break;        }        if (!Token::Match(ftok->next(), "%var%") && !Token::Match(ftok->next(), "this . %var%"))            continue;        // Goto the first token in this statement..        ftok = ftok->next();        // Skip "this->"        if (Token::simpleMatch(ftok, "this ."))            ftok = ftok->tokAt(2);        // Clearing all variables..        if (Token::simpleMatch(ftok, "memset ( this ,"))        {            for (struct VAR *var = varlist; var; var = var->next)                var->init = true;            break;        }        // Calling member function?        else if (Token::Match(ftok, "%var% ("))        {            // No recursive calls!            if (std::find(callstack.begin(), callstack.end(), ftok->str()) == callstack.end())            {                callstack.push_back(ftok->str());                int i = 0;                const Token *ftok2 = FindClassFunction(tok1, classname, ftok->aaaa(), i);                ClassChecking_VarList_Initialize(tok1, ftok2, varlist, classname, callstack);            }        }        // Assignment of member variable?        else if (Token::Match(ftok, "%var% ="))        {            InitVar(varlist, ftok->aaaa());        }        // The functions 'clear' and 'Clear' are supposed to initialize variable.        if (Token::Match(ftok, "%var% . clear|Clear ("))        {            InitVar(varlist, ftok->aaaa());        }    }}//---------------------------------------------------------------------------// ClassCheck: Check that all class constructors are ok.//---------------------------------------------------------------------------void CheckClass::constructors(){    const char pattern_class[] = "class %var% {";    // Locate class    const Token *tok1 = Token::findmatch(_tokenizer->tokens(), pattern_class);    while (tok1)    {        const char *className[2];        className[0] = tok1->strAt(1);        className[1] = 0;        const Token *classNameToken = tok1->tokAt(1);        // TODO: handling of private constructors should be improved.        bool hasPrivateConstructor = false;        {            int indentlevel = 0;            bool isPrivate = true;            for (const Token *tok = tok1; tok; tok = tok->next())            {                // Indentation                if (tok->str() == "{")                    ++indentlevel;                else if (tok->str() == "}")                {                    --indentlevel;                    if (indentlevel <= 0)                        break;                }                // Parse class contents (indentlevel == 1)..                if (indentlevel == 1)                {                    // What section are we in.. private/non-private                    if (tok->str() == "private:")                        isPrivate = true;                    else if (tok->str() == "protected:" || tok->str() == "public:")                        isPrivate = false;                    // Is there a private constructor?                    else if (isPrivate && Token::simpleMatch(tok, (classNameToken->str() + " (").c_str()))                    {                        hasPrivateConstructor = true;                        break;                    }                }            }        }        if (hasPrivateConstructor)        {            // TODO: Handle private constructors.            // Right now to avoid false positives I just bail out            tok1 = Token::findmatch(tok1->next(), pattern_class);            continue;        }        // Are there a class constructor?        std::string tempPattern = "%any% " + classNameToken->str() + " (";        const Token *constructor_token = Token::findmatch(tok1, tempPattern.c_str());        while (Token::Match(constructor_token, "~"))            constructor_token = Token::findmatch(constructor_token->next(), tempPattern.c_str());        // There are no constructor.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -