diff --git a/lib/check.h b/lib/check.h index 6bb711a11..082f63c1b 100644 --- a/lib/check.h +++ b/lib/check.h @@ -37,6 +37,10 @@ */ #define CHECK_WRONG_DATA(X) (X) +namespace tinyxml2 { + class XMLElement; +} + /// @addtogroup Core /// @{ @@ -108,6 +112,11 @@ public: return nullptr; } + virtual FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const { + (void)xmlElement; + return nullptr; + } + virtual void analyseWholeProgram(const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger) { (void)fileInfo; (void)settings; diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index e2ea978ae..be951abb2 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -32,6 +32,7 @@ #include #include #include +#include //--------------------------------------------------------------------------- @@ -1966,6 +1967,38 @@ Check::FileInfo* CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, con return fileInfo; } +Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const +{ + const std::string ArrayUsage("ArrayUsage"); + const std::string ArraySize("ArraySize"); + + MyFileInfo *fileInfo = new MyFileInfo; + for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) { + if (e->Name() == ArrayUsage) { + const char *array = e->Attribute("array"); + const char *arrayIndex = e->Attribute("index"); + const char *fileName = e->Attribute("fileName"); + const char *linenr = e->Attribute("linenr"); + if (!array || !arrayIndex || !MathLib::isInt(arrayIndex) || !fileName || !linenr || !MathLib::isInt(linenr)) + continue; + struct MyFileInfo::ArrayUsage arrayUsage; + arrayUsage.index = MathLib::toLongNumber(arrayIndex); + arrayUsage.fileName = fileName; + arrayUsage.linenr = MathLib::toLongNumber(linenr); + fileInfo->arrayUsage[array] = arrayUsage; + } else if (e->Name() == ArraySize) { + const char *array = e->Attribute("array"); + const char *size = e->Attribute("size"); + if (!array || !size || !MathLib::isInt(size)) + continue; + fileInfo->arraySize[array] = MathLib::toLongNumber(size); + } + } + + return fileInfo; +} + + void CheckBufferOverrun::analyseWholeProgram(const std::list &fileInfo, const Settings&, ErrorLogger &errorLogger) { // Merge all fileInfo diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h index a9dcf276f..46d2c168f 100644 --- a/lib/checkbufferoverrun.h +++ b/lib/checkbufferoverrun.h @@ -227,6 +227,8 @@ public: /** @brief Parse current TU and extract file info */ Check::FileInfo *getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const; + Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const; + /** @brief Analyse all file infos for all TU */ void analyseWholeProgram(const std::list &fileInfo, const Settings& settings, ErrorLogger &errorLogger); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index bb54c4ae4..7ca1afada 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -25,13 +25,14 @@ #include "path.h" #include "checkunusedfunctions.h" +#include "timer.h" +#include "version.h" #include #include #include #include -#include "timer.h" -#include "version.h" +#include #ifdef HAVE_RULES #define PCRE_STATIC @@ -742,6 +743,50 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::map fileInfoList; + + // Load all analyzer info data.. + const std::string filesTxt(buildDir + "/files.txt"); + std::ifstream fin(filesTxt.c_str()); + std::string filesTxtLine; + while (std::getline(fin, filesTxtLine)) { + const std::string::size_type firstColon = filesTxtLine.find(':'); + if (firstColon == std::string::npos) + continue; + const std::string::size_type lastColon = filesTxtLine.rfind(':'); + if (firstColon == lastColon) + continue; + const std::string xmlfile = buildDir + '/' + filesTxtLine.substr(0,firstColon); + const std::string sourcefile = filesTxtLine.substr(lastColon+1); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLError error = doc.LoadFile(xmlfile.c_str()); + if (error != tinyxml2::XML_SUCCESS) + continue; + + const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement(); + if (rootNode == nullptr) + continue; + + for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) { + if (std::strcmp(e->Name(), "FileInfo") != 0) + continue; + const char *checkClassAttr = e->Attribute("check"); + if (!checkClassAttr) + continue; + for (std::list::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) { + if (checkClassAttr == (*it)->name()) + fileInfoList.push_back((*it)->loadFileInfoFromXml(e)); + } + } + } + + // Analyse the tokens + for (std::list::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) + (*it)->analyseWholeProgram(fileInfoList, _settings, *this); + + for (std::list::iterator fi = fileInfoList.begin(); fi != fileInfoList.end(); ++fi) + delete(*fi); } bool CppCheck::isUnusedFunctionCheckEnabled() const