diff --git a/Makefile b/Makefile
index 7c90b45d5..315709a12 100644
--- a/Makefile
+++ b/Makefile
@@ -128,7 +128,8 @@ MAN_SOURCE=man/cppcheck.1.xml
###### Object Files
-LIBOBJ = $(SRCDIR)/astutils.o \
+LIBOBJ = $(SRCDIR)/analyzerinfo.o \
+ $(SRCDIR)/astutils.o \
$(SRCDIR)/check.o \
$(SRCDIR)/check64bit.o \
$(SRCDIR)/checkassert.o \
@@ -299,6 +300,9 @@ endif
###### Build
+$(SRCDIR)/analyzerinfo.o: lib/analyzerinfo.cpp lib/cxx11emu.h lib/analyzerinfo.h lib/config.h
+ $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/analyzerinfo.o $(SRCDIR)/analyzerinfo.cpp
+
$(SRCDIR)/astutils.o: lib/astutils.cpp lib/cxx11emu.h lib/astutils.h lib/symboldatabase.h lib/config.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/astutils.o $(SRCDIR)/astutils.cpp
@@ -380,10 +384,10 @@ $(SRCDIR)/checkunusedvar.o: lib/checkunusedvar.cpp lib/cxx11emu.h lib/checkunuse
$(SRCDIR)/checkvaarg.o: lib/checkvaarg.cpp lib/cxx11emu.h lib/checkvaarg.h lib/config.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/symboldatabase.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/checkvaarg.o $(SRCDIR)/checkvaarg.cpp
-$(SRCDIR)/cppcheck.o: lib/cppcheck.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/preprocessor.h lib/path.h lib/version.h
+$(SRCDIR)/cppcheck.o: lib/cppcheck.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h lib/preprocessor.h lib/path.h lib/version.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/cppcheck.o $(SRCDIR)/cppcheck.cpp
-$(SRCDIR)/errorlogger.o: lib/errorlogger.cpp lib/cxx11emu.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/path.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/utils.h
+$(SRCDIR)/errorlogger.o: lib/errorlogger.cpp lib/cxx11emu.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/path.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h lib/utils.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/errorlogger.o $(SRCDIR)/errorlogger.cpp
$(SRCDIR)/importproject.o: lib/importproject.cpp lib/cxx11emu.h lib/importproject.h lib/config.h lib/platform.h lib/path.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/token.h lib/valueflow.h
@@ -434,10 +438,10 @@ $(SRCDIR)/tokenlist.o: lib/tokenlist.cpp lib/cxx11emu.h lib/tokenlist.h lib/conf
$(SRCDIR)/valueflow.o: lib/valueflow.cpp lib/cxx11emu.h lib/valueflow.h lib/config.h lib/astutils.h lib/errorlogger.h lib/suppressions.h lib/mathlib.h lib/settings.h lib/library.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/symboldatabase.h lib/token.h lib/tokenlist.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/valueflow.o $(SRCDIR)/valueflow.cpp
-cli/cmdlineparser.o: cli/cmdlineparser.cpp lib/cxx11emu.h cli/cmdlineparser.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h cli/cppcheckexecutor.h cli/filelister.h lib/path.h cli/threadexecutor.h
+cli/cmdlineparser.o: cli/cmdlineparser.cpp lib/cxx11emu.h cli/cmdlineparser.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h cli/cppcheckexecutor.h cli/filelister.h lib/path.h cli/threadexecutor.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/cmdlineparser.o cli/cmdlineparser.cpp
-cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp lib/cxx11emu.h cli/cppcheckexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h cli/cmdlineparser.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h cli/filelister.h lib/path.h lib/pathmatch.h lib/preprocessor.h cli/threadexecutor.h lib/utils.h
+cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp lib/cxx11emu.h cli/cppcheckexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h cli/cmdlineparser.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h cli/filelister.h lib/path.h lib/pathmatch.h lib/preprocessor.h cli/threadexecutor.h lib/utils.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/cppcheckexecutor.o cli/cppcheckexecutor.cpp
cli/filelister.o: cli/filelister.cpp lib/cxx11emu.h cli/filelister.h lib/path.h lib/config.h lib/pathmatch.h
@@ -446,7 +450,7 @@ cli/filelister.o: cli/filelister.cpp lib/cxx11emu.h cli/filelister.h lib/path.h
cli/main.o: cli/main.cpp lib/cxx11emu.h cli/cppcheckexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/main.o cli/main.cpp
-cli/threadexecutor.o: cli/threadexecutor.cpp lib/cxx11emu.h cli/threadexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/importproject.h lib/platform.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h cli/cppcheckexecutor.h
+cli/threadexecutor.o: cli/threadexecutor.cpp lib/cxx11emu.h cli/threadexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/importproject.h lib/platform.h lib/cppcheck.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h cli/cppcheckexecutor.h
$(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o cli/threadexecutor.o cli/threadexecutor.cpp
test/options.o: test/options.cpp lib/cxx11emu.h test/options.h
@@ -488,10 +492,10 @@ test/testcondition.o: test/testcondition.cpp lib/cxx11emu.h lib/tokenize.h lib/e
test/testconstructors.o: test/testconstructors.cpp lib/cxx11emu.h lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkclass.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/settings.h lib/library.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testconstructors.o test/testconstructors.cpp
-test/testcppcheck.o: test/testcppcheck.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h test/testsuite.h lib/path.h
+test/testcppcheck.o: test/testcppcheck.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h test/testsuite.h lib/path.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcppcheck.o test/testcppcheck.cpp
-test/testerrorlogger.o: test/testerrorlogger.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h test/testsuite.h
+test/testerrorlogger.o: test/testerrorlogger.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testerrorlogger.o test/testerrorlogger.cpp
test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/cxx11emu.h lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkexceptionsafety.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/settings.h lib/library.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/utils.h test/testsuite.h
@@ -578,13 +582,13 @@ test/teststring.o: test/teststring.cpp lib/cxx11emu.h lib/tokenize.h lib/errorlo
test/testsuite.o: test/testsuite.cpp lib/cxx11emu.h test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/options.h test/redirect.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsuite.o test/testsuite.cpp
-test/testsuppressions.o: test/testsuppressions.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h test/testsuite.h
+test/testsuppressions.o: test/testsuppressions.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsuppressions.o test/testsuppressions.cpp
test/testsymboldatabase.o: test/testsymboldatabase.cpp lib/cxx11emu.h test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/testutils.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/symboldatabase.h lib/token.h lib/valueflow.h lib/utils.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsymboldatabase.o test/testsymboldatabase.cpp
-test/testthreadexecutor.o: test/testthreadexecutor.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h test/testsuite.h
+test/testthreadexecutor.o: test/testthreadexecutor.cpp lib/cxx11emu.h lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/check.h lib/token.h lib/valueflow.h lib/tokenize.h lib/tokenlist.h lib/analyzerinfo.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testthreadexecutor.o test/testthreadexecutor.cpp
test/testtimer.o: test/testtimer.cpp lib/cxx11emu.h lib/timer.h lib/config.h test/testsuite.h lib/errorlogger.h lib/suppressions.h
diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp
index fc3527769..f8e618fa8 100644
--- a/cli/cmdlineparser.cpp
+++ b/cli/cmdlineparser.cpp
@@ -120,6 +120,9 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
return true;
}
+ else if (std::strncmp(argv[i], "--cppcheck-build-dir=", 21) == 0)
+ _settings->buildDir = argv[i] + 21;
+
// Flag used for various purposes during debugging
else if (std::strcmp(argv[i], "--debug") == 0)
_settings->debug = _settings->debugwarnings = true;
@@ -797,6 +800,9 @@ void CmdLineParser::PrintHelp()
"If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c,\n"
"*.tpp, and *.txx files are checked recursively from the given directory.\n\n"
"Options:\n"
+ " --analyze-dir=
Analysis output directory. Useful for various data.\n"
+ " Some possible usages are; whole program analysis,\n"
+ " incremental analysis, distributed analysis.\n"
" --check-config Check cppcheck configuration. The normal code\n"
" analysis is disabled by this flag.\n"
" --check-library Show information messages when library files have\n"
diff --git a/lib/analyzerinfo.cpp b/lib/analyzerinfo.cpp
new file mode 100644
index 000000000..037526291
--- /dev/null
+++ b/lib/analyzerinfo.cpp
@@ -0,0 +1,104 @@
+/*
+* Cppcheck - A tool for static C/C++ code analysis
+* Copyright (C) 2007-2016 Cppcheck team.
+*
+* 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 .
+*/
+
+#include "analyzerinfo.h"
+#include "path.h"
+#include
+
+AnalyzerInformation::AnalyzerInformation() {}
+AnalyzerInformation::~AnalyzerInformation()
+{
+ close();
+}
+
+void AnalyzerInformation::close()
+{
+ analyzerInfoFile.clear();
+ if (fout.is_open()) {
+ fout << "\n";
+ fout.close();
+ }
+}
+
+static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t checksum, std::list *errors)
+{
+ tinyxml2::XMLDocument doc;
+ tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str());
+ if (error != tinyxml2::XML_SUCCESS)
+ return false;
+
+ const tinyxml2::XMLElement * const rootNode = doc.FirstChildElement();
+ if (rootNode == nullptr)
+ return false;
+
+ const char *attr = rootNode->Attribute("checksum");
+ if (!attr || attr != std::to_string(checksum))
+ return false;
+
+ for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
+ if (std::strcmp(e->Name(), "error") == 0)
+ errors->push_back(ErrorLogger::ErrorMessage(e));
+ }
+
+ return true;
+}
+
+bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, std::size_t checksum, std::list *errors)
+{
+ if (buildDir.empty() || sourcefile.empty())
+ return true;
+ close();
+
+ analyzerInfoFile = Path::fromNativeSeparators(buildDir);
+ if (analyzerInfoFile.back() != '/')
+ analyzerInfoFile += '/';
+ const std::string::size_type pos = sourcefile.rfind("/");
+ if (pos == std::string::npos)
+ analyzerInfoFile += sourcefile;
+ else
+ analyzerInfoFile += sourcefile.substr(pos+1);
+ analyzerInfoFile += ".analyzerinfo";
+
+ const std::string start = "";
+
+ if (skipAnalysis(analyzerInfoFile, checksum, errors)) {
+ return false;
+ }
+
+ fout.open(analyzerInfoFile);
+ if (fout.is_open()) {
+ fout << "\n";
+ fout << start << '\n';
+ } else {
+ analyzerInfoFile.clear();
+ }
+
+ return true;
+}
+
+void AnalyzerInformation::reportErr(const ErrorLogger::ErrorMessage &msg, bool verbose)
+{
+ if (fout.is_open())
+ fout << msg.toXML(verbose,2) << '\n';
+}
+
+void AnalyzerInformation::setFileInfo(const std::string &check, const std::string &fileInfo)
+{
+ if (fout.is_open() && !fileInfo.empty())
+ fout << " \n" << fileInfo << " \n";
+}
diff --git a/lib/analyzerinfo.h b/lib/analyzerinfo.h
new file mode 100644
index 000000000..ffaaf02b8
--- /dev/null
+++ b/lib/analyzerinfo.h
@@ -0,0 +1,63 @@
+/*
+* Cppcheck - A tool for static C/C++ code analysis
+* Copyright (C) 2007-2016 Cppcheck team.
+*
+* 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 .
+*/
+
+//---------------------------------------------------------------------------
+#ifndef analyzerinfoH
+#define analyzerinfoH
+//---------------------------------------------------------------------------
+
+#include "config.h"
+#include "errorlogger.h"
+#include
+#include
+
+
+/// @addtogroup Core
+/// @{
+
+/**
+* @brief Analyzer information
+*
+* Store various analysis information:
+* - checksum
+* - error messages
+* - whole program analysis data
+*
+* The information can be used for various purposes. It allows:
+* - 'make' - only analyze TUs that are changed and generate full report
+* - should be possible to add distributed analysis later
+* - multi-threaded whole program analysis
+*/
+class CPPCHECKLIB AnalyzerInformation {
+public:
+ AnalyzerInformation();
+ ~AnalyzerInformation();
+
+ /** Close current TU.analyzerinfo file */
+ void close();
+ bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, std::size_t checksum, std::list *errors);
+ void reportErr(const ErrorLogger::ErrorMessage &msg, bool verbose);
+ void setFileInfo(const std::string &check, const std::string &fileInfo);
+private:
+ std::ofstream fout;
+ std::string analyzerInfoFile;
+};
+
+/// @}
+//---------------------------------------------------------------------------
+#endif // analyzerinfoH
diff --git a/lib/check.h b/lib/check.h
index 637616efc..7d0c35776 100644
--- a/lib/check.h
+++ b/lib/check.h
@@ -90,6 +90,9 @@ public:
public:
FileInfo() {}
virtual ~FileInfo() {}
+ virtual std::string toString() const {
+ return std::string();
+ }
};
virtual FileInfo * getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const {
diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp
index a7eaa5bb1..c1092da49 100644
--- a/lib/checkbufferoverrun.cpp
+++ b/lib/checkbufferoverrun.cpp
@@ -1896,6 +1896,24 @@ void CheckBufferOverrun::arrayIndexThenCheckError(const Token *tok, const std::s
"not be accessed if the index is out of limits.", CWE398, false);
}
+std::string CheckBufferOverrun::MyFileInfo::toString() const
+{
+ std::ostringstream ret;
+ for (std::map::const_iterator it = arrayUsage.begin(); it != arrayUsage.end(); ++it) {
+ ret << " first) << '\"'
+ << " index=\"" << it->second.index << '\"'
+ << " fileName=\"" << ErrorLogger::toxml(it->second.fileName) << '\"'
+ << " linenr=\"" << it->second.linenr << "\"/>\n";
+ }
+ for (std::map::const_iterator it = arraySize.begin(); it != arraySize.end(); ++it) {
+ ret << " first) << '\"'
+ << " size=\"" << it->second << "\"/>\n";
+ }
+ return ret.str();
+}
+
Check::FileInfo* CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const
{
(void)settings;
diff --git a/lib/checkbufferoverrun.h b/lib/checkbufferoverrun.h
index 45bc22297..571f89adc 100644
--- a/lib/checkbufferoverrun.h
+++ b/lib/checkbufferoverrun.h
@@ -209,6 +209,8 @@ public:
/* data for multifile checking */
class MyFileInfo : public Check::FileInfo {
public:
+ std::string toString() const;
+
struct ArrayUsage {
MathLib::bigint index;
std::string fileName;
diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp
index 9cc3e1d17..653003483 100644
--- a/lib/checkunusedfunctions.cpp
+++ b/lib/checkunusedfunctions.cpp
@@ -272,3 +272,19 @@ void CheckUnusedFunctions::analyseWholeProgram(const std::list
(void)fileInfo;
check(&errorLogger, settings);
}
+
+std::string CheckUnusedFunctions::analyzerInfo(const std::string &filename) const
+{
+ std::ostringstream ret;
+ for (std::map::const_iterator it = _functions.begin(); it != _functions.end(); ++it) {
+ if (it->second.filename != filename)
+ continue;
+ ret << " first) << '\"'
+ << " lineNumber=\"" << it->second.lineNumber << '\"'
+ << " usedSameFile=\"" << (it->second.usedSameFile?1:0) << '\"'
+ << " usedOtherFile=\"" << (it->second.usedOtherFile?1:0) << "\"/>\n";
+ }
+ return ret.str();
+}
+
diff --git a/lib/checkunusedfunctions.h b/lib/checkunusedfunctions.h
index 982511547..c5964aafd 100644
--- a/lib/checkunusedfunctions.h
+++ b/lib/checkunusedfunctions.h
@@ -55,6 +55,8 @@ public:
static CheckUnusedFunctions instance;
+ std::string analyzerInfo(const std::string &filename) const;
+
private:
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
@@ -72,9 +74,7 @@ private:
/**
* Dummy implementation, just to provide error for --errorlist
*/
- void runSimplifiedChecks(const Tokenizer *, const Settings *, ErrorLogger *) {
-
- }
+ void runSimplifiedChecks(const Tokenizer *, const Settings *, ErrorLogger *) {}
static std::string myName() {
return "Unused functions";
diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp
index a9cd09d8a..9410a0a56 100644
--- a/lib/cppcheck.cpp
+++ b/lib/cppcheck.cpp
@@ -24,6 +24,8 @@
#include "check.h"
#include "path.h"
+#include "checkunusedfunctions.h"
+
#include
#include
#include
@@ -135,6 +137,18 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin
tokens1.removeComments();
preprocessor.removeComments();
+ if (!_settings.buildDir.empty()) {
+ std::list errors;
+ unsigned int checksum = preprocessor.calculateChecksum(tokens1);
+ if (!analyzerInformation.analyzeFile(_settings.buildDir, filename, checksum, &errors)) {
+ while (!errors.empty()) {
+ reportErr(errors.front());
+ errors.pop_front();
+ }
+ return exitcode; // known results => no need to reanalyze file
+ }
+ }
+
// Get directives
preprocessor.setDirectives(tokens1);
@@ -343,6 +357,9 @@ unsigned int CppCheck::processFile(const std::string& filename, const std::strin
exitcode=1; // e.g. reflect a syntax error
}
+ analyzerInformation.setFileInfo("CheckUnusedFunctions", CheckUnusedFunctions::instance.analyzerInfo(filename));
+ analyzerInformation.close();
+
// In jointSuppressionReport mode, unmatched suppressions are
// collected after all files are processed
if (!_settings.jointSuppressionReport && (_settings.isEnabled("information") || _settings.checkConfiguration)) {
@@ -411,8 +428,10 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer)
// Analyse the tokens..
for (std::list::const_iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) {
Check::FileInfo *fi = (*it)->getFileInfo(&tokenizer, &_settings);
- if (fi != nullptr)
+ if (fi != nullptr) {
fileInfo.push_back(fi);
+ analyzerInformation.setFileInfo((*it)->name(), fi->toString());
+ }
}
executeRules("normal", tokenizer);
@@ -635,6 +654,7 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
_errorList.push_back(errmsg);
_errorLogger.reportErr(msg);
+ analyzerInformation.reportErr(msg, _settings.verbose);
}
void CppCheck::reportOut(const std::string &outmsg)
diff --git a/lib/cppcheck.h b/lib/cppcheck.h
index 81e95fa03..dfb0e5ae4 100644
--- a/lib/cppcheck.h
+++ b/lib/cppcheck.h
@@ -25,6 +25,7 @@
#include "settings.h"
#include "errorlogger.h"
#include "check.h"
+#include "analyzerinfo.h"
#include
#include
@@ -214,6 +215,8 @@ private:
/** File info used for whole program analysis */
std::list fileInfo;
+
+ AnalyzerInformation analyzerInformation;
};
/// @}
diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp
index def486834..56317ff6b 100644
--- a/lib/errorlogger.cpp
+++ b/lib/errorlogger.cpp
@@ -111,6 +111,23 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list& callstack
setmsg(msg);
}
+ErrorLogger::ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg) : _cwe(0U)
+{
+ _id = errmsg->Attribute("id");
+ _severity = Severity::fromString(errmsg->Attribute("severity"));
+ const char *attr = errmsg->Attribute("cwe");
+ std::istringstream(attr ? attr : "0") >> _cwe.id;
+ attr = errmsg->Attribute("inconclusive");
+ _inconclusive = attr && (std::strcmp(attr, "true") == 0);
+ _shortMessage = errmsg->Attribute("msg");
+ _verboseMessage = errmsg->Attribute("verbose");
+ for (const tinyxml2::XMLElement *e = errmsg->FirstChildElement(); e; e = e->NextSiblingElement()) {
+ if (std::strcmp(e->Name(),"location")==0) {
+ _callStack.push_back(ErrorLogger::ErrorMessage::FileLocation(e->Attribute("file"), std::atoi(e->Attribute("line"))));
+ }
+ }
+}
+
void ErrorLogger::ErrorMessage::setmsg(const std::string &msg)
{
// If a message ends to a '\n' and contains only a one '\n'
diff --git a/lib/errorlogger.h b/lib/errorlogger.h
index 82b7dcbaf..f82178a9b 100644
--- a/lib/errorlogger.h
+++ b/lib/errorlogger.h
@@ -40,6 +40,9 @@ struct CWE {
class Token;
class TokenList;
+namespace tinyxml2 {
+ class XMLElement;
+}
/// @addtogroup Core
/// @{
@@ -213,6 +216,7 @@ public:
ErrorMessage(const std::list& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive);
ErrorMessage(const std::list& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, const CWE &cwe, bool inconclusive);
ErrorMessage();
+ ErrorMessage(const tinyxml2::XMLElement * const errmsg);
/**
* Format the error message in XML format
diff --git a/lib/lib.pri b/lib/lib.pri
index 5e2bc2fe2..2b489f2d6 100644
--- a/lib/lib.pri
+++ b/lib/lib.pri
@@ -4,6 +4,7 @@ include($$PWD/pcrerules.pri)
include($$PWD/../externals/externals.pri)
INCLUDEPATH += $$PWD
HEADERS += $${PWD}/check.h \
+ $${PWD}/analyzerinfo.h \
$${PWD}/astutils.h \
$${PWD}/check.h \
$${PWD}/check64bit.h \
@@ -51,7 +52,8 @@ HEADERS += $${PWD}/check.h \
$${PWD}/valueflow.h \
-SOURCES += $${PWD}/astutils.cpp \
+SOURCES += $${PWD}/analyzerinfo.cpp \
+ $${PWD}/astutils.cpp \
$${PWD}/check.cpp \
$${PWD}/check64bit.cpp \
$${PWD}/checkassert.cpp \
diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp
index a74813a36..add5b0549 100644
--- a/lib/preprocessor.cpp
+++ b/lib/preprocessor.cpp
@@ -24,6 +24,7 @@
#include "simplecpp.h"
#include
+#include
#include
#include
#include
@@ -806,3 +807,19 @@ void Preprocessor::dump(std::ostream &out) const
}
out << " " << std::endl;
}
+
+std::size_t Preprocessor::calculateChecksum(const simplecpp::TokenList &tokens1) const
+{
+ std::ostringstream ostr;
+ for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) {
+ if (!tok->comment)
+ ostr << tok->str;
+ }
+ for (std::map::const_iterator it = tokenlists.begin(); it != tokenlists.end(); ++it) {
+ for (const simplecpp::Token *tok = it->second->cfront(); tok; tok = tok->next) {
+ if (!tok->comment)
+ ostr << tok->str;
+ }
+ }
+ return std::hash {}(ostr.str());
+}
diff --git a/lib/preprocessor.h b/lib/preprocessor.h
index 676c339d2..3c883d78d 100644
--- a/lib/preprocessor.h
+++ b/lib/preprocessor.h
@@ -160,6 +160,8 @@ public:
bool validateCfg(const std::string &cfg, const std::list ¯oUsageList);
void validateCfgError(const std::string &file, const unsigned int line, const std::string &cfg, const std::string ¯o);
+ std::size_t calculateChecksum(const simplecpp::TokenList &tokens1) const;
+
private:
/**
diff --git a/lib/settings.h b/lib/settings.h
index 38407d89a..98ffa4fe4 100644
--- a/lib/settings.h
+++ b/lib/settings.h
@@ -56,6 +56,9 @@ private:
public:
Settings();
+ /** @brief --cppcheck-build-dir */
+ std::string buildDir;
+
/** @brief Is --debug given? */
bool debug;