diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 2d36a4f40..89559c60a 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1136,7 +1136,9 @@ public: virtual ExecutionPath *copy() = 0; bool bailOut() const - { return bailout_; } + { + return bailout_; + } /** * bail out all execution paths diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index c8c078df2..d4f474741 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -122,6 +122,10 @@ void CppCheck::parseFromArgs(int argc, const char* const argv[]) _settings.suppressions(f); } + // Enables inline suppressions. + else if (strcmp(argv[i], "--inline-suppr") == 0) + _settings._inlineSuppressions = true; + // Verbose error messages (configuration info) else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) _settings._verbose = true; @@ -331,8 +335,9 @@ void CppCheck::parseFromArgs(int argc, const char* const argv[]) "Syntax:\n" " cppcheck [--all] [--append=file] [--auto-dealloc file.lst] [--enable]\n" " [--error-exitcode=[n]] [--force] [--help] [-Idir] [-j [jobs]]\n" - " [--quiet] [--style] [--suppressions file.txt] [--verbose]\n" - " [--version] [--xml] [file or path1] [file or path] ...\n" + " [--quiet] [--style] [--suppressions file.txt] [--inline-suppr]\n" + " [--verbose] [--version] [--xml] [file or path1]\n" + " [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" @@ -373,6 +378,9 @@ void CppCheck::parseFromArgs(int argc, const char* const argv[]) " --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" + " --inline-suppr Enable inline suppressions. Use them by placing one or\n" + " more comments in the form: // cppcheck-suppress memleak\n" + " on the lines before the warning to suppress.\n" " --template '[text]' Format the error messages. E.g.\n" " '{file}:{line},{severity},{id},{message}' or\n" " '{file}({line}):({severity}) {message}'\n" diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index eae9e7477..7c77072b7 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -33,7 +33,7 @@ #include #include -Preprocessor::Preprocessor(const Settings *settings, ErrorLogger *errorLogger) : _settings(settings), _errorLogger(errorLogger) +Preprocessor::Preprocessor(Settings *settings, ErrorLogger *errorLogger) : _settings(settings), _errorLogger(errorLogger) { } @@ -70,7 +70,7 @@ static char readChar(std::istream &istr) } /** Just read the code into a string. Perform simple cleanup of the code */ -std::string Preprocessor::read(std::istream &istr) +std::string Preprocessor::read(std::istream &istr, const std::string &filename, Settings *settings) { // Get filedata from stream.. bool ignoreSpace = true; @@ -152,7 +152,7 @@ std::string Preprocessor::read(std::istream &istr) } } - return removeParantheses(removeComments(code.str())); + return removeParantheses(removeComments(code.str(), filename, settings)); } static bool hasbom(const std::string &str) @@ -164,7 +164,7 @@ static bool hasbom(const std::string &str) } -std::string Preprocessor::removeComments(const std::string &str) +std::string Preprocessor::removeComments(const std::string &str, const std::string &filename, Settings *settings) { // For the error report int lineno = 1; @@ -175,19 +175,46 @@ std::string Preprocessor::removeComments(const std::string &str) unsigned int newlines = 0; std::ostringstream code; char previous = 0; + std::vector suppressionIDs; + for (std::string::size_type i = hasbom(str) ? 3 : 0; i < str.length(); ++i) { char ch = str[i]; if (ch < 0) throw std::runtime_error("The code contains characters that are unhandled"); + // We have finished a line that didn't contain any comment + // (the '\n' is swallowed when a // comment is detected) + if (ch == '\n' && !suppressionIDs.empty()) + { + // Add the suppressions. + for (size_t j(0); j < suppressionIDs.size(); ++j) + settings->addSuppression(suppressionIDs[j], filename, lineno); + suppressionIDs.clear(); + } + // Remove comments.. if (str.compare(i, 2, "//", 0, 2) == 0) { + size_t commentStart = i + 2; i = str.find('\n', i); if (i == std::string::npos) break; + if (settings->_inlineSuppressions) + { + std::string comment(str, commentStart, i - commentStart); + std::istringstream iss(comment); + std::string word; + iss >> word; + if (word == "cppcheck-suppress") + { + iss >> word; + if (iss) + suppressionIDs.push_back(word); + } + } + code << "\n"; previous = '\n'; ++lineno; @@ -256,11 +283,15 @@ std::string Preprocessor::removeComments(const std::string &str) // if there has been sequences, add extra newlines.. - if (ch == '\n' && newlines > 0) + if (ch == '\n') { - code << std::string(newlines, '\n'); - newlines = 0; - previous = '\n'; + ++lineno; + if (newlines > 0) + { + code << std::string(newlines, '\n'); + newlines = 0; + previous = '\n'; + } } } } @@ -490,7 +521,7 @@ std::string Preprocessor::replaceIfDefined(const std::string &str) void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, std::list &resultConfigurations, const std::string &filename, const std::list &includePaths) { - processedFile = read(istr); + processedFile = read(istr, filename, _settings); // Replace all tabs with spaces.. std::replace(processedFile.begin(), processedFile.end(), '\t', ' '); @@ -1201,7 +1232,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filename if (fin.is_open()) { filename = *iter + filename; - processedFile = Preprocessor::read(fin); + processedFile = Preprocessor::read(fin, filename, _settings); fileOpened = true; break; } @@ -1213,7 +1244,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filename std::ifstream fin(filename.c_str()); if (fin.is_open()) { - processedFile = Preprocessor::read(fin); + processedFile = Preprocessor::read(fin, filename, _settings); fileOpened = true; } } @@ -1577,7 +1608,7 @@ static bool getlines(std::istream &istr, std::string &line) c = (char)istr.get(); if (!istr.good()) return true; - if (c == '\n' && line.compare(0,1,"#")==0) + if (c == '\n' && line.compare(0, 1, "#") == 0) return true; line += c; } diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 58a386cf3..4e052b3b4 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -35,7 +35,7 @@ class Preprocessor { public: - Preprocessor(const Settings *settings = 0, ErrorLogger *errorLogger = 0); + Preprocessor(Settings *settings = 0, ErrorLogger *errorLogger = 0); /** * Extract the code for each configuration @@ -70,7 +70,7 @@ public: void preprocess(std::istream &istr, std::string &processedFile, std::list &resultConfigurations, const std::string &filename, const std::list &includePaths); /** Just read the code into a string. Perform simple cleanup of the code */ - static std::string read(std::istream &istr); + static std::string read(std::istream &istr, const std::string &filename, Settings *settings); /** * Get preprocessed code for a given configuration @@ -104,7 +104,7 @@ protected: * @return code without comments * @throws std::runtime_error when code contains unhandled characters */ - static std::string removeComments(const std::string &str); + static std::string removeComments(const std::string &str, const std::string &filename, Settings *settings); /** * Remove redundant parantheses from preprocessor commands. This should only be called from read(). @@ -171,7 +171,7 @@ private: */ void handleIncludes(std::string &code, const std::string &filename, const std::list &includePaths); - const Settings *_settings; + Settings *_settings; ErrorLogger *_errorLogger; }; diff --git a/lib/settings.cpp b/lib/settings.cpp index 05e8dfdc6..1473a9885 100755 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -29,6 +29,7 @@ Settings::Settings() _showAll = false; _checkCodingStyle = false; _errorsOnly = false; + _inlineSuppressions = false; _verbose = false; _force = false; _xml = false; diff --git a/lib/settings.h b/lib/settings.h index 27ef2e407..0918b4238 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -56,6 +56,7 @@ public: bool _showAll; bool _checkCodingStyle; bool _errorsOnly; + bool _inlineSuppressions; bool _verbose; /** Force checking t he files with "too many" configurations. */