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

📄 checkclass.cpp

📁 cppcheck is a static C/C++ code analyzer that checks for memory leaks, mismatching allocation-deallo
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        if (! constructor_token)        {            // If "--style" has been given, give a warning            if (ErrorLogger::noConstructor(_settings))            {                // If the class has member variables there should be an constructor                struct VAR *varlist = ClassChecking_GetVarList(tok1);                if (varlist)                {                    _errorLogger->noConstructor(_tokenizer, tok1, classNameToken->str());                }                // Delete the varlist..                while (varlist)                {                    struct VAR *nextvar = varlist->next;                    delete varlist;                    varlist = nextvar;                }            }            tok1 = Token::findmatch(tok1->next(), pattern_class);            continue;        }        // Check that all member variables are initialized..        struct VAR *varlist = ClassChecking_GetVarList(tok1);        // Check constructors        CheckConstructors(tok1, varlist, className[0]);        // Check assignment operators        CheckConstructors(tok1, varlist, "operator =");        // Delete the varlist..        while (varlist)        {            struct VAR *nextvar = varlist->next;            delete varlist;            varlist = nextvar;        }        tok1 = Token::findmatch(tok1->next(), pattern_class);    }}void CheckClass::CheckConstructors(const Token *tok1, struct VAR *varlist, const char funcname[]){    const char * const className = tok1->strAt(1);    int indentlevel = 0;    const Token *constructor_token = FindClassFunction(tok1, className, funcname, indentlevel);    std::list<std::string> callstack;    ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack);    while (constructor_token)    {        // Check if any variables are uninitialized        for (struct VAR *var = varlist; var; var = var->next)        {            if (var->init)                continue;            // Is it a static member variable?            std::ostringstream pattern;            pattern << className << "::" << var->name << "=";            if (Token::findmatch(_tokenizer->tokens(), pattern.str().c_str()))                continue;            // It's non-static and it's not initialized => error            _errorLogger->uninitVar(_tokenizer, constructor_token, className, var->name);        }        for (struct VAR *var = varlist; var; var = var->next)            var->init = false;        constructor_token = FindClassFunction(constructor_token->next(), className, funcname, indentlevel);        callstack.clear();        ClassChecking_VarList_Initialize(tok1, constructor_token, varlist, className, callstack);    }}//---------------------------------------------------------------------------// ClassCheck: Unused private functions//---------------------------------------------------------------------------void CheckClass::privateFunctions(){    // Locate some class    for (const Token *tok1 = Token::findmatch(_tokenizer->tokens(), "class %var% {"); tok1; tok1 = Token::findmatch(tok1->next(), "class %var% {"))    {        const std::string &classname = tok1->next()->str();        // The class implementation must be available..        const std::string classconstructor(classname + " :: " + classname);        if (tok1->fileIndex() > 0 && !Token::findmatch(_tokenizer->tokens(), classconstructor.c_str()))            continue;        // Get private functions..        std::list<const Token *> FuncList;        FuncList.clear();        bool priv = false;        unsigned int indent_level = 0;        for (const Token *tok = tok1; tok; tok = tok->next())        {            if (Token::Match(tok, "friend %var%"))            {                // Todo: Handle friend classes                FuncList.clear();                break;            }            if (tok->str() == "{")                ++indent_level;            else if (tok->str() == "}")            {                if (indent_level <= 1)                    break;                --indent_level;            }            else if (tok->str() == "private:")                priv = true;            else if (tok->str() == "public:")                priv = false;            else if (tok->str() == "protected:")                priv = false;            else if (priv && indent_level == 1)            {                if (Token::Match(tok, "typedef %type% ("))                    tok = tok->tokAt(2);                if (Token::Match(tok, "%var% (") &&                    !Token::Match(tok, classname.c_str()))                {                    FuncList.push_back(tok);                }            }        }        // Check that all private functions are used..        bool HasFuncImpl = false;        bool inclass = false;        indent_level = 0;        const std::string pattern_function(classname + " ::");        for (const Token *ftok = _tokenizer->tokens(); ftok; ftok = ftok->next())        {            if (ftok->str() == "{")                ++indent_level;            else if (ftok->str() == "}")            {                if (indent_level > 0)                    --indent_level;                if (indent_level == 0)                    inclass = false;            }            if (Token::Match(ftok, ("class " + classname + " :|{").c_str()))            {                indent_level = 0;                inclass = true;            }            // Check member class functions to see what functions are used..            if ((inclass && indent_level == 1 && Token::Match(ftok, ") const| {")) ||                (Token::Match(ftok, (classname + " :: ~| %var% (").c_str())))            {                while (ftok && ftok->str() != ")")                    ftok = ftok->next();                if (!ftok)                    break;                if (Token::Match(ftok, ") : %var% ("))                {                    while (!Token::Match(ftok->next(), "[{};]"))                        ftok = ftok->next();                }                if (!Token::Match(ftok, ") const| {"))                    continue;                if (ftok->fileIndex() == 0)                    HasFuncImpl = true;                // Parse function..                int indentlevel2 = 0;                for (const Token *tok2 = ftok; tok2; tok2 = tok2->next())                {                    if (tok2->str() == "{")                        ++indentlevel2;                    else if (tok2->str() == "}")                    {                        --indentlevel2;                        if (indentlevel2 < 1)                            break;                    }                    else if (Token::Match(tok2, "%var% ("))                    {                        // Remove function from FuncList                        for (std::list<const Token *>::iterator it = FuncList.begin(); it != FuncList.end(); ++it)                        {                            if (tok2->str() == (*it)->str())                            {                                FuncList.remove(*it);                                break;                            }                        }                    }                }            }        }        while (HasFuncImpl && !FuncList.empty())        {            // Final check; check if the function pointer is used somewhere..            const std::string _pattern("return|(|)|,|= " + FuncList.front()->str());            if (!Token::findmatch(_tokenizer->tokens(), _pattern.c_str()))            {                _errorLogger->unusedPrivateFunction(_tokenizer, FuncList.front(), classname, FuncList.front()->str());            }            FuncList.pop_front();        }    }}//---------------------------------------------------------------------------// ClassCheck: Check that memset is not used on classes//---------------------------------------------------------------------------void CheckClass::noMemset(){    // Locate all 'memset' tokens..    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())    {        if (!Token::Match(tok, "memset|memcpy|memmove"))            continue;        // Todo: Handle memcpy and memmove        const char *type = NULL;        if (Token::Match(tok, "memset ( %var% , %num% , sizeof ( %type% ) )"))            type = tok->strAt(8);        else if (Token::Match(tok, "memset ( & %var% , %num% , sizeof ( %type% ) )"))            type = tok->strAt(9);        else if (Token::Match(tok, "memset ( %var% , %num% , sizeof ( struct %type% ) )"))            type = tok->strAt(9);        else if (Token::Match(tok, "memset ( & %var% , %num% , sizeof ( struct %type% ) )"))            type = tok->strAt(10);        else if (Token::Match(tok, "%type% ( %var% , %var% , sizeof ( %type% ) )"))            type = tok->strAt(8);        // No type defined => The tokens didn't match        if (!(type && type[0]))            continue;        // Warn if type is a class..        const std::string pattern1(std::string("class ") + type);        if (Token::findmatch(_tokenizer->tokens(), pattern1.c_str()))        {            _errorLogger->memsetClass(_tokenizer, tok, tok->str());            continue;        }        // Warn if type is a struct that contains any std::*        const std::string pattern2(std::string("struct ") + type);        for (const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str()); tstruct; tstruct = tstruct->next())        {            if (tstruct->str() == "}")                break;            if (Token::Match(tstruct, "std :: %type% %var% ;"))            {                _errorLogger->memsetStruct(_tokenizer, tok, tok->str(), tstruct->strAt(2));                break;            }        }    }}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// ClassCheck: "void operator=("//---------------------------------------------------------------------------void CheckClass::operatorEq(){    const Token *tok = Token::findmatch(_tokenizer->tokens(), "void operator = (");    if (tok)    {        _errorLogger->operatorEq(_tokenizer, tok);    }}//---------------------------------------------------------------------------//---------------------------------------------------------------------------// A destructor in a base class should be virtual//---------------------------------------------------------------------------void CheckClass::virtualDestructor(){    const char pattern_classdecl[] = "class %var% : %var%";    const Token *derived = _tokenizer->tokens();    while ((derived = Token::findmatch(derived, pattern_classdecl)) != NULL)    {        // Check that the derived class has a non empty destructor..        {            std::ostringstream destructorPattern;            destructorPattern << "~ " << derived->strAt(1) << " ( ) {";            const Token *derived_destructor = Token::findmatch(_tokenizer->tokens(), destructorPattern.str().c_str());            // No destructor..            if (! derived_destructor)            {                derived = derived->next();                continue;            }            // Empty destructor..            if (Token::Match(derived_destructor, "~ %var% ( ) { }"))            {                derived = derived->next();                continue;            }        }        const Token *derivedClass = derived->tokAt(1);        // Iterate through each base class...        derived = derived->tokAt(3);        while (Token::Match(derived, "%var%"))        {            bool isPublic = Token::Match(derived, "public");            // What kind of inheritance is it.. public|protected|private            if (Token::Match(derived, "public|protected|private"))                derived = derived->next();            // Name of base class..            const char *baseName[2];            baseName[0] = derived->strAt(0);            baseName[1] = 0;            // Update derived so it's ready for the next loop.            derived = derived->next();            if (Token::Match(derived, ","))                derived = derived->next();            // If not public inheritance, skip checking of this base class..            if (! isPublic)                continue;            // Find the destructor declaration for the base class.            const Token *base = Token::findmatch(_tokenizer->tokens(), (std::string("%any% ~ ") + baseName[0] + " (").c_str());            while (Token::Match(base, "::"))                base = Token::findmatch(base->next(), (std::string("%any% ~ ") + baseName[0] + + " (").c_str());            while (Token::Match(base, "%var%") && !Token::Match(base, "virtual"))                base = base->previous();            // Check that there is a destructor..            if (! base)            {                // Is the class declaration available?                base = Token::findmatch(_tokenizer->tokens(), (std::string("class ") + baseName[0] + " :|{").c_str());                if (base)                {                    _errorLogger->virtualDestructor(_tokenizer, base, baseName[0], derivedClass->str());                }            }            // There is a destructor. Check that it's virtual..            else if (base->str() != "virtual")            {                _errorLogger->virtualDestructor(_tokenizer, base, baseName[0], derivedClass->str());            }        }    }}//---------------------------------------------------------------------------

⌨️ 快捷键说明

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