From 56c7ac37718c6bacf9cad4e93ff752d2136e2437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 19 Nov 2023 18:56:48 +0100 Subject: [PATCH 01/40] Fix #12182 (speedup valueFlow by only running valueFlowNumber once) (#5678) --- lib/valueflow.cpp | 23 ++++++++------ test/cli/test-other.py | 71 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 9 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 97c2c453dee..c1e6424362f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1042,6 +1042,16 @@ static void setTokenValue(Token* tok, } } + // C++ init + else if (parent->str() == "{" && Token::simpleMatch(parent->previous(), "= {") && Token::simpleMatch(parent->link(), "} ;")) { + const Token* lhs = parent->previous()->astOperand1(); + if (lhs && lhs->valueType()) { + if (lhs->valueType()->isIntegral() || lhs->valueType()->isFloat() || (lhs->valueType()->pointer > 0 && value.isIntValue())) { + setTokenValue(parent, value, settings); + } + } + } + else if (Token::Match(parent, ":: %name%") && parent->astOperand2() == tok) { setTokenValue(parent, value, settings); } @@ -1335,16 +1345,12 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b if (!tok->isTemplateArg()) value.setKnown(); setTokenValue(tok->next(), std::move(value), settings); - } else if (Token::Match(tok, "%name% = {") && tok->variable() && - (tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))) { - if (Token::simpleMatch(tok->tokAt(3), "}")) { + } else if (Token::simpleMatch(tok, "= { } ;")) { + const Token* lhs = tok->astOperand1(); + if (lhs && lhs->valueType() && (lhs->valueType()->isIntegral() || lhs->valueType()->pointer > 0)) { ValueFlow::Value value(0); value.setKnown(); - setTokenValue(tok->tokAt(2), std::move(value), settings); - } else if (tok->tokAt(2)->astOperand1() && tok->tokAt(2)->astOperand1()->hasKnownIntValue()) { - ValueFlow::Value value(tok->tokAt(2)->astOperand1()->getKnownIntValue()); - value.setKnown(); - setTokenValue(tok->tokAt(2), std::move(value), settings); + setTokenValue(tok->next(), std::move(value), settings); } } return tok->next(); @@ -9448,7 +9454,6 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowUnknownFunctionReturn(tokenlist, settings)), VFA(valueFlowGlobalConstVar(tokenlist, settings)), VFA(valueFlowEnumValue(symboldatabase, settings)), - VFA(valueFlowNumber(tokenlist, settings)), VFA(valueFlowGlobalStaticVar(tokenlist, settings)), VFA(valueFlowPointerAlias(tokenlist, settings)), VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), diff --git a/test/cli/test-other.py b/test/cli/test-other.py index fcdf7539295..2d39cc74179 100644 --- a/test/cli/test-other.py +++ b/test/cli/test-other.py @@ -191,6 +191,77 @@ def test_slow_long_line(tmpdir): cppcheck([filename]) # should not take more than ~1 second +@pytest.mark.timeout(60) +def test_slow_large_constant_expression(tmpdir): + # 12182 + filename = os.path.join(tmpdir, 'hang.c') + with open(filename, 'wt') as f: + f.write(""" +#define FLAG1 0 +#define FLAG2 0 +#define FLAG3 0 +#define FLAG4 0 +#define FLAG5 0 +#define FLAG6 0 +#define FLAG7 0 +#define FLAG8 0 +#define FLAG9 0 +#define FLAG10 0 +#define FLAG11 0 +#define FLAG12 0 +#define FLAG13 0 +#define FLAG14 0 +#define FLAG15 0 +#define FLAG16 0 +#define FLAG17 0 +#define FLAG18 0 +#define FLAG19 0 +#define FLAG20 0 +#define FLAG21 0 +#define FLAG22 0 +#define FLAG23 0 +#define FLAG24 0 + +#define maxval(x, y) ((x) > (y) ? (x) : (y)) + +#define E_SAMPLE_SIZE maxval( FLAG1, \ + maxval( FLAG2, \ + maxval( FLAG3, \ + maxval( FLAG4, \ + maxval( FLAG5, \ + maxval( FLAG6, \ + maxval( FLAG7, \ + maxval( FLAG8, \ + maxval( FLAG9, \ + maxval( FLAG10, \ + maxval( FLAG11, \ + maxval( FLAG12, \ + maxval( FLAG13, \ + maxval( FLAG14, \ + FLAG15 )))))))))))))) + +#define SAMPLE_SIZE maxval( E_SAMPLE_SIZE, \ + maxval( sizeof(st), \ + maxval( FLAG16, \ + maxval( FLAG17, \ + maxval( FLAG18, \ + maxval( FLAG19, \ + maxval( FLAG20, \ + maxval( FLAG21, \ + maxval( FLAG22, \ + maxval( FLAG23, \ + FLAG24 )))))))))) + +typedef struct { + int n; +} st; + +x = SAMPLE_SIZE; + """) + + cppcheck([filename]) + + def test_execute_addon_failure(tmpdir): test_file = os.path.join(tmpdir, 'test.cpp') with open(test_file, 'wt') as f: From 4addad16439ba54f1fb1abac2400fea14a6b5a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Sun, 19 Nov 2023 19:45:10 +0100 Subject: [PATCH 02/40] moved settings-related code from `CppCheckExecutor` to `CmdLineParser` (#5672) `CppCheckExecutor` contains some code which is not related to the execution but actually to the creation of the settings. This is causing inconsistencies in the error handling/logging as well as interfering with the testability. --- Makefile | 4 +- cli/cmdlineparser.cpp | 267 ++++++++++++++++++++++++++++++++++ cli/cmdlineparser.h | 40 +++++ cli/cppcheckexecutor.cpp | 307 +++------------------------------------ cli/cppcheckexecutor.h | 32 ---- 5 files changed, 331 insertions(+), 319 deletions(-) diff --git a/Makefile b/Makefile index 0590db67eb3..5ac59a8cdc8 100644 --- a/Makefile +++ b/Makefile @@ -647,10 +647,10 @@ $(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vfvalue.cpp -cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h +cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp -cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/filelister.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h +cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cppcheckexecutor.cpp cli/cppcheckexecutorseh.o: cli/cppcheckexecutorseh.cpp cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h lib/config.h lib/filesettings.h lib/platform.h lib/standards.h lib/utils.h diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 442fd7daf8f..e83da8e92ca 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -18,14 +18,20 @@ #include "cmdlineparser.h" +#include "addoninfo.h" #include "check.h" +#include "color.h" #include "config.h" +#include "cppcheck.h" #include "cppcheckexecutor.h" #include "errorlogger.h" #include "errortypes.h" +#include "filelister.h" #include "filesettings.h" #include "importproject.h" +#include "library.h" #include "path.h" +#include "pathmatch.h" #include "platform.h" #include "settings.h" #include "standards.h" @@ -34,6 +40,7 @@ #include "utils.h" #include +#include #include #include #include // EXIT_FAILURE @@ -109,6 +116,24 @@ static bool addPathsToSet(const std::string& fileName, std::set& se return true; } +namespace { + class XMLErrorMessagesLogger : public ErrorLogger + { + void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override + { + std::cout << outmsg << std::endl; + } + + void reportErr(const ErrorMessage &msg) override + { + reportOut(msg.toXML()); + } + + void reportProgress(const std::string & /*filename*/, const char /*stage*/[], const std::size_t /*value*/) override + {} + }; +} + CmdLineParser::CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail) : mLogger(logger) , mSettings(settings) @@ -116,6 +141,161 @@ CmdLineParser::CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppress , mSuppressionsNoFail(suppressionsNoFail) {} +bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) +{ + const bool success = parseFromArgs(argc, argv); + + if (success) { + if (getShowVersion() && !getShowErrorMessages()) { + if (!mSettings.cppcheckCfgProductName.empty()) { + mLogger.printRaw(mSettings.cppcheckCfgProductName); + } else { + const char * const extraVersion = CppCheck::extraVersion(); + if (*extraVersion != 0) + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); + else + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); + } + } + + if (getShowErrorMessages()) { + XMLErrorMessagesLogger xmlLogger; + std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); + CppCheck::getErrorMessages(xmlLogger); + std::cout << ErrorMessage::getXMLFooter() << std::endl; + } + + if (exitAfterPrinting()) { + Settings::terminate(); + return true; + } + } else { + return false; + } + + // Libraries must be loaded before FileLister is executed to ensure markup files will be + // listed properly. + if (!loadLibraries(mSettings)) + return false; + + if (!loadAddons(mSettings)) + return false; + + // Check that all include paths exist + { + for (std::list::iterator iter = mSettings.includePaths.begin(); + iter != mSettings.includePaths.end(); + ) { + const std::string path(Path::toNativeSeparators(*iter)); + if (Path::isDirectory(path)) + ++iter; + else { + // TODO: this bypasses the template format and other settings + // If the include path is not found, warn user and remove the non-existing path from the list. + if (mSettings.severity.isEnabled(Severity::information)) + std::cout << "(information) Couldn't find path given by -I '" << path << '\'' << std::endl; + iter = mSettings.includePaths.erase(iter); + } + } + } + + // Output a warning for the user if he tries to exclude headers + const std::vector& ignored = getIgnoredPaths(); + const bool warn = std::any_of(ignored.cbegin(), ignored.cend(), [](const std::string& i) { + return Path::isHeader(i); + }); + if (warn) { + mLogger.printMessage("filename exclusion does not apply to header (.h and .hpp) files."); + mLogger.printMessage("Please use --suppress for ignoring results from the header files."); + } + + const std::vector& pathnamesRef = getPathNames(); + const std::list& fileSettingsRef = getFileSettings(); + + // the inputs can only be used exclusively - CmdLineParser should already handle this + assert(!(!pathnamesRef.empty() && !fileSettingsRef.empty())); + + if (!fileSettingsRef.empty()) { + std::list fileSettings; + if (!mSettings.fileFilters.empty()) { + // filter only for the selected filenames from all project files + std::copy_if(fileSettingsRef.cbegin(), fileSettingsRef.cend(), std::back_inserter(fileSettings), [&](const FileSettings &fs) { + return matchglobs(mSettings.fileFilters, fs.filename); + }); + if (fileSettings.empty()) { + mLogger.printError("could not find any files matching the filter."); + return false; + } + } + else { + fileSettings = fileSettingsRef; + } + + mFileSettings.clear(); + + // sort the markup last + std::copy_if(fileSettings.cbegin(), fileSettings.cend(), std::back_inserter(mFileSettings), [&](const FileSettings &fs) { + return !mSettings.library.markupFile(fs.filename) || !mSettings.library.processMarkupAfterCode(fs.filename); + }); + + std::copy_if(fileSettings.cbegin(), fileSettings.cend(), std::back_inserter(mFileSettings), [&](const FileSettings &fs) { + return mSettings.library.markupFile(fs.filename) && mSettings.library.processMarkupAfterCode(fs.filename); + }); + } + + if (!pathnamesRef.empty()) { + std::list> filesResolved; + // TODO: this needs to be inlined into PathMatch as it depends on the underlying filesystem +#if defined(_WIN32) + // For Windows we want case-insensitive path matching + const bool caseSensitive = false; +#else + const bool caseSensitive = true; +#endif + // Execute recursiveAddFiles() to each given file parameter + const PathMatch matcher(ignored, caseSensitive); + for (const std::string &pathname : pathnamesRef) { + const std::string err = FileLister::recursiveAddFiles(filesResolved, Path::toNativeSeparators(pathname), mSettings.library.markupExtensions(), matcher); + if (!err.empty()) { + // TODO: bail out? + mLogger.printMessage(err); + } + } + + std::list> files; + if (!mSettings.fileFilters.empty()) { + std::copy_if(filesResolved.cbegin(), filesResolved.cend(), std::inserter(files, files.end()), [&](const decltype(filesResolved)::value_type& entry) { + return matchglobs(mSettings.fileFilters, entry.first); + }); + if (files.empty()) { + mLogger.printError("could not find any files matching the filter."); + return false; + } + } + else { + files = std::move(filesResolved); + } + + // sort the markup last + std::copy_if(files.cbegin(), files.cend(), std::inserter(mFiles, mFiles.end()), [&](const decltype(files)::value_type& entry) { + return !mSettings.library.markupFile(entry.first) || !mSettings.library.processMarkupAfterCode(entry.first); + }); + + std::copy_if(files.cbegin(), files.cend(), std::inserter(mFiles, mFiles.end()), [&](const decltype(files)::value_type& entry) { + return mSettings.library.markupFile(entry.first) && mSettings.library.processMarkupAfterCode(entry.first); + }); + } + + if (mFiles.empty() && mFileSettings.empty()) { + mLogger.printError("could not find or open any of the paths given."); + if (!ignored.empty()) + mLogger.printMessage("Maybe all paths were ignored?"); + return false; + } + + return true; +} + // TODO: normalize/simplify/native all path parameters // TODO: error out on all missing given files/paths bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) @@ -1444,3 +1624,90 @@ bool CmdLineParser::isCppcheckPremium() const { mSettings.loadCppcheckCfg(); return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium"); } + +bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename) +{ + const Library::Error err = destination.load(basepath.c_str(), filename); + + if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT) + std::cout << "cppcheck: Found unknown elements in configuration file '" << filename << "': " << err.reason << std::endl; + else if (err.errorcode != Library::ErrorCode::OK) { + std::cout << "cppcheck: Failed to load library configuration file '" << filename << "'. "; + switch (err.errorcode) { + case Library::ErrorCode::OK: + break; + case Library::ErrorCode::FILE_NOT_FOUND: + std::cout << "File not found"; + break; + case Library::ErrorCode::BAD_XML: + std::cout << "Bad XML"; + break; + case Library::ErrorCode::UNKNOWN_ELEMENT: + std::cout << "Unexpected element"; + break; + case Library::ErrorCode::MISSING_ATTRIBUTE: + std::cout << "Missing attribute"; + break; + case Library::ErrorCode::BAD_ATTRIBUTE_VALUE: + std::cout << "Bad attribute value"; + break; + case Library::ErrorCode::UNSUPPORTED_FORMAT: + std::cout << "File is of unsupported format version"; + break; + case Library::ErrorCode::DUPLICATE_PLATFORM_TYPE: + std::cout << "Duplicate platform type"; + break; + case Library::ErrorCode::PLATFORM_TYPE_REDEFINED: + std::cout << "Platform type redefined"; + break; + } + if (!err.reason.empty()) + std::cout << " '" + err.reason + "'"; + std::cout << std::endl; + return false; + } + return true; +} + +bool CmdLineParser::loadLibraries(Settings& settings) +{ + if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg")) { + const std::string msg("Failed to load std.cfg. Your Cppcheck installation is broken, please re-install."); +#ifdef FILESDIR + const std::string details("The Cppcheck binary was compiled with FILESDIR set to \"" + FILESDIR "\" and will therefore search for " + "std.cfg in " FILESDIR "/cfg."); +#else + const std::string cfgfolder(Path::fromNativeSeparators(Path::getPathFromFilename(settings.exename)) + "cfg"); + const std::string details("The Cppcheck binary was compiled without FILESDIR set. Either the " + "std.cfg should be available in " + cfgfolder + " or the FILESDIR " + "should be configured."); +#endif + std::cout << msg << " " << details << std::endl; + return false; + } + + bool result = true; + for (const auto& lib : settings.libraries) { + if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str())) { + result = false; + } + } + return result; +} + +bool CmdLineParser::loadAddons(Settings& settings) +{ + bool result = true; + for (const std::string &addon: settings.addons) { + AddonInfo addonInfo; + const std::string failedToGetAddonInfo = addonInfo.getAddonInfo(addon, settings.exename); + if (!failedToGetAddonInfo.empty()) { + std::cout << failedToGetAddonInfo << std::endl; + result = false; + continue; + } + settings.addonInfos.emplace_back(std::move(addonInfo)); + } + return result; +} diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index e797f05e0a2..cd5560a83ac 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "cmdlinelogger.h" @@ -30,6 +31,7 @@ class Settings; class Suppressions; +class Library; /// @addtogroup CLI /// @{ @@ -55,6 +57,16 @@ class CmdLineParser { */ CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail); + /** + * @brief Parse command line args and fill settings and file lists + * from there. + * + * @param argc argc from main() + * @param argv argv from main() + * @return false when errors are found in the input + */ + bool fillSettingsFromArgs(int argc, const char* const argv[]); + /** * Parse given command line. * @return true if command line was ok, false if there was an error. @@ -82,6 +94,13 @@ class CmdLineParser { return mPathNames; } + /** + * Return the files user gave to command line. + */ + const std::list>& getFiles() const { + return mFiles; + } + /** * Return the file settings read from command line. */ @@ -130,9 +149,30 @@ class CmdLineParser { return true; } + /** + * Tries to load a library and prints warning/error messages + * @return false, if an error occurred (except unknown XML elements) + */ + static bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename); + + /** + * @brief Load libraries + * @param settings Settings + * @return Returns true if successful + */ + static bool loadLibraries(Settings& settings); + + /** + * @brief Load addons + * @param settings Settings + * @return Returns true if successful + */ + static bool loadAddons(Settings& settings); + CmdLineLogger &mLogger; std::vector mPathNames; + std::list> mFiles; std::list mFileSettings; std::vector mIgnoredPaths; Settings &mSettings; diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index fc3349e24a0..832684c967f 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -18,7 +18,6 @@ #include "cppcheckexecutor.h" -#include "addoninfo.h" #include "analyzerinfo.h" #include "checkersreport.h" #include "cmdlinelogger.h" @@ -28,11 +27,7 @@ #include "cppcheck.h" #include "errorlogger.h" #include "errortypes.h" -#include "filelister.h" #include "filesettings.h" -#include "library.h" -#include "path.h" -#include "pathmatch.h" #include "settings.h" #include "singleexecutor.h" #include "suppressions.h" @@ -47,16 +42,13 @@ #endif #include -#include #include #include // EXIT_SUCCESS and EXIT_FAILURE #include #include -#include #include #include #include // IWYU pragma: keep -#include #include #include @@ -72,44 +64,26 @@ #include #endif -namespace { - class XMLErrorMessagesLogger : public ErrorLogger - { - void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override - { - std::cout << outmsg << std::endl; - } - - void reportErr(const ErrorMessage &msg) override - { - reportOut(msg.toXML()); - } - - void reportProgress(const std::string & /*filename*/, const char /*stage*/[], const std::size_t /*value*/) override - {} - }; +class CmdLineLoggerStd : public CmdLineLogger +{ +public: + CmdLineLoggerStd() = default; - class CmdLineLoggerStd : public CmdLineLogger + void printMessage(const std::string &message) override { - public: - CmdLineLoggerStd() = default; - - void printMessage(const std::string &message) override - { - printRaw("cppcheck: " + message); - } + printRaw("cppcheck: " + message); + } - void printError(const std::string &message) override - { - printMessage("error: " + message); - } + void printError(const std::string &message) override + { + printMessage("error: " + message); + } - void printRaw(const std::string &message) override - { - std::cout << message << std::endl; - } - }; -} + void printRaw(const std::string &message) override + { + std::cout << message << std::endl; + } +}; class CppCheckExecutor::StdLogger : public ErrorLogger { @@ -195,173 +169,23 @@ class CppCheckExecutor::StdLogger : public ErrorLogger /*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout; #endif -bool CppCheckExecutor::parseFromArgs(Settings &settings, int argc, const char* const argv[]) -{ - CmdLineLoggerStd logger; - CmdLineParser parser(logger, settings, settings.nomsg, settings.nofail); - const bool success = parser.parseFromArgs(argc, argv); - - if (success) { - if (parser.getShowVersion() && !parser.getShowErrorMessages()) { - if (!settings.cppcheckCfgProductName.empty()) { - logger.printRaw(settings.cppcheckCfgProductName); - } else { - const char * const extraVersion = CppCheck::extraVersion(); - if (*extraVersion != 0) - logger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); - else - logger.printRaw(std::string("Cppcheck ") + CppCheck::version()); - } - } - - if (parser.getShowErrorMessages()) { - XMLErrorMessagesLogger xmlLogger; - std::cout << ErrorMessage::getXMLHeader(settings.cppcheckCfgProductName); - CppCheck::getErrorMessages(xmlLogger); - std::cout << ErrorMessage::getXMLFooter() << std::endl; - } - - if (parser.exitAfterPrinting()) { - Settings::terminate(); - return true; - } - } else { - return false; - } - - // Libraries must be loaded before FileLister is executed to ensure markup files will be - // listed properly. - if (!loadLibraries(settings)) - return false; - - if (!loadAddons(settings)) - return false; - - // Check that all include paths exist - { - for (std::list::iterator iter = settings.includePaths.begin(); - iter != settings.includePaths.end(); - ) { - const std::string path(Path::toNativeSeparators(*iter)); - if (Path::isDirectory(path)) - ++iter; - else { - // TODO: this bypasses the template format and other settings - // If the include path is not found, warn user and remove the non-existing path from the list. - if (settings.severity.isEnabled(Severity::information)) - std::cout << "(information) Couldn't find path given by -I '" << path << '\'' << std::endl; - iter = settings.includePaths.erase(iter); - } - } - } - - // Output a warning for the user if he tries to exclude headers - const std::vector& ignored = parser.getIgnoredPaths(); - const bool warn = std::any_of(ignored.cbegin(), ignored.cend(), [](const std::string& i) { - return Path::isHeader(i); - }); - if (warn) { - logger.printMessage("filename exclusion does not apply to header (.h and .hpp) files."); - logger.printMessage("Please use --suppress for ignoring results from the header files."); - } - - const std::vector& pathnamesRef = parser.getPathNames(); - const std::list& fileSettingsRef = parser.getFileSettings(); - - // the inputs can only be used exclusively - CmdLineParser should already handle this - assert(!(!pathnamesRef.empty() && !fileSettingsRef.empty())); - - if (!fileSettingsRef.empty()) { - std::list fileSettings; - if (!settings.fileFilters.empty()) { - // filter only for the selected filenames from all project files - std::copy_if(fileSettingsRef.cbegin(), fileSettingsRef.cend(), std::back_inserter(fileSettings), [&](const FileSettings &fs) { - return matchglobs(settings.fileFilters, fs.filename); - }); - if (fileSettings.empty()) { - logger.printError("could not find any files matching the filter."); - return false; - } - } - else { - fileSettings = fileSettingsRef; - } - - // sort the markup last - std::copy_if(fileSettings.cbegin(), fileSettings.cend(), std::back_inserter(mFileSettings), [&](const FileSettings &fs) { - return !settings.library.markupFile(fs.filename) || !settings.library.processMarkupAfterCode(fs.filename); - }); - - std::copy_if(fileSettings.cbegin(), fileSettings.cend(), std::back_inserter(mFileSettings), [&](const FileSettings &fs) { - return settings.library.markupFile(fs.filename) && settings.library.processMarkupAfterCode(fs.filename); - }); - } - - if (!pathnamesRef.empty()) { - std::list> filesResolved; - // TODO: this needs to be inlined into PathMatch as it depends on the underlying filesystem -#if defined(_WIN32) - // For Windows we want case-insensitive path matching - const bool caseSensitive = false; -#else - const bool caseSensitive = true; -#endif - // Execute recursiveAddFiles() to each given file parameter - const PathMatch matcher(ignored, caseSensitive); - for (const std::string &pathname : pathnamesRef) { - const std::string err = FileLister::recursiveAddFiles(filesResolved, Path::toNativeSeparators(pathname), settings.library.markupExtensions(), matcher); - if (!err.empty()) { - // TODO: bail out? - logger.printMessage(err); - } - } - - std::list> files; - if (!settings.fileFilters.empty()) { - std::copy_if(filesResolved.cbegin(), filesResolved.cend(), std::inserter(files, files.end()), [&](const decltype(filesResolved)::value_type& entry) { - return matchglobs(settings.fileFilters, entry.first); - }); - if (files.empty()) { - logger.printError("could not find any files matching the filter."); - return false; - } - } - else { - files = std::move(filesResolved); - } - - // sort the markup last - std::copy_if(files.cbegin(), files.cend(), std::inserter(mFiles, mFiles.end()), [&](const decltype(files)::value_type& entry) { - return !settings.library.markupFile(entry.first) || !settings.library.processMarkupAfterCode(entry.first); - }); - - std::copy_if(files.cbegin(), files.cend(), std::inserter(mFiles, mFiles.end()), [&](const decltype(files)::value_type& entry) { - return settings.library.markupFile(entry.first) && settings.library.processMarkupAfterCode(entry.first); - }); - } - - if (mFiles.empty() && mFileSettings.empty()) { - logger.printError("could not find or open any of the paths given."); - if (!ignored.empty()) - logger.printMessage("Maybe all paths were ignored?"); - return false; - } - - return true; -} - int CppCheckExecutor::check(int argc, const char* const argv[]) { CheckUnusedFunctions::clear(); Settings settings; - if (!parseFromArgs(settings, argc, argv)) { + CmdLineLoggerStd logger; + CmdLineParser parser(logger, settings, settings.nomsg, settings.nofail); + if (!parser.fillSettingsFromArgs(argc, argv)) { return EXIT_FAILURE; } if (Settings::terminated()) { return EXIT_SUCCESS; } + mFiles = parser.getFiles(); + mFileSettings = parser.getFileSettings(); + mStdLogger = new StdLogger(settings); CppCheck cppCheck(*mStdLogger, true, executeCommand); cppCheck.settings() = settings; @@ -490,49 +314,6 @@ void CppCheckExecutor::StdLogger::writeCheckersReport() const } -bool CppCheckExecutor::loadLibraries(Settings& settings) -{ - if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg")) { - const std::string msg("Failed to load std.cfg. Your Cppcheck installation is broken, please re-install."); -#ifdef FILESDIR - const std::string details("The Cppcheck binary was compiled with FILESDIR set to \"" - FILESDIR "\" and will therefore search for " - "std.cfg in " FILESDIR "/cfg."); -#else - const std::string cfgfolder(Path::fromNativeSeparators(Path::getPathFromFilename(settings.exename)) + "cfg"); - const std::string details("The Cppcheck binary was compiled without FILESDIR set. Either the " - "std.cfg should be available in " + cfgfolder + " or the FILESDIR " - "should be configured."); -#endif - std::cout << msg << " " << details << std::endl; - return false; - } - - bool result = true; - for (const auto& lib : settings.libraries) { - if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str())) { - result = false; - } - } - return result; -} - -bool CppCheckExecutor::loadAddons(Settings& settings) -{ - bool result = true; - for (const std::string &addon: settings.addons) { - AddonInfo addonInfo; - const std::string failedToGetAddonInfo = addonInfo.getAddonInfo(addon, settings.exename); - if (!failedToGetAddonInfo.empty()) { - std::cout << failedToGetAddonInfo << std::endl; - result = false; - continue; - } - settings.addonInfos.emplace_back(std::move(addonInfo)); - } - return result; -} - #ifdef _WIN32 // fix trac ticket #439 'Cppcheck reports wrong filename for filenames containing 8-bit ASCII' static inline std::string ansiToOEM(const std::string &msg, bool doConvert) @@ -635,50 +416,6 @@ FILE* CppCheckExecutor::getExceptionOutput() } #endif -bool CppCheckExecutor::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename) -{ - const Library::Error err = destination.load(basepath.c_str(), filename); - - if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT) - std::cout << "cppcheck: Found unknown elements in configuration file '" << filename << "': " << err.reason << std::endl; - else if (err.errorcode != Library::ErrorCode::OK) { - std::cout << "cppcheck: Failed to load library configuration file '" << filename << "'. "; - switch (err.errorcode) { - case Library::ErrorCode::OK: - break; - case Library::ErrorCode::FILE_NOT_FOUND: - std::cout << "File not found"; - break; - case Library::ErrorCode::BAD_XML: - std::cout << "Bad XML"; - break; - case Library::ErrorCode::UNKNOWN_ELEMENT: - std::cout << "Unexpected element"; - break; - case Library::ErrorCode::MISSING_ATTRIBUTE: - std::cout << "Missing attribute"; - break; - case Library::ErrorCode::BAD_ATTRIBUTE_VALUE: - std::cout << "Bad attribute value"; - break; - case Library::ErrorCode::UNSUPPORTED_FORMAT: - std::cout << "File is of unsupported format version"; - break; - case Library::ErrorCode::DUPLICATE_PLATFORM_TYPE: - std::cout << "Duplicate platform type"; - break; - case Library::ErrorCode::PLATFORM_TYPE_REDEFINED: - std::cout << "Platform type redefined"; - break; - } - if (!err.reason.empty()) - std::cout << " '" + err.reason + "'"; - std::cout << std::endl; - return false; - } - return true; -} - /** * Execute a shell command and read the output from it. Returns true if command terminated successfully. */ diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index 48e13b75247..34157ddfbd0 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -29,7 +29,6 @@ #include class CppCheck; -class Library; class Settings; class ErrorLogger; @@ -75,12 +74,6 @@ class CppCheckExecutor { private: - /** - * Tries to load a library and prints warning/error messages - * @return false, if an error occurred (except unknown XML elements) - */ - static bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename); - /** * Execute a shell command and read the output from it. Returns exitcode of the executed command,. */ @@ -88,17 +81,6 @@ class CppCheckExecutor { protected: - /** - * @brief Parse command line args and get settings and file lists - * from there. - * - * @param settings the settings to store into - * @param argc argc from main() - * @param argv argv from main() - * @return false when errors are found in the input - */ - bool parseFromArgs(Settings &settings, int argc, const char* const argv[]); - static bool reportSuppressions(const Settings &settings, bool unusedFunctionCheckEnabled, const std::list> &files, ErrorLogger& errorLogger); /** @@ -121,20 +103,6 @@ class CppCheckExecutor { */ int check_internal(CppCheck& cppcheck); - /** - * @brief Load libraries - * @param settings Settings - * @return Returns true if successful - */ - static bool loadLibraries(Settings& settings); - - /** - * @brief Load addons - * @param settings Settings - * @return Returns true if successful - */ - static bool loadAddons(Settings& settings); - /** * Filename associated with size of file */ From cd21918520a9134586ddaa9be06ba6a752640ecb Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sun, 19 Nov 2023 19:51:32 +0100 Subject: [PATCH 03/40] Fix FP memleak with outparam allocation (f'up to #12186) (#5677) I wonder if it is worth trying to get this right. We also have FPs when the return value is assigned to a variable, and that seems much harder to fix. --- lib/checkleakautovar.cpp | 17 +++++++++++++++++ test/cfg/gnu.c | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 3894de25521..2b3b65c8c94 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -1108,6 +1108,23 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO } } + // don't warn when returning after checking return value of outparam allocation + const Scope* scope = tok->scope(); + if (scope->type == Scope::ScopeType::eIf || scope->type== Scope::ScopeType::eElse) { + if (scope->type == Scope::ScopeType::eElse) { + scope = scope->bodyStart->tokAt(-2)->scope(); + } + const Token* const ifEnd = scope->bodyStart->previous(); + const Token* const ifStart = ifEnd->link(); + const Token* const alloc = it->second.allocTok; + if (precedes(ifStart, alloc) && succeeds(ifEnd, alloc)) { + int argn{}; + if (const Token* ftok = getTokenArgumentFunction(alloc, argn)) + if (Token::Match(ftok->next()->astParent(), "%comp%")) + continue; + } + } + // return deallocated pointer if (used != PtrUsage::NONE && it->second.status == VarInfo::DEALLOC) deallocReturnError(tok, it->second.allocTok, var->name()); diff --git a/test/cfg/gnu.c b/test/cfg/gnu.c index d7fbe6d6667..35b65e816c7 100644 --- a/test/cfg/gnu.c +++ b/test/cfg/gnu.c @@ -380,6 +380,24 @@ void memleak_asprintf5(char* p) { // cppcheck-suppress memleak } +void memleak_asprintf6(const char* fmt, const int arg) { + char* ptr; + if (-1 == asprintf(&ptr, fmt, arg)) + return; + printf("%s", ptr); + free(ptr); +} + +void memleak_asprintf7(const char* fmt, const int arg) { + char* ptr; + if (asprintf(&ptr, fmt, arg) != -1) { + printf("%s", ptr); + free(ptr); + } + else + return; +} + void memleak_xmalloc() { char *p = (char*)xmalloc(10); From 92c089d4ad3a0819b91c1339313fdc5e65f2f959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 20 Nov 2023 07:23:45 +0100 Subject: [PATCH 04/40] fixed some "Parameter can be made pointer/reference to const" Rider warnings (#5680) --- gui/codeeditor.cpp | 2 +- gui/codeeditor.h | 2 +- gui/cppchecklibrarydata.cpp | 2 +- gui/settingsdialog.cpp | 2 +- gui/settingsdialog.h | 2 +- tools/triage/mainwindow.cpp | 2 +- tools/triage/mainwindow.h | 2 +- tools/triage/mainwindow.ui | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gui/codeeditor.cpp b/gui/codeeditor.cpp index 2a195565df6..b48b3a9bcf8 100644 --- a/gui/codeeditor.cpp +++ b/gui/codeeditor.cpp @@ -420,7 +420,7 @@ void CodeEditor::highlightErrorLine() setExtraSelections(extraSelections); } -void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) +void CodeEditor::lineNumberAreaPaintEvent(const QPaintEvent *event) { QPainter painter(mLineNumberArea); painter.fillRect(event->rect(), mWidgetStyle->lineNumBGColor); diff --git a/gui/codeeditor.h b/gui/codeeditor.h index 553ee7b05da..6e06db9881f 100644 --- a/gui/codeeditor.h +++ b/gui/codeeditor.h @@ -91,7 +91,7 @@ class CodeEditor : public QPlainTextEdit { CodeEditor &operator=(const CodeEditor &) = delete; ~CodeEditor() override; - void lineNumberAreaPaintEvent(QPaintEvent *event); + void lineNumberAreaPaintEvent(const QPaintEvent *event); int lineNumberAreaWidth(); void setStyle(const CodeEditorStyle& newStyle); diff --git a/gui/cppchecklibrarydata.cpp b/gui/cppchecklibrarydata.cpp index 5911d6fc43d..7c7d20261a4 100644 --- a/gui/cppchecklibrarydata.cpp +++ b/gui/cppchecklibrarydata.cpp @@ -453,7 +453,7 @@ static CppcheckLibraryData::Markup loadMarkup(QXmlStreamReader &xmlReader) return markup; } -static CppcheckLibraryData::Entrypoint loadEntrypoint(QXmlStreamReader &xmlReader) +static CppcheckLibraryData::Entrypoint loadEntrypoint(const QXmlStreamReader &xmlReader) { CppcheckLibraryData::Entrypoint entrypoint; entrypoint.name = xmlReader.attributes().value("name").toString(); diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 72569b9f962..8acf493dac1 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -214,7 +214,7 @@ void SettingsDialog::saveSettingValues() const CodeEditorStyle::saveSettings(&settings, *mCurrentStyle); } -void SettingsDialog::saveCheckboxValue(QSettings *settings, QCheckBox *box, +void SettingsDialog::saveCheckboxValue(QSettings *settings, const QCheckBox *box, const QString &name) { settings->setValue(name, checkStateToBool(box->checkState())); diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h index e04582d8035..7b1fb694c5f 100644 --- a/gui/settingsdialog.h +++ b/gui/settingsdialog.h @@ -185,7 +185,7 @@ protected slots: * @param box checkbox to save * @param name name for QSettings to store the value */ - static void saveCheckboxValue(QSettings *settings, QCheckBox *box, const QString &name); + static void saveCheckboxValue(QSettings *settings, const QCheckBox *box, const QString &name); /** * @brief Convert bool to Qt::CheckState diff --git a/tools/triage/mainwindow.cpp b/tools/triage/mainwindow.cpp index 2eac338d284..22ffe8e536d 100644 --- a/tools/triage/mainwindow.cpp +++ b/tools/triage/mainwindow.cpp @@ -285,7 +285,7 @@ bool MainWindow::unpackArchive(const QString &archiveName) return runProcess("tar", args); } -void MainWindow::showResult(QListWidgetItem *item) +void MainWindow::showResult(const QListWidgetItem *item) { ui->statusBar->clearMessage(); const bool local = item->text().startsWith(DACA2_PACKAGES); diff --git a/tools/triage/mainwindow.h b/tools/triage/mainwindow.h index 6c5085b4d1d..624e3ebafd1 100644 --- a/tools/triage/mainwindow.h +++ b/tools/triage/mainwindow.h @@ -47,7 +47,7 @@ public slots: void loadFile(); void loadFromClipboard(); void filter(const QString& filter); - void showResult(QListWidgetItem *item); + void showResult(const QListWidgetItem *item); void refreshResults(); void fileTreeFilter(const QString &str); void findInFilesClicked(); diff --git a/tools/triage/mainwindow.ui b/tools/triage/mainwindow.ui index 540c4871793..5e24e942210 100644 --- a/tools/triage/mainwindow.ui +++ b/tools/triage/mainwindow.ui @@ -450,7 +450,7 @@ results itemDoubleClicked(QListWidgetItem*) MainWindow - showResult(QListWidgetItem*) + showResult(const QListWidgetItem*) 28 @@ -481,7 +481,7 @@ loadFile() - showResult(QListWidgetItem*) + showResult(const QListWidgetItem*) loadFromClipboard() filter(QString) refreshResults() From 3bafe164a3d8063c5cecb28aa397e274acf50aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 20 Nov 2023 10:06:46 +0100 Subject: [PATCH 05/40] enabled some clang-tidy warnings for non-GUI code (#5679) There are some clang-tidy warnings which cannot properly handle the extensions used in the Qt code so the produce lots of false positives and were previously enabled. With clang-tidy now offering the possibility to inherit the parent configuration we can enable these across the project and simply disable them for the GUI code. No additional warnings were found as they were already fixed in earlier commits without enabling the checks in question. --- .clang-tidy | 2 -- clang-tidy.md | 20 +++++++++++--------- gui/.clang-tidy | 5 +++++ tools/triage/.clang-tidy | 5 +++++ 4 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 gui/.clang-tidy create mode 100644 tools/triage/.clang-tidy diff --git a/.clang-tidy b/.clang-tidy index b721e1b9461..e96c20ed6dd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -61,7 +61,6 @@ Checks: > -readability-braces-around-statements, -readability-const-return-type, -readability-container-data-pointer, - -readability-convert-member-functions-to-static, -readability-function-cognitive-complexity, -readability-function-size, -readability-identifier-length, @@ -69,7 +68,6 @@ Checks: > -readability-implicit-bool-conversion, -readability-isolate-declaration, -readability-magic-numbers, - -readability-redundant-access-specifiers, -readability-suspicious-call-argument, -readability-uppercase-literal-suffix WarningsAsErrors: '*' diff --git a/clang-tidy.md b/clang-tidy.md index a31fea4a915..1b9c0aef180 100644 --- a/clang-tidy.md +++ b/clang-tidy.md @@ -71,10 +71,6 @@ These might change the behavior of code which might not be intended (need to fil This leads to a mismatch of raw string literals and regular ones and does reduce the readability. -`readability-convert-member-functions-to-static`
- -Disabled because of false positives with Qt `slot` methods (see https://github.com/llvm/llvm-project/issues/57520). - `-clang-analyzer-*`
Disabled because of false positives (needs to file an upstream bug report). @@ -112,10 +108,6 @@ Produces a lot of false positives since it is too vague in its analysis. Produces warnings which might be considered false positives starting with C++11 - see https://github.com/llvm/llvm-project/issues/54526. -`readability-redundant-access-specifiers`
- -Reports warning with the Qt ` slots:` syntax in class declarations - see https://github.com/llvm/llvm-project/issues/60055. - `modernize-avoid-c-arrays`
Produces warnings when `const char[]` is being used which is quite common in our code. Does not make sense to enable before C++17 when `std::string_view` becomes available. @@ -196,4 +188,14 @@ This is the most expensive check for several files and it is providing much in t `modernize-use-nullptr` -This is already covered by the `-Wzero-as-null-pointer-constant` compiler warning so there is no need for an additional check. \ No newline at end of file +This is already covered by the `-Wzero-as-null-pointer-constant` compiler warning so there is no need for an additional check. + +### Disabled for GUI only + +`readability-convert-member-functions-to-static`
+ +Disabled because of false positives with Qt `slot` methods (see https://github.com/llvm/llvm-project/issues/57520). + +`readability-redundant-access-specifiers`
+ +Reports warning with the Qt ` slots:` syntax in class declarations - see https://github.com/llvm/llvm-project/issues/60055. diff --git a/gui/.clang-tidy b/gui/.clang-tidy new file mode 100644 index 00000000000..8a62240d85a --- /dev/null +++ b/gui/.clang-tidy @@ -0,0 +1,5 @@ +--- +Checks: > + -readability-convert-member-functions-to-static, + -readability-redundant-access-specifiers +InheritParentConfig: true diff --git a/tools/triage/.clang-tidy b/tools/triage/.clang-tidy new file mode 100644 index 00000000000..8a62240d85a --- /dev/null +++ b/tools/triage/.clang-tidy @@ -0,0 +1,5 @@ +--- +Checks: > + -readability-convert-member-functions-to-static, + -readability-redundant-access-specifiers +InheritParentConfig: true From 036df0aca9a9fa68180c3f5654b9443b49a1286f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 20 Nov 2023 11:54:41 +0100 Subject: [PATCH 06/40] Fix #12181 (Suppressions: allow that id with * is added) (#5681) --- lib/suppressions.cpp | 17 ++++++++--------- man/manual.md | 6 +++--- test/testsuppressions.cpp | 9 +++++++++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index d395a4c1ed2..af5470423ee 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -58,9 +58,10 @@ static bool isAcceptedErrorIdChar(char c) case '_': case '-': case '.': + case '*': return true; default: - return std::isalnum(c); + return c > 0 && std::isalnum(c); } } @@ -255,14 +256,12 @@ std::string Suppressions::addSuppression(Suppressions::Suppression suppression) if (suppression.errorId.empty() && suppression.hash == 0) return "Failed to add suppression. No id."; - if (suppression.errorId != "*") { - for (std::string::size_type pos = 0; pos < suppression.errorId.length(); ++pos) { - if (suppression.errorId[pos] < 0 || !isAcceptedErrorIdChar(suppression.errorId[pos])) { - return "Failed to add suppression. Invalid id \"" + suppression.errorId + "\""; - } - if (pos == 0 && std::isdigit(suppression.errorId[pos])) { - return "Failed to add suppression. Invalid id \"" + suppression.errorId + "\""; - } + for (std::string::size_type pos = 0; pos < suppression.errorId.length(); ++pos) { + if (!isAcceptedErrorIdChar(suppression.errorId[pos])) { + return "Failed to add suppression. Invalid id \"" + suppression.errorId + "\""; + } + if (pos == 0 && std::isdigit(suppression.errorId[pos])) { + return "Failed to add suppression. Invalid id \"" + suppression.errorId + "\""; } } diff --git a/man/manual.md b/man/manual.md index 332bc9a2a57..b0a9a6088f4 100644 --- a/man/manual.md +++ b/man/manual.md @@ -451,10 +451,10 @@ The format for an error suppression is one of: [error id]:[filename2] [error id] -The `error id` is the id that you want to suppress. The easiest way to get it is to use the --template=gcc command line flag. The id is shown in brackets. +The `error id` is the id that you want to suppress. The id of a warning is shown in brackets in the normal cppcheck text output. The suppression `error id` may contain \* to match any sequence of tokens. -The filename may include the wildcard characters \* or ?, which matches any sequence of characters or any single character respectively. -It is recommended to use "/" as path separator on all operating systems. The filename must match the filename in the reported warning exactly. +The filename may include the wildcard characters \* or ?, which matches any sequence of characters or any single character respectively. +It is recommended to use forward-slash `/` as path separator on all operating systems. The filename must match the filename in the reported warning exactly. For instance, if the warning contains a relative path, then the suppression must match that relative path. ## Command line suppression diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp index 87aee88a02a..2c8eccf06bd 100644 --- a/test/testsuppressions.cpp +++ b/test/testsuppressions.cpp @@ -51,6 +51,7 @@ class TestSuppressions : public TestFixture { TEST_CASE(suppressionsDosFormat); // Ticket #1836 TEST_CASE(suppressionsFileNameWithColon); // Ticket #1919 - filename includes colon TEST_CASE(suppressionsGlob); + TEST_CASE(suppressionsGlobId); TEST_CASE(suppressionsFileNameWithExtraPath); TEST_CASE(suppressionsSettings); TEST_CASE(suppressionsSettingsThreads); @@ -171,6 +172,14 @@ class TestSuppressions : public TestFixture { } } + void suppressionsGlobId() const { + Suppressions suppressions; + std::istringstream s("a*\n"); + ASSERT_EQUALS("", suppressions.parseFile(s)); + ASSERT_EQUALS(true, suppressions.isSuppressed(errorMessage("abc", "xyz.cpp", 1))); + ASSERT_EQUALS(false, suppressions.isSuppressed(errorMessage("def", "xyz.cpp", 1))); + } + void suppressionsFileNameWithExtraPath() const { // Ticket #2797 Suppressions suppressions; From d7c7a39afe5635fe80a1c4f0c43bb1f43de2c390 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:26:05 +0100 Subject: [PATCH 07/40] Fix crash in CheckLeakAutoVar (f'up to #12186) (#5683) --- lib/checkleakautovar.cpp | 4 ++-- test/testleakautovar.cpp | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 2b3b65c8c94..d99a28d030d 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -1109,8 +1109,8 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO } // don't warn when returning after checking return value of outparam allocation - const Scope* scope = tok->scope(); - if (scope->type == Scope::ScopeType::eIf || scope->type== Scope::ScopeType::eElse) { + if (it->second.allocTok && (tok->scope()->type == Scope::ScopeType::eIf || tok->scope()->type== Scope::ScopeType::eElse)) { + const Scope* scope = tok->scope(); if (scope->type == Scope::ScopeType::eElse) { scope = scope->bodyStart->tokAt(-2)->scope(); } diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 0b70e28f263..700292c9c42 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -1594,6 +1594,16 @@ class TestLeakAutoVar : public TestFixture { " s->p = NULL;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + const Settings s = settingsBuilder().library("std.cfg").build(); + check("struct S {};\n" + "void f(int i, std::vector> &v) {\n" + " if (i < 1) {\n" + " auto s = new S;\n" + " v.push_back(std::unique_ptr(s));\n" + " }\n" + "}\n", &s); + ASSERT_EQUALS("", errout.str()); // don't crash } void goto1() { From d09a6514cd30190428c1fa293cc27890012c820f Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 20 Nov 2023 19:43:29 +0100 Subject: [PATCH 08/40] Fix #11012 FP unassignedVariable when passed in init list (#5684) --- lib/checkunusedvar.cpp | 2 +- test/testunusedvar.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 812d60aef4f..161a309c61f 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1090,7 +1090,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const } else if (Token::Match(tok->previous(), "[{,] %var% [,}]")) { - variables.read(tok->varId(), tok); + variables.use(tok->varId(), tok); } else if (tok->varId() && Token::Match(tok, "%var% .")) { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 75ae9b961fa..fc04d144a39 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -176,6 +176,7 @@ class TestUnusedVar : public TestFixture { TEST_CASE(localvararray3); // ticket #3980 TEST_CASE(localvararray4); // ticket #4839 TEST_CASE(localvararray5); // ticket #7092 + TEST_CASE(localvararray6); TEST_CASE(localvarstring1); TEST_CASE(localvarstring2); // ticket #2929 TEST_CASE(localvarconst1); @@ -6059,6 +6060,17 @@ class TestUnusedVar : public TestFixture { ASSERT_EQUALS("[test.cpp:2]: (style) Unused variable: v\n", errout.str()); } + void localvararray6() { + functionVariableUsage("struct S { int* p; };\n" // #11012 + "void g(struct S* ps);\n" + "void f() {\n" + " int i[2];\n" + " struct S s = { i };\n" + " g(&s);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void localvarstring1() { // ticket #1597 functionVariableUsage("void foo() {\n" " std::string s;\n" From f444696d5cbcfb2f420148912629bfdcaaacbacd Mon Sep 17 00:00:00 2001 From: andymacg <117683405+andymacg@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:19:20 -0500 Subject: [PATCH 09/40] Fix #12198: Expect function pointers in Misra 17.7 check (#5675) --- addons/misra.py | 4 +++- addons/test/misra/misra-test.c | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/misra.py b/addons/misra.py index f6e0698df0e..cc26146dd10 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -3333,7 +3333,9 @@ def misra_17_7(self, data): continue if token.str != '(' or token.astParent: continue - if not token.previous.isName or token.previous.varId: + if not token.astOperand1 or not token.astOperand1.isName: + continue + if token.astOperand1.varId and get_function_pointer_type(token.astOperand1.variable.typeStartToken) is None: continue if token.valueType is None: continue diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 14eddd8600c..db73cfd6466 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -1739,6 +1739,9 @@ static void misra_17_6(int x[static 20]) {(void)x;} // 17.6 static int calculation(int x) { return x + 1; } static void misra_17_7(void) { calculation(123); // 17.7 + int (*calc_ptr)(int) = &calculation; + calc_ptr(123); // 17.7 + int y = calc_ptr(123); } static void misra_17_8(int x) { From f9521cfb4e2189e319bd767554a162d08d9e729d Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:01:22 +0100 Subject: [PATCH 10/40] Fix #12208 FN constParameterReference with nested struct/class (#5685) --- lib/symboldatabase.cpp | 7 +++++-- lib/valueflow.cpp | 6 +++--- test/testsymboldatabase.cpp | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 5e9c9d24081..339ea640ee6 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -5867,8 +5867,11 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const if (tok1) tok1 = tok1->tokAt(2); - if (currScope && tok1) - return currScope->findFunction(tok1); + if (currScope && tok1) { + const Function* func = currScope->findFunction(tok1); + if (func) + return func; + } } } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c1e6424362f..3a375e3eef6 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -127,7 +127,7 @@ #include #include -static void bailoutInternal(const std::string& type, TokenList &tokenlist, ErrorLogger *errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function) +static void bailoutInternal(const std::string& type, const TokenList &tokenlist, ErrorLogger *errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, std::string function) { if (function.find("operator") != std::string::npos) function = "(valueFlow)"; @@ -4011,7 +4011,7 @@ struct LifetimeStore { } } - static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, TokenList &tokenlist, const Settings* settings, ErrorLogger *errorLogger) { + static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const TokenList &tokenlist, const Settings* settings, ErrorLogger *errorLogger) { if (!var) return LifetimeStore{}; if (!var->isArgument()) @@ -7038,7 +7038,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart, const Token* expr, bool globalvar, const MathLib::bigint value, - TokenList& tokenlist, + const TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings) { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 13570130609..103716158a6 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -452,6 +452,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(findFunction50); // #11904 - method with same name and arguments in derived class TEST_CASE(findFunction51); // #11975 - method with same name in derived class TEST_CASE(findFunction52); + TEST_CASE(findFunction53); TEST_CASE(findFunctionContainer); TEST_CASE(findFunctionExternC); TEST_CASE(findFunctionGlobalScope); // ::foo @@ -7671,6 +7672,21 @@ class TestSymbolDatabase : public TestFixture { ASSERT(g->function()->tokenDef->linenr() == 1); } + void findFunction53() { + GET_SYMBOL_DB("namespace N {\n" // #12208 + " struct S {\n" + " S(const int*);\n" + " };\n" + "}\n" + "void f(int& r) {\n" + " N::S(&r);\n" + "}\n"); + const Token* S = Token::findsimplematch(tokenizer.tokens(), "S ( &"); + ASSERT(S->function() && S->function()->tokenDef); + ASSERT(S->function()->tokenDef->linenr() == 3); + ASSERT(S->function()->isConstructor()); + } + void findFunctionContainer() { { GET_SYMBOL_DB("void dostuff(std::vector v);\n" From f5630e704952ac5470c572f5545da1d3aa4c0078 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:28:38 +0100 Subject: [PATCH 11/40] Fix #12209 "debug: Executable scope 'x' with unknown function." with anonymous namespace (#5688) --- lib/symboldatabase.cpp | 5 ++++- test/testsymboldatabase.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 339ea640ee6..a3c7722100f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3254,7 +3254,8 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To } } - if (scope1->className == tok1->str() && (scope1->type != Scope::eFunction)) { + const bool isAnonymousNamespace = (scope1->type == Scope::eNamespace && scope1->className.empty()); + if ((scope1->className == tok1->str() && (scope1->type != Scope::eFunction)) || isAnonymousNamespace) { // do the scopes match (same scope) or do their names match (multiple namespaces) if ((*scope == scope1->nestedIn) || (*scope && (*scope)->className == scope1->nestedIn->className && @@ -3286,6 +3287,8 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To tok1 = tok1->tokAt(2); scope2 = scope2->findRecordInNestedList(tok1->str()); } + if (isAnonymousNamespace) + scope2 = scope2->findRecordInNestedList(tok1->str()); if (count == 1 && scope2) { match = true; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 103716158a6..559adb26179 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -373,6 +373,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(createSymbolDatabaseFindAllScopes4); TEST_CASE(createSymbolDatabaseFindAllScopes5); TEST_CASE(createSymbolDatabaseFindAllScopes6); + TEST_CASE(createSymbolDatabaseFindAllScopes7); TEST_CASE(createSymbolDatabaseIncompleteVars); @@ -5461,6 +5462,31 @@ class TestSymbolDatabase : public TestFixture { ASSERT_EQUALS(classNC.derivedFrom[1].type, &classNB); } + void createSymbolDatabaseFindAllScopes7() + { + GET_SYMBOL_DB("namespace {\n" + " struct S {\n" + " void f();\n" + " };\n" + "}\n" + "void S::f() {}\n"); + ASSERT(db); + ASSERT_EQUALS(4, db->scopeList.size()); + auto anon = db->scopeList.begin(); + ++anon; + ASSERT(anon->className.empty()); + ASSERT_EQUALS(anon->type, Scope::eNamespace); + auto S = anon; + ++S; + ASSERT_EQUALS(S->type, Scope::eStruct); + ASSERT_EQUALS(S->className, "S"); + ASSERT_EQUALS(S->nestedIn, &*anon); + const Token* f = Token::findsimplematch(tokenizer.tokens(), "f ( ) {"); + ASSERT(f && f->function() && f->function()->functionScope && f->function()->functionScope->bodyStart); + ASSERT_EQUALS(f->function()->functionScope->functionOf, &*S); + ASSERT_EQUALS(f->function()->functionScope->bodyStart->linenr(), 6); + } + void createSymbolDatabaseIncompleteVars() { { From 2b61c9ef2f9fec9bcf45c82c42a66ee52093ee68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Tue, 21 Nov 2023 11:35:17 +0100 Subject: [PATCH 12/40] Tokenizer: moved `VariableMap` into anonymous namespace (#5686) --- lib/symboldatabase.cpp | 19 ++++---- lib/symboldatabase.h | 4 +- lib/templatesimplifier.cpp | 6 +-- lib/tokenize.cpp | 95 ++++++++++++++++++-------------------- lib/tokenize.h | 37 ++++----------- 5 files changed, 69 insertions(+), 92 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index a3c7722100f..dd8c6d0bf38 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -206,7 +206,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // skip variable declaration else if (Token::Match(tok2, "*|&|>")) continue; - else if (Token::Match(tok2, "%name% (") && mTokenizer.isFunctionHead(tok2->next(), "{;")) + else if (Token::Match(tok2, "%name% (") && Tokenizer::isFunctionHead(tok2->next(), "{;")) continue; else if (Token::Match(tok2, "%name% [|=")) continue; @@ -531,7 +531,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // class function? else if (isFunction(tok, scope, &funcStart, &argStart, &declEnd)) { if (tok->previous()->str() != "::" || tok->strAt(-2) == scope->className) { - Function function(&mTokenizer, tok, scope, funcStart, argStart); + Function function(tok, scope, funcStart, argStart); // save the access type function.access = access[scope]; @@ -547,7 +547,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() function.arg = function.argDef; // out of line function - if (const Token *endTok = mTokenizer.isFunctionHead(end, ";")) { + if (const Token *endTok = Tokenizer::isFunctionHead(end, ";")) { tok = endTok; scope->addFunction(function); } @@ -1864,7 +1864,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const const Token* tok1 = tok->previous(); const Token* tok2 = tok->next()->link()->next(); - if (!mTokenizer.isFunctionHead(tok->next(), ";:{")) + if (!Tokenizer::isFunctionHead(tok->next(), ";:{")) return false; // skip over destructor "~" @@ -2418,8 +2418,7 @@ static bool isOperator(const Token *tokenDef) return name.size() > 8 && startsWith(name,"operator") && std::strchr("+-*/%&|~^<>!=[(", name[8]); } -Function::Function(const Tokenizer *mTokenizer, - const Token *tok, +Function::Function(const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef) @@ -2520,7 +2519,7 @@ Function::Function(const Tokenizer *mTokenizer, tok = tok->next(); } - if (mTokenizer->isFunctionHead(end, ":{")) { + if (Tokenizer::isFunctionHead(end, ":{")) { // assume implementation is inline (definition and implementation same) token = tokenDef; arg = argDef; @@ -3168,7 +3167,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok, const Token *argStart, const Token* funcStart) { - Function function(&mTokenizer, tok, scope, funcStart, argStart); + Function function(tok, scope, funcStart, argStart); scope->addFunction(std::move(function)); return &scope->functionList.back(); } @@ -3232,7 +3231,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To if (!func->hasBody()) { const Token *closeParen = (*tok)->next()->link(); if (closeParen) { - const Token *eq = mTokenizer.isFunctionHead(closeParen, ";"); + const Token *eq = Tokenizer::isFunctionHead(closeParen, ";"); if (eq && Token::simpleMatch(eq->tokAt(-2), "= default ;")) { func->isDefault(true); return; @@ -3305,7 +3304,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To if (func->argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) { const Token *closeParen = (*tok)->next()->link(); if (closeParen) { - const Token *eq = mTokenizer.isFunctionHead(closeParen, ";"); + const Token *eq = Tokenizer::isFunctionHead(closeParen, ";"); if (eq && Token::simpleMatch(eq->tokAt(-2), "= default ;")) { func->isDefault(true); return; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 163a86bef95..83b0fb33119 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -749,7 +749,7 @@ class CPPCHECKLIB Function { public: enum Type { eConstructor, eCopyConstructor, eMoveConstructor, eOperatorEqual, eDestructor, eFunction, eLambda }; - Function(const Tokenizer *mTokenizer, const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef); + Function(const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef); Function(const Token *tokenDef, const std::string &clangType); const std::string &name() const { @@ -1438,7 +1438,7 @@ class CPPCHECKLIB SymbolDatabase { void debugSymbolDatabase() const; void addClassFunction(Scope **scope, const Token **tok, const Token *argStart); - Function *addGlobalFunctionDecl(Scope*& scope, const Token* tok, const Token *argStart, const Token* funcStart); + static Function *addGlobalFunctionDecl(Scope*& scope, const Token* tok, const Token *argStart, const Token* funcStart); Function *addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart); void addNewFunction(Scope **scope, const Token **tok); bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart, const Token** declEnd) const; diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index fa7c02c01ca..e1af536d3e8 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -1422,14 +1422,14 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to } else if (Token::Match(tok->next(), "%type% <")) { const Token *closing = tok->tokAt(2)->findClosingBracket(); if (closing) { - if (closing->strAt(1) == "(" && Tokenizer::isFunctionHead(closing->next(), ";|{|:", true)) + if (closing->strAt(1) == "(" && Tokenizer::isFunctionHead(closing->next(), ";|{|:")) return true; while (tok->next() && tok->next() != closing) { tok = tok->next(); namepos++; } } - } else if (Token::Match(tok->next(), "%type% (") && Tokenizer::isFunctionHead(tok->tokAt(2), ";|{|:", true)) { + } else if (Token::Match(tok->next(), "%type% (") && Tokenizer::isFunctionHead(tok->tokAt(2), ";|{|:")) { return true; } tok = tok->next(); @@ -1934,7 +1934,7 @@ void TemplateSimplifier::expandTemplate( const Token *tok4 = tok3->next()->findClosingBracket(); while (tok4 && tok4->str() != "(") tok4 = tok4->next(); - if (!Tokenizer::isFunctionHead(tok4, ":{", true)) + if (!Tokenizer::isFunctionHead(tok4, ":{")) continue; // find function return type start tok5 = tok5->next()->findClosingBracket(); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 75fa0ebea9c..35ee843fa8c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -93,12 +93,7 @@ static void skipEnumBody(T **tok) *tok = defStart->link()->next(); } -const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith) const -{ - return Tokenizer::isFunctionHead(tok, endsWith, isCPP()); -} - -const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp) +const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &endsWith) { if (!tok) return nullptr; @@ -113,7 +108,7 @@ const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &end } return (tok && endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr; } - if (cpp && tok->str() == ")") { + if (tok->isCpp() && tok->str() == ")") { tok = tok->next(); while (Token::Match(tok, "const|noexcept|override|final|volatile|mutable|&|&& !!(") || (Token::Match(tok, "%name% !!(") && tok->isUpperCaseName())) @@ -2791,7 +2786,7 @@ namespace { } } // namespace -bool Tokenizer::isMemberFunction(const Token *openParen) const +bool Tokenizer::isMemberFunction(const Token *openParen) { return (Token::Match(openParen->tokAt(-2), ":: %name% (") || Token::Match(openParen->tokAt(-3), ":: ~ %name% (")) && @@ -3901,7 +3896,7 @@ const Token * Tokenizer::startOfExecutableScope(const Token * tok) if (tok->str() != ")") return nullptr; - tok = isFunctionHead(tok, ":{", true); + tok = Tokenizer::isFunctionHead(tok, ":{"); if (Token::Match(tok, ": %name% [({]")) { while (Token::Match(tok, "[:,] %name% [({]")) @@ -4088,32 +4083,31 @@ void Tokenizer::simplifyTemplates() //--------------------------------------------------------------------------- -/** Class used in Tokenizer::setVarIdPass1 */ -class VariableMap { -private: - std::unordered_map mVariableId; - std::unordered_map mVariableId_global; - std::stack>> mScopeInfo; - mutable nonneg int mVarId{}; -public: - VariableMap() = default; - void enterScope(); - bool leaveScope(); - void addVariable(const std::string& varname, bool globalNamespace); - bool hasVariable(const std::string& varname) const { - return mVariableId.find(varname) != mVariableId.end(); - } +namespace { + /** Class used in Tokenizer::setVarIdPass1 */ + class VariableMap { + private: + std::unordered_map mVariableId; + std::unordered_map mVariableId_global; + std::stack>> mScopeInfo; + mutable nonneg int mVarId{}; + public: + VariableMap() = default; + void enterScope(); + bool leaveScope(); + void addVariable(const std::string& varname, bool globalNamespace); + bool hasVariable(const std::string& varname) const { + return mVariableId.find(varname) != mVariableId.end(); + } - const std::unordered_map& map(bool global) const { - return global ? mVariableId_global : mVariableId; - } - nonneg int getVarId() const { - return mVarId; - } - nonneg int& getVarId() { - return mVarId; - } -}; + const std::unordered_map& map(bool global) const { + return global ? mVariableId_global : mVariableId; + } + nonneg int& getVarId() { + return mVarId; + } + }; +} void VariableMap::enterScope() @@ -4298,9 +4292,9 @@ static bool setVarIdParseDeclaration(Token** tok, const VariableMap& variableMap } -void Tokenizer::setVarIdStructMembers(Token **tok1, - std::map>& structMembers, - nonneg int &varId) const +static void setVarIdStructMembers(Token **tok1, + std::map>& structMembers, + nonneg int &varId) { Token *tok = *tok1; @@ -4334,7 +4328,7 @@ void Tokenizer::setVarIdStructMembers(Token **tok1, while (Token::Match(tok->next(), ")| . %name% !!(")) { // Don't set varid for trailing return type if (tok->strAt(1) == ")" && (tok->linkAt(1)->previous()->isName() || tok->linkAt(1)->strAt(-1) == "]") && - isFunctionHead(tok->linkAt(1), "{|;")) { + Tokenizer::isFunctionHead(tok->linkAt(1), "{|;")) { tok = tok->tokAt(3); continue; } @@ -4363,10 +4357,10 @@ void Tokenizer::setVarIdStructMembers(Token **tok1, *tok1 = tok; } -void Tokenizer::setVarIdClassDeclaration(Token* const startToken, - VariableMap& variableMap, - const nonneg int scopeStartVarId, - std::map>& structMembers) +static bool setVarIdClassDeclaration(Token* const startToken, + VariableMap& variableMap, + const nonneg int scopeStartVarId, + std::map>& structMembers) { // end of scope const Token* const endToken = startToken->link(); @@ -4389,7 +4383,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken, const Token *initListArgLastToken = nullptr; for (Token *tok = startToken->next(); tok != endToken; tok = tok->next()) { if (!tok) - syntaxError(nullptr); + return false; if (initList) { if (tok == initListArgLastToken) initListArgLastToken = nullptr; @@ -4416,7 +4410,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken, if (Token::Match(tok->previous(), "::|.") && tok->strAt(-2) != "this" && !Token::simpleMatch(tok->tokAt(-5), "( * this ) .")) continue; if (!tok->next()) - syntaxError(nullptr); + return false; if (tok->next()->str() == "::") { if (tok->str() == className) tok = tok->tokAt(2); @@ -4435,6 +4429,7 @@ void Tokenizer::setVarIdClassDeclaration(Token* const startToken, } else if (indentlevel == 0 && tok->str() == ":" && !initListArgLastToken) initList = true; } + return true; } @@ -4602,10 +4597,12 @@ void Tokenizer::setVarIdPass1() } // Set variable ids in class declaration.. if (!initlist && !isC() && !scopeStack.top().isExecutable && tok->link() && !isNamespace) { - setVarIdClassDeclaration(tok->link(), - variableMap, - scopeStack.top().startVarid, - structMembers); + if (!setVarIdClassDeclaration(tok->link(), + variableMap, + scopeStack.top().startVarid, + structMembers)) { + syntaxError(nullptr); + } } if (!scopeStack.top().isStructInit) { @@ -9883,7 +9880,7 @@ void Tokenizer::createSymbolDatabase() mSymbolDatabase->validate(); } -bool Tokenizer::operatorEnd(const Token * tok) const +bool Tokenizer::operatorEnd(const Token * tok) { if (tok && tok->str() == ")") { if (isFunctionHead(tok, "{|;|?|:|[")) diff --git a/lib/tokenize.h b/lib/tokenize.h index 4ca59e5a77f..8da9789f83f 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -38,7 +38,6 @@ class Token; class TemplateSimplifier; class ErrorLogger; class Preprocessor; -class VariableMap; enum class Severity; namespace simplecpp { @@ -269,7 +268,7 @@ class CPPCHECKLIB Tokenizer { /** */ - bool isMemberFunction(const Token *openParen) const; + static bool isMemberFunction(const Token *openParen); /** */ @@ -366,16 +365,7 @@ class CPPCHECKLIB Tokenizer { * @param endsWith string after function head * @return token matching with endsWith if syntax seems to be a function head else nullptr */ - const Token * isFunctionHead(const Token *tok, const std::string &endsWith) const; - - /** - * is token pointing at function head? - * @param tok A '(' or ')' token in a possible function head - * @param endsWith string after function head - * @param cpp c++ code - * @return token matching with endsWith if syntax seems to be a function head else nullptr - */ - static const Token * isFunctionHead(const Token *tok, const std::string &endsWith, bool cpp); + static const Token * isFunctionHead(const Token *tok, const std::string &endsWith); const Preprocessor *getPreprocessor() const { assert(mPreprocessor); @@ -580,21 +570,12 @@ class CPPCHECKLIB Tokenizer { void unsupportedTypedef(const Token *tok) const; - void setVarIdClassDeclaration(Token* const startToken, // cppcheck-suppress functionConst // has side effects - VariableMap& variableMap, - const nonneg int scopeStartVarId, - std::map>& structMembers); - - void setVarIdStructMembers(Token **tok1, - std::map>& structMembers, - nonneg int &varId) const; - - void setVarIdClassFunction(const std::string &classname, // cppcheck-suppress functionConst // has side effects - Token * const startToken, - const Token * const endToken, - const std::map &varlist, - std::map>& structMembers, - nonneg int &varId_); + static void setVarIdClassFunction(const std::string &classname, + Token * const startToken, + const Token * const endToken, + const std::map &varlist, + std::map>& structMembers, + nonneg int &varId_); /** * Output list of unknown types. @@ -604,7 +585,7 @@ class CPPCHECKLIB Tokenizer { /** Find end of SQL (or PL/SQL) block */ static const Token *findSQLBlockEnd(const Token *tokSQLStart); - bool operatorEnd(const Token * tok) const; + static bool operatorEnd(const Token * tok); public: const SymbolDatabase *getSymbolDatabase() const { From 8b6cbe2e9ede9c7dc975e119a17ba5d989749daf Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 21 Nov 2023 12:57:38 +0100 Subject: [PATCH 13/40] Fix crash in SymbolDatabase::addClassFunction() (f'up to #12209) (#5689) --- lib/symboldatabase.cpp | 2 +- test/testsymboldatabase.cpp | 62 ++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index dd8c6d0bf38..d7612bbead4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3286,7 +3286,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To tok1 = tok1->tokAt(2); scope2 = scope2->findRecordInNestedList(tok1->str()); } - if (isAnonymousNamespace) + if (scope2 && isAnonymousNamespace) scope2 = scope2->findRecordInNestedList(tok1->str()); if (count == 1 && scope2) { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 559adb26179..ff6a6b6e645 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -5464,27 +5464,47 @@ class TestSymbolDatabase : public TestFixture { void createSymbolDatabaseFindAllScopes7() { - GET_SYMBOL_DB("namespace {\n" - " struct S {\n" - " void f();\n" - " };\n" - "}\n" - "void S::f() {}\n"); - ASSERT(db); - ASSERT_EQUALS(4, db->scopeList.size()); - auto anon = db->scopeList.begin(); - ++anon; - ASSERT(anon->className.empty()); - ASSERT_EQUALS(anon->type, Scope::eNamespace); - auto S = anon; - ++S; - ASSERT_EQUALS(S->type, Scope::eStruct); - ASSERT_EQUALS(S->className, "S"); - ASSERT_EQUALS(S->nestedIn, &*anon); - const Token* f = Token::findsimplematch(tokenizer.tokens(), "f ( ) {"); - ASSERT(f && f->function() && f->function()->functionScope && f->function()->functionScope->bodyStart); - ASSERT_EQUALS(f->function()->functionScope->functionOf, &*S); - ASSERT_EQUALS(f->function()->functionScope->bodyStart->linenr(), 6); + { + GET_SYMBOL_DB("namespace {\n" + " struct S {\n" + " void f();\n" + " };\n" + "}\n" + "void S::f() {}\n"); + ASSERT(db); + ASSERT_EQUALS(4, db->scopeList.size()); + auto anon = db->scopeList.begin(); + ++anon; + ASSERT(anon->className.empty()); + ASSERT_EQUALS(anon->type, Scope::eNamespace); + auto S = anon; + ++S; + ASSERT_EQUALS(S->type, Scope::eStruct); + ASSERT_EQUALS(S->className, "S"); + ASSERT_EQUALS(S->nestedIn, &*anon); + const Token* f = Token::findsimplematch(tokenizer.tokens(), "f ( ) {"); + ASSERT(f && f->function() && f->function()->functionScope && f->function()->functionScope->bodyStart); + ASSERT_EQUALS(f->function()->functionScope->functionOf, &*S); + ASSERT_EQUALS(f->function()->functionScope->bodyStart->linenr(), 6); + } + { + GET_SYMBOL_DB("namespace {\n" + " int i = 0;\n" + "}\n" + "namespace N {\n" + " namespace {\n" + " template\n" + " struct S {\n" + " void f();\n" + " };\n" + " template\n" + " void S::f() {}\n" + " }\n" + " S g() { return {}; }\n" + "}\n"); + ASSERT(db); // don't crash + ASSERT_EQUALS("", errout.str()); + } } void createSymbolDatabaseIncompleteVars() From 693702d98d7dab4a9249e5fa99a3ad99c772682b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Wed, 22 Nov 2023 11:02:35 +0100 Subject: [PATCH 14/40] compilerDefinitions.cmake: fixed faulty `add_compile_definitions()` value for MSVC (#5690) also fixes `(7,9): error : macro name must be an identifier` with `clang-cl` allowing the build to complete --- cmake/compilerDefinitions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/compilerDefinitions.cmake b/cmake/compilerDefinitions.cmake index 6adac130d8b..ecf9bf2dd89 100644 --- a/cmake/compilerDefinitions.cmake +++ b/cmake/compilerDefinitions.cmake @@ -1,6 +1,6 @@ if (MSVC) # Visual Studio only sets _DEBUG - add_compile_definitions($<$:-DDEBUG>) + add_compile_definitions($<$:DEBUG>) add_definitions(-DWIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) From 727d086dc41acb7b6cea43f1c911b0a3d23bae4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 22 Nov 2023 12:47:48 +0100 Subject: [PATCH 15/40] Fix #12217 (misra 11.4: report conversion in macro) (#5692) --- addons/cppcheckdata.py | 5 ++++- addons/misra.py | 25 +++++++++++++++++++++++++ addons/test/misra/misra-test.c | 5 ++++- lib/tokenize.cpp | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 550d2ea7174..d8bfcddd12f 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -254,6 +254,7 @@ class Token: isCast externLang isExpandedMacro Is this token a expanded macro token + macroName Macro name that this token is expanded from isRemovedVoidParameter Has void parameter been removed? isSplittedVarDeclComma Is this a comma changed to semicolon in a split variable declaration ('int a,b;' => 'int a; int b;') isSplittedVarDeclEq Is this a '=' changed to semicolon in a split variable declaration ('int a=5;' => 'int a; a=5;') @@ -313,6 +314,7 @@ class Token: isCast = False isUnsigned = False isSigned = False + macroName = None isExpandedMacro = False isRemovedVoidParameter = False isSplittedVarDeclComma = False @@ -386,7 +388,8 @@ def __init__(self, element): if element.get('isCast'): self.isCast = True self.externLang = element.get('externLang') - if element.get('isExpandedMacro'): + self.macroName = element.get('macroName') + if self.macroName or element.get('isExpandedMacro'): self.isExpandedMacro = True if element.get('isRemovedVoidParameter'): self.isRemovedVoidParameter = True diff --git a/addons/misra.py b/addons/misra.py index cc26146dd10..a93b9b518fe 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -2520,6 +2520,20 @@ def misra_11_3(self, data): self.reportError(token, 11, 3) def misra_11_4(self, data): + # Get list of macro definitions + macros = {} + for directive in data.directives: + #define X ((peripheral_t *)0x40000U) + res = re.match(r'#define ([A-Za-z0-9_]+).*', directive.str) + if res: + if res.group(1) in macros: + macros[res.group(1)].append(directive) + else: + macros[res.group(1)] = [directive] + + # If macro definition is non-compliant then warn about the macro definition instead of + # the macro usages. To reduce diagnostics for a non-compliant macro. + bad_macros = [] for token in data.tokenlist: if not isCast(token): continue @@ -2530,6 +2544,17 @@ def misra_11_4(self, data): if vt2.pointer > 0 and vt1.pointer == 0 and (vt1.isIntegral() or vt1.isEnum()) and vt2.type != 'void': self.reportError(token, 11, 4) elif vt1.pointer > 0 and vt2.pointer == 0 and (vt2.isIntegral() or vt2.isEnum()) and vt1.type != 'void': + if token.macroName is not None and \ + token.macroName == token.astOperand1.macroName and \ + token.astOperand1.isInt and \ + token.link.previous.str == '*' and \ + token.macroName == token.link.previous.macroName and \ + token.macroName in macros and \ + len(macros[token.macroName]) == 1: + if token.macroName not in bad_macros: + bad_macros.append(token.macroName) + self.reportError(macros[token.macroName][0], 11, 4) + continue self.reportError(token, 11, 4) def misra_11_5(self, data): diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index db73cfd6466..60295a837f1 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -798,12 +798,15 @@ static void misra_11_3(u8* p, struct Fred *fred) { struct Wilma *wilma = (struct Wilma *)fred; // 11.3 } +typedef struct { uint32_t something; } struct_11_4; +#define A_11_4 ((struct_11_4 *)0x40000U) // 11.4 + static void misra_11_4(u8*p) { u64 y = (u64)p; // 11.4 u8 *misra_11_4_A = ( u8 * ) 0x0005;// 11.4 s32 misra_11_4_B; u8 *q = ( u8 * ) misra_11_4_B; // 11.4 - + dummy = A_11_4->something; // no-warning } static void misra_11_5(void *p) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 35ee843fa8c..26255413810 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5946,7 +5946,7 @@ void Tokenizer::dump(std::ostream &out) const if (tok->isExternC()) outs += " externLang=\"C\""; if (tok->isExpandedMacro()) - outs += " isExpandedMacro=\"true\""; + outs += " macroName=\"" + tok->getMacroName() + "\""; if (tok->isTemplateArg()) outs += " isTemplateArg=\"true\""; if (tok->isRemovedVoidParameter()) From 83b5cb5b2f1dca5b6eaf22e292143fd2cd242828 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 22 Nov 2023 14:05:53 +0100 Subject: [PATCH 16/40] Fix #12203 false negative: constParameterReference when taking address (#5682) --- lib/checkother.cpp | 20 +------------------- lib/token.cpp | 4 ++-- test/testother.cpp | 27 ++++++++++++--------------- 3 files changed, 15 insertions(+), 36 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 18407800aa3..90787a71d4d 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1429,25 +1429,7 @@ void CheckOther::checkConstVariable() } } if (tok->isUnaryOp("&") && Token::Match(tok, "& %varid%", var->declarationId())) { - const Token* opTok = tok->astParent(); - int argn = -1; - if (opTok && opTok->isUnaryOp("!")) - continue; - if (opTok && (opTok->isComparisonOp() || opTok->isAssignmentOp() || opTok->isCalculation())) { - if (opTok->isComparisonOp() || opTok->isCalculation()) { - if (opTok->astOperand1() != tok) - opTok = opTok->astOperand1(); - else - opTok = opTok->astOperand2(); - } - if (opTok && opTok->valueType() && var->valueType() && opTok->valueType()->isConst(var->valueType()->pointer)) - continue; - } else if (const Token* ftok = getTokenArgumentFunction(tok, argn)) { - bool inconclusive{}; - if (var->valueType() && !isVariableChangedByFunctionCall(ftok, var->valueType()->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) - continue; - } - usedInAssignment = true; + usedInAssignment = isExpressionChangedAt(tok->next(), tok, 0, false, mSettings, true); break; } if (astIsRangeBasedForDecl(tok) && Token::Match(tok->astParent()->astOperand2(), "%varid%", var->declarationId())) { diff --git a/lib/token.cpp b/lib/token.cpp index 0b548aa14b4..be6d7730e97 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2109,10 +2109,10 @@ static void mergeAdjacent(std::list& values) static void removeOverlaps(std::list& values) { - for (ValueFlow::Value& x : values) { + for (const ValueFlow::Value& x : values) { if (x.isNonValue()) continue; - values.remove_if([&](ValueFlow::Value& y) { + values.remove_if([&](const ValueFlow::Value& y) { if (y.isNonValue()) return false; if (&x == &y) diff --git a/test/testother.cpp b/test/testother.cpp index b5dc0432eb3..b926f8ebeae 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2794,16 +2794,14 @@ class TestOther : public TestFixture { "void a(T& x) {\n" " x.dostuff();\n" " const U * y = dynamic_cast(&x);\n" - " y->mutate();\n" // to avoid warnings that y can be const "}"); - TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it + ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" " U const * y = dynamic_cast(&x);\n" - " y->mutate();\n" // to avoid warnings that y can be const "}"); - TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it + ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" @@ -2814,17 +2812,9 @@ class TestOther : public TestFixture { check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" - " const U const * const * const * const y = dynamic_cast(&x);\n" - " y->mutate();\n" // to avoid warnings that y can be const + " U const * const * * const y = dynamic_cast(&x);\n" "}"); - TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it - check("struct T : public U { void dostuff() const {}};\n" - "void a(T& x) {\n" - " x.dostuff();\n" - " const U const * const * * const y = dynamic_cast(&x);\n" - " y->mutate();\n" // to avoid warnings that y can be const - "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" @@ -3374,6 +3364,13 @@ class TestOther : public TestFixture { " return is >> s.x;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("bool f(std::string& s1, std::string& s2) {\n" // #12203 + " return &s1 == &s2;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 's1' can be declared as reference to const\n" + "[test.cpp:1]: (style) Parameter 's2' can be declared as reference to const\n", + errout.str()); } void constParameterCallback() { @@ -3763,7 +3760,7 @@ class TestOther : public TestFixture { check("void f(int& i) {\n" " new (&i) int();\n" "}\n"); - ASSERT_EQUALS("", errout.str()); // don't crash + TODO_ASSERT_EQUALS("", "[test.cpp:1]: (style) Parameter 'i' can be declared as reference to const\n", errout.str()); // don't crash check("void f(int& i) {\n" " int& r = i;\n" From 331db40d3b5c16c20ecc84f84fd4586d5550824f Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 22 Nov 2023 19:20:56 +0100 Subject: [PATCH 17/40] Revert recent changes in checkConstVariable(), add tests (refs #12203) (#5696) --- lib/checkother.cpp | 20 +++++++++++++++++++- test/testother.cpp | 26 +++++++++++++++++++------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 90787a71d4d..c55219abf9a 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1429,7 +1429,25 @@ void CheckOther::checkConstVariable() } } if (tok->isUnaryOp("&") && Token::Match(tok, "& %varid%", var->declarationId())) { - usedInAssignment = isExpressionChangedAt(tok->next(), tok, 0, false, mSettings, true); + const Token* opTok = tok->astParent(); + int argn = -1; + if (opTok && (opTok->isUnaryOp("!") || opTok->isComparisonOp())) + continue; + if (opTok && (opTok->isAssignmentOp() || opTok->isCalculation())) { + if (opTok->isCalculation()) { + if (opTok->astOperand1() != tok) + opTok = opTok->astOperand1(); + else + opTok = opTok->astOperand2(); + } + if (opTok && opTok->valueType() && var->valueType() && opTok->valueType()->isConst(var->valueType()->pointer)) + continue; + } else if (const Token* ftok = getTokenArgumentFunction(tok, argn)) { + bool inconclusive{}; + if (var->valueType() && !isVariableChangedByFunctionCall(ftok, var->valueType()->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) + continue; + } + usedInAssignment = true; break; } if (astIsRangeBasedForDecl(tok) && Token::Match(tok->astParent()->astOperand2(), "%varid%", var->declarationId())) { diff --git a/test/testother.cpp b/test/testother.cpp index b926f8ebeae..83fad7c3111 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2794,31 +2794,34 @@ class TestOther : public TestFixture { "void a(T& x) {\n" " x.dostuff();\n" " const U * y = dynamic_cast(&x);\n" + " y->mutate();\n" // to avoid warnings that y can be const "}"); - ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); + TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" " U const * y = dynamic_cast(&x);\n" + " y->mutate();\n" // to avoid warnings that y can be const "}"); - ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); + TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" - " U * const y = dynamic_cast(&x);\n" + " const U const * const * const * const y = dynamic_cast(&x);\n" " y->mutate();\n" // to avoid warnings that y can be const "}"); ASSERT_EQUALS("", errout.str()); check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" - " U const * const * * const y = dynamic_cast(&x);\n" + " const U const * const * const * const y = dynamic_cast(&x);\n" + " y->mutate();\n" // to avoid warnings that y can be const "}"); - ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); + TODO_ASSERT_EQUALS("can be const", errout.str(), ""); //Currently taking the address is treated as a non-const operation when it should depend on what we do with it check("struct T : public U { void dostuff() const {}};\n" "void a(T& x) {\n" " x.dostuff();\n" - " my::fancy const * * const y = dynamic_cast const * * const>(&x);\n" + " const U const * const * * const y = dynamic_cast(&x);\n" " y->mutate();\n" // to avoid warnings that y can be const "}"); ASSERT_EQUALS("", errout.str()); @@ -3371,6 +3374,15 @@ class TestOther : public TestFixture { ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 's1' can be declared as reference to const\n" "[test.cpp:1]: (style) Parameter 's2' can be declared as reference to const\n", errout.str()); + + check("struct S {\n" + " void f(int& r) { p = &r; }\n" + " int* p;\n" + "};\n" + "void g(std::vector& v1, std::vector& v2) {\n" + " std::transform(v1.begin(), v1.end(), v2.begin(), [](auto& x) { return &x; });\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void constParameterCallback() { @@ -3760,7 +3772,7 @@ class TestOther : public TestFixture { check("void f(int& i) {\n" " new (&i) int();\n" "}\n"); - TODO_ASSERT_EQUALS("", "[test.cpp:1]: (style) Parameter 'i' can be declared as reference to const\n", errout.str()); // don't crash + ASSERT_EQUALS("", errout.str()); // don't crash check("void f(int& i) {\n" " int& r = i;\n" From 86bb7c98e402897f6e1f615a1e37ed300f4665a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Fri, 24 Nov 2023 18:45:48 +0100 Subject: [PATCH 18/40] enabled and mitigated `readability-const-return-type` clang-tidy warnings (#5644) --- .clang-tidy | 1 - clang-tidy.md | 1 - gui/test/translationhandler/testtranslationhandler.cpp | 2 +- lib/standards.h | 2 +- lib/utils.h | 1 + 5 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index e96c20ed6dd..b0f8a59348f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -59,7 +59,6 @@ Checks: > -portability-std-allocator-const, -readability-avoid-const-params-in-decls, -readability-braces-around-statements, - -readability-const-return-type, -readability-container-data-pointer, -readability-function-cognitive-complexity, -readability-function-size, diff --git a/clang-tidy.md b/clang-tidy.md index 1b9c0aef180..a1abd9a5f5c 100644 --- a/clang-tidy.md +++ b/clang-tidy.md @@ -118,7 +118,6 @@ Also reports a false positive about templates which deduce the array length: htt We run this separately via `clang-include-cleaner` in the `iwyu.yml` workflow as the findings of the include checkers still need to be reviewed manually before applying them. `bugprone-branch-clone`
-`readability-const-return-type`
`modernize-return-braced-init-list`
`misc-throw-by-value-catch-by-reference`
`readability-avoid-const-params-in-decls`
diff --git a/gui/test/translationhandler/testtranslationhandler.cpp b/gui/test/translationhandler/testtranslationhandler.cpp index f6a925c6b1a..7abb1c8f7c0 100644 --- a/gui/test/translationhandler/testtranslationhandler.cpp +++ b/gui/test/translationhandler/testtranslationhandler.cpp @@ -24,7 +24,7 @@ #include #include -static const QStringList getTranslationNames(const TranslationHandler& handler) +static QStringList getTranslationNames(const TranslationHandler& handler) { QStringList names; for (const TranslationInfo& translation : handler.getTranslations()) { diff --git a/lib/standards.h b/lib/standards.h index f22cd76329a..619ce623594 100644 --- a/lib/standards.h +++ b/lib/standards.h @@ -59,7 +59,7 @@ struct Standards { } return false; } - const std::string getC() const { + std::string getC() const { switch (c) { case C89: return "c89"; diff --git a/lib/utils.h b/lib/utils.h index d5721574abf..9d11a68e983 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -36,6 +36,7 @@ struct SelectMapKeys { template + // NOLINTNEXTLINE(readability-const-return-type) - false positive typename Pair::first_type operator()(const Pair& p) const { return p.first; } From 8e1ae7e41200a9a8dec5a7a61ce632dd988501a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Sat, 25 Nov 2023 21:12:24 +0100 Subject: [PATCH 19/40] CmdLineParser: various refactorings and cleanups as well as testing improvements (#5676) --- cli/cmdlineparser.cpp | 90 +++++++-------- cli/cmdlineparser.h | 23 +--- lib/settings.cpp | 1 + test/fixture.cpp | 6 +- test/fixture.h | 3 +- test/testcmdlineparser.cpp | 229 +++++++++++++------------------------ 6 files changed, 135 insertions(+), 217 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index e83da8e92ca..c3864b878fd 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -146,25 +146,6 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) const bool success = parseFromArgs(argc, argv); if (success) { - if (getShowVersion() && !getShowErrorMessages()) { - if (!mSettings.cppcheckCfgProductName.empty()) { - mLogger.printRaw(mSettings.cppcheckCfgProductName); - } else { - const char * const extraVersion = CppCheck::extraVersion(); - if (*extraVersion != 0) - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); - else - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); - } - } - - if (getShowErrorMessages()) { - XMLErrorMessagesLogger xmlLogger; - std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); - CppCheck::getErrorMessages(xmlLogger); - std::cout << ErrorMessage::getXMLFooter() << std::endl; - } - if (exitAfterPrinting()) { Settings::terminate(); return true; @@ -526,9 +507,16 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // print all possible error messages.. else if (std::strcmp(argv[i], "--errorlist") == 0) { - mShowErrorMessages = true; - mSettings.xml = true; + // TODO: make this an exclusive option mExitAfterPrint = true; + mSettings.loadCppcheckCfg(); + { + XMLErrorMessagesLogger xmlLogger; + std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); + CppCheck::getErrorMessages(xmlLogger); + std::cout << ErrorMessage::getXMLFooter() << std::endl; + } + return true; } // --error-exitcode=1 @@ -606,10 +594,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // Print help else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { - mPathNames.clear(); - mShowHelp = true; + // TODO: make this an exclusive option mExitAfterPrint = true; - break; + printHelp(); + return true; } // Ignored paths @@ -829,18 +817,19 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--plist-output=", 15) == 0) { mSettings.plistOutput = Path::simplifyPath(Path::fromNativeSeparators(argv[i] + 15)); if (mSettings.plistOutput.empty()) - mSettings.plistOutput = "./"; - else if (!endsWith(mSettings.plistOutput,'/')) - mSettings.plistOutput += '/'; + mSettings.plistOutput = "."; const std::string plistOutput = Path::toNativeSeparators(mSettings.plistOutput); if (!Path::isDirectory(plistOutput)) { - std::string message("plist folder does not exist: \""); + std::string message("plist folder does not exist: '"); message += plistOutput; - message += "\"."; + message += "'."; mLogger.printError(message); return false; } + + if (!endsWith(mSettings.plistOutput,'/')) + mSettings.plistOutput += '/'; } // Special Cppcheck Premium options @@ -1163,9 +1152,18 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings.verbose = true; else if (std::strcmp(argv[i], "--version") == 0) { - mShowVersion = true; + // TODO: make this an exclusive parameter mExitAfterPrint = true; mSettings.loadCppcheckCfg(); + if (!mSettings.cppcheckCfgProductName.empty()) { + mLogger.printRaw(mSettings.cppcheckCfgProductName); + } else { + const char * const extraVersion = CppCheck::extraVersion(); + if (*extraVersion != '\0') + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); + else + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); + } return true; } @@ -1231,11 +1229,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } if (argc <= 1) { - mShowHelp = true; mExitAfterPrint = true; - } - - if (mShowHelp) { printHelp(); return true; } @@ -1630,40 +1624,40 @@ bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& base const Library::Error err = destination.load(basepath.c_str(), filename); if (err.errorcode == Library::ErrorCode::UNKNOWN_ELEMENT) - std::cout << "cppcheck: Found unknown elements in configuration file '" << filename << "': " << err.reason << std::endl; + mLogger.printMessage("Found unknown elements in configuration file '" + std::string(filename) + "': " + err.reason); // TODO: print as errors else if (err.errorcode != Library::ErrorCode::OK) { - std::cout << "cppcheck: Failed to load library configuration file '" << filename << "'. "; + std::string msg = "Failed to load library configuration file '" + std::string(filename) + "'. "; switch (err.errorcode) { case Library::ErrorCode::OK: break; case Library::ErrorCode::FILE_NOT_FOUND: - std::cout << "File not found"; + msg += "File not found"; break; case Library::ErrorCode::BAD_XML: - std::cout << "Bad XML"; + msg += "Bad XML"; break; case Library::ErrorCode::UNKNOWN_ELEMENT: - std::cout << "Unexpected element"; + msg += "Unexpected element"; break; case Library::ErrorCode::MISSING_ATTRIBUTE: - std::cout << "Missing attribute"; + msg +="Missing attribute"; break; case Library::ErrorCode::BAD_ATTRIBUTE_VALUE: - std::cout << "Bad attribute value"; + msg += "Bad attribute value"; break; case Library::ErrorCode::UNSUPPORTED_FORMAT: - std::cout << "File is of unsupported format version"; + msg += "File is of unsupported format version"; break; case Library::ErrorCode::DUPLICATE_PLATFORM_TYPE: - std::cout << "Duplicate platform type"; + msg += "Duplicate platform type"; break; case Library::ErrorCode::PLATFORM_TYPE_REDEFINED: - std::cout << "Platform type redefined"; + msg += "Platform type redefined"; break; } if (!err.reason.empty()) - std::cout << " '" + err.reason + "'"; - std::cout << std::endl; + msg += " '" + err.reason + "'"; + mLogger.printMessage(msg); // TODO: print as errors return false; } return true; @@ -1683,7 +1677,7 @@ bool CmdLineParser::loadLibraries(Settings& settings) "std.cfg should be available in " + cfgfolder + " or the FILESDIR " "should be configured."); #endif - std::cout << msg << " " << details << std::endl; + mLogger.printRaw(msg + " " + details); // TODO: do not print as raw? return false; } @@ -1703,7 +1697,7 @@ bool CmdLineParser::loadAddons(Settings& settings) AddonInfo addonInfo; const std::string failedToGetAddonInfo = addonInfo.getAddonInfo(addon, settings.exename); if (!failedToGetAddonInfo.empty()) { - std::cout << failedToGetAddonInfo << std::endl; + mLogger.printRaw(failedToGetAddonInfo); // TODO: do not print as raw result = false; continue; } diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index cd5560a83ac..b93716b76bd 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -73,20 +73,6 @@ class CmdLineParser { */ bool parseFromArgs(int argc, const char* const argv[]); - /** - * Return if user wanted to see program version. - */ - bool getShowVersion() const { - return mShowVersion; - } - - /** - * Return if user wanted to see list of error messages. - */ - bool getShowErrorMessages() const { - return mShowErrorMessages; - } - /** * Return the path names user gave to command line. */ @@ -153,21 +139,21 @@ class CmdLineParser { * Tries to load a library and prints warning/error messages * @return false, if an error occurred (except unknown XML elements) */ - static bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename); + bool tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename); /** * @brief Load libraries * @param settings Settings * @return Returns true if successful */ - static bool loadLibraries(Settings& settings); + bool loadLibraries(Settings& settings); /** * @brief Load addons * @param settings Settings * @return Returns true if successful */ - static bool loadAddons(Settings& settings); + bool loadAddons(Settings& settings); CmdLineLogger &mLogger; @@ -178,9 +164,6 @@ class CmdLineParser { Settings &mSettings; Suppressions &mSuppressions; Suppressions &mSuppressionsNoFail; - bool mShowHelp{}; - bool mShowVersion{}; - bool mShowErrorMessages{}; bool mExitAfterPrint{}; std::string mVSConfig; }; diff --git a/lib/settings.cpp b/lib/settings.cpp index c0cf5da27a3..eb1e9847c96 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -40,6 +40,7 @@ Settings::Settings() setCheckLevelNormal(); } +// TODO: report error when the config is invalid void Settings::loadCppcheckCfg() { std::string fileName = Path::getPathFromFilename(exename) + "cppcheck.cfg"; diff --git a/test/fixture.cpp b/test/fixture.cpp index bb2103e99a4..3fa8b68b280 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -109,12 +109,16 @@ bool TestFixture::prepareTest(const char testname[]) } else { std::cout << classname << "::" << mTestname << std::endl; } - teardownTestInternal(); return true; } return false; } +void TestFixture::teardownTest() +{ + teardownTestInternal(); +} + std::string TestFixture::getLocationStr(const char * const filename, const unsigned int linenr) const { return std::string(filename) + ':' + std::to_string(linenr) + '(' + classname + "::" + mTestname + ')'; diff --git a/test/fixture.h b/test/fixture.h index 49e7655138a..1224e388dc1 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -62,6 +62,7 @@ class TestFixture : public ErrorLogger { bool prepareTest(const char testname[]); virtual void prepareTestInternal() {} + void teardownTest(); virtual void teardownTestInternal() {} std::string getLocationStr(const char * const filename, const unsigned int linenr) const; @@ -254,7 +255,7 @@ extern std::ostringstream errout; extern std::ostringstream output; // TODO: most asserts do not actually assert i.e. do not return -#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); NAME(); } } while (false) +#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); NAME(); teardownTest(); } } while (false) #define ASSERT( CONDITION ) if (!assert_(__FILE__, __LINE__, (CONDITION))) return #define ASSERT_LOC( CONDITION, FILE_, LINE_ ) assert_(FILE_, LINE_, (CONDITION)) #define CHECK_EQUALS( EXPECTED, ACTUAL ) assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 3d969046489..e1bf241aa7f 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -77,7 +77,7 @@ class TestCmdlineParser : public TestFixture { void destroy() { if (!buf.empty()) - throw std::runtime_error("unconsumed messages"); + throw std::runtime_error("unconsumed messages: " + buf); } private: @@ -108,7 +108,8 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(nooptions); TEST_CASE(helpshort); TEST_CASE(helplong); - TEST_CASE(showversion); + TEST_CASE(version); + TEST_CASE(versionWithCfg); TEST_CASE(onefile); TEST_CASE(onepath); TEST_CASE(optionwithoutfile); @@ -250,9 +251,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(showtimeNone); TEST_CASE(showtimeEmpty); TEST_CASE(showtimeInvalid); - TEST_CASE(errorlist1); - TEST_CASE(errorlistverbose1); - TEST_CASE(errorlistverbose2); + TEST_CASE(errorlist); TEST_CASE(ignorepathsnopath); #if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING) TEST_CASE(exceptionhandling); @@ -303,6 +302,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(projectMissing); TEST_CASE(projectNoPaths); TEST_CASE(addon); + TEST_CASE(addonMissing); #ifdef HAVE_RULES TEST_CASE(rule); #else @@ -321,6 +321,8 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(unsignedChar); TEST_CASE(unsignedChar2); TEST_CASE(signedCharUnsignedChar); + TEST_CASE(library); + TEST_CASE(libraryMissing); TEST_CASE(ignorepaths1); TEST_CASE(ignorepaths2); @@ -368,21 +370,36 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } - void showversion() { + void version() { REDIRECT; const char * const argv[] = {"cppcheck", "--version"}; ASSERT(parser->parseFromArgs(2, argv)); - ASSERT_EQUALS(true, parser->getShowVersion()); - ASSERT_EQUALS("", logger->str()); // version is not actually shown + ASSERT_EQUALS("Cppcheck 2.13 dev\n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void versionWithCfg() { + REDIRECT; + ScopedFile file("cppcheck.cfg", + "{\n" + "\"productName\": \"The Product\"" + "}\n"); + const char * const argv[] = {"cppcheck", "--version"}; + ASSERT(parser->parseFromArgs(2, argv)); + // TODO: somehow the config is not loaded on some systems + (void)logger->str(); //ASSERT_EQUALS("The Product\n", logger->str()); // TODO: include version? + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + + // TODO: test extraVersion + void onefile() { REDIRECT; const char * const argv[] = {"cppcheck", "file.cpp"}; ASSERT(parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, (int)parser->getPathNames().size()); ASSERT_EQUALS("file.cpp", parser->getPathNames().at(0)); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void onepath() { @@ -391,7 +408,7 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, (int)parser->getPathNames().size()); ASSERT_EQUALS("src", parser->getPathNames().at(0)); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void optionwithoutfile() { @@ -400,6 +417,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(0, (int)parser->getPathNames().size()); ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void verboseshort() { @@ -408,7 +426,7 @@ class TestCmdlineParser : public TestFixture { settings->verbose = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->verbose); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void verboselong() { @@ -417,7 +435,7 @@ class TestCmdlineParser : public TestFixture { settings->verbose = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->verbose); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void debugSimplified() { @@ -426,7 +444,7 @@ class TestCmdlineParser : public TestFixture { settings->debugSimplified = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->debugSimplified); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void debugwarnings() { @@ -435,7 +453,7 @@ class TestCmdlineParser : public TestFixture { settings->debugwarnings = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->debugwarnings); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void forceshort() { @@ -444,7 +462,7 @@ class TestCmdlineParser : public TestFixture { settings->force = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->force); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void forcelong() { @@ -453,7 +471,7 @@ class TestCmdlineParser : public TestFixture { settings->force = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->force); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths1() { @@ -462,7 +480,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "-rp", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths2() { @@ -471,7 +489,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--relative-paths", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths3() { @@ -484,7 +502,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, settings->basePaths.size()); ASSERT_EQUALS("C:/foo", settings->basePaths[0]); ASSERT_EQUALS("C:/bar", settings->basePaths[1]); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths4() { @@ -498,7 +516,7 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, settings->basePaths.size()); ASSERT_EQUALS("C:/foo", settings->basePaths[0]); ASSERT_EQUALS("C:/bar", settings->basePaths[1]); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void quietshort() { @@ -507,7 +525,7 @@ class TestCmdlineParser : public TestFixture { settings->quiet = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->quiet); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void quietlong() { @@ -516,7 +534,7 @@ class TestCmdlineParser : public TestFixture { settings->quiet = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->quiet); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines_noarg() { @@ -549,7 +567,7 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("_WIN32=1", settings->userDefines); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines2() { @@ -558,7 +576,7 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS("_WIN32=1;NODEBUG=1", settings->userDefines); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines3() { @@ -567,7 +585,7 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS("DEBUG=1", settings->userDefines); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines4() { @@ -576,7 +594,7 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("DEBUG=", settings->userDefines); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void enforceLanguage1() { @@ -585,7 +603,6 @@ class TestCmdlineParser : public TestFixture { settings->enforcedLang = Settings::Language::None; ASSERT(parser->parseFromArgs(2, argv)); ASSERT_EQUALS(Settings::Language::None, settings->enforcedLang); - ASSERT_EQUALS("", logger->str()); } void enforceLanguage2() { @@ -594,7 +611,6 @@ class TestCmdlineParser : public TestFixture { settings->enforcedLang = Settings::Language::None; ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS(Settings::Language::CPP, settings->enforcedLang); - ASSERT_EQUALS("", logger->str()); } void enforceLanguage3() { @@ -617,7 +633,6 @@ class TestCmdlineParser : public TestFixture { settings->enforcedLang = Settings::Language::None; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Settings::Language::CPP, settings->enforcedLang); - ASSERT_EQUALS("", logger->str()); } void enforceLanguage6() { @@ -626,7 +641,6 @@ class TestCmdlineParser : public TestFixture { settings->enforcedLang = Settings::Language::None; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Settings::Language::C, settings->enforcedLang); - ASSERT_EQUALS("", logger->str()); } void enforceLanguage7() { @@ -650,7 +664,6 @@ class TestCmdlineParser : public TestFixture { settings->includePaths.clear(); ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); - ASSERT_EQUALS("", logger->str()); } void includesslash() { @@ -659,7 +672,6 @@ class TestCmdlineParser : public TestFixture { settings->includePaths.clear(); ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); - ASSERT_EQUALS("", logger->str()); } void includesbackslash() { @@ -668,7 +680,6 @@ class TestCmdlineParser : public TestFixture { settings->includePaths.clear(); ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); - ASSERT_EQUALS("", logger->str()); } void includesnospace() { @@ -677,7 +688,6 @@ class TestCmdlineParser : public TestFixture { settings->includePaths.clear(); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); - ASSERT_EQUALS("", logger->str()); } void includes2() { @@ -688,7 +698,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("include/", settings->includePaths.front()); settings->includePaths.pop_front(); ASSERT_EQUALS("framework/", settings->includePaths.front()); - ASSERT_EQUALS("", logger->str()); } void includesFile() { @@ -702,7 +711,6 @@ class TestCmdlineParser : public TestFixture { auto it = settings->includePaths.cbegin(); ASSERT_EQUALS("path/sub/", *it++); ASSERT_EQUALS("path2/sub1/", *it); - ASSERT_EQUALS("", logger->str()); } void includesFileNoFile() { @@ -724,7 +732,6 @@ class TestCmdlineParser : public TestFixture { auto it = settings->configExcludePaths.cbegin(); ASSERT_EQUALS("path/sub/", *it++); ASSERT_EQUALS("path2/sub1/", *it); - ASSERT_EQUALS("", logger->str()); } void configExcludesFileNoFile() { @@ -743,7 +750,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->checks.isEnabled(Checks::unusedFunction)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); ASSERT(!settings->checks.isEnabled(Checks::internalCheck)); - ASSERT_EQUALS("", logger->str()); } void enabledStyle() { @@ -756,7 +762,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->severity.isEnabled(Severity::portability)); ASSERT(!settings->checks.isEnabled(Checks::unusedFunction)); ASSERT(!settings->checks.isEnabled(Checks::internalCheck)); - ASSERT_EQUALS("", logger->str()); } void enabledPerformance() { @@ -769,7 +774,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(!settings->severity.isEnabled(Severity::portability)); ASSERT(!settings->checks.isEnabled(Checks::unusedFunction)); ASSERT(!settings->checks.isEnabled(Checks::missingInclude)); - ASSERT_EQUALS("", logger->str()); } void enabledPortability() { @@ -782,7 +786,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->severity.isEnabled(Severity::portability)); ASSERT(!settings->checks.isEnabled(Checks::unusedFunction)); ASSERT(!settings->checks.isEnabled(Checks::missingInclude)); - ASSERT_EQUALS("", logger->str()); } void enabledInformation() { @@ -799,7 +802,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--enable=unusedFunction", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->checks.isEnabled(Checks::unusedFunction)); - ASSERT_EQUALS("", logger->str()); } void enabledMissingInclude() { @@ -807,7 +809,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--enable=missingInclude", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); - ASSERT_EQUALS("", logger->str()); } #ifdef CHECK_INTERNAL @@ -816,7 +817,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--enable=internal", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->checks.isEnabled(Checks::internalCheck)); - ASSERT_EQUALS("", logger->str()); } #endif @@ -830,7 +830,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->severity.isEnabled(Severity::portability)); ASSERT(!settings->checks.isEnabled(Checks::unusedFunction)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); - ASSERT_EQUALS("", logger->str()); } void enabledInvalid() { @@ -870,7 +869,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::unusedFunction)); ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::missingInclude)); ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::internalCheck)); - ASSERT_EQUALS("", logger->str()); } void disableMultiple() { @@ -888,7 +886,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::unusedFunction)); ASSERT_EQUALS(true, settings->checks.isEnabled(Checks::missingInclude)); ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::internalCheck)); - ASSERT_EQUALS("", logger->str()); } // make sure the implied "style" checks are not added when "--enable=style" is specified @@ -907,7 +904,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(true, settings->checks.isEnabled(Checks::unusedFunction)); ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::missingInclude)); ASSERT_EQUALS(false, settings->checks.isEnabled(Checks::internalCheck)); - ASSERT_EQUALS("", logger->str()); } void disableInformationPartial() { @@ -925,7 +921,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT(!settings->severity.isEnabled(Severity::information)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); - ASSERT_EQUALS("", logger->str()); } void disableInvalid() { @@ -955,7 +950,6 @@ class TestCmdlineParser : public TestFixture { settings->certainty.clear(); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->certainty.isEnabled(Certainty::inconclusive)); - ASSERT_EQUALS("", logger->str()); } void errorExitcode() { @@ -964,7 +958,6 @@ class TestCmdlineParser : public TestFixture { settings->exitCode = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(5, settings->exitCode); - ASSERT_EQUALS("", logger->str()); } void errorExitcodeMissing() { @@ -1001,7 +994,6 @@ class TestCmdlineParser : public TestFixture { auto it = settings->nofail.getSuppressions().cbegin(); ASSERT_EQUALS("uninitvar", (it++)->errorId); ASSERT_EQUALS("unusedFunction", it->errorId); - ASSERT_EQUALS("", logger->str()); } void exitcodeSuppressionsNoFile() { @@ -1023,7 +1015,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("file1.c", *it++); ASSERT_EQUALS("file2.cpp", *it++); ASSERT_EQUALS("file.cpp", *it); - ASSERT_EQUALS("", logger->str()); } void fileListNoFile() { @@ -1039,7 +1030,6 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--file-list=-", "file.cpp"}; TODO_ASSERT_EQUALS(true, false, parser->parseFromArgs(3, argv)); - TODO_ASSERT_EQUALS("", "", logger->str()); } */ void fileListInvalid() { @@ -1055,7 +1045,6 @@ class TestCmdlineParser : public TestFixture { settings->inlineSuppressions = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->inlineSuppressions); - ASSERT_EQUALS("", logger->str()); } void jobs() { @@ -1064,7 +1053,6 @@ class TestCmdlineParser : public TestFixture { settings->jobs = 0; ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS(3, settings->jobs); - ASSERT_EQUALS("", logger->str()); } void jobs2() { @@ -1073,7 +1061,6 @@ class TestCmdlineParser : public TestFixture { settings->jobs = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(3, settings->jobs); - ASSERT_EQUALS("", logger->str()); } void jobsMissingCount() { @@ -1114,7 +1101,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS(12, settings->maxConfigs); ASSERT_EQUALS(false, settings->force); - ASSERT_EQUALS("", logger->str()); } void maxConfigsMissingCount() { @@ -1147,7 +1133,6 @@ class TestCmdlineParser : public TestFixture { settings->reportProgress = -1; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(10, settings->reportProgress); - ASSERT_EQUALS("", logger->str()); } void reportProgress2() { @@ -1172,7 +1157,6 @@ class TestCmdlineParser : public TestFixture { settings->reportProgress = -1; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(0, settings->reportProgress); - ASSERT_EQUALS("", logger->str()); } void reportProgress5() { @@ -1181,7 +1165,6 @@ class TestCmdlineParser : public TestFixture { settings->reportProgress = -1; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->reportProgress); - ASSERT_EQUALS("", logger->str()); } void stdc99() { @@ -1190,7 +1173,6 @@ class TestCmdlineParser : public TestFixture { settings->standards.c = Standards::C89; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->standards.c == Standards::C99); - ASSERT_EQUALS("", logger->str()); } void stdcpp11() { @@ -1199,7 +1181,6 @@ class TestCmdlineParser : public TestFixture { settings->standards.cpp = Standards::CPP03; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->standards.cpp == Standards::CPP11); - ASSERT_EQUALS("", logger->str()); } void stdunknown1() { @@ -1222,7 +1203,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Win64, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformWin32A() { @@ -1231,7 +1211,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Win32A, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformWin32W() { @@ -1240,7 +1219,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Win32W, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformUnix32() { @@ -1249,7 +1227,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformUnix32Unsigned() { @@ -1258,7 +1235,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformUnix64() { @@ -1267,7 +1243,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformUnix64Unsigned() { @@ -1276,7 +1251,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformNative() { @@ -1285,7 +1259,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Native, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformUnspecified() { @@ -1294,7 +1267,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Native)); ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unspecified, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformPlatformFile() { @@ -1303,7 +1275,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::File, settings->platform.type); - ASSERT_EQUALS("", logger->str()); } void platformUnknown() { @@ -1319,7 +1290,6 @@ class TestCmdlineParser : public TestFixture { settings->plistOutput = ""; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->plistOutput == "./"); - ASSERT_EQUALS("", logger->str()); } void plistDoesNotExist() { @@ -1327,8 +1297,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--plist-output=./cppcheck_reports", "file.cpp"}; // Fails since folder pointed by --plist-output= does not exist ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); - // TODO: output contains non-native separator - //ASSERT_EQUALS("cppcheck: error: plist folder does not exist: \"cppcheck_reports/\".\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: plist folder does not exist: 'cppcheck_reports'.\n", logger->str()); } void suppressionsOld() { @@ -1349,7 +1318,6 @@ class TestCmdlineParser : public TestFixture { auto it = settings->nomsg.getSuppressions().cbegin(); ASSERT_EQUALS("uninitvar", (it++)->errorId); ASSERT_EQUALS("unusedFunction", it->errorId); - ASSERT_EQUALS("", logger->str()); } void suppressionsNoFile1() { @@ -1386,7 +1354,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1))); - ASSERT_EQUALS("", logger->str()); } void suppressionSingleFile() { @@ -1394,7 +1361,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--suppress=uninitvar:file.cpp", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); - ASSERT_EQUALS("", logger->str()); } void suppressionTwo() { @@ -1412,7 +1378,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); - ASSERT_EQUALS("", logger->str()); } void templates() { @@ -1423,7 +1388,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column} {info}", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templatesGcc() { @@ -1434,7 +1398,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: warning: {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templatesVs() { @@ -1445,7 +1408,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templatesEdit() { @@ -1456,7 +1418,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templatesCppcheck1() { @@ -1467,7 +1428,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{callstack}: ({severity}{inconclusive:, inconclusive}) {message}", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templatesDaca2() { @@ -1479,7 +1439,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}", settings->templateLocation); ASSERT_EQUALS(true, settings->daca); - ASSERT_EQUALS("", logger->str()); } void templatesSelfcheck() { @@ -1490,7 +1449,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } // TODO: we should bail out on this @@ -1502,7 +1460,6 @@ class TestCmdlineParser : public TestFixture { TODO_ASSERT(!parser->parseFromArgs(3, argv)); ASSERT_EQUALS("selfchek", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templateFormatInvalid() { @@ -1524,7 +1481,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void templateLocationInvalid() { @@ -1544,7 +1500,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); - ASSERT_EQUALS("", logger->str()); } void xml() { @@ -1555,7 +1510,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->xml); ASSERT_EQUALS(1, settings->xml_version); - ASSERT_EQUALS("", logger->str()); } void xmlver2() { @@ -1566,7 +1520,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->xml); ASSERT_EQUALS(2, settings->xml_version); - ASSERT_EQUALS("", logger->str()); } void xmlver2both() { @@ -1577,7 +1530,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT(settings->xml); ASSERT_EQUALS(2, settings->xml_version); - ASSERT_EQUALS("", logger->str()); } void xmlver2both2() { @@ -1588,7 +1540,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT(settings->xml); ASSERT_EQUALS(2, settings->xml_version); - ASSERT_EQUALS("", logger->str()); } void xmlverunknown() { @@ -1622,7 +1573,6 @@ class TestCmdlineParser : public TestFixture { settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY); - ASSERT_EQUALS("", logger->str()); } void showtimeFile() { @@ -1631,7 +1581,6 @@ class TestCmdlineParser : public TestFixture { settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE); - ASSERT_EQUALS("", logger->str()); } void showtimeFileTotal() { @@ -1640,7 +1589,6 @@ class TestCmdlineParser : public TestFixture { settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL); - ASSERT_EQUALS("", logger->str()); } void showtimeTop5() { @@ -1658,7 +1606,6 @@ class TestCmdlineParser : public TestFixture { settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE); - ASSERT_EQUALS("", logger->str()); } void showtimeTop5Summary() { @@ -1667,7 +1614,6 @@ class TestCmdlineParser : public TestFixture { settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY); - ASSERT_EQUALS("", logger->str()); } void showtimeNone() { @@ -1676,7 +1622,6 @@ class TestCmdlineParser : public TestFixture { settings->showtime = SHOWTIME_MODES::SHOWTIME_FILE; ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_NONE); - ASSERT_EQUALS("", logger->str()); } void showtimeEmpty() { @@ -1693,31 +1638,16 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: unrecognized --showtime mode: 'top10'. Supported modes: file, file-total, summary, top5, top5_file, top5_summary.\n", logger->str()); } - void errorlist1() { + void errorlist() { REDIRECT; const char * const argv[] = {"cppcheck", "--errorlist"}; ASSERT(parser->parseFromArgs(2, argv)); - ASSERT(parser->getShowErrorMessages()); - ASSERT_EQUALS("", logger->str()); + ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger + ASSERT(startsWith(GET_REDIRECT_OUTPUT, "\n")); } - void errorlistverbose1() { - REDIRECT; - const char * const argv[] = {"cppcheck", "--verbose", "--errorlist"}; - settings->verbose = false; - ASSERT(parser->parseFromArgs(3, argv)); - ASSERT(settings->verbose); - ASSERT_EQUALS("", logger->str()); - } - - void errorlistverbose2() { - REDIRECT; - const char * const argv[] = {"cppcheck", "--errorlist", "--verbose"}; - settings->verbose = false; - ASSERT(parser->parseFromArgs(3, argv)); - ASSERT(settings->verbose); - ASSERT_EQUALS("", logger->str()); - } + // TODO: test --errorlist with product name void ignorepathsnopath() { REDIRECT; @@ -1736,7 +1666,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->exceptionHandling); ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput()); - ASSERT_EQUALS("", logger->str()); } void exceptionhandling2() { @@ -1747,7 +1676,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->exceptionHandling); ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput()); - ASSERT_EQUALS("", logger->str()); } void exceptionhandling3() { @@ -1758,7 +1686,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->exceptionHandling); ASSERT_EQUALS(stdout, CppCheckExecutor::getExceptionOutput()); - ASSERT_EQUALS("", logger->str()); } void exceptionhandlingInvalid() { @@ -1798,7 +1725,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->clang); ASSERT_EQUALS("exe", settings->clangExecutable); - ASSERT_EQUALS("", logger->str()); } void clang2() { @@ -1809,7 +1735,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT(settings->clang); ASSERT_EQUALS("clang-14", settings->clangExecutable); - ASSERT_EQUALS("", logger->str()); } void clangInvalid() { @@ -1825,7 +1750,6 @@ class TestCmdlineParser : public TestFixture { settings->valueFlowMaxIterations = SIZE_MAX; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(0, settings->valueFlowMaxIterations); - ASSERT_EQUALS("", logger->str()); } void valueFlowMaxIterations2() { @@ -1834,7 +1758,6 @@ class TestCmdlineParser : public TestFixture { settings->valueFlowMaxIterations = SIZE_MAX; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(11, settings->valueFlowMaxIterations); - ASSERT_EQUALS("", logger->str()); } void valueFlowMaxIterationsInvalid() { @@ -1864,7 +1787,6 @@ class TestCmdlineParser : public TestFixture { settings->checksMaxTime = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->checksMaxTime); - ASSERT_EQUALS("", logger->str()); } void checksMaxTime2() { @@ -1888,7 +1810,6 @@ class TestCmdlineParser : public TestFixture { settings->loadAverage = 0; ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS(12, settings->loadAverage); - ASSERT_EQUALS("", logger->str()); } void loadAverage2() { @@ -1897,7 +1818,6 @@ class TestCmdlineParser : public TestFixture { settings->loadAverage = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->loadAverage); - ASSERT_EQUALS("", logger->str()); } void loadAverageInvalid() { @@ -1921,7 +1841,6 @@ class TestCmdlineParser : public TestFixture { settings->maxCtuDepth = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->maxCtuDepth); - ASSERT_EQUALS("", logger->str()); } void maxCtuDepthInvalid() { @@ -1937,7 +1856,6 @@ class TestCmdlineParser : public TestFixture { settings->performanceValueFlowMaxTime = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->performanceValueFlowMaxTime); - ASSERT_EQUALS("", logger->str()); } void performanceValueflowMaxTimeInvalid() { @@ -1953,7 +1871,6 @@ class TestCmdlineParser : public TestFixture { settings->performanceValueFlowMaxIfCount = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->performanceValueFlowMaxIfCount); - ASSERT_EQUALS("", logger->str()); } void performanceValueFlowMaxIfCountInvalid() { @@ -1969,7 +1886,6 @@ class TestCmdlineParser : public TestFixture { settings->templateMaxTime = 0; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->templateMaxTime); - ASSERT_EQUALS("", logger->str()); } void templateMaxTimeInvalid() { @@ -2022,7 +1938,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(1, parser->getPathNames().size()); auto it = parser->getPathNames().cbegin(); ASSERT_EQUALS("dir", *it); - ASSERT_EQUALS("", logger->str()); } void projectMultiple() { @@ -2072,6 +1987,17 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void addonMissing() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--addon=misra2", "file.cpp"}; + settings->addons.clear(); + ASSERT(!parser->fillSettingsFromArgs(3, argv)); + ASSERT_EQUALS(1, settings->addons.size()); + ASSERT_EQUALS("misra2", *settings->addons.cbegin()); + ASSERT_EQUALS("Did not find addon misra2.py\n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void signedChar() { REDIRECT; const char * const argv[] = {"cppcheck", "--fsigned-char", "file.cpp"}; @@ -2125,7 +2051,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(1, settings->rules.size()); auto it = settings->rules.cbegin(); ASSERT_EQUALS(".+", it->pattern); - ASSERT_EQUALS("", logger->str()); } #else void ruleNotSupported() { @@ -2150,7 +2075,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(1, settings->rules.size()); auto it = settings->rules.cbegin(); ASSERT_EQUALS(".+", it->pattern); - ASSERT_EQUALS("", logger->str()); } void ruleFileEmpty() { @@ -2183,13 +2107,33 @@ class TestCmdlineParser : public TestFixture { } #endif + void library() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=posix", "file.cpp"}; + settings->libraries.clear(); + ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(1, settings->libraries.size()); + ASSERT_EQUALS("posix", *settings->libraries.cbegin()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + + void libraryMissing() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=posix2", "file.cpp"}; + settings->libraries.clear(); + ASSERT(!parser->fillSettingsFromArgs(3, argv)); + ASSERT_EQUALS(1, settings->libraries.size()); + ASSERT_EQUALS("posix2", *settings->libraries.cbegin()); + ASSERT_EQUALS("cppcheck: Failed to load library configuration file 'posix2'. File not found\n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void ignorepaths1() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"}; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); - ASSERT_EQUALS("", logger->str()); } void ignorepaths2() { @@ -2198,7 +2142,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(4, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); - ASSERT_EQUALS("", logger->str()); } void ignorepaths3() { @@ -2208,7 +2151,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]); - ASSERT_EQUALS("", logger->str()); } void ignorepaths4() { @@ -2218,7 +2160,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]); - ASSERT_EQUALS("", logger->str()); } void ignorefilepaths1() { @@ -2227,7 +2168,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]); - ASSERT_EQUALS("", logger->str()); } void ignorefilepaths2() { @@ -2236,7 +2176,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src/foo.cpp", parser->getIgnoredPaths()[0]); - ASSERT_EQUALS("", logger->str()); } void checkconfig() { @@ -2245,7 +2184,6 @@ class TestCmdlineParser : public TestFixture { settings->checkConfiguration = false; ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->checkConfiguration); - ASSERT_EQUALS("", logger->str()); } void unknownParam() { @@ -2261,7 +2199,6 @@ class TestCmdlineParser : public TestFixture { ASSERT(parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->userUndefs.size()); ASSERT(settings->userUndefs.find("_WIN32") != settings->userUndefs.end()); - ASSERT_EQUALS("", logger->str()); } void undefs2() { @@ -2271,7 +2208,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, settings->userUndefs.size()); ASSERT(settings->userUndefs.find("_WIN32") != settings->userUndefs.end()); ASSERT(settings->userUndefs.find("NODEBUG") != settings->userUndefs.end()); - ASSERT_EQUALS("", logger->str()); } void undefs_noarg() { @@ -2302,7 +2238,6 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--cppcheck-build-dir=.", "file.cpp"}; ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); - ASSERT_EQUALS("", logger->str()); } void cppcheckBuildDirNonExistent() { From 1d3f9beb2169e149c01e1abb5baf46131f88c285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Sat, 25 Nov 2023 22:07:49 +0100 Subject: [PATCH 20/40] CppCheckExecutor: do not modify settings after they were passed to `CppCheck` (#5697) --- cli/cppcheckexecutor.cpp | 16 +++++++++------- cli/cppcheckexecutor.h | 2 +- cli/cppcheckexecutorseh.cpp | 2 +- cli/cppcheckexecutorseh.h | 2 +- cli/cppcheckexecutorsig.cpp | 2 +- cli/cppcheckexecutorsig.h | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 832684c967f..4320c020f0f 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -183,10 +183,13 @@ int CppCheckExecutor::check(int argc, const char* const argv[]) return EXIT_SUCCESS; } + settings.loadSummaries(); + mFiles = parser.getFiles(); mFileSettings = parser.getFileSettings(); mStdLogger = new StdLogger(settings); + CppCheck cppCheck(*mStdLogger, true, executeCommand); cppCheck.settings() = settings; @@ -230,9 +233,10 @@ bool CppCheckExecutor::reportSuppressions(const Settings &settings, bool unusedF /* * That is a method which gets called from check_wrapper * */ -int CppCheckExecutor::check_internal(CppCheck& cppcheck) +int CppCheckExecutor::check_internal(CppCheck& cppcheck) const { - Settings& settings = cppcheck.settings(); + const auto& settings = cppcheck.settings(); + auto& suppressions = cppcheck.settings().nomsg; if (settings.reportProgress >= 0) mStdLogger->resetLatestProgressOutputTime(); @@ -242,8 +246,6 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) } if (!settings.buildDir.empty()) { - settings.loadSummaries(); - std::list fileNames; for (std::list>::const_iterator i = mFiles.cbegin(); i != mFiles.cend(); ++i) fileNames.emplace_back(i->first); @@ -256,13 +258,13 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) unsigned int returnValue; if (settings.useSingleJob()) { // Single process - SingleExecutor executor(cppcheck, mFiles, mFileSettings, settings, settings.nomsg, *mStdLogger); + SingleExecutor executor(cppcheck, mFiles, mFileSettings, settings, suppressions, *mStdLogger); returnValue = executor.check(); } else { #if defined(THREADING_MODEL_THREAD) - ThreadExecutor executor(mFiles, mFileSettings, settings, settings.nomsg, *mStdLogger, CppCheckExecutor::executeCommand); + ThreadExecutor executor(mFiles, mFileSettings, settings, suppressions, *mStdLogger, CppCheckExecutor::executeCommand); #elif defined(THREADING_MODEL_FORK) - ProcessExecutor executor(mFiles, mFileSettings, settings, settings.nomsg, *mStdLogger, CppCheckExecutor::executeCommand); + ProcessExecutor executor(mFiles, mFileSettings, settings, suppressions, *mStdLogger, CppCheckExecutor::executeCommand); #endif returnValue = executor.check(); } diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index 34157ddfbd0..f54e49dee2e 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -101,7 +101,7 @@ class CppCheckExecutor { * given value is returned instead of default 0. * If no errors are found, 0 is returned. */ - int check_internal(CppCheck& cppcheck); + int check_internal(CppCheck& cppcheck) const; /** * Filename associated with size of file diff --git a/cli/cppcheckexecutorseh.cpp b/cli/cppcheckexecutorseh.cpp index 7f571bd53a6..9ec2df0a2b5 100644 --- a/cli/cppcheckexecutorseh.cpp +++ b/cli/cppcheckexecutorseh.cpp @@ -253,7 +253,7 @@ namespace { * TODO Check for multi-threading issues! * */ -int check_wrapper_seh(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&), CppCheck& cppcheck) +int check_wrapper_seh(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&) const, CppCheck& cppcheck) { FILE *outputFile = CppCheckExecutor::getExceptionOutput(); __try { diff --git a/cli/cppcheckexecutorseh.h b/cli/cppcheckexecutorseh.h index 56616d95af9..93f51456cde 100644 --- a/cli/cppcheckexecutorseh.h +++ b/cli/cppcheckexecutorseh.h @@ -26,7 +26,7 @@ class CppCheckExecutor; class CppCheck; -int check_wrapper_seh(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&), CppCheck& cppcheck); +int check_wrapper_seh(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&) const, CppCheck& cppcheck); #endif diff --git a/cli/cppcheckexecutorsig.cpp b/cli/cppcheckexecutorsig.cpp index 0d1156e0ae7..279a95633c9 100644 --- a/cli/cppcheckexecutorsig.cpp +++ b/cli/cppcheckexecutorsig.cpp @@ -298,7 +298,7 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * context) } } -int check_wrapper_sig(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&), CppCheck& cppcheck) +int check_wrapper_sig(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&) const, CppCheck& cppcheck) { // determine stack vs. heap char stackVariable; diff --git a/cli/cppcheckexecutorsig.h b/cli/cppcheckexecutorsig.h index 4279378e4b1..5c8c161d2ff 100644 --- a/cli/cppcheckexecutorsig.h +++ b/cli/cppcheckexecutorsig.h @@ -26,7 +26,7 @@ class CppCheckExecutor; class CppCheck; -int check_wrapper_sig(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&), CppCheck& cppcheck); +int check_wrapper_sig(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&) const, CppCheck& cppcheck); #endif // CPPCHECKEXECUTORSIG_H From c1f61327454fac9fbb313e640bc9092506abbcc7 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 25 Nov 2023 22:57:07 +0100 Subject: [PATCH 21/40] Fix #12219 FP constParameterCallback for template argument (#5695) --- lib/symboldatabase.cpp | 17 ++++++----------- test/testsymboldatabase.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index d7612bbead4..ac053cfe52d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1101,23 +1101,18 @@ void SymbolDatabase::createSymbolDatabaseSetFunctionPointers(bool firstPass) } // Set function call pointers + const Token* inTemplateArg = nullptr; for (Token* tok = mTokenizer.list.front(); tok != mTokenizer.list.back(); tok = tok->next()) { + if (inTemplateArg == nullptr && tok->link() && tok->str() == "<") + inTemplateArg = tok->link(); + if (inTemplateArg == tok) + inTemplateArg = nullptr; if (tok->isName() && !tok->function() && tok->varId() == 0 && ((tok->astParent() && tok->astParent()->isComparisonOp()) || Token::Match(tok, "%name% [{(,)>;]")) && !isReservedName(tok->str())) { if (tok->next()->str() == ">" && !tok->next()->link()) continue; - bool isTemplateArg = false; - if (!Token::Match(tok->next(), "(|{")) { - const Token *start = tok; - while (Token::Match(start->tokAt(-2), "%name% ::")) - start = start->tokAt(-2); - if (!Token::Match(start->previous(), "[(,<=]") && !Token::simpleMatch(start->previous(), "::") && !Token::Match(start->tokAt(-2), "[(,<=] &") && !Token::Match(start, "%name% ;")) - continue; - isTemplateArg = Token::simpleMatch(start->previous(), "<") || Token::simpleMatch(start->tokAt(-2), "<"); - } - const Function *function = findFunction(tok); - if (!function || (isTemplateArg && function->isConstructor())) + if (!function || (inTemplateArg && function->isConstructor())) continue; tok->function(function); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index ff6a6b6e645..d363f32454f 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -454,6 +454,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(findFunction51); // #11975 - method with same name in derived class TEST_CASE(findFunction52); TEST_CASE(findFunction53); + TEST_CASE(findFunction54); TEST_CASE(findFunctionContainer); TEST_CASE(findFunctionExternC); TEST_CASE(findFunctionGlobalScope); // ::foo @@ -7733,6 +7734,38 @@ class TestSymbolDatabase : public TestFixture { ASSERT(S->function()->isConstructor()); } + void findFunction54() { + { + GET_SYMBOL_DB("struct S {\n" + " explicit S(int& r) { if (r) {} }\n" + " bool f(const std::map& m);\n" + "};\n"); + const Token* S = Token::findsimplematch(tokenizer.tokens(), "S ("); + ASSERT(S && S->function()); + ASSERT(S->function()->isConstructor()); + ASSERT(!S->function()->functionPointerUsage); + S = Token::findsimplematch(S->next(), "S >"); + ASSERT(S && S->type()); + ASSERT_EQUALS(S->type()->name(), "S"); + } + { + GET_SYMBOL_DB("struct S {\n" + " explicit S(int& r) { if (r) {} }\n" + " bool f(const std::map>& m);\n" + "};\n"); + const Token* S = Token::findsimplematch(tokenizer.tokens(), "S ("); + ASSERT(S && S->function()); + ASSERT(S->function()->isConstructor()); + ASSERT(!S->function()->functionPointerUsage); + S = Token::findsimplematch(S->next(), "S ,"); + ASSERT(S && S->type()); + ASSERT_EQUALS(S->type()->name(), "S"); + S = Token::findsimplematch(S->next(), "S >"); + ASSERT(S && S->type()); + ASSERT_EQUALS(S->type()->name(), "S"); + } + } + void findFunctionContainer() { { GET_SYMBOL_DB("void dostuff(std::vector v);\n" From 33981fe42c1f7524496883ec897b3834a7adba58 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 25 Nov 2023 22:58:16 +0100 Subject: [PATCH 22/40] Fix #12214 FN constParameterReference / #12216 FP constParameterReference (#5691) --- lib/astutils.cpp | 4 ++++ lib/checkother.cpp | 21 ++------------------- lib/tokenize.cpp | 9 +++------ lib/valueflow.cpp | 4 ++-- test/cfg/std.cpp | 2 +- test/cfg/wxwidgets.cpp | 2 +- test/testother.cpp | 18 ++++++++++++++++-- 7 files changed, 29 insertions(+), 31 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index c1025da349e..2da5f3f219e 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2290,6 +2290,8 @@ static T* getTokenArgumentFunctionImpl(T* tok, int& argn) tok = tok->astOperand1(); while (tok && (tok->isUnaryOp("*") || tok->str() == "[")) tok = tok->astOperand1(); + if (Token::Match(tok, ". * %name%")) // bailout for pointer to member + return tok->tokAt(2); while (Token::simpleMatch(tok, ".")) tok = tok->astOperand2(); while (Token::simpleMatch(tok, "::")) { @@ -2630,6 +2632,8 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, if (!ftok->function() || !ftok->function()->isConst()) return true; } + if (Token::Match(tok2->astParent(), ". * %name%")) // bailout + return true; if (Token::simpleMatch(tok2, "[") && astIsContainer(tok) && vt && vt->container && vt->container->stdAssociativeLike) return true; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index c55219abf9a..041b9d022cc 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1390,6 +1390,8 @@ void CheckOther::checkConstVariable() continue; if (var->isVolatile()) continue; + if (var->nameToken()->isExpandedMacro()) + continue; if (isStructuredBindingVariable(var)) // TODO: check all bound variables continue; if (isVariableChanged(var, mSettings, mTokenizer->isCPP())) @@ -1461,25 +1463,6 @@ void CheckOther::checkConstVariable() if (usedInAssignment) continue; } - // Skip if we ever cast this variable to a pointer/reference to a non-const type - { - bool castToNonConst = false; - for (const Token* tok = var->nameToken(); tok != scope->bodyEnd && tok != nullptr; tok = tok->next()) { - if (tok->isCast()) { - if (!tok->valueType()) { - castToNonConst = true; // safe guess - break; - } - const bool isConst = tok->valueType()->isConst(tok->valueType()->pointer); - if (!isConst) { - castToNonConst = true; - break; - } - } - } - if (castToNonConst) - continue; - } constVariableError(var, hasFunction ? function : nullptr); } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 26255413810..3cfef404952 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -619,7 +619,7 @@ namespace { bool mUsed = false; public: - TypedefSimplifier(Token* typedefToken, int &num) : mTypedefToken(typedefToken) { + explicit TypedefSimplifier(Token* typedefToken) : mTypedefToken(typedefToken) { Token* start = typedefToken->next(); if (Token::simpleMatch(start, "typename")) start = start->next(); @@ -641,7 +641,6 @@ namespace { mRangeTypeQualifiers = rangeQualifiers; Token* typeName = rangeBefore.second->previous(); if (typeName->isKeyword()) { - (void)num; // TODO typeName->insertToken("T:" + std::to_string(num++)); typeName->insertToken(nameToken->str()); } @@ -1048,8 +1047,7 @@ void Tokenizer::simplifyTypedef() std::map numberOfTypedefs; for (Token* tok = list.front(); tok; tok = tok->next()) { if (tok->str() == "typedef") { - int dummy = 0; - TypedefSimplifier ts(tok, dummy); + TypedefSimplifier ts(tok); if (!ts.fail()) numberOfTypedefs[ts.name()]++; continue; @@ -1057,7 +1055,6 @@ void Tokenizer::simplifyTypedef() } int indentlevel = 0; - int typeNum = 1; std::map typedefs; for (Token* tok = list.front(); tok; tok = tok->next()) { if (!tok->isName()) { @@ -1069,7 +1066,7 @@ void Tokenizer::simplifyTypedef() } if (indentlevel == 0 && tok->str() == "typedef") { - TypedefSimplifier ts(tok, typeNum); + TypedefSimplifier ts(tok); if (!ts.fail() && numberOfTypedefs[ts.name()] == 1) { if (mSettings->severity.isEnabled(Severity::portability) && ts.isInvalidConstFunctionType(typedefs)) reportError(tok->next(), Severity::portability, "invalidConstFunctionType", diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3a375e3eef6..16d7595a9dd 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5238,7 +5238,7 @@ static const Scope* getLoopScope(const Token* tok) } // -static void valueFlowConditionExpressions(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowConditionExpressions(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) { for (const Scope * scope : symboldatabase.functionScopes) { if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) { @@ -7482,7 +7482,7 @@ static void valueFlowInjectParameter(const TokenList& tokenlist, settings); } -static void valueFlowSwitchVariable(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings) +static void valueFlowSwitchVariable(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings) { for (const Scope &scope : symboldatabase.scopeList) { if (scope.type != Scope::ScopeType::eSwitch) diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index ecabb2f95c5..b0926a0eed5 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -4206,7 +4206,7 @@ void uninivar_istream_read(std::istream &f) f.read(buffer, size); } -void uninitvar_string_compare(std::string &teststr, std::wstring &testwstr) +void uninitvar_string_compare(const std::string &teststr, const std::wstring &testwstr) { const char *pStrUninit; // cppcheck-suppress uninitvar diff --git a/test/cfg/wxwidgets.cpp b/test/cfg/wxwidgets.cpp index 0b4f85c873c..7472fc54350 100644 --- a/test/cfg/wxwidgets.cpp +++ b/test/cfg/wxwidgets.cpp @@ -29,7 +29,7 @@ #include #include -void uninitvar_wxRegEx_GetMatch(wxRegEx &obj, size_t *start, size_t *len, size_t index) +void uninitvar_wxRegEx_GetMatch(const wxRegEx &obj, size_t *start, size_t *len, size_t index) { size_t s,l; size_t *sPtr,*lPtr; diff --git a/test/testother.cpp b/test/testother.cpp index 83fad7c3111..a97f52b8dad 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2873,7 +2873,7 @@ class TestOther : public TestFixture { " x.f();\n" " foo( static_cast(0) );\n" "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (style) Parameter 'x' can be declared as reference to const\n", errout.str()); check("class a {\n" " void foo(const int& i) const;\n" @@ -3375,6 +3375,18 @@ class TestOther : public TestFixture { "[test.cpp:1]: (style) Parameter 's2' can be declared as reference to const\n", errout.str()); + check("void f(int& r) {\n" // #12214 + " (void)(true);\n" + " if (r) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'r' can be declared as reference to const\n", errout.str()); + + check("struct S { void f(int&); };\n" // #12216 + "void g(S& s, int& r, void (S::* p2m)(int&)) {\n" + " (s.*p2m)(r);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + check("struct S {\n" " void f(int& r) { p = &r; }\n" " int* p;\n" @@ -10861,7 +10873,9 @@ class TestOther : public TestFixture { " for (auto &j : g(std::move(l))) { (void)j; }\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (warning) Access of moved variable 'l'.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) Variable 'j' can be declared as reference to const\n" + "[test.cpp:4]: (warning) Access of moved variable 'l'.\n", + errout.str()); } void moveCallback() From 42a64d4d39f89036969bce17d7334ca65a564ec9 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 25 Nov 2023 22:59:51 +0100 Subject: [PATCH 23/40] Fix #12218 syntaxError with typedef in namespace (#5694) --- lib/tokenize.cpp | 2 ++ test/testsimplifytypedef.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 3cfef404952..7358a088fe6 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1942,6 +1942,8 @@ void Tokenizer::simplifyTypedefCpp() tok2 = tok2->next(); tok2->next()->insertToken("0"); } + if (Token::Match(tok2->tokAt(-1), "class|struct|union") && tok2->strAt(-1) == typeStart->str()) + tok2->deletePrevious(); tok2->str(typeStart->str()); // restore qualification if it was removed diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 89a38f394e9..d321026a384 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -212,6 +212,7 @@ class TestSimplifyTypedef : public TestFixture { TEST_CASE(simplifyTypedef146); TEST_CASE(simplifyTypedef147); TEST_CASE(simplifyTypedef148); + TEST_CASE(simplifyTypedef149); TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -3443,6 +3444,18 @@ class TestSimplifyTypedef : public TestFixture { ASSERT_EQUALS("int & r = i ;", tok(code)); } + void simplifyTypedef149() { // #12218 + const char* code{}; + code = "namespace N {\n" + " typedef struct S {} S;\n" + "}\n" + "void g(int);\n" + "void f() {\n" + " g(sizeof(struct N::S));\n" + "}\n"; + ASSERT_EQUALS("namespace N { struct S { } ; } void g ( int ) ; void f ( ) { g ( sizeof ( struct N :: S ) ) ; }", tok(code)); + } + void simplifyTypedefFunction1() { { const char code[] = "typedef void (*my_func)();\n" From f2461781fde6a1ed8b92f49ed3fb03a3af475d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Sun, 26 Nov 2023 14:04:35 +0100 Subject: [PATCH 24/40] added `xml.h` wrapper for TinyXML2 / cleaned up suppressions of Clang compiler warnings (#5700) --- Makefile | 32 ++++++------ cli/cmdlineparser.cpp | 2 +- cmake/compileroptions.cmake | 79 ++++++++++++++--------------- gui/test/xmlreportv2/CMakeLists.txt | 3 ++ lib/analyzerinfo.cpp | 3 +- lib/checkbufferoverrun.cpp | 3 +- lib/checkclass.cpp | 13 ++--- lib/checkmemoryleak.cpp | 2 +- lib/checkunusedfunctions.cpp | 2 +- lib/cppcheck.cpp | 2 +- lib/cppcheck.vcxproj | 1 + lib/ctu.cpp | 2 +- lib/errorlogger.cpp | 2 +- lib/importproject.cpp | 2 +- lib/json.h | 4 ++ lib/lib.pri | 3 +- lib/library.cpp | 2 +- lib/platform.cpp | 2 +- lib/suppressions.cpp | 2 +- lib/xml.h | 36 +++++++++++++ test/fixture.cpp | 2 +- test/testerrorlogger.cpp | 2 +- test/testlibrary.cpp | 2 +- test/testplatform.cpp | 2 +- tools/dmake.cpp | 1 + 25 files changed, 125 insertions(+), 81 deletions(-) create mode 100644 lib/xml.h diff --git a/Makefile b/Makefile index 5ac59a8cdc8..09c40c0e234 100644 --- a/Makefile +++ b/Makefile @@ -470,7 +470,7 @@ $(libcppdir)/symboldatabase.o: lib/symboldatabase.cpp lib/addoninfo.h lib/astuti $(libcppdir)/addoninfo.o: lib/addoninfo.cpp externals/picojson/picojson.h lib/addoninfo.h lib/config.h lib/json.h lib/path.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/addoninfo.cpp -$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/path.h lib/platform.h lib/standards.h lib/utils.h +$(libcppdir)/analyzerinfo.o: lib/analyzerinfo.cpp externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/path.h lib/platform.h lib/standards.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/analyzerinfo.cpp $(libcppdir)/astutils.o: lib/astutils.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errortypes.h lib/findtoken.h lib/infer.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/valueptr.h lib/vfvalue.h @@ -494,10 +494,10 @@ $(libcppdir)/checkbool.o: lib/checkbool.cpp lib/addoninfo.h lib/astutils.h lib/c $(libcppdir)/checkboost.o: lib/checkboost.cpp lib/check.h lib/checkboost.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.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)/checkboost.cpp -$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/color.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/suppressions.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 +$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/color.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/suppressions.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 lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkbufferoverrun.cpp -$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/color.h lib/config.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/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkclass.h lib/color.h lib/config.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/suppressions.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)/checkclass.cpp $(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkcondition.h lib/checkother.h lib/config.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/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h @@ -551,7 +551,7 @@ $(libcppdir)/checktype.o: lib/checktype.cpp lib/addoninfo.h lib/check.h lib/chec $(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checknullpointer.h lib/checkuninitvar.h lib/color.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/suppressions.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/check.h lib/checkunusedfunctions.h lib/color.h lib/config.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/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/color.h lib/config.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/suppressions.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 externals/simplecpp/simplecpp.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkunusedvar.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.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 @@ -566,13 +566,13 @@ $(libcppdir)/clangimport.o: lib/clangimport.cpp lib/addoninfo.h lib/clangimport. $(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/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/settings.h lib/standards.h lib/suppressions.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 +$(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/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/settings.h lib/standards.h lib/suppressions.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 $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp -$(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/color.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/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/color.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/suppressions.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)/ctu.cpp -$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/errorlogger.cpp $(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h lib/utils.h @@ -584,7 +584,7 @@ $(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/addoninfo.h lib/anal $(libcppdir)/fwdanalysis.o: lib/fwdanalysis.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/fwdanalysis.h lib/library.h lib/mathlib.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/fwdanalysis.cpp -$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/config.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/config.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.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)/importproject.cpp $(libcppdir)/infer.o: lib/infer.cpp lib/calculate.h lib/config.h lib/errortypes.h lib/infer.h lib/mathlib.h lib/valueptr.h lib/vfvalue.h @@ -593,7 +593,7 @@ $(libcppdir)/infer.o: lib/infer.cpp lib/calculate.h lib/config.h lib/errortypes. $(libcppdir)/keywords.o: lib/keywords.cpp lib/config.h lib/keywords.h lib/standards.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/keywords.cpp -$(libcppdir)/library.o: lib/library.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.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/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h +$(libcppdir)/library.o: lib/library.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.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/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/library.cpp $(libcppdir)/mathlib.o: lib/mathlib.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errortypes.h lib/mathlib.h lib/utils.h @@ -608,7 +608,7 @@ $(libcppdir)/pathanalysis.o: lib/pathanalysis.cpp lib/astutils.h lib/config.h li $(libcppdir)/pathmatch.o: lib/pathmatch.cpp lib/config.h lib/path.h lib/pathmatch.h lib/utils.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/pathmatch.cpp -$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/path.h lib/platform.h lib/standards.h lib/utils.h +$(libcppdir)/platform.o: lib/platform.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/path.h lib/platform.h lib/standards.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/platform.cpp $(libcppdir)/preprocessor.o: lib/preprocessor.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h @@ -626,7 +626,7 @@ $(libcppdir)/settings.o: lib/settings.cpp externals/picojson/picojson.h lib/addo $(libcppdir)/summaries.o: lib/summaries.cpp lib/addoninfo.h lib/analyzerinfo.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/summaries.h lib/suppressions.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)/summaries.cpp -$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h +$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.h lib/suppressions.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)/suppressions.cpp $(libcppdir)/templatesimplifier.o: lib/templatesimplifier.cpp lib/addoninfo.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h @@ -647,7 +647,7 @@ $(libcppdir)/utils.o: lib/utils.cpp lib/config.h lib/utils.h $(libcppdir)/vfvalue.o: lib/vfvalue.cpp lib/config.h lib/errortypes.h lib/mathlib.h lib/templatesimplifier.h lib/token.h lib/utils.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/vfvalue.cpp -cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h +cli/cmdlineparser.o: cli/cmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/filelister.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h lib/xml.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/cmdlineparser.cpp cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h cli/cppcheckexecutorseh.h cli/cppcheckexecutorsig.h cli/executor.h cli/processexecutor.h cli/singleexecutor.h cli/threadexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkersreport.h lib/checkunusedfunctions.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h @@ -680,7 +680,7 @@ cli/stacktrace.o: cli/stacktrace.cpp cli/stacktrace.h lib/config.h lib/utils.h cli/threadexecutor.o: cli/threadexecutor.cpp cli/executor.h cli/threadexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ cli/threadexecutor.cpp -test/fixture.o: test/fixture.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h test/options.h test/redirect.h +test/fixture.o: test/fixture.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h test/options.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/fixture.cpp test/helpers.o: test/helpers.cpp cli/filelister.h externals/simplecpp/simplecpp.h lib/addoninfo.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/pathmatch.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/helpers.h @@ -743,7 +743,7 @@ test/testconstructors.o: test/testconstructors.cpp lib/addoninfo.h lib/check.h l test/testcppcheck.o: test/testcppcheck.cpp lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcppcheck.cpp -test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h +test/testerrorlogger.o: test/testerrorlogger.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testerrorlogger.cpp test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/addoninfo.h lib/check.h lib/checkexceptionsafety.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h @@ -773,7 +773,7 @@ test/testio.o: test/testio.cpp lib/addoninfo.h lib/check.h lib/checkio.h lib/col test/testleakautovar.o: test/testleakautovar.cpp lib/addoninfo.h lib/check.h lib/checkleakautovar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testleakautovar.cpp -test/testlibrary.o: test/testlibrary.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h +test/testlibrary.o: test/testlibrary.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testlibrary.cpp test/testmathlib.o: test/testmathlib.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h @@ -797,7 +797,7 @@ test/testpath.o: test/testpath.cpp lib/addoninfo.h lib/check.h lib/color.h lib/c test/testpathmatch.o: test/testpathmatch.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/pathmatch.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testpathmatch.cpp -test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h +test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h lib/xml.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testplatform.cpp test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/addoninfo.h lib/check.h lib/checkpostfixoperator.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index c3864b878fd..8aa1fb4d22f 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -56,7 +56,7 @@ #ifdef HAVE_RULES // xml is used for rules -#include +#include "xml.h" #endif static bool addFilesToList(const std::string& fileList, std::vector& pathNames) diff --git a/cmake/compileroptions.cmake b/cmake/compileroptions.cmake index 2a535201759..5d4f67b1b54 100644 --- a/cmake/compileroptions.cmake +++ b/cmake/compileroptions.cmake @@ -80,53 +80,48 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_link_options(-lc++) endif() - # TODO: fix and enable these warnings - or move to suppression list below + # TODO: fix and enable these warnings - or move to suppression list below add_compile_options_safe(-Wno-documentation-unknown-command) # TODO: Clang currently does not support all commands - add_compile_options_safe(-Wno-inconsistent-missing-destructor-override) # caused by Qt moc code - add_compile_options_safe(-Wno-unused-exception-parameter) - add_compile_options_safe(-Wno-old-style-cast) - add_compile_options_safe(-Wno-sign-conversion) - add_compile_options_safe(-Wno-shadow-field-in-constructor) - add_compile_options_safe(-Wno-covered-switch-default) - add_compile_options_safe(-Wno-shorten-64-to-32) - add_compile_options_safe(-Wno-zero-as-null-pointer-constant) # TODO: enable when warnings are fixed in in simplecpp and tinyxml2 - add_compile_options_safe(-Wno-implicit-int-conversion) - add_compile_options_safe(-Wno-double-promotion) - add_compile_options_safe(-Wno-shadow-field) - add_compile_options_safe(-Wno-shadow-uncaptured-local) - add_compile_options_safe(-Wno-implicit-float-conversion) - add_compile_options_safe(-Wno-switch-enum) - add_compile_options_safe(-Wno-float-conversion) - add_compile_options_safe(-Wno-enum-enum-conversion) - add_compile_options_safe(-Wno-date-time) - add_compile_options_safe(-Wno-suggest-override) # TODO: enable when warnings are fixed in in tinyxml2 - add_compile_options_safe(-Wno-suggest-destructor-override) # TODO: enable when warnings are fixed in in tinyxml2 - add_compile_options_safe(-Wno-extra-semi-stmt) # TODO: enable when warnings are fixed in in tinyxml2 - add_compile_options(-Wno-disabled-macro-expansion) - add_compile_options_safe(-Wno-bitwise-instead-of-logical) - - # these cannot be fixed properly without adopting later C++ standards - add_compile_options_safe(-Wno-unsafe-buffer-usage) - add_compile_options_safe(-Wno-global-constructors) - add_compile_options_safe(-Wno-exit-time-destructors) - - # can only be partially addressed - add_compile_options(-Wno-padded) - - # no need for C++98 compatibility - add_compile_options(-Wno-c++98-compat) - add_compile_options(-Wno-c++98-compat-pedantic) - - # only need to be addressed to work around issues in older compilers - add_compile_options_safe(-Wno-return-std-move-in-c++11) + add_compile_options_safe(-Wno-unused-exception-parameter) + add_compile_options_safe(-Wno-old-style-cast) + add_compile_options_safe(-Wno-sign-conversion) + add_compile_options_safe(-Wno-shadow-field-in-constructor) + add_compile_options_safe(-Wno-covered-switch-default) + add_compile_options_safe(-Wno-shorten-64-to-32) + add_compile_options_safe(-Wno-implicit-int-conversion) + add_compile_options_safe(-Wno-double-promotion) + add_compile_options_safe(-Wno-shadow-field) + add_compile_options_safe(-Wno-shadow-uncaptured-local) + add_compile_options_safe(-Wno-implicit-float-conversion) + add_compile_options_safe(-Wno-switch-enum) + add_compile_options_safe(-Wno-float-conversion) + add_compile_options_safe(-Wno-enum-enum-conversion) + add_compile_options_safe(-Wno-date-time) + add_compile_options(-Wno-disabled-macro-expansion) + add_compile_options_safe(-Wno-bitwise-instead-of-logical) + + # these cannot be fixed properly without adopting later C++ standards + add_compile_options_safe(-Wno-unsafe-buffer-usage) + add_compile_options_safe(-Wno-global-constructors) + add_compile_options_safe(-Wno-exit-time-destructors) + + # can only be partially addressed + add_compile_options(-Wno-padded) + + # no need for C++98 compatibility + add_compile_options(-Wno-c++98-compat) + add_compile_options(-Wno-c++98-compat-pedantic) + + # only needs to be addressed to work around issues in older compilers + add_compile_options_safe(-Wno-return-std-move-in-c++11) # warnings we are currently not interested in - add_compile_options(-Wno-four-char-constants) - add_compile_options(-Wno-weak-vtables) + add_compile_options(-Wno-four-char-constants) + add_compile_options(-Wno-weak-vtables) - if(ENABLE_COVERAGE OR ENABLE_COVERAGE_XML) + if(ENABLE_COVERAGE OR ENABLE_COVERAGE_XML) message(FATAL_ERROR "Do not use clang to generate code coverage. Use GCC instead.") - endif() + endif() endif() if (MSVC) diff --git a/gui/test/xmlreportv2/CMakeLists.txt b/gui/test/xmlreportv2/CMakeLists.txt index cea8a4a3841..b1c66660d12 100644 --- a/gui/test/xmlreportv2/CMakeLists.txt +++ b/gui/test/xmlreportv2/CMakeLists.txt @@ -28,6 +28,9 @@ if (BUILD_CORE_DLL) target_compile_definitions(test-xmlreportv2 PRIVATE CPPCHECKLIB_IMPORT TINYXML2_IMPORT) target_link_libraries(test-xmlreportv2 cppcheck-core) endif() +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_compile_options_safe(test-xmlreportv2 -Wno-extra-semi-stmt) +endif() if (REGISTER_GUI_TESTS) add_test(NAME test-xmlreportv2 COMMAND $) diff --git a/lib/analyzerinfo.cpp b/lib/analyzerinfo.cpp index 1ee29621ac8..2efad8d5d04 100644 --- a/lib/analyzerinfo.cpp +++ b/lib/analyzerinfo.cpp @@ -23,11 +23,12 @@ #include "path.h" #include "utils.h" -#include #include #include #include // IWYU pragma: keep +#include "xml.h" + AnalyzerInformation::~AnalyzerInformation() { close(); diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index e50e5a2b111..d9acf389218 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -40,7 +40,8 @@ #include #include // std::accumulate #include -#include + +#include "xml.h" //--------------------------------------------------------------------------- diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 783468c13f5..c6005eca1ee 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -38,7 +38,7 @@ #include #include -#include +#include "xml.h" namespace CTU { class FileInfo; @@ -2523,14 +2523,15 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member ((lastVarTok->valueType()->container->getYield(end->str()) == Library::Container::Yield::START_ITERATOR) || (lastVarTok->valueType()->container->getYield(end->str()) == Library::Container::Yield::END_ITERATOR)) && (tok1->previous()->isComparisonOp() || - (tok1->previous()->isAssignmentOp() && tok1->tokAt(-2)->variable() && Token::Match(tok1->tokAt(-2)->variable()->typeEndToken(), "const_iterator|const_reverse_iterator"))))) - ; + (tok1->previous()->isAssignmentOp() && tok1->tokAt(-2)->variable() && Token::Match(tok1->tokAt(-2)->variable()->typeEndToken(), "const_iterator|const_reverse_iterator"))))) { + // empty body + } else if (var->smartPointerType() && var->smartPointerType()->classScope && isConstMemberFunc(var->smartPointerType()->classScope, end)) { - ; + // empty body } else if (var->isSmartPointer() && Token::simpleMatch(tok1->next(), ".") && tok1->next()->originalName().empty() && mSettings->library.isFunctionConst(end)) { - ; + // empty body } else if (hasOverloadedMemberAccess(end, var->typeScope())) { - ; + // empty body } else if (!var->typeScope() || (end->function() != func && !isConstMemberFunc(var->typeScope(), end))) { if (!mSettings->library.isFunctionConst(end)) return false; diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 2459adb0b6c..a3c7d4a0177 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -753,7 +753,7 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const vari deallocated = true; break; } - }; + } return deallocated; }; diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index f1f8abae0f6..24151998ce1 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -41,7 +41,7 @@ #include #include -#include +#include "xml.h" namespace CTU { class FileInfo; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 7cc42b6a54c..f70bca725a2 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -70,7 +70,7 @@ #include -#include +#include "xml.h" #ifdef HAVE_RULES #ifdef _WIN32 diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 62c0301768b..e53ce4d856b 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -167,6 +167,7 @@ + diff --git a/lib/ctu.cpp b/lib/ctu.cpp index c5ab93eb2b8..004ed4bccd8 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -36,7 +36,7 @@ #include #include -#include +#include "xml.h" //--------------------------------------------------------------------------- static constexpr char ATTR_CALL_ID[] = "call-id"; diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index 886ebd516d8..a8a18b6c365 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -37,7 +37,7 @@ #include #include -#include +#include "xml.h" const std::set ErrorLogger::mCriticalErrorIds{ "cppcheckError", diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 2b7790e5982..266be13517d 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -36,7 +36,7 @@ #include #include -#include +#include "xml.h" #include "json.h" diff --git a/lib/json.h b/lib/json.h index 521d6b9c9cf..760dbaa5efa 100644 --- a/lib/json.h +++ b/lib/json.h @@ -19,13 +19,17 @@ #ifndef jsonH #define jsonH +#include "config.h" + SUPPRESS_WARNING_PUSH("-Wfloat-equal") SUPPRESS_WARNING_CLANG_PUSH("-Wtautological-type-limit-compare") SUPPRESS_WARNING_GCC_PUSH("-Wparentheses") +SUPPRESS_WARNING_CLANG_PUSH("-Wextra-semi-stmt") #define PICOJSON_USE_INT64 #include +SUPPRESS_WARNING_CLANG_POP SUPPRESS_WARNING_GCC_POP SUPPRESS_WARNING_CLANG_POP SUPPRESS_WARNING_POP diff --git a/lib/lib.pri b/lib/lib.pri index baa723f8a54..5125fb684a0 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -77,7 +77,8 @@ HEADERS += $${PWD}/addoninfo.h \ $${PWD}/valueflow.h \ $${PWD}/valueptr.h \ $${PWD}/version.h \ - $${PWD}/vfvalue.h + $${PWD}/vfvalue.h \ + $${PWD}/xml.h SOURCES += $${PWD}/valueflow.cpp \ $${PWD}/tokenize.cpp \ diff --git a/lib/library.cpp b/lib/library.cpp index 593e764485c..9ce1a4f36aa 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include "xml.h" static std::vector getnames(const char *names) { diff --git a/lib/platform.cpp b/lib/platform.cpp index 9d849072c6a..f54b9110afe 100644 --- a/lib/platform.cpp +++ b/lib/platform.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include "xml.h" Platform::Platform() { diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index af5470423ee..782d657d17b 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -33,7 +33,7 @@ #include // IWYU pragma: keep #include -#include +#include "xml.h" Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg, const std::set ¯oNames) { diff --git a/lib/xml.h b/lib/xml.h new file mode 100644 index 00000000000..b2c2c34fce0 --- /dev/null +++ b/lib/xml.h @@ -0,0 +1,36 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2023 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 xmlH +#define xmlH + +#include "config.h" + +SUPPRESS_WARNING_CLANG_PUSH("-Wzero-as-null-pointer-constant") +SUPPRESS_WARNING_CLANG_PUSH("-Wextra-semi-stmt") +SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-override") +SUPPRESS_WARNING_CLANG_PUSH("-Wsuggest-destructor-override") + +#include + +SUPPRESS_WARNING_CLANG_POP +SUPPRESS_WARNING_CLANG_POP +SUPPRESS_WARNING_CLANG_POP +SUPPRESS_WARNING_CLANG_POP + +#endif // xmlH diff --git a/test/fixture.cpp b/test/fixture.cpp index 3fa8b68b280..a99a80a0d93 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include "xml.h" std::ostringstream errout; std::ostringstream output; diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index 52ef7e7033b..ddd7d61e514 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include "xml.h" class TestErrorLogger : public TestFixture { public: diff --git a/test/testlibrary.cpp b/test/testlibrary.cpp index 7fa157ad0ad..11870ba9029 100644 --- a/test/testlibrary.cpp +++ b/test/testlibrary.cpp @@ -33,7 +33,7 @@ #include #include -#include +#include "xml.h" #define ASSERT_EQ(expected, actual) ASSERT(expected == actual) diff --git a/test/testplatform.cpp b/test/testplatform.cpp index 0b680be232b..177ce1ad61a 100644 --- a/test/testplatform.cpp +++ b/test/testplatform.cpp @@ -22,7 +22,7 @@ #include -#include +#include "xml.h" class TestPlatform : public TestFixture { diff --git a/tools/dmake.cpp b/tools/dmake.cpp index 474a6b31dbd..1ca4262c0e5 100644 --- a/tools/dmake.cpp +++ b/tools/dmake.cpp @@ -336,6 +336,7 @@ int main(int argc, char **argv) libfiles_h.emplace_back("tokenrange.h"); libfiles_h.emplace_back("valueptr.h"); libfiles_h.emplace_back("version.h"); + libfiles_h.emplace_back("xml.h"); std::sort(libfiles_h.begin(), libfiles_h.end()); std::vector clifiles_h; From d1b42d0771fd9bc36e48547b0979586050e939b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Sun, 26 Nov 2023 14:42:11 +0100 Subject: [PATCH 25/40] fixed #12056 - qt.cfg: implemented `Q_OBJECT` to get rid of `symbolDatabaseWarning` in selfcheck (#5533) --- .selfcheck_suppressions | 4 +--- .selfcheck_unused_suppressions | 5 ++++- cfg/qt.cfg | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.selfcheck_suppressions b/.selfcheck_suppressions index cbfadadbe02..872a521be37 100644 --- a/.selfcheck_suppressions +++ b/.selfcheck_suppressions @@ -4,14 +4,12 @@ bitwiseOnBoolean # temporary suppressions - fix the warnings! simplifyUsing:lib/valueptr.h +simplifyUsing:gui/temp/moc_*.cpp varid0:gui/projectfile.cpp templateInstantiation # warnings in Qt generated code we cannot fix -symbolDatabaseWarning:gui/temp/moc_*.cpp -simplifyUsing:gui/temp/moc_*.cpp funcArgNamesDifferent:gui/temp/moc_*.cpp -symbolDatabaseWarning:tools/triage/temp/moc_*.cpp naming-varname:gui/temp/ui_*.h naming-varname:cmake.output/gui/ui_*.h functionStatic:gui/temp/ui_fileview.h diff --git a/.selfcheck_unused_suppressions b/.selfcheck_unused_suppressions index 8e470d2e415..68f296fef3d 100644 --- a/.selfcheck_unused_suppressions +++ b/.selfcheck_unused_suppressions @@ -9,4 +9,7 @@ unusedFunction:gui/codeeditor.* # usage is disabled unusedFunction:lib/symboldatabase.cpp # false positive - #10661 -unusedFunction:oss-fuzz/main.cpp \ No newline at end of file +unusedFunction:oss-fuzz/main.cpp + +# Q_OBJECT functions which are not called in our code +unusedFunction:cmake.output.notest/gui/cppcheck-gui_autogen/*/moc_aboutdialog.cpp \ No newline at end of file diff --git a/cfg/qt.cfg b/cfg/qt.cfg index e78a6653311..51033609767 100644 --- a/cfg/qt.cfg +++ b/cfg/qt.cfg @@ -5081,7 +5081,7 @@ - + From 5fed6e7dd9dacc49edc9256d9ca4d02d7d2468a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 27 Nov 2023 11:16:20 +0100 Subject: [PATCH 26/40] json.h: suppress `-Wzero-as-null-pointer-constant` Clang warning (#5701) --- lib/json.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/json.h b/lib/json.h index 760dbaa5efa..0f2da5c346c 100644 --- a/lib/json.h +++ b/lib/json.h @@ -25,10 +25,12 @@ SUPPRESS_WARNING_PUSH("-Wfloat-equal") SUPPRESS_WARNING_CLANG_PUSH("-Wtautological-type-limit-compare") SUPPRESS_WARNING_GCC_PUSH("-Wparentheses") SUPPRESS_WARNING_CLANG_PUSH("-Wextra-semi-stmt") +SUPPRESS_WARNING_CLANG_PUSH("-Wzero-as-null-pointer-constant") #define PICOJSON_USE_INT64 #include +SUPPRESS_WARNING_CLANG_POP SUPPRESS_WARNING_CLANG_POP SUPPRESS_WARNING_GCC_POP SUPPRESS_WARNING_CLANG_POP From a937862a5d13441587ecec1327e45351d3c0931d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 27 Nov 2023 12:06:03 +0100 Subject: [PATCH 27/40] CmdLineParser: return enum from `parseFromArgs()` instead of using additional member (#5698) --- cli/cmdlineparser.cpp | 153 +++++++------ cli/cmdlineparser.h | 12 +- test/testcmdlineparser.cpp | 448 +++++++++++++++++++------------------ 3 files changed, 307 insertions(+), 306 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 8aa1fb4d22f..be5b3468f2d 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -143,14 +143,15 @@ CmdLineParser::CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppress bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) { - const bool success = parseFromArgs(argc, argv); + const Result result = parseFromArgs(argc, argv); - if (success) { - if (exitAfterPrinting()) { - Settings::terminate(); - return true; - } - } else { + switch (result) { + case Result::Success: + break; + case Result::Exit: + Settings::terminate(); + return true; + case Result::Fail: return false; } @@ -279,7 +280,7 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) // TODO: normalize/simplify/native all path parameters // TODO: error out on all missing given files/paths -bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) +CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const argv[]) { bool def = false; bool maxconfigs = false; @@ -299,7 +300,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) ++i; if (i >= argc || argv[i][0] == '-') { mLogger.printError("argument to '-D' is missing."); - return false; + return Result::Fail; } define = argv[i]; @@ -335,7 +336,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) ++i; if (i >= argc || argv[i][0] == '-') { mLogger.printError("argument to '-I' is missing."); - return false; + return Result::Fail; } path = argv[i]; } @@ -363,7 +364,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) ++i; if (i >= argc || argv[i][0] == '-') { mLogger.printError("argument to '-U' is missing."); - return false; + return Result::Fail; } undef = argv[i]; @@ -404,7 +405,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--checks-max-time=", 18) == 0) { if (!parseNumberArg(argv[i], 18, mSettings.checksMaxTime, true)) - return false; + return Result::Fail; } else if (std::strcmp(argv[i], "--clang") == 0) { @@ -425,7 +426,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string cfgExcludesFile(23 + argv[i]); if (!addPathsToSet(cfgExcludesFile, mSettings.configExcludePaths)) { mLogger.printError("unable to open config excludes file at '" + cfgExcludesFile + "'"); - return false; + return Result::Fail; } } @@ -436,7 +437,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) if (!Path::isDirectory(mSettings.buildDir)) { mLogger.printError("Directory '" + mSettings.buildDir + "' specified by --cppcheck-build-dir argument has to be existent."); - return false; + return Result::Fail; } } @@ -461,12 +462,13 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string errmsg = mSettings.removeEnabled(argv[i] + 10); if (!errmsg.empty()) { mLogger.printError(errmsg); - return false; + return Result::Fail; } } // documentation.. else if (std::strcmp(argv[i], "--doc") == 0) { + // TODO: make an exclusive option std::ostringstream doc; // Get documentation.. for (const Check * it : Check::instances()) { @@ -478,8 +480,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } mLogger.printRaw(doc.str()); - mExitAfterPrint = true; - return true; + return Result::Exit; } // dump cppcheck data @@ -491,7 +492,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string errmsg = mSettings.addEnabled(enable_arg); if (!errmsg.empty()) { mLogger.printError(errmsg); - return false; + return Result::Fail; } // when "style" is enabled, also enable "warning", "performance" and "portability" if (enable_arg.find("style") != std::string::npos) { @@ -508,7 +509,6 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // print all possible error messages.. else if (std::strcmp(argv[i], "--errorlist") == 0) { // TODO: make this an exclusive option - mExitAfterPrint = true; mSettings.loadCppcheckCfg(); { XMLErrorMessagesLogger xmlLogger; @@ -516,13 +516,13 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) CppCheck::getErrorMessages(xmlLogger); std::cout << ErrorMessage::getXMLFooter() << std::endl; } - return true; + return Result::Exit; } // --error-exitcode=1 else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) { if (!parseNumberArg(argv[i], 17, mSettings.exitCode)) - return false; + return Result::Fail; } // Exception handling inside cppcheck client @@ -531,7 +531,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings.exceptionHandling = true; #else mLogger.printError("Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled."); - return false; + return Result::Fail; #endif } @@ -541,13 +541,13 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string exceptionOutfilename = argv[i] + 21; if (exceptionOutfilename != "stderr" && exceptionOutfilename != "stdout") { mLogger.printError("invalid '--exception-handling' argument"); - return false; + return Result::Fail; } mSettings.exceptionHandling = true; CppCheckExecutor::setExceptionOutput((exceptionOutfilename == "stderr") ? stderr : stdout); #else mLogger.printError("Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled."); - return false; + return Result::Fail; #endif } @@ -559,12 +559,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) std::ifstream f(filename); if (!f.is_open()) { mLogger.printError("couldn't open the file: \"" + filename + "\"."); - return false; + return Result::Fail; } const std::string errmsg(mSuppressionsNoFail.parseFile(f)); if (!errmsg.empty()) { mLogger.printError(errmsg); - return false; + return Result::Fail; } } @@ -578,7 +578,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string fileList = argv[i] + 12; if (!addFilesToList(fileList, mPathNames)) { mLogger.printError("couldn't open the file: \"" + fileList + "\"."); - return false; + return Result::Fail; } } @@ -595,9 +595,8 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // Print help else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { // TODO: make this an exclusive option - mExitAfterPrint = true; printHelp(); - return true; + return Result::Exit; } // Ignored paths @@ -609,7 +608,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) ++i; if (i >= argc || argv[i][0] == '-') { mLogger.printError("argument to '-i' is missing."); - return false; + return Result::Fail; } path = argv[i]; } @@ -642,7 +641,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string includesFile(16 + argv[i]); if (!addIncludePathsToList(includesFile, mSettings.includePaths)) { mLogger.printError("unable to open includes file at '" + includesFile + "'"); - return false; + return Result::Fail; } } @@ -663,7 +662,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) ++i; if (i >= argc || argv[i][0] == '-') { mLogger.printError("argument to '-j' is missing."); - return false; + return Result::Fail; } numberString = argv[i]; @@ -677,20 +676,20 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) std::string err; if (!strToInt(numberString, tmp, &err)) { mLogger.printError("argument to '-j' is not valid - " + err + "."); - return false; + return Result::Fail; } if (tmp == 0) { // TODO: implement get CPU logical core count and use that. // Usually, -j 0 would mean "use all available cores," but // if we get a 0, we just stall and don't do any work. mLogger.printError("argument for '-j' must be greater than 0."); - return false; + return Result::Fail; } if (tmp > 1024) { // Almost nobody has 1024 logical cores, but somebody out // there does. mLogger.printError("argument for '-j' is allowed to be 1024 at max."); - return false; + return Result::Fail; } mSettings.jobs = tmp; } @@ -704,7 +703,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) ++i; if (i >= argc || argv[i][0] == '-') { mLogger.printError("argument to '-l' is missing."); - return false; + return Result::Fail; } numberString = argv[i]; @@ -718,12 +717,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) std::string err; if (!strToInt(numberString, tmp, &err)) { mLogger.printError("argument to '-l' is not valid - " + err + "."); - return false; + return Result::Fail; } mSettings.loadAverage = tmp; #else mLogger.printError("Option -l cannot be used as Cppcheck has not been built with fork threading model."); - return false; + return Result::Fail; #endif } @@ -736,7 +735,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) i++; if (i >= argc || argv[i][0] == '-') { mLogger.printError("no language given to '-x' option."); - return false; + return Result::Fail; } str = argv[i]; } @@ -747,7 +746,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings.enforcedLang = Settings::Language::CPP; else { mLogger.printError("unknown language '" + str + "' enforced."); - return false; + return Result::Fail; } } @@ -760,10 +759,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--max-configs=", 14) == 0) { int tmp; if (!parseNumberArg(argv[i], 14, tmp)) - return false; + return Result::Fail; if (tmp < 1) { mLogger.printError("argument to '--max-configs=' must be greater than 0."); - return false; + return Result::Fail; } mSettings.maxConfigs = tmp; @@ -774,7 +773,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // max ctu depth else if (std::strncmp(argv[i], "--max-ctu-depth=", 16) == 0) { if (!parseNumberArg(argv[i], 16, mSettings.maxCtuDepth)) - return false; + return Result::Fail; } // Write results in file @@ -785,12 +784,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // is always executed. else if (std::strncmp(argv[i], "--performance-valueflow-max-time=", 33) == 0) { if (!parseNumberArg(argv[i], 33, mSettings.performanceValueFlowMaxTime, true)) - return false; + return Result::Fail; } else if (std::strncmp(argv[i], "--performance-valueflow-max-if-count=", 37) == 0) { if (!parseNumberArg(argv[i], 37, mSettings.performanceValueFlowMaxIfCount, true)) - return false; + return Result::Fail; } // Specify platform @@ -801,7 +800,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::vector paths = {argv[0]}; if (!mSettings.platform.set(platform, errstr, paths)) { mLogger.printError(errstr); - return false; + return Result::Fail; } // TODO: remove @@ -825,7 +824,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) message += plistOutput; message += "'."; mLogger.printError(message); - return false; + return Result::Fail; } if (!endsWith(mSettings.plistOutput,'/')) @@ -847,7 +846,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) if (project.projectType != ImportProject::Type::NONE) { mLogger.printError("multiple --project options are not supported."); - return false; + return Result::Fail; } mSettings.checkAllConfigurations = false; // Can be overridden with --max-configs or --force @@ -874,7 +873,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::vector paths = {projectFile, argv[0]}; if (!mSettings.platform.set(platform, errstr, paths)) { mLogger.printError(errstr); - return false; + return Result::Fail; } } @@ -892,15 +891,15 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } if (projType == ImportProject::Type::MISSING) { mLogger.printError("failed to open project '" + projectFile + "'. The file does not exist."); - return false; + return Result::Fail; } if (projType == ImportProject::Type::UNKNOWN) { mLogger.printError("failed to load project '" + projectFile + "'. The format is unknown."); - return false; + return Result::Fail; } if (projType == ImportProject::Type::FAILURE) { mLogger.printError("failed to load project '" + projectFile + "'. An error occurred."); - return false; + return Result::Fail; } } @@ -933,7 +932,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } } else { mLogger.printError("no paths specified for the '" + std::string(argv[i]) + "' option."); - return false; + return Result::Fail; } } @@ -945,7 +944,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--report-progress=", 18) == 0) { int tmp; if (!parseNumberArg(argv[i], 18, tmp, true)) - return false; + return Result::Fail; mSettings.reportProgress = tmp; } @@ -957,7 +956,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings.rules.emplace_back(std::move(rule)); #else mLogger.printError("Option --rule cannot be used as Cppcheck has not been built with rules support."); - return false; + return Result::Fail; #endif } @@ -1003,11 +1002,11 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } } else { mLogger.printError("unable to load rule-file '" + ruleFile + "' (" + tinyxml2::XMLDocument::ErrorIDToName(err) + ")."); - return false; + return Result::Fail; } #else mLogger.printError("Option --rule-file cannot be used as Cppcheck has not been built with rules support."); - return false; + return Result::Fail; #endif } @@ -1032,11 +1031,11 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) mSettings.showtime = SHOWTIME_MODES::SHOWTIME_NONE; else if (showtimeMode.empty()) { mLogger.printError("no mode provided for --showtime"); - return false; + return Result::Fail; } else { mLogger.printError("unrecognized --showtime mode: '" + showtimeMode + "'. Supported modes: file, file-total, summary, top5, top5_file, top5_summary."); - return false; + return Result::Fail; } } @@ -1052,7 +1051,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } else { mLogger.printError("unknown --std value '" + std + "'"); - return false; + return Result::Fail; } } @@ -1061,7 +1060,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string errmsg(mSuppressions.addSuppressionLine(suppression)); if (!errmsg.empty()) { mLogger.printError(errmsg); - return false; + return Result::Fail; } } @@ -1083,12 +1082,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } mLogger.printError(message); - return false; + return Result::Fail; } const std::string errmsg(mSuppressions.parseFile(f)); if (!errmsg.empty()) { mLogger.printError(errmsg); - return false; + return Result::Fail; } } @@ -1097,7 +1096,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const std::string errmsg(mSuppressions.parseXmlFile(filename)); if (!errmsg.empty()) { mLogger.printError(errmsg); - return false; + return Result::Fail; } } @@ -1135,17 +1134,17 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--template-max-time=", 20) == 0) { if (!parseNumberArg(argv[i], 20, mSettings.templateMaxTime)) - return false; + return Result::Fail; } else if (std::strncmp(argv[i], "--typedef-max-time=", 19) == 0) { if (!parseNumberArg(argv[i], 19, mSettings.typedefMaxTime)) - return false; + return Result::Fail; } else if (std::strncmp(argv[i], "--valueflow-max-iterations=", 27) == 0) { if (!parseNumberArg(argv[i], 27, mSettings.valueFlowMaxIterations)) - return false; + return Result::Fail; } else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0) @@ -1153,7 +1152,6 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strcmp(argv[i], "--version") == 0) { // TODO: make this an exclusive parameter - mExitAfterPrint = true; mSettings.loadCppcheckCfg(); if (!mSettings.cppcheckCfgProductName.empty()) { mLogger.printRaw(mSettings.cppcheckCfgProductName); @@ -1164,7 +1162,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); } - return true; + return Result::Exit; } // Write results in results.xml @@ -1175,11 +1173,11 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--xml-version=", 14) == 0) { int tmp; if (!parseNumberArg(argv[i], 14, tmp)) - return false; + return Result::Fail; if (tmp != 2) { // We only have xml version 2 mLogger.printError("'--xml-version' can only be 2."); - return false; + return Result::Fail; } mSettings.xml_version = tmp; @@ -1192,7 +1190,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) message += argv[i]; message += "\"."; mLogger.printError(message); - return false; + return Result::Fail; } } @@ -1229,20 +1227,19 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } if (argc <= 1) { - mExitAfterPrint = true; printHelp(); - return true; + return Result::Exit; } if (!mPathNames.empty() && project.projectType != ImportProject::Type::NONE) { mLogger.printError("--project cannot be used in conjunction with source files."); - return false; + return Result::Fail; } // Print error only if we have "real" command and expect files - if (!mExitAfterPrint && mPathNames.empty() && project.guiProject.pathNames.empty() && project.fileSettings.empty()) { + if (mPathNames.empty() && project.guiProject.pathNames.empty() && project.fileSettings.empty()) { mLogger.printError("no C or C++ source files found."); - return false; + return Result::Fail; } if (!project.guiProject.pathNames.empty()) @@ -1255,7 +1252,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) if (mSettings.basePaths.empty() && mSettings.relativePaths) mSettings.basePaths = mPathNames; - return true; + return Result::Success; } void CmdLineParser::printHelp() const diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index b93716b76bd..db3bb963890 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -57,6 +57,8 @@ class CmdLineParser { */ CmdLineParser(CmdLineLogger &logger, Settings &settings, Suppressions &suppressions, Suppressions &suppressionsNoFail); + enum class Result { Success, Exit, Fail }; + /** * @brief Parse command line args and fill settings and file lists * from there. @@ -71,7 +73,7 @@ class CmdLineParser { * Parse given command line. * @return true if command line was ok, false if there was an error. */ - bool parseFromArgs(int argc, const char* const argv[]); + Result parseFromArgs(int argc, const char* const argv[]); /** * Return the path names user gave to command line. @@ -94,13 +96,6 @@ class CmdLineParser { return mFileSettings; } - /** - * Return if we should exit after printing version, help etc. - */ - bool exitAfterPrinting() const { - return mExitAfterPrint; - } - /** * Return a list of paths user wants to ignore. */ @@ -164,7 +159,6 @@ class CmdLineParser { Settings &mSettings; Suppressions &mSuppressions; Suppressions &mSuppressionsNoFail; - bool mExitAfterPrint{}; std::string mVSConfig; }; diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index e1bf241aa7f..dc54eba807c 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -104,6 +104,18 @@ class TestCmdlineParser : public TestFixture { // TODO: verify that the redirect output is empty } + // add overload so the enums can be compared without a cast + template + bool assertEquals(const char* const filename, const unsigned int linenr, const T& expected, const U& actual) const + { + return TestFixture::assertEquals(filename, linenr, expected, actual); + } + + bool assertEquals(const char* const filename, const unsigned int linenr, const CmdLineParser::Result& expected, const CmdLineParser::Result& actual) const + { + return TestFixture::assertEquals(filename, linenr, static_cast(expected), static_cast(actual)); + } + void run() override { TEST_CASE(nooptions); TEST_CASE(helpshort); @@ -345,11 +357,10 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(cppcheckBuildDirEmpty); } - void nooptions() { REDIRECT; const char * const argv[] = {"cppcheck"}; - ASSERT(parser->parseFromArgs(1, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(1, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -357,7 +368,7 @@ class TestCmdlineParser : public TestFixture { void helpshort() { REDIRECT; const char * const argv[] = {"cppcheck", "-h"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -365,7 +376,7 @@ class TestCmdlineParser : public TestFixture { void helplong() { REDIRECT; const char * const argv[] = {"cppcheck", "--help"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -373,7 +384,7 @@ class TestCmdlineParser : public TestFixture { void version() { REDIRECT; const char * const argv[] = {"cppcheck", "--version"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("Cppcheck 2.13 dev\n", logger->str()); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -385,7 +396,7 @@ class TestCmdlineParser : public TestFixture { "\"productName\": \"The Product\"" "}\n"); const char * const argv[] = {"cppcheck", "--version"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); // TODO: somehow the config is not loaded on some systems (void)logger->str(); //ASSERT_EQUALS("The Product\n", logger->str()); // TODO: include version? ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); @@ -396,7 +407,7 @@ class TestCmdlineParser : public TestFixture { void onefile() { REDIRECT; const char * const argv[] = {"cppcheck", "file.cpp"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, (int)parser->getPathNames().size()); ASSERT_EQUALS("file.cpp", parser->getPathNames().at(0)); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); @@ -405,7 +416,7 @@ class TestCmdlineParser : public TestFixture { void onepath() { REDIRECT; const char * const argv[] = {"cppcheck", "src"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, (int)parser->getPathNames().size()); ASSERT_EQUALS("src", parser->getPathNames().at(0)); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); @@ -414,7 +425,7 @@ class TestCmdlineParser : public TestFixture { void optionwithoutfile() { REDIRECT; const char * const argv[] = {"cppcheck", "-v"}; - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(0, (int)parser->getPathNames().size()); ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str()); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); @@ -424,7 +435,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-v", "file.cpp"}; settings->verbose = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->verbose); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -433,7 +444,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--verbose", "file.cpp"}; settings->verbose = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->verbose); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -442,7 +453,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--debug-simplified", "file.cpp"}; settings->debugSimplified = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->debugSimplified); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -451,7 +462,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--debug-warnings", "file.cpp"}; settings->debugwarnings = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->debugwarnings); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -460,7 +471,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-f", "file.cpp"}; settings->force = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->force); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -469,7 +480,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--force", "file.cpp"}; settings->force = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->force); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -478,7 +489,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; settings->relativePaths = false; const char * const argv[] = {"cppcheck", "-rp", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -487,7 +498,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; settings->relativePaths = false; const char * const argv[] = {"cppcheck", "--relative-paths", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -497,7 +508,7 @@ class TestCmdlineParser : public TestFixture { settings->relativePaths = false; settings->basePaths.clear(); const char * const argv[] = {"cppcheck", "-rp=C:/foo;C:\\bar", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); ASSERT_EQUALS(2, settings->basePaths.size()); ASSERT_EQUALS("C:/foo", settings->basePaths[0]); @@ -511,7 +522,7 @@ class TestCmdlineParser : public TestFixture { settings->basePaths.clear(); const char * const argv[] = {"cppcheck", "--relative-paths=C:/foo;C:\\bar", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); ASSERT_EQUALS(2, settings->basePaths.size()); ASSERT_EQUALS("C:/foo", settings->basePaths[0]); @@ -523,7 +534,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-q", "file.cpp"}; settings->quiet = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->quiet); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -532,7 +543,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--quiet", "file.cpp"}; settings->quiet = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->quiet); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -541,7 +552,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-D"}; // Fails since -D has no param - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-D' is missing.\n", logger->str()); } @@ -549,7 +560,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-D", "-v", "file.cpp"}; // Fails since -D has no param - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-D' is missing.\n", logger->str()); } @@ -557,7 +568,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-D", "--quiet", "file.cpp"}; // Fails since -D has no param - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-D' is missing.\n", logger->str()); } @@ -565,7 +576,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-D_WIN32", "file.cpp"}; settings->userDefines.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("_WIN32=1", settings->userDefines); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -574,7 +585,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-D_WIN32", "-DNODEBUG", "file.cpp"}; settings->userDefines.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("_WIN32=1;NODEBUG=1", settings->userDefines); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -583,7 +594,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-D", "DEBUG", "file.cpp"}; settings->userDefines.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("DEBUG=1", settings->userDefines); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -592,7 +603,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-DDEBUG=", "file.cpp"}; // #5137 - defining empty macro settings->userDefines.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("DEBUG=", settings->userDefines); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -601,7 +612,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "file.cpp"}; settings->enforcedLang = Settings::Language::None; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(Settings::Language::None, settings->enforcedLang); } @@ -609,21 +620,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-x", "c++", "file.cpp"}; settings->enforcedLang = Settings::Language::None; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(Settings::Language::CPP, settings->enforcedLang); } void enforceLanguage3() { REDIRECT; const char * const argv[] = {"cppcheck", "-x"}; - ASSERT(!parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: no language given to '-x' option.\n", logger->str()); } void enforceLanguage4() { REDIRECT; const char * const argv[] = {"cppcheck", "-x", "--inconclusive", "file.cpp"}; - ASSERT(!parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: no language given to '-x' option.\n", logger->str()); } @@ -631,7 +642,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--language=c++", "file.cpp"}; settings->enforcedLang = Settings::Language::None; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Settings::Language::CPP, settings->enforcedLang); } @@ -639,14 +650,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--language=c", "file.cpp"}; settings->enforcedLang = Settings::Language::None; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Settings::Language::C, settings->enforcedLang); } void enforceLanguage7() { REDIRECT; const char * const argv[] = {"cppcheck", "--language=unknownLanguage", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unknown language 'unknownLanguage' enforced.\n", logger->str()); } @@ -654,7 +665,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-I"}; // Fails since -I has no param - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-I' is missing.\n", logger->str()); } @@ -662,7 +673,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-I", "include", "file.cpp"}; settings->includePaths.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); } @@ -670,7 +681,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-I", "include/", "file.cpp"}; settings->includePaths.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); } @@ -678,7 +689,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-I", "include\\", "file.cpp"}; settings->includePaths.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); } @@ -686,7 +697,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-Iinclude", "file.cpp"}; settings->includePaths.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); } @@ -694,7 +705,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-I", "include/", "-I", "framework/", "file.cpp"}; settings->includePaths.clear(); - ASSERT(parser->parseFromArgs(6, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(6, argv)); ASSERT_EQUALS("include/", settings->includePaths.front()); settings->includePaths.pop_front(); ASSERT_EQUALS("framework/", settings->includePaths.front()); @@ -706,7 +717,7 @@ class TestCmdlineParser : public TestFixture { "path/sub\n" "path2/sub1\n"); const char * const argv[] = {"cppcheck", "--includes-file=includes.txt", "file.cpp"}; - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(2, settings->includePaths.size()); auto it = settings->includePaths.cbegin(); ASSERT_EQUALS("path/sub/", *it++); @@ -716,7 +727,7 @@ class TestCmdlineParser : public TestFixture { void includesFileNoFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--includes-file=fileThatDoesNotExist.txt", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unable to open includes file at 'fileThatDoesNotExist.txt'\n", logger->str()); } @@ -727,7 +738,7 @@ class TestCmdlineParser : public TestFixture { "path2/sub1\n"); const char * const argv[] = {"cppcheck", "--config-excludes-file=excludes.txt", "file.cpp"}; settings->configExcludePaths.clear(); - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(2, settings->configExcludePaths.size()); auto it = settings->configExcludePaths.cbegin(); ASSERT_EQUALS("path/sub/", *it++); @@ -737,14 +748,14 @@ class TestCmdlineParser : public TestFixture { void configExcludesFileNoFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--config-excludes-file=fileThatDoesNotExist.txt", "file.cpp"}; - ASSERT_EQUALS( false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unable to open config excludes file at 'fileThatDoesNotExist.txt'\n", logger->str()); } void enabledAll() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=all", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->severity.isEnabled(Severity::style)); ASSERT(settings->severity.isEnabled(Severity::warning)); ASSERT(settings->checks.isEnabled(Checks::unusedFunction)); @@ -755,7 +766,7 @@ class TestCmdlineParser : public TestFixture { void enabledStyle() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=style", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->severity.isEnabled(Severity::style)); ASSERT(settings->severity.isEnabled(Severity::warning)); ASSERT(settings->severity.isEnabled(Severity::performance)); @@ -767,7 +778,7 @@ class TestCmdlineParser : public TestFixture { void enabledPerformance() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=performance", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(!settings->severity.isEnabled(Severity::style)); ASSERT(!settings->severity.isEnabled(Severity::warning)); ASSERT(settings->severity.isEnabled(Severity::performance)); @@ -779,7 +790,7 @@ class TestCmdlineParser : public TestFixture { void enabledPortability() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=portability", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(!settings->severity.isEnabled(Severity::style)); ASSERT(!settings->severity.isEnabled(Severity::warning)); ASSERT(!settings->severity.isEnabled(Severity::performance)); @@ -791,7 +802,7 @@ class TestCmdlineParser : public TestFixture { void enabledInformation() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=information", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->severity.isEnabled(Severity::information)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); ASSERT_EQUALS("cppcheck: '--enable=information' will no longer implicitly enable 'missingInclude' starting with 2.16. Please enable it explicitly if you require it.\n", logger->str()); @@ -800,14 +811,14 @@ class TestCmdlineParser : public TestFixture { void enabledUnusedFunction() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=unusedFunction", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->checks.isEnabled(Checks::unusedFunction)); } void enabledMissingInclude() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=missingInclude", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); } @@ -815,7 +826,7 @@ class TestCmdlineParser : public TestFixture { void enabledInternal() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=internal", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->checks.isEnabled(Checks::internalCheck)); } #endif @@ -823,7 +834,7 @@ class TestCmdlineParser : public TestFixture { void enabledMultiple() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=missingInclude,portability,warning", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(!settings->severity.isEnabled(Severity::style)); ASSERT(settings->severity.isEnabled(Severity::warning)); ASSERT(!settings->severity.isEnabled(Severity::performance)); @@ -835,21 +846,21 @@ class TestCmdlineParser : public TestFixture { void enabledInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=warning,missingIncludeSystem,style", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --enable parameter with the unknown name 'missingIncludeSystem'\n", logger->str()); } void enabledError() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=error", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --enable parameter with the unknown name 'error'\n", logger->str()); } void enabledEmpty() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --enable parameter is empty\n", logger->str()); } @@ -859,7 +870,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--enable=all", "--disable=all", "file.cpp"}; settings->severity.clear(); settings->checks.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::error)); ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::warning)); ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::style)); @@ -876,7 +887,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--enable=all", "--disable=style", "--disable=unusedFunction", "file.cpp"}; settings->severity.clear(); settings->checks.clear(); - ASSERT(parser->parseFromArgs(5, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(5, argv)); ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::error)); ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning)); ASSERT_EQUALS(false, settings->severity.isEnabled(Severity::style)); @@ -894,7 +905,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--enable=style", "--disable=performance", "--enable=unusedFunction", "file.cpp"}; settings->severity.clear(); settings->checks.clear(); - ASSERT(parser->parseFromArgs(5, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(5, argv)); ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::error)); ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::warning)); ASSERT_EQUALS(true, settings->severity.isEnabled(Severity::style)); @@ -909,7 +920,7 @@ class TestCmdlineParser : public TestFixture { void disableInformationPartial() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=information", "--disable=missingInclude", "file.cpp"}; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT(settings->severity.isEnabled(Severity::information)); ASSERT(!settings->checks.isEnabled(Checks::missingInclude)); ASSERT_EQUALS("cppcheck: '--enable=information' will no longer implicitly enable 'missingInclude' starting with 2.16. Please enable it explicitly if you require it.\n", logger->str()); @@ -918,7 +929,7 @@ class TestCmdlineParser : public TestFixture { void disableInformationPartial2() { REDIRECT; const char * const argv[] = {"cppcheck", "--enable=missingInclude", "--disable=information", "file.cpp"}; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT(!settings->severity.isEnabled(Severity::information)); ASSERT(settings->checks.isEnabled(Checks::missingInclude)); } @@ -926,21 +937,21 @@ class TestCmdlineParser : public TestFixture { void disableInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--disable=leaks", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --disable parameter with the unknown name 'leaks'\n", logger->str()); } void disableError() { REDIRECT; const char * const argv[] = {"cppcheck", "--disable=error", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --disable parameter with the unknown name 'error'\n", logger->str()); } void disableEmpty() { REDIRECT; const char * const argv[] = {"cppcheck", "--disable=", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --disable parameter is empty\n", logger->str()); } @@ -948,7 +959,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--inconclusive", "file.cpp"}; settings->certainty.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->certainty.isEnabled(Certainty::inconclusive)); } @@ -956,7 +967,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--error-exitcode=5", "file.cpp"}; settings->exitCode = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(5, settings->exitCode); } @@ -964,7 +975,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--error-exitcode=", "file.cpp"}; // Fails since exit code not given - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str()); } @@ -972,14 +983,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--error-exitcode=foo", "file.cpp"}; // Fails since invalid exit code - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str()); } void exitcodeSuppressionsOld() { REDIRECT; const char * const argv[] = {"cppcheck", "--exitcode-suppressions", "suppr.txt", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exitcode-suppressions\".\n", logger->str()); } @@ -989,7 +1000,7 @@ class TestCmdlineParser : public TestFixture { "uninitvar\n" "unusedFunction\n"); const char * const argv[] = {"cppcheck", "--exitcode-suppressions=suppr.txt", "file.cpp"}; - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(2, settings->nofail.getSuppressions().size()); auto it = settings->nofail.getSuppressions().cbegin(); ASSERT_EQUALS("uninitvar", (it++)->errorId); @@ -999,7 +1010,7 @@ class TestCmdlineParser : public TestFixture { void exitcodeSuppressionsNoFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--exitcode-suppressions", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exitcode-suppressions\".\n", logger->str()); } @@ -1009,7 +1020,7 @@ class TestCmdlineParser : public TestFixture { "file1.c\n" "file2.cpp\n"); const char * const argv[] = {"cppcheck", "--file-list=files.txt", "file.cpp"}; - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(3, parser->getPathNames().size()); auto it = parser->getPathNames().cbegin(); ASSERT_EQUALS("file1.c", *it++); @@ -1020,7 +1031,7 @@ class TestCmdlineParser : public TestFixture { void fileListNoFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--file-list=files.txt", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: couldn't open the file: \"files.txt\".\n", logger->str()); } @@ -1035,7 +1046,7 @@ class TestCmdlineParser : public TestFixture { void fileListInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--file-list", "files.txt", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--file-list\".\n", logger->str()); } @@ -1043,7 +1054,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--inline-suppr", "file.cpp"}; settings->inlineSuppressions = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->inlineSuppressions); } @@ -1051,7 +1062,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-j", "3", "file.cpp"}; settings->jobs = 0; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(3, settings->jobs); } @@ -1059,7 +1070,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-j3", "file.cpp"}; settings->jobs = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(3, settings->jobs); } @@ -1067,7 +1078,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-j", "file.cpp"}; // Fails since -j is missing thread count - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str()); } @@ -1075,21 +1086,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-j", "e", "file.cpp"}; // Fails since invalid count given for -j - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str()); } void jobsNoJobs() { REDIRECT; const char * const argv[] = {"cppcheck", "-j0", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument for '-j' must be greater than 0.\n", logger->str()); } void jobsTooBig() { REDIRECT; const char * const argv[] = {"cppcheck", "-j1025", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument for '-j' is allowed to be 1024 at max.\n", logger->str()); } @@ -1098,7 +1109,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "-f", "--max-configs=12", "file.cpp"}; settings->force = false; settings->maxConfigs = 0; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(12, settings->maxConfigs); ASSERT_EQUALS(false, settings->force); } @@ -1107,7 +1118,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--max-configs=", "file.cpp"}; // Fails since --max-configs= is missing limit - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str()); } @@ -1115,7 +1126,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--max-configs=e", "file.cpp"}; // Fails since invalid count given for --max-configs= - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str()); } @@ -1123,7 +1134,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--max-configs=0", "file.cpp"}; // Fails since limit must be greater than 0 - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' must be greater than 0.\n", logger->str()); } @@ -1131,7 +1142,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--report-progress", "file.cpp"}; settings->reportProgress = -1; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(10, settings->reportProgress); } @@ -1139,7 +1150,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--report-progress=", "file.cpp"}; settings->reportProgress = -1; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' is not valid - not an integer.\n", logger->str()); } @@ -1147,7 +1158,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--report-progress=-1", "file.cpp"}; settings->reportProgress = -1; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' needs to be a positive integer.\n", logger->str()); } @@ -1155,7 +1166,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--report-progress=0", "file.cpp"}; settings->reportProgress = -1; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(0, settings->reportProgress); } @@ -1163,7 +1174,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--report-progress=1", "file.cpp"}; settings->reportProgress = -1; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->reportProgress); } @@ -1171,7 +1182,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--std=c99", "file.cpp"}; settings->standards.c = Standards::C89; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->standards.c == Standards::C99); } @@ -1179,21 +1190,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--std=c++11", "file.cpp"}; settings->standards.cpp = Standards::CPP03; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->standards.cpp == Standards::CPP11); } void stdunknown1() { REDIRECT; const char *const argv[] = {"cppcheck", "--std=d++11", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unknown --std value 'd++11'\n", logger->str()); } void stdunknown2() { REDIRECT; const char *const argv[] = {"cppcheck", "--std=cplusplus11", "file.cpp"}; - TODO_ASSERT(!parser->parseFromArgs(3, argv)); + TODO_ASSERT_EQUALS(static_cast(CmdLineParser::Result::Fail), static_cast(CmdLineParser::Result::Success), static_cast(parser->parseFromArgs(3, argv))); TODO_ASSERT_EQUALS("cppcheck: error: unknown --std value 'cplusplus11'\n", "", logger->str()); } @@ -1201,7 +1212,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win64", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Win64, settings->platform.type); } @@ -1209,7 +1220,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win32A", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Win32A, settings->platform.type); } @@ -1217,7 +1228,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win32W", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Win32W, settings->platform.type); } @@ -1225,7 +1236,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix32", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type); } @@ -1233,7 +1244,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix32-unsigned", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type); } @@ -1241,7 +1252,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix64", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type); } @@ -1249,7 +1260,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix64-unsigned", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type); } @@ -1257,7 +1268,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=native", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Native, settings->platform.type); } @@ -1265,7 +1276,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unspecified", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Native)); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::Unspecified, settings->platform.type); } @@ -1273,14 +1284,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=avr8", "file.cpp"}; ASSERT(settings->platform.set(Platform::Type::Unspecified)); - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(Platform::Type::File, settings->platform.type); } void platformUnknown() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win128", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized platform: 'win128'.\n", logger->str()); } @@ -1288,7 +1299,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--plist-output=", "file.cpp"}; settings->plistOutput = ""; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->plistOutput == "./"); } @@ -1296,14 +1307,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--plist-output=./cppcheck_reports", "file.cpp"}; // Fails since folder pointed by --plist-output= does not exist - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: plist folder does not exist: 'cppcheck_reports'.\n", logger->str()); } void suppressionsOld() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppressions", "suppr.txt", "file.cpp"}; - ASSERT(!parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--suppressions\".\n", logger->str()); } @@ -1313,7 +1324,7 @@ class TestCmdlineParser : public TestFixture { "uninitvar\n" "unusedFunction\n"); const char * const argv[] = {"cppcheck", "--suppressions-list=suppr.txt", "file.cpp"}; - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(2, settings->nomsg.getSuppressions().size()); auto it = settings->nomsg.getSuppressions().cbegin(); ASSERT_EQUALS("uninitvar", (it++)->errorId); @@ -1323,21 +1334,21 @@ class TestCmdlineParser : public TestFixture { void suppressionsNoFile1() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppressions-list=", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(false, logger->str().find("If you want to pass two files") != std::string::npos); } void suppressionsNoFile2() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppressions-list=a.suppr,b.suppr", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, logger->str().find("If you want to pass two files") != std::string::npos); } void suppressionsNoFile3() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppressions-list=a.suppr b.suppr", "file.cpp"}; - ASSERT_EQUALS(false, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, logger->str().find("If you want to pass two files") != std::string::npos); } @@ -1352,21 +1363,21 @@ class TestCmdlineParser : public TestFixture { void suppressionSingle() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1))); } void suppressionSingleFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar:file.cpp", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); } void suppressionTwo() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar,noConstructor", "file.cpp"}; - TODO_ASSERT_EQUALS(true, false, parser->parseFromArgs(3, argv)); + TODO_ASSERT_EQUALS(static_cast(CmdLineParser::Result::Success), static_cast(CmdLineParser::Result::Fail), static_cast(parser->parseFromArgs(3, argv))); TODO_ASSERT_EQUALS(true, false, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); TODO_ASSERT_EQUALS(true, false, settings->nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); TODO_ASSERT_EQUALS("", "cppcheck: error: Failed to add suppression. Invalid id \"uninitvar,noConstructor\"\n", logger->str()); @@ -1375,7 +1386,7 @@ class TestCmdlineParser : public TestFixture { void suppressionTwoSeparate() { REDIRECT; const char * const argv[] = {"cppcheck", "--suppress=uninitvar", "--suppress=noConstructor", "file.cpp"}; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("uninitvar", "file.cpp", 1U))); ASSERT_EQUALS(true, settings->nomsg.isSuppressed(errorMessage("noConstructor", "file.cpp", 1U))); } @@ -1385,7 +1396,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template={file}:{line},{severity},{id},{message}", "--template-location={file}:{line}:{column} {info}", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("{file}:{line},{severity},{id},{message}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column} {info}", settings->templateLocation); } @@ -1395,7 +1406,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=gcc", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: warning: {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); } @@ -1405,7 +1416,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=vs", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}({line}): {severity}: {message}", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); } @@ -1415,7 +1426,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=edit", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file} +{line}: {severity}: {message}", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); } @@ -1425,7 +1436,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=cppcheck1", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{callstack}: ({severity}{inconclusive:, inconclusive}) {message}", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); } @@ -1435,7 +1446,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=daca2", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}", settings->templateLocation); ASSERT_EQUALS(true, settings->daca); @@ -1446,7 +1457,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=selfcheck", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); } @@ -1457,7 +1468,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--template=selfchek", "file.cpp"}; settings->templateFormat.clear(); settings->templateLocation.clear(); - TODO_ASSERT(!parser->parseFromArgs(3, argv)); + TODO_ASSERT_EQUALS(static_cast(CmdLineParser::Result::Fail), static_cast(CmdLineParser::Result::Success), static_cast(parser->parseFromArgs(3, argv))); ASSERT_EQUALS("selfchek", settings->templateFormat); ASSERT_EQUALS("", settings->templateLocation); } @@ -1467,7 +1478,7 @@ class TestCmdlineParser : public TestFixture { settings->templateFormat.clear(); settings->templateLocation.clear(); const char* const argv[] = { "cppcheck", "--template", "file.cpp" }; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--template\".\n", logger->str()); } @@ -1478,7 +1489,7 @@ class TestCmdlineParser : public TestFixture { settings->templateFormat.clear(); settings->templateLocation.clear(); const char* const argv[] = { "cppcheck", "--template=", "file.cpp" }; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); } @@ -1486,7 +1497,7 @@ class TestCmdlineParser : public TestFixture { void templateLocationInvalid() { REDIRECT; const char* const argv[] = { "cppcheck", "--template-location", "--template={file}", "file.cpp" }; - ASSERT(!parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--template-location\".\n", logger->str()); } @@ -1497,7 +1508,7 @@ class TestCmdlineParser : public TestFixture { settings->templateFormat.clear(); settings->templateLocation.clear(); const char* const argv[] = { "cppcheck", "--template-location=", "file.cpp" }; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("{file}:{line}:{column}: {inconclusive:}{severity}:{inconclusive: inconclusive:} {message} [{id}]\n{code}", settings->templateFormat); ASSERT_EQUALS("{file}:{line}:{column}: note: {info}\n{code}", settings->templateLocation); } @@ -1507,7 +1518,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--xml", "file.cpp"}; settings->xml_version = 1; settings->xml = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->xml); ASSERT_EQUALS(1, settings->xml_version); } @@ -1517,7 +1528,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--xml-version=2", "file.cpp"}; settings->xml_version = 1; settings->xml = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->xml); ASSERT_EQUALS(2, settings->xml_version); } @@ -1527,7 +1538,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--xml", "--xml-version=2", "file.cpp"}; settings->xml_version = 1; settings->xml = false; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT(settings->xml); ASSERT_EQUALS(2, settings->xml_version); } @@ -1537,7 +1548,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--xml-version=2", "--xml", "file.cpp"}; settings->xml_version = 1; settings->xml = false; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT(settings->xml); ASSERT_EQUALS(2, settings->xml_version); } @@ -1546,7 +1557,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--xml", "--xml-version=3", "file.cpp"}; // FAils since unknown XML format version - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: '--xml-version' can only be 2.\n", logger->str()); } @@ -1554,15 +1565,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"}; // FAils since unknown XML format version - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--xml-version=' is not valid - not an integer.\n", logger->str()); } void doc() { REDIRECT; const char * const argv[] = {"cppcheck", "--doc"}; - ASSERT(parser->parseFromArgs(2, argv)); - ASSERT(parser->exitAfterPrinting()); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT(startsWith(logger->str(), "## ")); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -1571,7 +1581,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_SUMMARY); } @@ -1579,7 +1589,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=file", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE); } @@ -1587,7 +1597,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=file-total", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_FILE_TOTAL); } @@ -1595,7 +1605,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=top5", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE); ASSERT_EQUALS("cppcheck: --showtime=top5 is deprecated and will be removed in Cppcheck 2.14. Please use --showtime=top5_file or --showtime=top5_summary instead.\n", logger->str()); } @@ -1604,7 +1614,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=top5_file", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_FILE); } @@ -1612,7 +1622,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=top5_summary", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_NONE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_TOP5_SUMMARY); } @@ -1620,28 +1630,28 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=none", "file.cpp"}; settings->showtime = SHOWTIME_MODES::SHOWTIME_FILE; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->showtime == SHOWTIME_MODES::SHOWTIME_NONE); } void showtimeEmpty() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: no mode provided for --showtime\n", logger->str()); } void showtimeInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=top10", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized --showtime mode: 'top10'. Supported modes: file, file-total, summary, top5, top5_file, top5_summary.\n", logger->str()); } void errorlist() { REDIRECT; const char * const argv[] = {"cppcheck", "--errorlist"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger ASSERT(startsWith(GET_REDIRECT_OUTPUT, "\n")); @@ -1653,7 +1663,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-i"}; // Fails since no ignored path given - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-i' is missing.\n", logger->str()); } @@ -1663,7 +1673,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--exception-handling", "file.cpp"}; settings->exceptionHandling = false; CppCheckExecutor::setExceptionOutput(stderr); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->exceptionHandling); ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput()); } @@ -1673,7 +1683,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--exception-handling=stderr", "file.cpp"}; settings->exceptionHandling = false; CppCheckExecutor::setExceptionOutput(stdout); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->exceptionHandling); ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput()); } @@ -1683,7 +1693,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--exception-handling=stdout", "file.cpp"}; settings->exceptionHandling = false; CppCheckExecutor::setExceptionOutput(stderr); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->exceptionHandling); ASSERT_EQUALS(stdout, CppCheckExecutor::getExceptionOutput()); } @@ -1691,28 +1701,28 @@ class TestCmdlineParser : public TestFixture { void exceptionhandlingInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--exception-handling=exfile"}; - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: invalid '--exception-handling' argument\n", logger->str()); } void exceptionhandlingInvalid2() { REDIRECT; const char * const argv[] = {"cppcheck", "--exception-handling-foo"}; - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exception-handling-foo\".\n", logger->str()); } #else void exceptionhandlingNotSupported() { REDIRECT; const char * const argv[] = {"cppcheck", "--exception-handling", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled.\n", logger->str()); } void exceptionhandlingNotSupported2() { REDIRECT; const char * const argv[] = {"cppcheck", "--exception-handling=stderr", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled.\n", logger->str()); } #endif @@ -1722,7 +1732,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--clang", "file.cpp"}; settings->clang = false; settings->clangExecutable = "exe"; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->clang); ASSERT_EQUALS("exe", settings->clangExecutable); } @@ -1732,7 +1742,7 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--clang=clang-14", "file.cpp"}; settings->clang = false; settings->clangExecutable = ""; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT(settings->clang); ASSERT_EQUALS("clang-14", settings->clangExecutable); } @@ -1740,7 +1750,7 @@ class TestCmdlineParser : public TestFixture { void clangInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--clang-foo"}; - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--clang-foo\".\n", logger->str()); } @@ -1748,7 +1758,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=0", "file.cpp"}; settings->valueFlowMaxIterations = SIZE_MAX; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(0, settings->valueFlowMaxIterations); } @@ -1756,28 +1766,28 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=11", "file.cpp"}; settings->valueFlowMaxIterations = SIZE_MAX; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(11, settings->valueFlowMaxIterations); } void valueFlowMaxIterationsInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--valueflow-max-iterations"}; - ASSERT(!parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--valueflow-max-iterations\".\n", logger->str()); } void valueFlowMaxIterationsInvalid2() { REDIRECT; const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"}; - ASSERT(!parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - not an integer.\n", logger->str()); } void valueFlowMaxIterationsInvalid3() { REDIRECT; const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=-1"}; - ASSERT(!parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - needs to be positive.\n", logger->str()); } @@ -1785,21 +1795,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--checks-max-time=12", "file.cpp"}; settings->checksMaxTime = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->checksMaxTime); } void checksMaxTime2() { REDIRECT; const char * const argv[] = {"cppcheck", "--checks-max-time=-1", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' needs to be a positive integer.\n", logger->str()); } void checksMaxTimeInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--checks-max-time=one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' is not valid - not an integer.\n", logger->str()); } @@ -1808,7 +1818,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-l", "12", "file.cpp"}; settings->loadAverage = 0; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(12, settings->loadAverage); } @@ -1816,21 +1826,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-l12", "file.cpp"}; settings->loadAverage = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->loadAverage); } void loadAverageInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "-l", "one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer.\n", logger->str()); } #else void loadAverageNotSupported() { REDIRECT; const char * const argv[] = {"cppcheck", "-l", "12", "file.cpp"}; - ASSERT(!parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: Option -l cannot be used as Cppcheck has not been built with fork threading model.\n", logger->str()); } #endif @@ -1839,14 +1849,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--max-ctu-depth=12", "file.cpp"}; settings->maxCtuDepth = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->maxCtuDepth); } void maxCtuDepthInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--max-ctu-depth=one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--max-ctu-depth=' is not valid - not an integer.\n", logger->str()); } @@ -1854,14 +1864,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--performance-valueflow-max-time=12", "file.cpp"}; settings->performanceValueFlowMaxTime = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->performanceValueFlowMaxTime); } void performanceValueflowMaxTimeInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--performance-valueflow-max-time=one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-time=' is not valid - not an integer.\n", logger->str()); } @@ -1869,14 +1879,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--performance-valueflow-max-if-count=12", "file.cpp"}; settings->performanceValueFlowMaxIfCount = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->performanceValueFlowMaxIfCount); } void performanceValueFlowMaxIfCountInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--performance-valueflow-max-if-count=one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer.\n", logger->str()); } @@ -1884,21 +1894,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--template-max-time=12", "file.cpp"}; settings->templateMaxTime = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->templateMaxTime); } void templateMaxTimeInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--template-max-time=one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - not an integer.\n", logger->str()); } void templateMaxTimeInvalid2() { REDIRECT; const char * const argv[] = {"cppcheck", "--template-max-time=-1", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - needs to be positive.\n", logger->str()); } @@ -1906,7 +1916,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--typedef-max-time=12", "file.cpp"}; settings->typedefMaxTime = 0; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->typedefMaxTime); ASSERT_EQUALS("", logger->str()); } @@ -1914,14 +1924,14 @@ class TestCmdlineParser : public TestFixture { void typedefMaxTimeInvalid() { REDIRECT; const char * const argv[] = {"cppcheck", "--typedef-max-time=one", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - not an integer.\n", logger->str()); } void typedefMaxTimeInvalid2() { REDIRECT; const char * const argv[] = {"cppcheck", "--typedef-max-time=-1", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - needs to be positive.\n", logger->str()); } @@ -1934,7 +1944,7 @@ class TestCmdlineParser : public TestFixture { "\n" ""); const char * const argv[] = {"cppcheck", "--project=project.cppcheck"}; - ASSERT(parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, parser->getPathNames().size()); auto it = parser->getPathNames().cbegin(); ASSERT_EQUALS("dir", *it); @@ -1944,7 +1954,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file("project.cppcheck", ""); const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "--project=project.cppcheck", "file.cpp"}; - ASSERT(!parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: multiple --project options are not supported.\n", logger->str()); } @@ -1952,28 +1962,28 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file("project.cppcheck", ""); const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: --project cannot be used in conjunction with source files.\n", logger->str()); } void projectEmpty() { REDIRECT; const char * const argv[] = {"cppcheck", "--project=", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: failed to open project ''. The file does not exist.\n", logger->str()); } void projectMissing() { REDIRECT; const char * const argv[] = {"cppcheck", "--project=project.cppcheck", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: failed to open project 'project.cppcheck'. The file does not exist.\n", logger->str()); } void projectNoPaths() { ScopedFile file("project.cppcheck", ""); const char * const argv[] = {"cppcheck", "--project=project.cppcheck"}; - ASSERT(!parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str()); } @@ -1981,7 +1991,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--addon=misra", "file.cpp"}; settings->addons.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->addons.size()); ASSERT_EQUALS("misra", *settings->addons.cbegin()); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); @@ -2002,7 +2012,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--fsigned-char", "file.cpp"}; settings->platform.defaultSign = '\0'; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS('s', settings->platform.defaultSign); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -2011,7 +2021,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=avr8", "--fsigned-char", "file.cpp"}; settings->platform.defaultSign = '\0'; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS('s', settings->platform.defaultSign); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -2020,7 +2030,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--funsigned-char", "file.cpp"}; settings->platform.defaultSign = '\0'; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS('u', settings->platform.defaultSign); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -2029,7 +2039,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=mips32", "--funsigned-char", "file.cpp"}; settings->platform.defaultSign = '\0'; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS('u', settings->platform.defaultSign); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -2038,7 +2048,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--fsigned-char", "--funsigned-char", "file.cpp"}; settings->platform.defaultSign = '\0'; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS('u', settings->platform.defaultSign); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } @@ -2047,7 +2057,7 @@ class TestCmdlineParser : public TestFixture { void rule() { REDIRECT; const char * const argv[] = {"cppcheck", "--rule=.+", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->rules.size()); auto it = settings->rules.cbegin(); ASSERT_EQUALS(".+", it->pattern); @@ -2056,7 +2066,7 @@ class TestCmdlineParser : public TestFixture { void ruleNotSupported() { REDIRECT; const char * const argv[] = {"cppcheck", "--rule=.+", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: Option --rule cannot be used as Cppcheck has not been built with rules support.\n", logger->str()); } #endif @@ -2071,7 +2081,7 @@ class TestCmdlineParser : public TestFixture { "\n" ""); const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->rules.size()); auto it = settings->rules.cbegin(); ASSERT_EQUALS(".+", it->pattern); @@ -2080,14 +2090,14 @@ class TestCmdlineParser : public TestFixture { void ruleFileEmpty() { REDIRECT; const char * const argv[] = {"cppcheck", "--rule-file=", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unable to load rule-file '' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str()); } void ruleFileMissing() { REDIRECT; const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str()); } @@ -2095,14 +2105,14 @@ class TestCmdlineParser : public TestFixture { REDIRECT; ScopedFile file("rule.xml", ""); const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' (XML_ERROR_EMPTY_DOCUMENT).\n", logger->str()); } #else void ruleFileNotSupported() { REDIRECT; const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: Option --rule-file cannot be used as Cppcheck has not been built with rules support.\n", logger->str()); } #endif @@ -2111,7 +2121,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--library=posix", "file.cpp"}; settings->libraries.clear(); - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->libraries.size()); ASSERT_EQUALS("posix", *settings->libraries.cbegin()); ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); @@ -2121,7 +2131,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--library=posix2", "file.cpp"}; settings->libraries.clear(); - ASSERT(!parser->fillSettingsFromArgs(3, argv)); + ASSERT_EQUALS(false, parser->fillSettingsFromArgs(3, argv)); ASSERT_EQUALS(1, settings->libraries.size()); ASSERT_EQUALS("posix2", *settings->libraries.cbegin()); ASSERT_EQUALS("cppcheck: Failed to load library configuration file 'posix2'. File not found\n", logger->str()); @@ -2131,7 +2141,7 @@ class TestCmdlineParser : public TestFixture { void ignorepaths1() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); } @@ -2139,7 +2149,7 @@ class TestCmdlineParser : public TestFixture { void ignorepaths2() { REDIRECT; const char * const argv[] = {"cppcheck", "-i", "src", "file.cpp"}; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); } @@ -2147,7 +2157,7 @@ class TestCmdlineParser : public TestFixture { void ignorepaths3() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc", "-imodule", "file.cpp"}; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(2, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]); @@ -2156,7 +2166,7 @@ class TestCmdlineParser : public TestFixture { void ignorepaths4() { REDIRECT; const char * const argv[] = {"cppcheck", "-i", "src", "-i", "module", "file.cpp"}; - ASSERT(parser->parseFromArgs(6, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(6, argv)); ASSERT_EQUALS(2, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src", parser->getIgnoredPaths()[0]); ASSERT_EQUALS("module", parser->getIgnoredPaths()[1]); @@ -2165,7 +2175,7 @@ class TestCmdlineParser : public TestFixture { void ignorefilepaths1() { REDIRECT; const char * const argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("foo.cpp", parser->getIgnoredPaths()[0]); } @@ -2173,7 +2183,7 @@ class TestCmdlineParser : public TestFixture { void ignorefilepaths2() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, parser->getIgnoredPaths().size()); ASSERT_EQUALS("src/foo.cpp", parser->getIgnoredPaths()[0]); } @@ -2182,21 +2192,21 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--check-config", "file.cpp"}; settings->checkConfiguration = false; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->checkConfiguration); } void unknownParam() { REDIRECT; const char * const argv[] = {"cppcheck", "--foo", "file.cpp"}; - ASSERT(!parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--foo\".\n", logger->str()); } void undefs() { REDIRECT; const char * const argv[] = {"cppcheck", "-U_WIN32", "file.cpp"}; - ASSERT(parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->userUndefs.size()); ASSERT(settings->userUndefs.find("_WIN32") != settings->userUndefs.end()); } @@ -2204,7 +2214,7 @@ class TestCmdlineParser : public TestFixture { void undefs2() { REDIRECT; const char * const argv[] = {"cppcheck", "-U_WIN32", "-UNODEBUG", "file.cpp"}; - ASSERT(parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS(2, settings->userUndefs.size()); ASSERT(settings->userUndefs.find("_WIN32") != settings->userUndefs.end()); ASSERT(settings->userUndefs.find("NODEBUG") != settings->userUndefs.end()); @@ -2214,7 +2224,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-U"}; // Fails since -U has no param - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-U' is missing.\n", logger->str()); } @@ -2222,7 +2232,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-U", "-v", "file.cpp"}; // Fails since -U has no param - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-U' is missing.\n", logger->str()); } @@ -2230,27 +2240,27 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "-U", "--quiet", "file.cpp"}; // Fails since -U has no param - ASSERT_EQUALS(false, parser->parseFromArgs(4, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("cppcheck: error: argument to '-U' is missing.\n", logger->str()); } void cppcheckBuildDirExistent() { REDIRECT; const char * const argv[] = {"cppcheck", "--cppcheck-build-dir=.", "file.cpp"}; - ASSERT_EQUALS(true, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); } void cppcheckBuildDirNonExistent() { REDIRECT; const char * const argv[] = {"cppcheck", "--cppcheck-build-dir=non-existent-path"}; - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: Directory 'non-existent-path' specified by --cppcheck-build-dir argument has to be existent.\n", logger->str()); } void cppcheckBuildDirEmpty() { REDIRECT; const char * const argv[] = {"cppcheck", "--cppcheck-build-dir="}; - ASSERT_EQUALS(false, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: Directory '' specified by --cppcheck-build-dir argument has to be existent.\n", logger->str()); } }; From a8eb9716705cbe883d08fc00ee6d7b0662b81276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 27 Nov 2023 12:06:33 +0100 Subject: [PATCH 28/40] CI-unixish.yml: removed usage of qmake from selfcheck (#5531) We deprecated qmake so we should no longer use it ourselves. --- .github/workflows/CI-unixish.yml | 18 ++++++++---------- .selfcheck_suppressions | 12 ++++++------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.github/workflows/CI-unixish.yml b/.github/workflows/CI-unixish.yml index 24d4de1faf5..af056b56058 100644 --- a/.github/workflows/CI-unixish.yml +++ b/.github/workflows/CI-unixish.yml @@ -480,17 +480,15 @@ jobs: make -j$(nproc) -s CPPFLAGS="-DCHECK_INTERNAL" CXXFLAGS="-g -O2 -w -DHAVE_BOOST" MATCHCOMPILER=yes VERIFY=1 # TODO: update to Qt6 - - name: Generate UI files + - name: CMake run: | - pushd gui - qmake CONFIG+=debug HAVE_QCHART=yes - make -j$(nproc) compiler_uic_make_all mocables + cmake -S . -B cmake.output -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DUSE_MATCHCOMPILER=Verify -DENABLE_CHECK_INTERNAL=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On - - name: Generate triage UI files + - name: Generate dependencies run: | - pushd tools/triage - qmake CONFIG+=debug - make -j$(nproc) compiler_uic_make_all mocables + # make sure auto-generated GUI files exist + make -C cmake.output autogen + make -C cmake.output gui-build-deps triage-build-ui-deps - name: Self check run: | @@ -512,9 +510,9 @@ jobs: ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b1 --addon=naming.json cli lib || ec=1 # check gui with qt settings mkdir b2 - ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b2 -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Igui/temp -Igui gui/*.cpp gui/temp/*.cpp || ec=1 + ./cppcheck $selfcheck_options $cppcheck_options --cppcheck-build-dir=b2 -DQT_VERSION=0x050000 -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt --addon=naming.json -Icmake.output/gui -Igui gui/*.cpp cmake.output/gui || ec=1 # self check test and tools ./cppcheck $selfcheck_options $cppcheck_options -Icli test/*.cpp tools/*.cpp || ec=1 # triage - ./cppcheck $selfcheck_options $cppcheck_options -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt -Itools/triage/temp -Igui tools/triage/*.cpp tools/triage/temp/*.cpp || ec=1 + ./cppcheck $selfcheck_options $cppcheck_options -DQ_MOC_OUTPUT_REVISION=67 -DQT_CHARTS_LIB --library=qt -Icmake.output/tools/triage -Igui tools/triage/*.cpp cmake.output/tools/triage || ec=1 exit $ec diff --git a/.selfcheck_suppressions b/.selfcheck_suppressions index 872a521be37..b6478d8717a 100644 --- a/.selfcheck_suppressions +++ b/.selfcheck_suppressions @@ -4,16 +4,16 @@ bitwiseOnBoolean # temporary suppressions - fix the warnings! simplifyUsing:lib/valueptr.h -simplifyUsing:gui/temp/moc_*.cpp varid0:gui/projectfile.cpp +naming-privateMemberVariable:gui/test/cppchecklibrarydata/testcppchecklibrarydata.h templateInstantiation +symbolDatabaseWarning:*/moc_*.cpp +simplifyUsing:*/moc_*.cpp # warnings in Qt generated code we cannot fix -funcArgNamesDifferent:gui/temp/moc_*.cpp -naming-varname:gui/temp/ui_*.h -naming-varname:cmake.output/gui/ui_*.h -functionStatic:gui/temp/ui_fileview.h -functionStatic:cmake.output/gui/ui_fileview.h +funcArgNamesDifferent:*/moc_*.cpp +naming-varname:*/ui_*.h +functionStatic:*/ui_fileview.h # --debug-warnings suppressions valueFlowBailout From db661051284a7a8bde30f99004ddf8542a37b0aa Mon Sep 17 00:00:00 2001 From: Swasti Shrivastava <37058682+swasti16@users.noreply.github.com> Date: Mon, 27 Nov 2023 22:58:53 +0530 Subject: [PATCH 29/40] Fix #10854: False positive: misra-c2012-9.2: inner union (#5693) --- addons/cppcheckdata.py | 4 ++++ addons/misra_9.py | 20 +++++++++++++++++++- addons/test/misra/misra-test.c | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index d8bfcddd12f..9bfd45972f8 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -569,6 +569,7 @@ class Scope: function = None nestedInId = None nestedIn = None + nestedList = None type = None isExecutable = None varlistId = None @@ -586,6 +587,7 @@ def __init__(self, element): self.bodyEnd = None self.nestedInId = element.get('nestedIn') self.nestedIn = None + self.nestedList = list() self.type = element.get('type') self.definedType = element.get('definedType') self.isExecutable = (self.type in ('Function', 'If', 'Else', 'For', 'While', 'Do', @@ -606,6 +608,8 @@ def setId(self, IdMap): self.bodyStart = IdMap[self.bodyStartId] self.bodyEnd = IdMap[self.bodyEndId] self.nestedIn = IdMap[self.nestedInId] + if self.nestedIn: + self.nestedIn.nestedList.append(self) self.function = IdMap[self.functionId] for v in self.varlistId: value = IdMap.get(v) diff --git a/addons/misra_9.py b/addons/misra_9.py index b844170662e..f35becad7bf 100644 --- a/addons/misra_9.py +++ b/addons/misra_9.py @@ -500,11 +500,29 @@ def createRecordChildrenDefs(ed, var): child = ElementDef("pointer", var.nameToken, var.nameToken.valueType) ed.addChild(child) return + child_dict = {} for variable in valueType.typeScope.varlist: if variable is var: continue child = getElementDef(variable.nameToken) - ed.addChild(child) + child_dict[variable.nameToken] = child + for scopes in valueType.typeScope.nestedList: + varscope = False + if scopes.nestedIn == valueType.typeScope: + for variable in valueType.typeScope.varlist: + if variable.nameToken and variable.nameToken.valueType and variable.nameToken.valueType.typeScope == scopes: + varscope = True + break + if not varscope: + ed1 = ElementDef("record", scopes.Id, valueType) + for variable in scopes.varlist: + child = getElementDef(variable.nameToken) + ed1.addChild(child) + child_dict[scopes.bodyStart] = ed1 + sorted_keys = sorted(list(child_dict.keys()), key=lambda k: "%s %s %s" % (k.file, k.linenr, k.column)) + for _key in sorted_keys: + ed.addChild(child_dict[_key]) + def getElementByDesignator(ed, token): if not token.str in [ '.', '[' ]: diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 60295a837f1..e8168ed5fda 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -418,6 +418,21 @@ static void misra_8_14(char * restrict str) {(void)str;} // 8.14 struct S_9_3 { struct S_9_3* p; int x; }; struct S_9_3* s_9_3_array[] = { x, NULL }; // 8.4 +// #10854 +struct Entry_9_2{ + union{ // 19.2 + const int *p; + int x; + }; + int y; +}; + +static void misra_9_2_10854(void){ + struct Entry_9_2 e1[] = + { + {{ .x = 1 }, .y = 2 } + }; +} static void misra_9_empty_or_zero_initializers(void) { int a[2] = {}; // 9.2 int b[2][2] = {}; // 9.2 From 9dd729e9bec3d56daa4cbffdf8fd16aeadb9ec54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 29 Nov 2023 16:13:01 +0100 Subject: [PATCH 30/40] Fixed #12228 (GUI: Compliance report for Misra C 2012 is not working properly) (#5709) --- gui/compliancereportdialog.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/gui/compliancereportdialog.cpp b/gui/compliancereportdialog.cpp index daae1df064d..adcb25b4d6a 100644 --- a/gui/compliancereportdialog.cpp +++ b/gui/compliancereportdialog.cpp @@ -95,6 +95,18 @@ ComplianceReportDialog::ComplianceReportDialog(ProjectFile* projectFile, QString mUI->setupUi(this); mUI->mEditProjectName->setText(projectFile->getProjectName()); connect(mUI->buttonBox, &QDialogButtonBox::clicked, this, &ComplianceReportDialog::buttonClicked); + mUI->mCodingStandard->clear(); + if (projectFile->getCodingStandards().contains("misra-c-2023")) + mUI->mCodingStandard->addItem("Misra C 2023"); + else if (projectFile->getAddons().contains("misra")) + mUI->mCodingStandard->addItem("Misra C 2012"); + if (projectFile->getCodingStandards().contains("misra-c++-2008")) + mUI->mCodingStandard->addItem("Misra C++ 2008"); + if (projectFile->getCodingStandards().contains("cert-c-2016")) + mUI->mCodingStandard->addItem("Cert C"); + if (projectFile->getCodingStandards().contains("cert-c++-2016")) + mUI->mCodingStandard->addItem("Cert C++"); + mUI->mCodingStandard->addItems(projectFile->getCodingStandards()); } ComplianceReportDialog::~ComplianceReportDialog() @@ -197,8 +209,9 @@ void ComplianceReportDialog::save() QStringList args{"--project-name=" + projectName, "--project-version=" + projectVersion, - "--output-file=" + outFile, - "--suppressions=" + suppressions.join(",")}; + "--output-file=" + outFile}; + if (!suppressions.isEmpty()) + args << "--suppressions=" + suppressions.join(","); args << ("--" + std); @@ -215,4 +228,13 @@ void ComplianceReportDialog::save() process.start(appPath + "/compliance-report", args); #endif process.waitForFinished(); + const QString output = process.readAll(); + if (!output.isEmpty()) { + QMessageBox msg(QMessageBox::Critical, + tr("Save compliance report"), + output, + QMessageBox::Ok, + this); + msg.exec(); + } } From e2082267e2a693084e46685aecf2c5cea3a3428b Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 1 Dec 2023 10:03:43 +0100 Subject: [PATCH 31/40] Fix #12218: class and union (#5705) Co-authored-by: chrchr-github --- lib/tokenize.cpp | 2 +- test/testsimplifytypedef.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7358a088fe6..2d82e02cdad 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1947,7 +1947,7 @@ void Tokenizer::simplifyTypedefCpp() tok2->str(typeStart->str()); // restore qualification if it was removed - if (typeStart->str() == "struct" || structRemoved) { + if (Token::Match(typeStart, "class|struct|union") || structRemoved) { if (structRemoved) tok2 = tok2->previous(); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index d321026a384..8d3f0bb883c 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -3454,6 +3454,33 @@ class TestSimplifyTypedef : public TestFixture { " g(sizeof(struct N::S));\n" "}\n"; ASSERT_EQUALS("namespace N { struct S { } ; } void g ( int ) ; void f ( ) { g ( sizeof ( struct N :: S ) ) ; }", tok(code)); + + code = "namespace N {\n" + " typedef class C {} C;\n" + "}\n" + "void g(int);\n" + "void f() {\n" + " g(sizeof(class N::C));\n" + "}\n"; + ASSERT_EQUALS("namespace N { class C { } ; } void g ( int ) ; void f ( ) { g ( sizeof ( class N :: C ) ) ; }", tok(code)); + + code = "namespace N {\n" + " typedef union U {} U;\n" + "}\n" + "void g(int);\n" + "void f() {\n" + " g(sizeof(union N::U));\n" + "}\n"; + ASSERT_EQUALS("namespace N { union U { } ; } void g ( int ) ; void f ( ) { g ( sizeof ( union N :: U ) ) ; }", tok(code)); + + code = "namespace N {\n" + " typedef enum E {} E;\n" + "}\n" + "void g(int);\n" + "void f() {\n" + " g(sizeof(enum N::E));\n" + "}\n"; + ASSERT_EQUALS("namespace N { enum E { } ; } void g ( int ) ; void f ( ) { g ( sizeof ( enum N :: E ) ) ; }", tok(code)); } void simplifyTypedefFunction1() { From 831dc7c3ae7ee80db30cfa8c3376ff2f87a638c8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 1 Dec 2023 10:05:02 +0100 Subject: [PATCH 32/40] Fix #12225 Improve documentation of --library in the manual (#5706) --- man/manual.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/man/manual.md b/man/manual.md index b0a9a6088f4..bc710d6d947 100644 --- a/man/manual.md +++ b/man/manual.md @@ -954,11 +954,65 @@ This allows you to create and manage multiple configuration files for different # Library configuration -When external libraries are used, such as WinAPI, POSIX, gtk, Qt, etc, Cppcheck doesn't know how the external functions behave. Cppcheck then fails to detect various problems such as memory leaks, buffer overflows, possible null pointer dereferences, etc. But this can be fixed with configuration files. - -Cppcheck already contains configurations for several libraries. They can be loaded as described below. Note that the configuration for the standard libraries of C and C++, std.cfg, is always loaded by cppcheck. If you create or update a configuration file for a popular library, we would appreciate if you upload it to us. - -## Using your own custom .cfg file +When external libraries are used, such as WinAPI, POSIX, gtk, Qt, etc, Cppcheck has no information about functions, types, or macros contained in those libraries. Cppcheck then fails to detect various problems in the code, or might even abort the analysis. But this can be fixed by using the appropriate configuration files. + +Cppcheck already contains configurations for several libraries. They can be loaded as described below. Note that the configuration for the standard libraries of C and C++, std.cfg, is always loaded by cppcheck. If you create or update a configuration file for a popular library, we would appreciate if you supplied it to the cppcheck project. + +## Using a .cfg file + +To use a .cfg file shipped with cppcheck, pass the `--library=` option. The table below shows the currently existing libraries: +| .cfg file | Library | Comment | +| ------------- | ------------- | ------------- | +| avr.cfg | | +| bento4.cfg | [Bento4](http://www.bento4.com/) | +| boost.cfg | [Boost](http://www.boost.org/)| +| bsd.cfg | [*BSD](https://www.freebsd.org/) | +| cairo.cfg | [cairo](https://www.cairographics.org/) | +| cppcheck-lib.cfg | [Cppcheck](http://cppcheck.net/) | Used in selfcheck of the Cppcheck code base +| cppunit.cfg | [CppUnit](https://sourceforge.net/projects/cppunit/) | +| dpdk.cfg | | +| embedded_sql.cfg | | +| emscripten.cfg | | +| ginac.cfg | | +| gnu.cfg | [*nix](https://www.gnu.org/) | +| googletest.cfg | [GoogleTest](https://github.com/google/googletest) | +| gtk.cfg | [GTK](https://www.gtk.org/) | +| icu.cfg | | +| kde.cfg | [KDE](https://kde.org/) | +| libcerror.cfg | [libcerror](https://github.com/libyal/libcerror) | +| libcurl.cfg | [libcurl](https://curl.se/libcurl/) | +| libsigc++.cfg | [libsigc++](https://github.com/libsigcplusplus/libsigcplusplus) | +| lua.cfg | | +| mfc.cfg | [MFC](https://learn.microsoft.com/en-us/cpp/mfc/mfc-desktop-applications) | +| microsoft_atl.cfg | [ATL](https://learn.microsoft.com/en-us/cpp/atl/active-template-library-atl-concepts) | +| microsoft_sal.cfg | [SAL annotations](https://learn.microsoft.com/en-us/cpp/c-runtime-library/sal-annotations) | +| microsoft_unittest.cfg | [CppUnitTest](https://learn.microsoft.com/en-us/visualstudio/test/microsoft-visualstudio-testtools-cppunittestframework-api-reference) | +| motif.cfg | | +| nspr.cfg | | +| ntl.cfg | | +| opencv2.cfg | [OpenCV](https://opencv.org/) | +| opengl.cfg | [OpenGL](https://opengl.org/) | +| openmp.cfg | [OpenMP](https://www.openmp.org/) | +| openssl.cfg | [OpenSSL](https://www.openssl.org/) | +| pcre.cfg | [PCRE](https://pcre.org/) | +| posix.cfg | [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/) | +| python.cfg | | +| qt.cfg | [Qt](https://www.qt.io/) | +| ruby.cfg | | +| sdl.cfg | | +| sfml.cfg | | +| sqlite3.cfg | [SQLite](https://www.sqlite.org/) | +| std.cfg | C/C++ standard library | Loaded by default +| tinyxml2.cfg | [TinyXML-2](https://github.com/leethomason/tinyxml2) | +| vcl.cfg | | +| windows.cfg | [Win32 API](https://learn.microsoft.com/en-us/windows/win32/) | +| wxsqlite3.cfg | | +| wxsvg.cfg | | +| wxwidgets.cfg | [wxWidgets](https://www.wxwidgets.org/) | +| zephyr.cfg | | +| zlib.cfg | [zlib](https://www.zlib.net) | + +## Creating a custom .cfg file You can create and use your own .cfg files for your projects. Use `--check-library` to get hints about what you should configure. From 7e8ea5bcf9e5df54a0a2b0a11b2e624b21156c31 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Fri, 1 Dec 2023 04:34:36 -0600 Subject: [PATCH 33/40] Avoid evaluating conditions twice when there isnt a value to evaluate (#5711) --- lib/programmemory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index fccfe409958..aaef10b6ad2 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -208,6 +208,8 @@ static bool evaluateCondition(const std::string& op, evaluateCondition(op, r, condition->astOperand2(), pm, settings)) { return true; } + if (!pm.hasValue(condition->exprId())) + return false; } MathLib::bigint result = 0; bool error = false; From 237bed8a919850611e4949f3af66c6b07179256e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Fri, 1 Dec 2023 14:19:47 +0100 Subject: [PATCH 34/40] CmdLineParser: made some options exclusive (#5704) --- cli/cmdlineparser.cpp | 113 ++++++++++++++++++------------------- test/testcmdlineparser.cpp | 48 +++++++++++++++- 2 files changed, 103 insertions(+), 58 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index be5b3468f2d..1eb8d2fb373 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -282,6 +282,62 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) // TODO: error out on all missing given files/paths CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const argv[]) { + if (argc <= 1) { + printHelp(); + return Result::Exit; + } + + // check for exclusive options + for (int i = 1; i < argc; i++) { + // documentation.. + if (std::strcmp(argv[i], "--doc") == 0) { + std::ostringstream doc; + // Get documentation.. + for (const Check * it : Check::instances()) { + const std::string& name(it->name()); + const std::string info(it->classInfo()); + if (!name.empty() && !info.empty()) + doc << "## " << name << " ##\n" + << info << "\n"; + } + + mLogger.printRaw(doc.str()); + return Result::Exit; + } + + // print all possible error messages.. + if (std::strcmp(argv[i], "--errorlist") == 0) { + mSettings.loadCppcheckCfg(); + { + XMLErrorMessagesLogger xmlLogger; + std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); + CppCheck::getErrorMessages(xmlLogger); + std::cout << ErrorMessage::getXMLFooter() << std::endl; + } + return Result::Exit; + } + + // Print help + if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { + printHelp(); + return Result::Exit; + } + + if (std::strcmp(argv[i], "--version") == 0) { + mSettings.loadCppcheckCfg(); + if (!mSettings.cppcheckCfgProductName.empty()) { + mLogger.printRaw(mSettings.cppcheckCfgProductName); + } else { + const char * const extraVersion = CppCheck::extraVersion(); + if (*extraVersion != '\0') + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); + else + mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); + } + return Result::Exit; + } + } + bool def = false; bool maxconfigs = false; @@ -466,23 +522,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } - // documentation.. - else if (std::strcmp(argv[i], "--doc") == 0) { - // TODO: make an exclusive option - std::ostringstream doc; - // Get documentation.. - for (const Check * it : Check::instances()) { - const std::string& name(it->name()); - const std::string info(it->classInfo()); - if (!name.empty() && !info.empty()) - doc << "## " << name << " ##\n" - << info << "\n"; - } - - mLogger.printRaw(doc.str()); - return Result::Exit; - } - // dump cppcheck data else if (std::strcmp(argv[i], "--dump") == 0) mSettings.dump = true; @@ -506,19 +545,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } - // print all possible error messages.. - else if (std::strcmp(argv[i], "--errorlist") == 0) { - // TODO: make this an exclusive option - mSettings.loadCppcheckCfg(); - { - XMLErrorMessagesLogger xmlLogger; - std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); - CppCheck::getErrorMessages(xmlLogger); - std::cout << ErrorMessage::getXMLFooter() << std::endl; - } - return Result::Exit; - } - // --error-exitcode=1 else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) { if (!parseNumberArg(argv[i], 17, mSettings.exitCode)) @@ -592,13 +618,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strcmp(argv[i], "--funsigned-char") == 0) mSettings.platform.defaultSign = 'u'; - // Print help - else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { - // TODO: make this an exclusive option - printHelp(); - return Result::Exit; - } - // Ignored paths else if (std::strncmp(argv[i], "-i", 2) == 0) { std::string path; @@ -1150,21 +1169,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0) mSettings.verbose = true; - else if (std::strcmp(argv[i], "--version") == 0) { - // TODO: make this an exclusive parameter - mSettings.loadCppcheckCfg(); - if (!mSettings.cppcheckCfgProductName.empty()) { - mLogger.printRaw(mSettings.cppcheckCfgProductName); - } else { - const char * const extraVersion = CppCheck::extraVersion(); - if (*extraVersion != '\0') - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version() + " ("+ extraVersion + ')'); - else - mLogger.printRaw(std::string("Cppcheck ") + CppCheck::version()); - } - return Result::Exit; - } - // Write results in results.xml else if (std::strcmp(argv[i], "--xml") == 0) mSettings.xml = true; @@ -1226,11 +1230,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mLogger.printMessage("unusedFunction check can't be used with '-j' option. Disabling unusedFunction check."); } - if (argc <= 1) { - printHelp(); - return Result::Exit; - } - if (!mPathNames.empty() && project.projectType != ImportProject::Type::NONE) { mLogger.printError("--project cannot be used in conjunction with source files."); return Result::Fail; diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index dc54eba807c..955a55751fd 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -119,9 +119,12 @@ class TestCmdlineParser : public TestFixture { void run() override { TEST_CASE(nooptions); TEST_CASE(helpshort); + TEST_CASE(helpshortExclusive); TEST_CASE(helplong); + TEST_CASE(helplongExclusive); TEST_CASE(version); TEST_CASE(versionWithCfg); + TEST_CASE(versionExclusive); TEST_CASE(onefile); TEST_CASE(onepath); TEST_CASE(optionwithoutfile); @@ -255,6 +258,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(xmlverunknown); TEST_CASE(xmlverinvalid); TEST_CASE(doc); + TEST_CASE(docExclusive); TEST_CASE(showtimeFile); TEST_CASE(showtimeFileTotal); TEST_CASE(showtimeTop5); @@ -264,6 +268,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(showtimeEmpty); TEST_CASE(showtimeInvalid); TEST_CASE(errorlist); + TEST_CASE(errorlistExclusive); TEST_CASE(ignorepathsnopath); #if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING) TEST_CASE(exceptionhandling); @@ -373,6 +378,14 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void helpshortExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "-h"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void helplong() { REDIRECT; const char * const argv[] = {"cppcheck", "--help"}; @@ -381,6 +394,14 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void helplongExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--help"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void version() { REDIRECT; const char * const argv[] = {"cppcheck", "--version"}; @@ -402,7 +423,15 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } - // TODO: test extraVersion + // TODO: test --version with extraVersion + + void versionExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--version"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("Cppcheck 2.13 dev\n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } void onefile() { REDIRECT; @@ -1577,6 +1606,14 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void docExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--doc"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT(startsWith(logger->str(), "## ")); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void showtimeSummary() { REDIRECT; const char * const argv[] = {"cppcheck", "--showtime=summary", "file.cpp"}; @@ -1659,6 +1696,15 @@ class TestCmdlineParser : public TestFixture { // TODO: test --errorlist with product name + void errorlistExclusive() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--library=missing", "--errorlist"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger + ASSERT(startsWith(GET_REDIRECT_OUTPUT, "\n")); + } + void ignorepathsnopath() { REDIRECT; const char * const argv[] = {"cppcheck", "-i"}; From d6a1a657df8c77e0a8878628b395d16acd4db7a1 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:39:16 +0100 Subject: [PATCH 35/40] Fix #11796 FN memleak with brace init (#5708) Co-authored-by: chrchr-github --- lib/checkleakautovar.cpp | 15 +++++++++------ test/testclass.cpp | 11 +++++++++++ test/testleakautovar.cpp | 11 +++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index d99a28d030d..61079e36b8f 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -328,7 +328,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, // check each token { - const Token * nextTok = checkTokenInsideExpression(tok, varInfo); + const bool isInit = Token::Match(tok, "%var% {|(") && tok->variable() && tok == tok->variable()->nameToken(); + const Token * nextTok = isInit ? nullptr : checkTokenInsideExpression(tok, varInfo); if (nextTok) { tok = nextTok; continue; @@ -337,26 +338,28 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, // look for end of statement - if (!Token::Match(tok, "[;{},]") || Token::Match(tok->next(), "[;{},]")) + const bool isInit = Token::Match(tok->tokAt(-1), "%var% {|(") && tok->tokAt(-1)->variable() && tok->tokAt(-1) == tok->tokAt(-1)->variable()->nameToken(); + if ((!Token::Match(tok, "[;{},]") || Token::Match(tok->next(), "[;{},]")) && !(isInit && tok->str() == "(")) continue; if (Token::Match(tok, "[;{},] %var% [")) continue; - tok = tok->next(); + if (!isInit) + tok = tok->next(); if (!tok || tok == endToken) break; if (Token::Match(tok, "const %type%")) tok = tok->tokAt(2); - while (tok->str() == "(") + while (!isInit && tok->str() == "(") tok = tok->next(); while (tok->isUnaryOp("*") && tok->astOperand1()->isUnaryOp("&")) tok = tok->astOperand1()->astOperand1(); // parse statement, skip to last member - const Token *varTok = tok; + const Token* varTok = isInit ? tok->tokAt(-1) : tok; while (Token::Match(varTok, "%name% ::|. %name% !!(")) varTok = varTok->tokAt(2); @@ -381,7 +384,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, }; // assignment.. - if (const Token* const tokAssignOp = isAssignment(varTok)) { + if (const Token* const tokAssignOp = isInit ? varTok : isAssignment(varTok)) { if (Token::simpleMatch(tokAssignOp->astOperand1(), ".")) continue; diff --git a/test/testclass.cpp b/test/testclass.cpp index 04a3f2f700c..df4a5b531aa 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -6621,6 +6621,17 @@ class TestClass : public TestFixture { ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'S::f' can be const.\n" "[test.cpp:8]: (performance, inconclusive) Technically the member function 'S::g' can be static (but you may consider moving to unnamed namespace).\n", errout.str()); + + checkConst("class C {\n" // #11653 + "public:\n" + " void f(bool b) const;\n" + "};\n" + "void C::f(bool b) const {\n" + " if (b)\n" + " f(false);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'C::f' can be static (but you may consider moving to unnamed namespace).\n", + errout.str()); } void const90() { // #11637 diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 700292c9c42..09891cf6631 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -88,6 +88,7 @@ class TestLeakAutoVar : public TestFixture { TEST_CASE(assign22); // #9139 TEST_CASE(assign23); TEST_CASE(assign24); // #7440 + TEST_CASE(assign25); TEST_CASE(isAutoDealloc); @@ -571,6 +572,16 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("[test.c:5]: (error) Memory leak: p\n", errout.str()); } + void assign25() { + check("void f() {\n" // #11796 + " int* p{ new int };\n" + " int* q(new int);\n" + "}", true); + ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: p\n" + "[test.cpp:4]: (error) Memory leak: q\n", + errout.str()); + } + void isAutoDealloc() { check("void f() {\n" " char *p = new char[100];" From 4182f943aa6fb06fac72c23420199b3253be1268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Fri, 1 Dec 2023 15:59:01 +0100 Subject: [PATCH 36/40] use more granular suppressions in selfcheck and prefer inline suppressions (#5703) --- .selfcheck_suppressions | 14 +++++++------- gui/resultstree.cpp | 16 ++++++++-------- lib/checkbufferoverrun.cpp | 1 + lib/checkclass.cpp | 1 + lib/checknullpointer.cpp | 2 ++ lib/checkunusedfunctions.cpp | 4 +++- lib/cppcheck.cpp | 5 +++++ lib/errorlogger.cpp | 1 + lib/fwdanalysis.cpp | 1 + lib/library.cpp | 7 ++++++- lib/symboldatabase.cpp | 1 + lib/templatesimplifier.cpp | 1 + lib/token.cpp | 16 ++++++++++++++++ tools/triage/mainwindow.cpp | 1 + 14 files changed, 54 insertions(+), 17 deletions(-) diff --git a/.selfcheck_suppressions b/.selfcheck_suppressions index b6478d8717a..03e54874475 100644 --- a/.selfcheck_suppressions +++ b/.selfcheck_suppressions @@ -1,12 +1,9 @@ missingIncludeSystem -shadowFunction -bitwiseOnBoolean # temporary suppressions - fix the warnings! simplifyUsing:lib/valueptr.h varid0:gui/projectfile.cpp naming-privateMemberVariable:gui/test/cppchecklibrarydata/testcppchecklibrarydata.h -templateInstantiation symbolDatabaseWarning:*/moc_*.cpp simplifyUsing:*/moc_*.cpp @@ -19,10 +16,13 @@ functionStatic:*/ui_fileview.h valueFlowBailout valueFlowBailoutIncompleteVar autoNoType -bailoutUninitVar naming-varname:externals/simplecpp/simplecpp.h naming-privateMemberVariable:externals/simplecpp/simplecpp.h -# TODO: use more granular suppressions - might expose false positives -*:externals/picojson/* -*:externals/tinyxml2/* + +# these warnings need to be addressed upstream +uninitMemberVar:externals/tinyxml2/tinyxml2.h +noExplicitConstructor:externals/tinyxml2/tinyxml2.h +missingOverride:externals/tinyxml2/tinyxml2.h +invalidPrintfArgType_sint:externals/tinyxml2/tinyxml2.h +naming-privateMemberVariable:externals/tinyxml2/tinyxml2.h \ No newline at end of file diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index 71494a19d0f..e73475cf8ca 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -643,8 +643,8 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e) } //Create an action for the application - QAction *recheckSelectedFiles = new QAction(tr("Recheck"), &menu); - QAction *copy = new QAction(tr("Copy"), &menu); + QAction *recheckAction = new QAction(tr("Recheck"), &menu); + QAction *copyAction = new QAction(tr("Copy"), &menu); QAction *hide = new QAction(tr("Hide"), &menu); QAction *hideallid = new QAction(tr("Hide all with id"), &menu); QAction *opencontainingfolder = new QAction(tr("Open containing folder"), &menu); @@ -654,13 +654,13 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e) opencontainingfolder->setDisabled(true); } if (mThread->isChecking()) - recheckSelectedFiles->setDisabled(true); + recheckAction->setDisabled(true); else - recheckSelectedFiles->setDisabled(false); + recheckAction->setDisabled(false); - menu.addAction(recheckSelectedFiles); + menu.addAction(recheckAction); menu.addSeparator(); - menu.addAction(copy); + menu.addAction(copyAction); menu.addSeparator(); menu.addAction(hide); menu.addAction(hideallid); @@ -672,8 +672,8 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e) menu.addSeparator(); menu.addAction(opencontainingfolder); - connect(recheckSelectedFiles, SIGNAL(triggered()), this, SLOT(recheckSelectedFiles())); - connect(copy, SIGNAL(triggered()), this, SLOT(copy())); + connect(recheckAction, SIGNAL(triggered()), this, SLOT(recheckAction())); + connect(copyAction, SIGNAL(triggered()), this, SLOT(copyAction())); connect(hide, SIGNAL(triggered()), this, SLOT(hideResult())); connect(hideallid, SIGNAL(triggered()), this, SLOT(hideAllIdResult())); connect(opencontainingfolder, SIGNAL(triggered()), this, SLOT(openContainingFolder())); diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index d9acf389218..c0c5ddb64c8 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -953,6 +953,7 @@ Check::FileInfo *CheckBufferOverrun::getFileInfo(const Tokenizer *tokenizer, con Check::FileInfo * CheckBufferOverrun::loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const { + // cppcheck-suppress shadowFunction - TODO: fix this const std::string arrayIndex("array-index"); const std::string pointerArith("pointer-arith"); diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c6005eca1ee..245455ad4ca 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2479,6 +2479,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, Member return false; const Token* assignTok = end->next()->astParent(); if (var && assignTok && assignTok->isAssignmentOp() && assignTok->astOperand1() && assignTok->astOperand1()->variable()) { + // cppcheck-suppress shadowFunction - TODO: fix this const Variable* assignVar = assignTok->astOperand1()->variable(); if (assignVar->isPointer() && !assignVar->isConst() && var->typeScope()) { const auto& funcMap = var->typeScope()->functionMap; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 86a6542f0b6..cf70f7293eb 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -514,6 +514,7 @@ static std::string arithmeticTypeString(const Token *tok) void CheckNullPointer::pointerArithmeticError(const Token* tok, const ValueFlow::Value *value, bool inconclusive) { + // cppcheck-suppress shadowFunction - TODO: fix this std::string arithmetic = arithmeticTypeString(tok); std::string errmsg; if (tok && tok->str()[0] == '-') { @@ -532,6 +533,7 @@ void CheckNullPointer::pointerArithmeticError(const Token* tok, const ValueFlow: void CheckNullPointer::redundantConditionWarning(const Token* tok, const ValueFlow::Value *value, const Token *condition, bool inconclusive) { + // cppcheck-suppress shadowFunction - TODO: fix this std::string arithmetic = arithmeticTypeString(tok); std::string errmsg; if (tok && tok->str()[0] == '-') { diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index 24151998ce1..eb789fdf727 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -459,8 +459,10 @@ void CheckUnusedFunctions::analyseWholeProgram(const Settings &settings, ErrorLo } if (std::strcmp(e2->Name(),"functiondecl") == 0) { const char* lineNumber = e2->Attribute("lineNumber"); - if (lineNumber) + if (lineNumber) { + // cppcheck-suppress templateInstantiation - TODO: fix this - see #11631 decls[functionName] = Location(sourcefile, strToInt(lineNumber)); + } } } } diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index f70bca725a2..2d772662d69 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1062,6 +1062,7 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer) const std::time_t maxTime = mSettings.checksMaxTime > 0 ? std::time(nullptr) + mSettings.checksMaxTime : 0; // call all "runChecks" in all registered Check classes + // cppcheck-suppress shadowFunction - TODO: fix this for (Check *check : Check::instances()) { if (Settings::terminated()) return; @@ -1104,6 +1105,7 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer) mAnalyzerInformation.setFileInfo("ctu", fi1->toString()); } + // cppcheck-suppress shadowFunction - TODO: fix this for (const Check *check : Check::instances()) { if (doUnusedFunctionOnly && dynamic_cast(check) == nullptr) continue; @@ -1735,6 +1737,7 @@ bool CppCheck::analyseWholeProgram() ctu.nestedCalls.insert(ctu.nestedCalls.end(), fi2->nestedCalls.cbegin(), fi2->nestedCalls.cend()); } } + // cppcheck-suppress shadowFunction - TODO: fix this for (Check *check : Check::instances()) errors |= check->analyseWholeProgram(&ctu, mFileInfo, mSettings, *this); // TODO: ctu return errors && (mExitCode > 0); @@ -1785,6 +1788,7 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::list< ctuFileInfo.loadFromXml(e); continue; } + // cppcheck-suppress shadowFunction - TODO: fix this for (const Check *check : Check::instances()) { if (checkClassAttr == check->name()) fileInfoList.push_back(check->loadFileInfoFromXml(e)); @@ -1796,6 +1800,7 @@ void CppCheck::analyseWholeProgram(const std::string &buildDir, const std::list< CTU::maxCtuDepth = mSettings.maxCtuDepth; // Analyse the tokens + // cppcheck-suppress shadowFunction - TODO: fix this for (Check *check : Check::instances()) check->analyseWholeProgram(&ctuFileInfo, fileInfoList, mSettings, *this); diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index a8a18b6c365..09aeba231a6 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -169,6 +169,7 @@ ErrorMessage::ErrorMessage(const tinyxml2::XMLElement * const errmsg) severity = attr ? severityFromString(attr) : Severity::none; attr = errmsg->Attribute("cwe"); + // cppcheck-suppress templateInstantiation - TODO: fix this - see #11631 cwe.id = attr ? strToInt(attr) : 0; attr = errmsg->Attribute("inconclusive"); diff --git a/lib/fwdanalysis.cpp b/lib/fwdanalysis.cpp index 1dd44759d02..e43b5dfec08 100644 --- a/lib/fwdanalysis.cpp +++ b/lib/fwdanalysis.cpp @@ -317,6 +317,7 @@ FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token * // ({ .. }) if (hasGccCompoundStatement(parent->astParent()->astOperand2())) return Result(Result::Type::BAILOUT); + // cppcheck-suppress shadowFunction - TODO: fix this const bool reassign = isSameExpression(mCpp, false, expr, parent, mLibrary, false, false, nullptr); if (reassign) return Result(Result::Type::WRITE, parent->astParent()); diff --git a/lib/library.cpp b/lib/library.cpp index 9ce1a4f36aa..f1058c7883a 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -392,8 +392,10 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc) if (end) mExecutableBlocks[extension].setEnd(end); const char * offset = blocknode->Attribute("offset"); - if (offset) + if (offset) { + // cppcheck-suppress templateInstantiation - TODO: fix this - see #11631 mExecutableBlocks[extension].setOffset(strToInt(offset)); + } } else @@ -706,6 +708,7 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co mReturnValueType[name] = type; if (const char *container = functionnode->Attribute("container")) mReturnValueContainer[name] = strToInt(container); + // cppcheck-suppress shadowFunction - TODO: fix this if (const char *unknownReturnValues = functionnode->Attribute("unknownValues")) { if (std::strcmp(unknownReturnValues, "all") == 0) { std::vector values{LLONG_MIN, LLONG_MAX}; @@ -1305,6 +1308,7 @@ bool Library::isCompliantValidationExpression(const char* p) error |= (*(p + 1) == '-'); } else if (*p == ':') { + // cppcheck-suppress bitwiseOnBoolean - TODO: fix this error |= range | (*(p + 1) == '.'); range = true; has_dot = false; @@ -1319,6 +1323,7 @@ bool Library::isCompliantValidationExpression(const char* p) has_dot = false; has_E = false; } else if (*p == '.') { + // cppcheck-suppress bitwiseOnBoolean - TODO: fix this error |= has_dot | (!std::isdigit(*(p + 1))); has_dot = true; } else if (*p == 'E' || *p == 'e') { diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index ac053cfe52d..960deb886c6 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2364,6 +2364,7 @@ const Type* Variable::smartPointerType() const while (Token::Match(typeTok, "%name%|::")) typeTok = typeTok->next(); if (Token::Match(typeTok, "< %name% >")) { + // cppcheck-suppress shadowFunction - TODO: fix this const Scope* scope = typeTok->scope(); const Type* ptrType{}; while (scope && !ptrType) { diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index e1af536d3e8..e156e4be792 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -2946,6 +2946,7 @@ bool TemplateSimplifier::matchSpecialization( startToken = startToken->previous(); if (!Token::simpleMatch(startToken, "template <")) continue; + // cppcheck-suppress shadowFunction - TODO: fix this std::vector templateParameters; getTemplateParametersInDeclaration(startToken->tokAt(2), templateParameters); diff --git a/lib/token.cpp b/lib/token.cpp index be6d7730e97..e77b2dfcf38 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -316,11 +316,13 @@ void Token::swapWithNext() std::swap(mFlags, mNext->mFlags); std::swap(mImpl, mNext->mImpl); if (mImpl->mTemplateSimplifierPointers) + // cppcheck-suppress shadowFunction - TODO: fix this for (auto *templateSimplifierPointer : *mImpl->mTemplateSimplifierPointers) { templateSimplifierPointer->token(this); } if (mNext->mImpl->mTemplateSimplifierPointers) + // cppcheck-suppress shadowFunction - TODO: fix this for (auto *templateSimplifierPointer : *mNext->mImpl->mTemplateSimplifierPointers) { templateSimplifierPointer->token(mNext); } @@ -341,6 +343,7 @@ void Token::takeData(Token *fromToken) mImpl = fromToken->mImpl; fromToken->mImpl = nullptr; if (mImpl->mTemplateSimplifierPointers) + // cppcheck-suppress shadowFunction - TODO: fix this for (auto *templateSimplifierPointer : *mImpl->mTemplateSimplifierPointers) { templateSimplifierPointer->token(this); } @@ -636,6 +639,7 @@ bool Token::simpleMatch(const Token *tok, const char pattern[], size_t pattern_l return false; // shortcut const char *current = pattern; const char *end = pattern + pattern_len; + // cppcheck-suppress shadowFunction - TODO: fix this const char *next = static_cast(std::memchr(pattern, ' ', pattern_len)); if (!next) next = end; @@ -781,6 +785,7 @@ nonneg int Token::getStrLength(const Token *tok) assert(tok->mTokType == eString); int len = 0; + // cppcheck-suppress shadowFunction - TODO: fix this const std::string str(getStringLiteral(tok->str())); std::string::const_iterator it = str.cbegin(); const std::string::const_iterator end = str.cend(); @@ -808,6 +813,7 @@ nonneg int Token::getStrArraySize(const Token *tok) { assert(tok != nullptr); assert(tok->tokType() == eString); + // cppcheck-suppress shadowFunction - TODO: fix this const std::string str(getStringLiteral(tok->str())); int sizeofstring = 1; for (int i = 0; i < (int)str.size(); i++) { @@ -1110,6 +1116,7 @@ Token* Token::insertToken(const std::string& tokenStr, const std::string& origin tok1 = tok1->previous()->findOpeningBracket(); if (tok1 && Token::Match(tok1->tokAt(-3), "%name% :: %name%")) { tok1 = tok1->tokAt(-2); + // cppcheck-suppress shadowFunction - TODO: fix this std::string scope = tok1->strAt(-1); while (Token::Match(tok1->tokAt(-2), ":: %name%")) { scope = tok1->strAt(-3) + " :: " + scope; @@ -1285,6 +1292,7 @@ std::string Token::stringifyList(const stringifyOptions& options, const std::vec std::string ret; unsigned int lineNumber = mImpl->mLineNumber - (options.linenumbers ? 1U : 0U); + // cppcheck-suppress shadowFunction - TODO: fix this unsigned int fileIndex = options.files ? ~0U : mImpl->mFileIndex; std::map lineNumbers; for (const Token *tok = this; tok != end; tok = tok->next()) { @@ -1701,6 +1709,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const { std::string outs; + // cppcheck-suppress shadowFunction int fileIndex = -1; int line = 0; if (xml) @@ -1708,6 +1717,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const else outs += "\n\n##Value flow\n"; for (const Token *tok = this; tok; tok = tok->next()) { + // cppcheck-suppress shadowFunction - TODO: fix this const auto* const values = tok->mImpl->mValues; if (!values) continue; @@ -2246,6 +2256,7 @@ void Token::assignProgressValues(Token *tok) void Token::assignIndexes() { + // cppcheck-suppress shadowFunction - TODO: fix this int index = (mPrevious ? mPrevious->mImpl->mIndex : 0) + 1; for (Token *tok = this; tok; tok = tok->next()) tok->mImpl->mIndex = index++; @@ -2283,9 +2294,11 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok) if (tok->function()) return tok->function()->retType; if (Token::simpleMatch(tok, "return")) { + // cppcheck-suppress shadowFunction - TODO: fix this const Scope *scope = tok->scope(); if (!scope) return nullptr; + // cppcheck-suppress shadowFunction - TODO: fix this const Function *function = scope->function; if (!function) return nullptr; @@ -2395,15 +2408,18 @@ std::pair Token::typeDecl(const Token* tok, bool poi return {var->typeStartToken(), var->typeEndToken()->next()}; } if (Token::simpleMatch(tok, "return")) { + // cppcheck-suppress shadowFunction - TODO: fix this const Scope* scope = tok->scope(); if (!scope) return {}; + // cppcheck-suppress shadowFunction - TODO: fix this const Function* function = scope->function; if (!function) return {}; return { function->retDef, function->returnDefEnd() }; } if (tok->previous() && tok->previous()->function()) { + // cppcheck-suppress shadowFunction - TODO: fix this const Function *function = tok->previous()->function(); return {function->retDef, function->returnDefEnd()}; } diff --git a/tools/triage/mainwindow.cpp b/tools/triage/mainwindow.cpp index 22ffe8e536d..27aa47b5b6e 100644 --- a/tools/triage/mainwindow.cpp +++ b/tools/triage/mainwindow.cpp @@ -359,6 +359,7 @@ void MainWindow::findInFilesClicked() ui->inFilesResult->clear(); const QString text = ui->filterEdit->text(); + // cppcheck-suppress shadowFunction - TODO: fix this QStringList filter; if (ui->hFilesFilter->isChecked()) filter.append(hFiles); From 3272a2bbe7a3e462a225eb98652479eebe6d9472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Fri, 1 Dec 2023 16:34:14 +0100 Subject: [PATCH 37/40] greatly improved `Settings::loadCppcheckCfg()` error handling (#5712) This also fixes the issue that `cppcheck.cfg` is no longer being loaded from executable path. That was introduced by #5704. --- .github/workflows/cppcheck-premium.yml | 2 +- Makefile | 4 +- cli/cmdlineparser.cpp | 32 +++++-- cli/cmdlineparser.h | 4 +- gui/mainwindow.cpp | 11 ++- lib/settings.cpp | 93 ++++++++++++++----- lib/settings.h | 2 +- releasenotes.txt | 1 + test/testcmdlineparser.cpp | 49 +++++++++- test/testsettings.cpp | 124 +++++++++++++++++++++++++ 10 files changed, 278 insertions(+), 44 deletions(-) diff --git a/.github/workflows/cppcheck-premium.yml b/.github/workflows/cppcheck-premium.yml index 11d6f3b8cac..2f9863d5e44 100644 --- a/.github/workflows/cppcheck-premium.yml +++ b/.github/workflows/cppcheck-premium.yml @@ -40,4 +40,4 @@ jobs: - name: Check run: | cppcheckpremium-${{ env.PREMIUM_VERSION }}/premiumaddon --check-loc-license cppcheck.lic > cppcheck-premium-loc - cppcheckpremium-${{ env.PREMIUM_VERSION }}/cppcheck -j$(nproc) -D__GNUC__ -D__CPPCHECK__ --suppressions-list=cppcheckpremium-suppressions --platform=unix64 --enable=style --premium=misra-c++-2008 --premium=cert-c++-2016 --error-exitcode=1 lib + cppcheckpremium-${{ env.PREMIUM_VERSION }}/cppcheck -j$(nproc) -D__GNUC__ -D__CPPCHECK__ --suppressions-list=cppcheckpremium-suppressions --platform=unix64 --enable=style --premium=misra-c++-2008 --premium=cert-c++-2016 --inline-suppr --error-exitcode=1 lib diff --git a/Makefile b/Makefile index 09c40c0e234..9153bf4b300 100644 --- a/Makefile +++ b/Makefile @@ -728,7 +728,7 @@ test/testclangimport.o: test/testclangimport.cpp lib/addoninfo.h lib/check.h lib test/testclass.o: test/testclass.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/checkclass.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclass.cpp -test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h +test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlinelogger.h cli/cmdlineparser.h cli/cppcheckexecutor.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcmdlineparser.cpp test/testcolor.o: test/testcolor.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h @@ -809,7 +809,7 @@ test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp test/testprocessexecutor.o: test/testprocessexecutor.cpp cli/executor.h cli/processexecutor.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/color.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testprocessexecutor.cpp -test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h +test/testsettings.o: test/testsettings.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/tokenize.h lib/tokenlist.h lib/utils.h test/fixture.h test/helpers.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testsettings.cpp test/testsimplifytemplate.o: test/testsimplifytemplate.cpp lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 1eb8d2fb373..dc8a9006337 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -282,6 +282,8 @@ bool CmdLineParser::fillSettingsFromArgs(int argc, const char* const argv[]) // TODO: error out on all missing given files/paths CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const argv[]) { + mSettings.exename = Path::getCurrentExecutablePath(argv[0]); + if (argc <= 1) { printHelp(); return Result::Exit; @@ -307,7 +309,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // print all possible error messages.. if (std::strcmp(argv[i], "--errorlist") == 0) { - mSettings.loadCppcheckCfg(); + if (!loadCppcheckCfg()) + return Result::Fail; { XMLErrorMessagesLogger xmlLogger; std::cout << ErrorMessage::getXMLHeader(mSettings.cppcheckCfgProductName); @@ -324,7 +327,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } if (std::strcmp(argv[i], "--version") == 0) { - mSettings.loadCppcheckCfg(); + if (!loadCppcheckCfg()) + return Result::Fail; if (!mSettings.cppcheckCfgProductName.empty()) { mLogger.printRaw(mSettings.cppcheckCfgProductName); } else { @@ -343,8 +347,6 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a ImportProject project; - mSettings.exename = Path::getCurrentExecutablePath(argv[0]); - for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { // User define @@ -1203,7 +1205,8 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a } } - mSettings.loadCppcheckCfg(); + if (!loadCppcheckCfg()) + return Result::Fail; // Default template format.. if (mSettings.templateFormat.empty()) { @@ -1609,10 +1612,10 @@ void CmdLineParser::printHelp() const mLogger.printRaw(oss.str()); } -bool CmdLineParser::isCppcheckPremium() const { - if (mSettings.cppcheckCfgProductName.empty()) - mSettings.loadCppcheckCfg(); - return startsWith(mSettings.cppcheckCfgProductName, "Cppcheck Premium"); +bool CmdLineParser::isCppcheckPremium() { + Settings settings; + settings.loadCppcheckCfg(); // TODO: how to handle errors? + return startsWith(settings.cppcheckCfgProductName, "Cppcheck Premium"); } bool CmdLineParser::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename) @@ -1701,3 +1704,14 @@ bool CmdLineParser::loadAddons(Settings& settings) } return result; } + +bool CmdLineParser::loadCppcheckCfg() +{ + const std::string cfgErr = mSettings.loadCppcheckCfg(); + if (!cfgErr.empty()) { + mLogger.printError("could not load cppcheck.cfg - " + cfgErr); + return false; + } + return true; +} + diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index db3bb963890..739d2b21b09 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -111,7 +111,7 @@ class CmdLineParser { void printHelp() const; private: - bool isCppcheckPremium() const; + static bool isCppcheckPremium(); template bool parseNumberArg(const char* const arg, std::size_t offset, T& num, bool mustBePositive = false) @@ -150,6 +150,8 @@ class CmdLineParser { */ bool loadAddons(Settings& settings); + bool loadCppcheckCfg(); + CmdLineLogger &mLogger; std::vector mPathNames; diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 2835f8983c6..3be305ee5f8 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -119,7 +119,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : { Settings tempSettings; tempSettings.exename = QCoreApplication::applicationFilePath().toStdString(); - tempSettings.loadCppcheckCfg(); + tempSettings.loadCppcheckCfg(); // TODO: how to handle error? mCppcheckCfgProductName = QString::fromStdString(tempSettings.cppcheckCfgProductName); mCppcheckCfgAbout = QString::fromStdString(tempSettings.cppcheckCfgAbout); } @@ -903,8 +903,7 @@ bool MainWindow::tryLoadLibrary(Library *library, const QString& filename) return true; } -Settings MainWindow::getCppcheckSettings() -{ +Settings MainWindow::getCppcheckSettings() { saveSettings(); // Save settings Settings result; @@ -915,7 +914,11 @@ Settings MainWindow::getCppcheckSettings() if (!std) QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir= at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.").arg("std.cfg")); - result.loadCppcheckCfg(); + { + const QString cfgErr = QString::fromStdString(result.loadCppcheckCfg()); + if (!cfgErr.isEmpty()) + QMessageBox::critical(this, tr("Error"), tr("Failed to load %1 - %2").arg("cppcheck.cfg").arg(cfgErr)); + } // If project file loaded, read settings from it if (mProjectFile) { diff --git a/lib/settings.cpp b/lib/settings.cpp index eb1e9847c96..54c96f672f2 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -40,40 +40,87 @@ Settings::Settings() setCheckLevelNormal(); } -// TODO: report error when the config is invalid -void Settings::loadCppcheckCfg() +std::string Settings::loadCppcheckCfg() { - std::string fileName = Path::getPathFromFilename(exename) + "cppcheck.cfg"; + static const std::string cfgFilename = "cppcheck.cfg"; + std::string fileName; #ifdef FILESDIR - if (Path::isFile(FILESDIR "/cppcheck.cfg")) - fileName = FILESDIR "/cppcheck.cfg"; + if (Path::isFile(Path::join(FILESDIR, cfgFilename))) + fileName = Path::join(FILESDIR, cfgFilename); #endif + // cppcheck-suppress knownConditionTrueFalse + if (fileName.empty()) { + fileName = Path::getPathFromFilename(exename) + cfgFilename; + if (!Path::isFile(fileName)) + return ""; + } std::ifstream fin(fileName); if (!fin.is_open()) - return; + return "could not open file"; picojson::value json; fin >> json; - if (!picojson::get_last_error().empty()) - return; - picojson::object obj = json.get(); - if (obj.count("productName") && obj["productName"].is()) - cppcheckCfgProductName = obj["productName"].get(); - if (obj.count("about") && obj["about"].is()) - cppcheckCfgAbout = obj["about"].get(); - if (obj.count("addons") && obj["addons"].is()) { - for (const picojson::value &v : obj["addons"].get()) { - const std::string &s = v.get(); - if (!Path::isAbsolute(s)) - addons.emplace(Path::getPathFromFilename(fileName) + s); - else - addons.emplace(s); + { + const std::string& lastErr = picojson::get_last_error(); + if (!lastErr.empty()) + return "not a valid JSON - " + lastErr; + } + const picojson::object& obj = json.get(); + { + const picojson::object::const_iterator it = obj.find("productName"); + if (it != obj.cend()) { + const auto& v = it->second; + if (!v.is()) + return "'productName' is not a string"; + cppcheckCfgProductName = v.get(); } } - if (obj.count("suppressions") && obj["suppressions"].is()) { - for (const picojson::value &v : obj["suppressions"].get()) - nomsg.addSuppressionLine(v.get()); + { + const picojson::object::const_iterator it = obj.find("about"); + if (it != obj.cend()) { + const auto& v = it->second; + if (!v.is()) + return "'about' is not a string"; + cppcheckCfgAbout = v.get(); + } + } + { + const picojson::object::const_iterator it = obj.find("addons"); + if (it != obj.cend()) { + const auto& entry = it->second; + if (!entry.is()) + return "'addons' is not an array"; + for (const picojson::value &v : entry.get()) + { + if (!v.is()) + return "'addons' array entry is not a string"; + const std::string &s = v.get(); + if (!Path::isAbsolute(s)) + addons.emplace(Path::join(Path::getPathFromFilename(fileName), s)); + else + addons.emplace(s); + } + } } + { + const picojson::object::const_iterator it = obj.find("suppressions"); + if (it != obj.cend()) { + const auto& entry = it->second; + if (!entry.is()) + return "'suppressions' is not an array"; + for (const picojson::value &v : entry.get()) + { + if (!v.is()) + return "'suppressions' array entry is not a string"; + const std::string &s = v.get(); + const std::string err = nomsg.addSuppressionLine(s); + if (!err.empty()) + return "could not parse suppression '" + s + "' - " + err; + } + } + } + + return ""; } std::string Settings::parseEnabled(const std::string &str, std::tuple, SimpleEnableGroup> &groups) diff --git a/lib/settings.h b/lib/settings.h index 96317f8b4a7..6833d8569aa 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -99,7 +99,7 @@ class CPPCHECKLIB WARN_UNUSED Settings { public: Settings(); - void loadCppcheckCfg(); + std::string loadCppcheckCfg(); /** @brief addons, either filename of python/json file or json data */ std::unordered_set addons; diff --git a/releasenotes.txt b/releasenotes.txt index 6144ba8695a..5e9b0d6db0e 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -32,3 +32,4 @@ Other: - You can suppress all warnings where macro is used using "-macro" - fixed CMake build with UBSAN and GCC - Added command-line options "--fsigned-char" and "--funsigned-char" to control the signess of the "char" type. This overrides previously specified "--platform" options and is overrides by following ones. +- An error is now reported when the "cppcheck.cfg" is invalid. The CLI version will also exit with a failure in that case. diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 955a55751fd..d5998c078b9 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -22,6 +22,7 @@ #include "cppcheckexecutor.h" #include "errortypes.h" #include "helpers.h" +#include "path.h" #include "platform.h" #include "redirect.h" #include "settings.h" @@ -125,6 +126,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(version); TEST_CASE(versionWithCfg); TEST_CASE(versionExclusive); + TEST_CASE(versionWithInvalidCfg); TEST_CASE(onefile); TEST_CASE(onepath); TEST_CASE(optionwithoutfile); @@ -268,7 +270,9 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(showtimeEmpty); TEST_CASE(showtimeInvalid); TEST_CASE(errorlist); + TEST_CASE(errorlistWithCfg); TEST_CASE(errorlistExclusive); + TEST_CASE(errorlistWithInvalidCfg); TEST_CASE(ignorepathsnopath); #if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING) TEST_CASE(exceptionhandling); @@ -360,6 +364,8 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(cppcheckBuildDirExistent); TEST_CASE(cppcheckBuildDirNonExistent); TEST_CASE(cppcheckBuildDirEmpty); + + TEST_CASE(invalidCppcheckCfg); } void nooptions() { @@ -412,7 +418,7 @@ class TestCmdlineParser : public TestFixture { void versionWithCfg() { REDIRECT; - ScopedFile file("cppcheck.cfg", + ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), "{\n" "\"productName\": \"The Product\"" "}\n"); @@ -433,6 +439,16 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } + void versionWithInvalidCfg() { + REDIRECT; + ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), + "{\n"); + const char * const argv[] = {"cppcheck", "--version"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void onefile() { REDIRECT; const char * const argv[] = {"cppcheck", "file.cpp"}; @@ -1690,11 +1706,19 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--errorlist"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger - ASSERT(startsWith(GET_REDIRECT_OUTPUT, "\n")); } - // TODO: test --errorlist with product name + void errorlistWithCfg() { + REDIRECT; + ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), + R"({"productName": "The Product"}\n)"); + const char * const argv[] = {"cppcheck", "--errorlist"}; + ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger + ASSERT(startsWith(GET_REDIRECT_OUTPUT, ErrorMessage::getXMLHeader("The Product"))); + } void errorlistExclusive() { REDIRECT; @@ -1705,6 +1729,16 @@ class TestCmdlineParser : public TestFixture { ASSERT(endsWith(GET_REDIRECT_OUTPUT, "\n")); } + void errorlistWithInvalidCfg() { + REDIRECT; + ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), + "{\n"); + const char * const argv[] = {"cppcheck", "--errorlist"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str()); + ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); + } + void ignorepathsnopath() { REDIRECT; const char * const argv[] = {"cppcheck", "-i"}; @@ -2309,6 +2343,15 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: Directory '' specified by --cppcheck-build-dir argument has to be existent.\n", logger->str()); } + + void invalidCppcheckCfg() { + REDIRECT; + ScopedFile file(Path::join(Path::getPathFromFilename(Path::getCurrentExecutablePath("")), "cppcheck.cfg"), + "{\n"); + const char * const argv[] = {"cppcheck", "test.cpp"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); + ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str()); + } }; REGISTER_TEST(TestCmdlineParser) diff --git a/test/testsettings.cpp b/test/testsettings.cpp index 03cc6e7a671..c3598300837 100644 --- a/test/testsettings.cpp +++ b/test/testsettings.cpp @@ -20,6 +20,7 @@ #include "errortypes.h" #include "settings.h" #include "fixture.h" +#include "helpers.h" class TestSettings : public TestFixture { public: @@ -28,6 +29,7 @@ class TestSettings : public TestFixture { private: void run() override { TEST_CASE(simpleEnableGroup); + TEST_CASE(loadCppcheckCfg); } void simpleEnableGroup() const { @@ -85,6 +87,128 @@ class TestSettings : public TestFixture { ASSERT_EQUALS(false, group.isEnabled(Checks::missingInclude)); ASSERT_EQUALS(false, group.isEnabled(Checks::internalCheck)); } + + void loadCppcheckCfg() + { + { + Settings s; + ASSERT_EQUALS("", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + "{}\n"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + "{\n"); + ASSERT_EQUALS("not a valid JSON - syntax error at line 1 near: ", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"productName": ""}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS("", s.cppcheckCfgProductName); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"productName": "product"}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS("product", s.cppcheckCfgProductName); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"productName": 1}\n)"); + ASSERT_EQUALS("'productName' is not a string", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"about": ""}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS("", s.cppcheckCfgAbout); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"about": "about"}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS("about", s.cppcheckCfgAbout); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"about": 1}\n)"); + ASSERT_EQUALS("'about' is not a string", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"addons": []}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS(0, s.addons.size()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"addons": 1}\n)"); + ASSERT_EQUALS("'addons' is not an array", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"addons": ["addon"]}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS(1, s.addons.size()); + ASSERT_EQUALS("addon", *s.addons.cbegin()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"addons": [1]}\n)"); + ASSERT_EQUALS("'addons' array entry is not a string", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"addons": []}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS(0, s.addons.size()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"suppressions": 1}\n)"); + ASSERT_EQUALS("'suppressions' is not an array", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"suppressions": ["id"]}\n)"); + ASSERT_EQUALS("", s.loadCppcheckCfg()); + ASSERT_EQUALS(1, s.nomsg.getSuppressions().size()); + ASSERT_EQUALS("id", s.nomsg.getSuppressions().cbegin()->errorId); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"suppressions": [""]}\n)"); + ASSERT_EQUALS("could not parse suppression '' - Failed to add suppression. No id.", s.loadCppcheckCfg()); + } + { + Settings s; + ScopedFile file("cppcheck.cfg", + R"({"suppressions": [1]}\n)"); + ASSERT_EQUALS("'suppressions' array entry is not a string", s.loadCppcheckCfg()); + } + + // TODO: test with FILESDIR + } }; REGISTER_TEST(TestSettings) From 55c2b75c2e0481db4779153f2792e7cf3f5cfb94 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 1 Dec 2023 17:42:27 +0100 Subject: [PATCH 38/40] Fix #6933 FN uninitvar with POD struct and STL types (#5713) Co-authored-by: chrchr-github --- lib/astutils.cpp | 5 +++++ test/cfg/qt.cpp | 7 +++++++ test/cfg/std.cpp | 2 +- test/testuninitvar.cpp | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 2da5f3f219e..62a616ee671 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3257,6 +3257,11 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings return ExprUsage::Used; } else if (ftok->str() == "{") { return indirect == 0 ? ExprUsage::Used : ExprUsage::Inconclusive; + } else if (ftok->variable() && ftok == ftok->variable()->nameToken()) { // variable init/constructor call + if (ftok->variable()->type() && ftok->variable()->type()->needInitialization == Type::NeedInitialization::True) + return ExprUsage::Used; + if (ftok->variable()->isStlType() || (ftok->variable()->valueType() && ftok->variable()->valueType()->container)) // STL types or containers don't initialize external variables + return ExprUsage::Used; } else { const bool isnullbad = settings->library.isnullargbad(ftok, argnr + 1); if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad) diff --git a/test/cfg/qt.cpp b/test/cfg/qt.cpp index 63ccf3b1d72..46310e32171 100644 --- a/test/cfg/qt.cpp +++ b/test/cfg/qt.cpp @@ -321,6 +321,13 @@ void duplicateExpression_QString_Compare(QString style) //#8723 {} } +void QVector_uninit() +{ + int i; + // cppcheck-suppress [uninitvar, unreadVariable] + QVector v(i); +} + void QStack1(QStack intStackArg) { for (int i = 0; i <= intStackArg.size(); ++i) { diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index b0926a0eed5..b8305bb62bf 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -1043,8 +1043,8 @@ void uninitvar_isxdigit(void) void uninitvar_proj(void) { double d; + // cppcheck-suppress uninitvar const std::complex dc(d,d); - // TODO cppcheck-suppress uninitvar (void)std::proj(dc); } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 37b2100f547..ff6490afb85 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -7251,6 +7251,24 @@ class TestUninitVar : public TestFixture { "[test.cpp:23]: (error) Uninitialized variable: s.t.j\n" "[test.cpp:27]: (error) Uninitialized variable: s.t.j\n", errout.str()); + + valueFlowUninit("struct S { int x; };\n" + "void f() {\n" + " int i;\n" + " S s(i);\n" + "}\n" + "void g() {\n" + " int i;\n" + " S t{ i };\n" + "}\n" + "void h() {\n" + " int i;\n" + " std::vector v(i);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: i\n" + "[test.cpp:8]: (error) Uninitialized variable: i\n" + "[test.cpp:12]: (error) Uninitialized variable: i\n", + errout.str()); } void uninitvar_memberfunction() { From ec9dbb31f4abda2625b52184fa9087db38bb1cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Fri, 1 Dec 2023 20:56:30 +0100 Subject: [PATCH 39/40] testrunner: make sure all redirected output is being consumed / some cleanups (#5714) --- test/fixture.cpp | 3 --- test/fixture.h | 14 +++++----- test/redirect.h | 46 +++++++++++++++----------------- test/testcmdlineparser.cpp | 52 +++++-------------------------------- test/testsymboldatabase.cpp | 2 +- test/testtokenlist.cpp | 2 +- 6 files changed, 36 insertions(+), 83 deletions(-) diff --git a/test/fixture.cpp b/test/fixture.cpp index a99a80a0d93..32863bbc637 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -34,9 +34,6 @@ #include "xml.h" -std::ostringstream errout; -std::ostringstream output; - /** * TestRegistry **/ diff --git a/test/fixture.h b/test/fixture.h index 1224e388dc1..dc1c62dcfe8 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -236,10 +236,16 @@ class TestFixture : public ErrorLogger { return SettingsBuilder(*this, std::move(settings)); } -public: + // TODO: make sure the output has been consumed in the test + std::ostringstream errout; + std::ostringstream output; + +private: void reportOut(const std::string &outmsg, Color c = Color::Reset) override; void reportErr(const ErrorMessage &msg) override; void run(const std::string &str); + +public: static void printHelp(); const std::string classname; @@ -248,12 +254,6 @@ class TestFixture : public ErrorLogger { static std::size_t runTests(const options& args); }; -// TODO: fix these -// NOLINTNEXTLINE(readability-redundant-declaration) -extern std::ostringstream errout; -// NOLINTNEXTLINE(readability-redundant-declaration) -extern std::ostringstream output; - // TODO: most asserts do not actually assert i.e. do not return #define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); NAME(); teardownTest(); } } while (false) #define ASSERT( CONDITION ) if (!assert_(__FILE__, __LINE__, (CONDITION))) return diff --git a/test/redirect.h b/test/redirect.h index 092e2c9bdd9..10e101c6101 100644 --- a/test/redirect.h +++ b/test/redirect.h @@ -19,12 +19,9 @@ #include #include +#include #include -// NOLINTNEXTLINE(readability-redundant-declaration) - TODO: fix this -extern std::ostringstream errout; -// NOLINTNEXTLINE(readability-redundant-declaration) - TODO: fix this -extern std::ostringstream output; /** * @brief Utility class for capturing cout and cerr to ostringstream buffers * for later use. Uses RAII to stop redirection when the object goes out of @@ -47,34 +44,35 @@ class RedirectOutputError { } /** Revert cout and cerr behaviour */ - ~RedirectOutputError() { + ~RedirectOutputError() noexcept(false) { std::cout.rdbuf(_oldCout); // restore cout's original streambuf std::cerr.rdbuf(_oldCerr); // restore cerrs's original streambuf - errout << _err.str(); - output << _out.str(); + { + const std::string s = _out.str(); + if (!s.empty()) + throw std::runtime_error("unconsumed stdout: " + s); // cppcheck-suppress exceptThrowInDestructor - FP #11031 + } + + { + const std::string s = _err.str(); + if (!s.empty()) + throw std::runtime_error("consumed stderr: " + s); + } } - /** Return what would be printed to cout. See also clearOutput() */ - std::string getOutput() const { - return _out.str(); - } - - /** Normally called after getOutput() to prevent same text to be returned - twice. */ - void clearOutput() { + /** Return what would be printed to cout. */ + std::string getOutput() { + std::string s = _out.str(); _out.str(""); + return s; } - /** Return what would be printed to cerr. See also clearErrout() */ - std::string getErrout() const { - return _err.str(); - } - - /** Normally called after getErrout() to prevent same text to be returned - twice. */ - void clearErrout() { + /** Return what would be printed to cerr. */ + std::string getErrout() { + std::string s = _err.str(); _err.str(""); + return s; } private: @@ -112,9 +110,7 @@ class SuppressOutput { #define REDIRECT RedirectOutputError redir #define GET_REDIRECT_OUTPUT redir.getOutput() -#define CLEAR_REDIRECT_OUTPUT redir.clearOutput() #define GET_REDIRECT_ERROUT redir.getErrout() -#define CLEAR_REDIRECT_ERROUT redir.clearErrout() #define SUPPRESS SuppressOutput supprout diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index d5998c078b9..9c493b8aa34 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -102,7 +102,6 @@ class TestCmdlineParser : public TestFixture { void teardownTestInternal() override { logger->destroy(); - // TODO: verify that the redirect output is empty } // add overload so the enums can be compared without a cast @@ -373,7 +372,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(1, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void helpshort() { @@ -381,7 +379,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "-h"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void helpshortExclusive() { @@ -389,7 +386,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--library=missing", "-h"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void helplong() { @@ -397,7 +393,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--help"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void helplongExclusive() { @@ -405,7 +400,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--library=missing", "--help"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); ASSERT(startsWith(logger->str(), "Cppcheck - A tool for static C/C++ code analysis")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void version() { @@ -413,7 +407,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--version"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("Cppcheck 2.13 dev\n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void versionWithCfg() { @@ -426,7 +419,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); // TODO: somehow the config is not loaded on some systems (void)logger->str(); //ASSERT_EQUALS("The Product\n", logger->str()); // TODO: include version? - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } // TODO: test --version with extraVersion @@ -436,7 +428,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--library=missing", "--version"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("Cppcheck 2.13 dev\n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void versionWithInvalidCfg() { @@ -446,7 +437,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--version"}; ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void onefile() { @@ -455,7 +445,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, (int)parser->getPathNames().size()); ASSERT_EQUALS("file.cpp", parser->getPathNames().at(0)); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void onepath() { @@ -464,7 +453,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(1, (int)parser->getPathNames().size()); ASSERT_EQUALS("src", parser->getPathNames().at(0)); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void optionwithoutfile() { @@ -473,7 +461,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS(0, (int)parser->getPathNames().size()); ASSERT_EQUALS("cppcheck: error: no C or C++ source files found.\n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void verboseshort() { @@ -482,7 +469,6 @@ class TestCmdlineParser : public TestFixture { settings->verbose = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->verbose); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void verboselong() { @@ -491,7 +477,6 @@ class TestCmdlineParser : public TestFixture { settings->verbose = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->verbose); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void debugSimplified() { @@ -500,7 +485,6 @@ class TestCmdlineParser : public TestFixture { settings->debugSimplified = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->debugSimplified); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void debugwarnings() { @@ -509,7 +493,6 @@ class TestCmdlineParser : public TestFixture { settings->debugwarnings = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->debugwarnings); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void forceshort() { @@ -518,7 +501,6 @@ class TestCmdlineParser : public TestFixture { settings->force = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->force); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void forcelong() { @@ -527,7 +509,6 @@ class TestCmdlineParser : public TestFixture { settings->force = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->force); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths1() { @@ -536,7 +517,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "-rp", "file.cpp"}; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths2() { @@ -545,7 +525,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--relative-paths", "file.cpp"}; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->relativePaths); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths3() { @@ -558,7 +537,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, settings->basePaths.size()); ASSERT_EQUALS("C:/foo", settings->basePaths[0]); ASSERT_EQUALS("C:/bar", settings->basePaths[1]); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void relativePaths4() { @@ -572,7 +550,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(2, settings->basePaths.size()); ASSERT_EQUALS("C:/foo", settings->basePaths[0]); ASSERT_EQUALS("C:/bar", settings->basePaths[1]); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void quietshort() { @@ -581,7 +558,6 @@ class TestCmdlineParser : public TestFixture { settings->quiet = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->quiet); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void quietlong() { @@ -590,7 +566,6 @@ class TestCmdlineParser : public TestFixture { settings->quiet = false; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(true, settings->quiet); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines_noarg() { @@ -623,7 +598,6 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("_WIN32=1", settings->userDefines); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines2() { @@ -632,7 +606,6 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("_WIN32=1;NODEBUG=1", settings->userDefines); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines3() { @@ -641,7 +614,6 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS("DEBUG=1", settings->userDefines); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void defines4() { @@ -650,7 +622,6 @@ class TestCmdlineParser : public TestFixture { settings->userDefines.clear(); ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("DEBUG=", settings->userDefines); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void enforceLanguage1() { @@ -1619,7 +1590,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--doc"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT(startsWith(logger->str(), "## ")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void docExclusive() { @@ -1627,7 +1597,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--library=missing", "--doc"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); ASSERT(startsWith(logger->str(), "## ")); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void showtimeSummary() { @@ -1706,8 +1675,9 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--errorlist"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger - ASSERT(startsWith(GET_REDIRECT_OUTPUT, ErrorMessage::getXMLHeader(""))); - ASSERT(endsWith(GET_REDIRECT_OUTPUT, "\n")); + const std::string errout_s = GET_REDIRECT_OUTPUT; + ASSERT(startsWith(errout_s, ErrorMessage::getXMLHeader(""))); + ASSERT(endsWith(errout_s, "\n")); } void errorlistWithCfg() { @@ -1725,8 +1695,9 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--library=missing", "--errorlist"}; ASSERT_EQUALS(CmdLineParser::Result::Exit, parser->parseFromArgs(3, argv)); ASSERT_EQUALS("", logger->str()); // empty since it is logged via ErrorLogger - ASSERT(startsWith(GET_REDIRECT_OUTPUT, "\n")); + const std::string errout_s = GET_REDIRECT_OUTPUT; + ASSERT(startsWith(errout_s, ErrorMessage::getXMLHeader(""))); + ASSERT(endsWith(errout_s, "\n")); } void errorlistWithInvalidCfg() { @@ -1736,7 +1707,6 @@ class TestCmdlineParser : public TestFixture { const char * const argv[] = {"cppcheck", "--errorlist"}; ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(2, argv)); ASSERT_EQUALS("cppcheck: error: could not load cppcheck.cfg - not a valid JSON - syntax error at line 1 near: \n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void ignorepathsnopath() { @@ -1998,7 +1968,6 @@ class TestCmdlineParser : public TestFixture { settings->typedefMaxTime = 0; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(12, settings->typedefMaxTime); - ASSERT_EQUALS("", logger->str()); } void typedefMaxTimeInvalid() { @@ -2074,7 +2043,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->addons.size()); ASSERT_EQUALS("misra", *settings->addons.cbegin()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void addonMissing() { @@ -2085,7 +2053,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(1, settings->addons.size()); ASSERT_EQUALS("misra2", *settings->addons.cbegin()); ASSERT_EQUALS("Did not find addon misra2.py\n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void signedChar() { @@ -2094,7 +2061,6 @@ class TestCmdlineParser : public TestFixture { settings->platform.defaultSign = '\0'; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS('s', settings->platform.defaultSign); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void signedChar2() { @@ -2103,7 +2069,6 @@ class TestCmdlineParser : public TestFixture { settings->platform.defaultSign = '\0'; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS('s', settings->platform.defaultSign); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void unsignedChar() { @@ -2112,7 +2077,6 @@ class TestCmdlineParser : public TestFixture { settings->platform.defaultSign = '\0'; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS('u', settings->platform.defaultSign); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void unsignedChar2() { @@ -2121,7 +2085,6 @@ class TestCmdlineParser : public TestFixture { settings->platform.defaultSign = '\0'; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS('u', settings->platform.defaultSign); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void signedCharUnsignedChar() { @@ -2130,7 +2093,6 @@ class TestCmdlineParser : public TestFixture { settings->platform.defaultSign = '\0'; ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv)); ASSERT_EQUALS('u', settings->platform.defaultSign); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } #ifdef HAVE_RULES @@ -2204,7 +2166,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->libraries.size()); ASSERT_EQUALS("posix", *settings->libraries.cbegin()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void libraryMissing() { @@ -2215,7 +2176,6 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(1, settings->libraries.size()); ASSERT_EQUALS("posix2", *settings->libraries.cbegin()); ASSERT_EQUALS("cppcheck: Failed to load library configuration file 'posix2'. File not found\n", logger->str()); - ASSERT_EQUALS("", GET_REDIRECT_OUTPUT); } void ignorepaths1() { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index d363f32454f..9a6a6f07884 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -76,7 +76,7 @@ class TestSymbolDatabase : public TestFixture { typetok = nullptr; } - const static SymbolDatabase* getSymbolDB_inner(Tokenizer& tokenizer, const char* code, const char* filename) { + const SymbolDatabase* getSymbolDB_inner(Tokenizer& tokenizer, const char* code, const char* filename) { errout.str(""); std::istringstream istr(code); return tokenizer.tokenize(istr, filename) ? tokenizer.getSymbolDatabase() : nullptr; diff --git a/test/testtokenlist.cpp b/test/testtokenlist.cpp index 2e764608ee4..0b979aa2df6 100644 --- a/test/testtokenlist.cpp +++ b/test/testtokenlist.cpp @@ -57,7 +57,7 @@ class TestTokenList : public TestFixture { ASSERT_EQUALS("0xF0000000", tokenlist.front()->str()); } - void inc() const { + void inc() { const char code[] = "a++1;1++b;"; errout.str(""); From ae27b613aed047e8fddfe59705571f6e0168f030 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 2 Dec 2023 14:15:10 +0100 Subject: [PATCH 40/40] Fix #12239 FP memleak when passing this in allocation (#5719) --- lib/checkleakautovar.cpp | 2 +- test/testleakautovar.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 61079e36b8f..2f9f5909dd4 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -263,7 +263,7 @@ static bool isLocalVarNoAutoDealloc(const Token *varTok, const bool isCpp) // non-pod variable if (isCpp) { // Possibly automatically deallocated memory - if (isAutoDealloc(var) && Token::Match(varTok, "%var% = new")) + if (isAutoDealloc(var) && Token::Match(varTok, "%var% [=({] new")) return false; if (!var->isPointer() && !var->typeStartToken()->isStandardType()) return false; diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 09891cf6631..6ca90726d4d 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -580,6 +580,20 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: p\n" "[test.cpp:4]: (error) Memory leak: q\n", errout.str()); + + check("struct S : B {\n" // #12239 + " void f();\n" + " void g();\n" + "};\n" + "void S::f() {\n" + " FD* fd(new FD(this));\n" + " fd->exec();\n" + "}\n" + "void S::g() {\n" + " FD* fd{ new FD(this) };\n" + " fd->exec();\n" + "}\n", true); + ASSERT_EQUALS("", errout.str()); } void isAutoDealloc() {