diff --git a/man/cppcheck.1.xml b/man/cppcheck.1.xml
index 9bdca39f0..80766539a 100644
--- a/man/cppcheck.1.xml
+++ b/man/cppcheck.1.xml
@@ -112,6 +112,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
+
@@ -208,6 +209,12 @@ files, this is not needed.
Check coding style.
+
+
+
+ Suppress warnings listed in the file. Filename and line as optional. The format of the single line in file is: [error id]:[filename]:[line]
+
+
diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp
index 302fe4086..8ba3d3e98 100644
--- a/src/cppcheck.cpp
+++ b/src/cppcheck.cpp
@@ -98,6 +98,20 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--style") == 0)
_settings._checkCodingStyle = true;
+ // Filter errors
+ else if (strcmp(argv[i], "--suppressions") == 0)
+ {
+ ++i;
+
+ if (i >= argc)
+ return "No file specified for the --suppressions option\n";
+
+ std::ifstream f(argv[i]);
+ if (!f.is_open())
+ return "couldn't open the file \"" + std::string(argv[i]) + "\"\n";
+ _settings.suppressions(f);
+ }
+
// Verbose error messages (configuration info)
else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
_settings._verbose = true;
@@ -301,8 +315,8 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
"Syntax:\n"
" cppcheck [--all] [--append=file] [--auto-dealloc file.lst]\n"
" [--error-exitcode=[n]] [--force] [--help] [-Idir] [-j [jobs]]\n"
- " [--quiet] [--style] [--unused-functions] [--verbose] [--version]\n"
- " [--xml] [file or path1] [file or path] ...\n"
+ " [--quiet] [--style] [--suppressions file.txt] [--unused-functions]\n"
+ " [--verbose] [--version] [--xml] [file or path1] [file or path] ...\n"
"\n"
"If path is given instead of filename, *.cpp, *.cxx, *.cc, *.c++ and *.c files\n"
"are checked recursively from given directory.\n\n"
@@ -331,6 +345,9 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
" -j [jobs] Start [jobs] threads to do the checking simultaneously.\n"
" -q, --quiet Only print error messages\n"
" -s, --style Check coding style\n"
+ " --suppressions file Suppress warnings listed in the file. Filename and line\n"
+ " are optional. The format of the single line in file is:\n"
+ " [error id]:[filename]:[line]\n"
" --template '[text]' Format the error messages. E.g.\n"
" '{file}:{line},{severity},{id},{message}' or\n"
" '{file}({line}):({severity}) {message}'\n"
@@ -528,6 +545,17 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
return;
+ std::string file;
+ unsigned int line(0);
+ if (!msg._callStack.empty())
+ {
+ file = msg._callStack.back().getfile();
+ line = msg._callStack.back().line;
+ }
+
+ if (_settings.isSuppressed(msg._id, file, line))
+ return;
+
_errorList.push_back(errmsg);
std::string errmsg2(errmsg);
if (_settings._verbose)
diff --git a/src/settings.cpp b/src/settings.cpp
index ac49b2737..34dcf8ed4 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
Settings::Settings()
{
@@ -59,6 +60,62 @@ void Settings::autoDealloc(std::istream &istr)
}
}
+bool Settings::suppressions(std::istream &istr)
+{
+ std::string line;
+ while (getline(istr, line))
+ {
+ // Skip empty lines
+ if (line.empty())
+ continue;
+
+ std::istringstream lineStream(line);
+ std::string id;
+ std::string file;
+ unsigned int lineNumber = 0;
+ if (std::getline(lineStream, id, ':'))
+ {
+ if (std::getline(lineStream, file, ':'))
+ {
+ lineStream >> lineNumber;
+ }
+ }
+
+ // We could perhaps check if the id is valid and return error if it is not
+ addSuppression(id, file, lineNumber);
+ }
+
+ return true;
+}
+
+void Settings::addSuppression(const std::string &errorId, const std::string &file, unsigned int line)
+{
+ _suppressions[errorId][file].push_back(line);
+ _suppressions[errorId][file].sort();
+}
+
+bool Settings::isSuppressed(const std::string &errorId, const std::string &file, unsigned int line)
+{
+ if (_suppressions.find(errorId) == _suppressions.end())
+ return false;
+
+ // Check are all errors of this type filtered out
+ if (_suppressions[errorId].find("") != _suppressions[errorId].end())
+ return true;
+
+ if (_suppressions[errorId].find(file) == _suppressions[errorId].end())
+ return false;
+
+ // Check should all errors in this file be filtered out
+ if (std::find(_suppressions[errorId][file].begin(), _suppressions[errorId][file].end(), 0) != _suppressions[errorId][file].end())
+ return true;
+
+ if (std::find(_suppressions[errorId][file].begin(), _suppressions[errorId][file].end(), line) == _suppressions[errorId][file].end())
+ return false;
+
+ return true;
+}
+
void Settings::addAutoAllocClass(const std::string &name)
{
_autoDealloc.push_back(name);
diff --git a/src/settings.h b/src/settings.h
index 99a4bf96b..20219257d 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include