diff --git a/Makefile b/Makefile index 02482206b9a..3fef3103d96 100644 --- a/Makefile +++ b/Makefile @@ -565,7 +565,7 @@ $(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/astutils.h lib/c $(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkuninitvar.cpp -$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/checkers.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h +$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/astutils.h lib/checkers.h lib/checkunusedfunctions.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedfunctions.cpp $(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h @@ -580,7 +580,7 @@ $(libcppdir)/clangimport.o: lib/clangimport.cpp lib/addoninfo.h lib/checkers.h l $(libcppdir)/color.o: lib/color.cpp lib/color.h lib/config.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/color.cpp -$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/clangimport.h lib/color.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h lib/vfvalue.h lib/xml.h +$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/clangimport.h lib/color.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/regex.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp $(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h diff --git a/lib/analyzerinfo.cpp b/lib/analyzerinfo.cpp index 9477f2e290d..6d5ac9a9b15 100644 --- a/lib/analyzerinfo.cpp +++ b/lib/analyzerinfo.cpp @@ -209,3 +209,37 @@ bool AnalyzerInformation::Info::parse(const std::string& filesTxtLine) { return true; } +// TODO: bail out on unexpected data +void AnalyzerInformation::processFilesTxt(const std::string& buildDir, const std::function& handler) +{ + const std::string filesTxt(buildDir + "/files.txt"); + std::ifstream fin(filesTxt.c_str()); + std::string filesTxtLine; + while (std::getline(fin, filesTxtLine)) { + AnalyzerInformation::Info filesTxtInfo; + if (!filesTxtInfo.parse(filesTxtLine)) { + return; + } + + const std::string xmlfile = buildDir + '/' + filesTxtInfo.afile; + + tinyxml2::XMLDocument doc; + const tinyxml2::XMLError error = doc.LoadFile(xmlfile.c_str()); + if (error != tinyxml2::XML_SUCCESS) + return; + + const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement(); + if (rootNode == nullptr) + return; + + for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) { + if (std::strcmp(e->Name(), "FileInfo") != 0) + continue; + const char *checkattr = e->Attribute("check"); + if (checkattr == nullptr) + continue; + handler(checkattr, e, filesTxtInfo); + } + } +} + diff --git a/lib/analyzerinfo.h b/lib/analyzerinfo.h index 732587e0a71..04ea1a5b339 100644 --- a/lib/analyzerinfo.h +++ b/lib/analyzerinfo.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -33,6 +34,7 @@ struct FileSettings; namespace tinyxml2 { class XMLDocument; + class XMLElement; }; /// @addtogroup Core @@ -75,6 +77,8 @@ class CPPCHECKLIB AnalyzerInformation { std::string sourceFile; }; + static void processFilesTxt(const std::string& buildDir, const std::function& handler); + protected: static std::string getFilesTxt(const std::list &sourcefiles, const std::string &userDefines, const std::list &fileSettings); diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index b45200d7128..7edaff6c241 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -20,6 +20,7 @@ //--------------------------------------------------------------------------- #include "checkunusedfunctions.h" +#include "analyzerinfo.h" #include "astutils.h" #include "errorlogger.h" #include "errortypes.h" @@ -34,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -457,55 +458,31 @@ void CheckUnusedFunctions::analyseWholeProgram(const Settings &settings, ErrorLo std::map decls; std::set calls; - 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 secondColon = filesTxtLine.find(':', firstColon+1); - if (secondColon == std::string::npos) - continue; - const std::string xmlfile = buildDir + '/' + filesTxtLine.substr(0,firstColon); - const std::string sourcefile = filesTxtLine.substr(secondColon+1); - - tinyxml2::XMLDocument doc; - const 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) + const auto handler = [&decls, &calls](const char* checkattr, const tinyxml2::XMLElement* e, const AnalyzerInformation::Info& filesTxtInfo) { + if (std::strcmp(checkattr,"CheckUnusedFunctions") != 0) + return; + for (const tinyxml2::XMLElement *e2 = e->FirstChildElement(); e2; e2 = e2->NextSiblingElement()) { + const char* functionName = e2->Attribute("functionName"); + if (functionName == nullptr) continue; - const char *checkattr = e->Attribute("check"); - if (checkattr == nullptr || std::strcmp(checkattr,"CheckUnusedFunctions") != 0) + const char* name = e2->Name(); + if (std::strcmp(name,"functioncall") == 0) { + calls.insert(functionName); continue; - for (const tinyxml2::XMLElement *e2 = e->FirstChildElement(); e2; e2 = e2->NextSiblingElement()) { - const char* functionName = e2->Attribute("functionName"); - if (functionName == nullptr) - continue; - const char* name = e2->Name(); - if (std::strcmp(name,"functioncall") == 0) { - calls.insert(functionName); - continue; - } - if (std::strcmp(name,"functiondecl") == 0) { - const char* lineNumber = e2->Attribute("lineNumber"); - if (lineNumber) { - const char* file = e2->Attribute("file"); - const char* column = default_if_null(e2->Attribute("column"), "0"); - // cppcheck-suppress templateInstantiation - TODO: fix this - see #11631 - decls[functionName] = Location(file ? file : sourcefile, strToInt(lineNumber), strToInt(column)); - } + } + if (std::strcmp(name,"functiondecl") == 0) { + const char* lineNumber = e2->Attribute("lineNumber"); + if (lineNumber) { + const char* file = e2->Attribute("file"); + const char* column = default_if_null(e2->Attribute("column"), "0"); + // cppcheck-suppress templateInstantiation - TODO: fix this - see #11631 + decls[functionName] = Location(file ? file : filesTxtInfo.sourceFile, strToInt(lineNumber), strToInt(column)); } } } - } + }; + + AnalyzerInformation::processFilesTxt(buildDir, handler); for (auto decl = decls.cbegin(); decl != decls.cend(); ++decl) { const std::string &functionName = stripTemplateParameters(decl->first); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 0fb23203718..c7c6ea65dfc 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -70,10 +70,11 @@ #include #include "json.h" -#include "xml.h" #include +namespace tinyxml2 { class XMLElement; } + static constexpr char Version[] = CPPCHECK_VERSION_STRING; static constexpr char ExtraVersion[] = ""; @@ -1851,50 +1852,26 @@ unsigned int CppCheck::analyseWholeProgram(const std::string &buildDir, const st return mLogger->exitcode(); executeAddonsWholeProgram(files, fileSettings, ctuInfo); + std::list fileInfoList; CTU::FileInfo ctuFileInfo; - // Load all analyzer info data.. - const std::string filesTxt(buildDir + "/files.txt"); - std::ifstream fin(filesTxt); - std::string filesTxtLine; - while (std::getline(fin, filesTxtLine)) { - AnalyzerInformation::Info filesTxtInfo; - if (!filesTxtInfo.parse(filesTxtLine)) - continue; - - const std::string xmlfile = buildDir + '/' + filesTxtInfo.afile; - - tinyxml2::XMLDocument doc; - const 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; - if (std::strcmp(checkClassAttr, "ctu") == 0) { - ctuFileInfo.loadFromXml(e); - continue; - } - // cppcheck-suppress shadowFunction - TODO: fix this - for (const Check *check : Check::instances()) { - if (checkClassAttr == check->name()) { - if (Check::FileInfo* fi = check->loadFileInfoFromXml(e)) { - fi->file0 = filesTxtInfo.sourceFile; - fileInfoList.push_back(fi); - } + const auto handler = [&fileInfoList, &ctuFileInfo](const char* checkattr, const tinyxml2::XMLElement* e, const AnalyzerInformation::Info& filesTxtInfo) { + if (std::strcmp(checkattr, "ctu") == 0) { + ctuFileInfo.loadFromXml(e); + return; + } + for (const Check *check : Check::instances()) { + if (checkattr == check->name()) { + if (Check::FileInfo* fi = check->loadFileInfoFromXml(e)) { + fi->file0 = filesTxtInfo.sourceFile; + fileInfoList.push_back(fi); } } } - } + }; + + AnalyzerInformation::processFilesTxt(buildDir, handler); // Analyse the tokens // cppcheck-suppress shadowFunction - TODO: fix this diff --git a/lib/ctu.cpp b/lib/ctu.cpp index 158c8c1e046..df8ee0f74b6 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -231,6 +231,7 @@ bool CTU::FileInfo::NestedCall::loadFromXml(const tinyxml2::XMLElement *xmlEleme return !error; } +// TODO: bail out on unexpected data void CTU::FileInfo::loadFromXml(const tinyxml2::XMLElement *xmlElement) { for (const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) { diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index 02d2e7fbde2..ad7fb641024 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -245,7 +245,7 @@ $(libcppdir)/checktype.o: ../lib/checktype.cpp ../lib/addoninfo.h ../lib/astutil $(libcppdir)/checkuninitvar.o: ../lib/checkuninitvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checknullpointer.h ../lib/checkuninitvar.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkuninitvar.cpp -$(libcppdir)/checkunusedfunctions.o: ../lib/checkunusedfunctions.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/astutils.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h +$(libcppdir)/checkunusedfunctions.o: ../lib/checkunusedfunctions.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/analyzerinfo.h ../lib/astutils.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/config.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkunusedfunctions.cpp $(libcppdir)/checkunusedvar.o: ../lib/checkunusedvar.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/checkunusedvar.h ../lib/config.h ../lib/errortypes.h ../lib/fwdanalysis.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h @@ -260,7 +260,7 @@ $(libcppdir)/clangimport.o: ../lib/clangimport.cpp ../lib/addoninfo.h ../lib/che $(libcppdir)/color.o: ../lib/color.cpp ../lib/color.h ../lib/config.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/color.cpp -$(libcppdir)/cppcheck.o: ../lib/cppcheck.cpp ../externals/picojson/picojson.h ../externals/simplecpp/simplecpp.h ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/analyzerinfo.h ../lib/check.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/clangimport.h ../lib/color.h ../lib/config.h ../lib/cppcheck.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/filesettings.h ../lib/json.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/version.h ../lib/vfvalue.h ../lib/xml.h +$(libcppdir)/cppcheck.o: ../lib/cppcheck.cpp ../externals/picojson/picojson.h ../externals/simplecpp/simplecpp.h ../lib/addoninfo.h ../lib/analyzerinfo.h ../lib/check.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/clangimport.h ../lib/color.h ../lib/config.h ../lib/cppcheck.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/filesettings.h ../lib/json.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/regex.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/version.h ../lib/vfvalue.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp $(libcppdir)/ctu.o: ../lib/ctu.cpp ../externals/tinyxml2/tinyxml2.h ../lib/astutils.h ../lib/check.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h