From a360c0bc0490880ffb8340caa53975014c43721a Mon Sep 17 00:00:00 2001 From: glank Date: Sun, 21 Sep 2025 20:34:42 +0200 Subject: [PATCH 01/29] Remove Preprocessor::loadFiles --- lib/cppcheck.cpp | 3 --- lib/path.cpp | 1 - lib/preprocessor.cpp | 10 ---------- lib/preprocessor.h | 2 -- test/testcppcheck.cpp | 1 - 5 files changed, 17 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index ad46f2651cd..fc1a51de645 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -993,9 +993,6 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string Preprocessor preprocessor(mSettings, mErrorLogger, file.lang()); - if (!preprocessor.loadFiles(tokens1, files)) - return mLogger->exitcode(); - if (!mSettings.plistOutput.empty()) { std::string filename2; if (file.spath().find('/') != std::string::npos) diff --git a/lib/path.cpp b/lib/path.cpp index 6770267cfda..2e9e7b6a439 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -230,7 +230,6 @@ bool Path::acceptFile(const std::string &path, const std::set &extr static bool hasEmacsCppMarker(const char* path) { // TODO: identify is called three times for each file - // Preprocessor::loadFiles() -> createDUI() // Preprocessor::preprocess() -> createDUI() // TokenList::createTokens() -> TokenList::determineCppC() #ifdef LOG_EMACS_MARKER diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index f7ccc9c0dc5..8b104813438 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -773,16 +773,6 @@ void Preprocessor::handleErrors(const simplecpp::OutputList& outputList, bool th } } -bool Preprocessor::loadFiles(const simplecpp::TokenList &rawtokens, std::vector &files) -{ - const simplecpp::DUI dui = createDUI(mSettings, "", mLang); - - simplecpp::OutputList outputList; - mFileCache = simplecpp::load(rawtokens, files, dui, &outputList); - handleErrors(outputList, false); - return !hasErrors(outputList); -} - void Preprocessor::removeComments(simplecpp::TokenList &tokens) const { tokens.removeComments(); diff --git a/lib/preprocessor.h b/lib/preprocessor.h index c1c034e2904..34ae6dfff72 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -120,8 +120,6 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { std::vector getRemarkComments(const simplecpp::TokenList &tokens) const; - bool loadFiles(const simplecpp::TokenList &rawtokens, std::vector &files); - void removeComments(simplecpp::TokenList &tokens) const; static void setPlatformInfo(simplecpp::TokenList &tokens, const Settings& settings); diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index c4b818b79b9..125ed6ebfd0 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -539,7 +539,6 @@ class TestCppcheck : public TestFixture { const simplecpp::TokenList tokens(istr, files, "m1.c"); Preprocessor preprocessor(settings, errorLogger, Standards::Language::C); - ASSERT(preprocessor.loadFiles(tokens, files)); AddonInfo premiumaddon; premiumaddon.name = "premiumaddon.json"; From d649490817e376cdadd4e29c51f5be97239adb89 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:18:53 +0200 Subject: [PATCH 02/29] Incremental configurations test --- externals/simplecpp/simplecpp.cpp | 3 + externals/simplecpp/simplecpp.h | 7 ++ lib/cppcheck.cpp | 32 ++++++-- lib/path.cpp | 1 + lib/preprocessor.cpp | 118 +++++++++++++----------------- lib/preprocessor.h | 13 +++- test/helpers.cpp | 13 ++-- test/helpers.h | 2 +- test/testcppcheck.cpp | 1 + test/testpreprocessor.cpp | 6 +- test/testtokenize.cpp | 3 +- 11 files changed, 115 insertions(+), 84 deletions(-) diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index fd3275499a3..85b87eee836 100755 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -3034,6 +3034,9 @@ std::pair simplecpp::FileDataCache::tryload(FileDat mIdMap.emplace(fileId, data); mData.emplace_back(data); + if (mCallback) + mCallback(*data); + return {data, true}; } diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 8268fa8d6a3..e3bd7a7d629 100755 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -414,6 +414,12 @@ namespace simplecpp { return mData.cend(); } + using callback_type = std::function; + + void set_callback(callback_type cb) { + mCallback = cb; + } + private: struct FileID { #ifdef SIMPLECPP_WINDOWS @@ -460,6 +466,7 @@ namespace simplecpp { container_type mData; name_map_type mNameMap; id_map_type mIdMap; + callback_type mCallback; }; SIMPLECPP_LIB long long characterLiteralToLL(const std::string& str); diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index fc1a51de645..4a824e5f796 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -105,6 +105,11 @@ class CppCheck::CppCheckLogger : public ErrorLogger closePlist(); } + std::vector& remarkComments() + { + return mRemarkComments; + } + void setRemarkComments(std::vector remarkComments) { mRemarkComments = std::move(remarkComments); @@ -1010,14 +1015,14 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string } // Parse comments and then remove them - mLogger->setRemarkComments(preprocessor.getRemarkComments(tokens1)); + preprocessor.addRemarkComments(tokens1, mLogger->remarkComments()); preprocessor.inlineSuppressions(tokens1, mSuppressions.nomsg); if (mSettings.dump || !mSettings.addons.empty()) { std::ostringstream oss; mSuppressions.nomsg.dump(oss); dumpProlog += oss.str(); } - preprocessor.removeComments(tokens1); + tokens1.removeComments(); if (!mSettings.buildDir.empty()) { analyzerInformation.reset(new AnalyzerInformation); @@ -1039,19 +1044,34 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string } // Get directives - std::list directives = preprocessor.createDirectives(tokens1); + std::list directives; + preprocessor.createDirectives(tokens1, directives); preprocessor.simplifyPragmaAsm(tokens1); + std::list configurations; + std::set configDefines = { "__cplusplus" }; + + preprocessor.setLoadCallback([&](auto& data) { + preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); + preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); + data.tokens.removeComments(); + preprocessor.createDirectives(data.tokens, directives); + preprocessor.simplifyPragmaAsm(data.tokens); + if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) + preprocessor.getConfigs(data.filename, data.tokens, configDefines, configurations); + }); + Preprocessor::setPlatformInfo(tokens1, mSettings); // Get configurations.. - std::set configurations; if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) { Timer::run("Preprocessor::getConfigs", mSettings.showtime, &s_timerResults, [&]() { - configurations = preprocessor.getConfigs(tokens1); + configurations = { "" }; + preprocessor.getConfigs(file.spath(), tokens1, configDefines, configurations); + preprocessor.loadFiles(tokens1, files); }); } else { - configurations.insert(mSettings.userDefines); + configurations = { mSettings.userDefines }; } if (mSettings.checkConfiguration) { diff --git a/lib/path.cpp b/lib/path.cpp index 2e9e7b6a439..6770267cfda 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -230,6 +230,7 @@ bool Path::acceptFile(const std::string &path, const std::set &extr static bool hasEmacsCppMarker(const char* path) { // TODO: identify is called three times for each file + // Preprocessor::loadFiles() -> createDUI() // Preprocessor::preprocess() -> createDUI() // TokenList::createTokens() -> TokenList::determineCppC() #ifdef LOG_EMACS_MARKER diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 8b104813438..8cbfa3ae1b0 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -306,9 +306,6 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens, Suppre return; std::list err; ::addInlineSuppressions(tokens, mSettings, suppressions, err); - for (const auto &filedata : mFileCache) { - ::addInlineSuppressions(filedata->tokens, mSettings, suppressions, err); - } for (const BadInlineSuppression &bad : err) { error(bad.file, bad.line, bad.errmsg); } @@ -324,43 +321,28 @@ std::vector Preprocessor::getRemarkComments(const simplecpp::Toke return ret; } -std::list Preprocessor::createDirectives(const simplecpp::TokenList &tokens) const +void Preprocessor::createDirectives(const simplecpp::TokenList &tokens, std::list& directives) const { - // directive list.. - std::list directives; - - std::vector list; - list.reserve(1U + mFileCache.size()); - list.push_back(&tokens); - std::transform(mFileCache.cbegin(), mFileCache.cend(), std::back_inserter(list), - [](const std::unique_ptr &filedata) { - return &filedata->tokens; - }); - - for (const simplecpp::TokenList *tokenList : list) { - for (const simplecpp::Token *tok = tokenList->cfront(); tok; tok = tok->next) { - if ((tok->op != '#') || (tok->previous && tok->previous->location.line == tok->location.line)) - continue; - if (tok->next && tok->next->str() == "endfile") + for (const simplecpp::Token *tok = tokens.cfront(); tok; tok = tok->next) { + if ((tok->op != '#') || (tok->previous && tok->previous->location.line == tok->location.line)) + continue; + if (tok->next && tok->next->str() == "endfile") + continue; + Directive directive(tok->location, ""); + for (const simplecpp::Token *tok2 = tok; tok2 && tok2->location.line == directive.linenr; tok2 = tok2->next) { + if (tok2->comment) continue; - Directive directive(tok->location, ""); - for (const simplecpp::Token *tok2 = tok; tok2 && tok2->location.line == directive.linenr; tok2 = tok2->next) { - if (tok2->comment) - continue; - if (!directive.str.empty() && (tok2->location.col > tok2->previous->location.col + tok2->previous->str().size())) - directive.str += ' '; - if (directive.str == "#" && tok2->str() == "file") - directive.str += "include"; - else - directive.str += tok2->str(); - - directive.strTokens.emplace_back(*tok2); - } - directives.push_back(std::move(directive)); + if (!directive.str.empty() && (tok2->location.col > tok2->previous->location.col + tok2->previous->str().size())) + directive.str += ' '; + if (directive.str == "#" && tok2->str() == "file") + directive.str += "include"; + else + directive.str += tok2->str(); + + directive.strTokens.emplace_back(*tok2); } + directives.push_back(std::move(directive)); } - - return directives; } static std::string readcondition(const simplecpp::Token *iftok, const std::set &defined, const std::set &undefined) @@ -512,7 +494,13 @@ static const simplecpp::Token *gotoEndIf(const simplecpp::Token *cmdtok) return nullptr; } -static void getConfigs(const simplecpp::TokenList &tokens, std::set &defined, const std::string &userDefines, const std::set &undefined, std::set &ret) +static void insertUniqueCfg(std::list& configs, std::string&& cfg) +{ + if (std::find(configs.begin(), configs.end(), cfg) == configs.end()) + configs.push_back(std::move(cfg)); +} + +static void getConfigs(const simplecpp::TokenList &tokens, std::set &defined, const std::string &userDefines, const std::set &undefined, std::list &ret) { std::vector configs_if; std::vector configs_ifndef; @@ -573,7 +561,7 @@ static void getConfigs(const simplecpp::TokenList &tokens, std::set configs_if.push_back((cmdtok->str() == "ifndef") ? std::string() : config); configs_ifndef.push_back((cmdtok->str() == "ifndef") ? std::move(config) : std::string()); - ret.insert(cfg(configs_if,userDefines)); + insertUniqueCfg(ret, cfg(configs_if,userDefines)); } else if (cmdtok->str() == "elif" || cmdtok->str() == "else") { if (getConfigsElseIsFalse(configs_if,userDefines)) { tok = gotoEndIf(tok); @@ -602,10 +590,10 @@ static void getConfigs(const simplecpp::TokenList &tokens, std::set if (isUndefined(config,undefined)) config.clear(); configs_if.push_back(std::move(config)); - ret.insert(cfg(configs_if, userDefines)); + insertUniqueCfg(ret, cfg(configs_if, userDefines)); } else if (!configs_ifndef.empty()) { configs_if.push_back(configs_ifndef.back()); - ret.insert(cfg(configs_if, userDefines)); + insertUniqueCfg(ret, cfg(configs_if, userDefines)); } } else if (cmdtok->str() == "endif" && !sameline(tok, cmdtok->next)) { if (!configs_if.empty()) @@ -615,19 +603,19 @@ static void getConfigs(const simplecpp::TokenList &tokens, std::set } else if (cmdtok->str() == "error") { if (!configs_ifndef.empty() && !configs_ifndef.back().empty()) { if (configs_ifndef.size() == 1U) - ret.erase(emptyString); + ret.remove(emptyString); std::vector configs(configs_if); configs.push_back(configs_ifndef.back()); - ret.erase(cfg(configs, userDefines)); - std::set temp; + ret.remove(cfg(configs, userDefines)); + std::list temp; temp.swap(ret); - for (const std::string &c: temp) { + for (std::string &c: temp) { if (c.find(configs_ifndef.back()) != std::string::npos) - ret.insert(c); + insertUniqueCfg(ret, std::move(c)); else if (c.empty()) - ret.insert(""); + insertUniqueCfg(ret, ""); else - ret.insert(c + ";" + configs_ifndef.back()); + insertUniqueCfg(ret, c + ";" + configs_ifndef.back()); } if (!elseError.empty()) elseError += ';'; @@ -637,10 +625,10 @@ static void getConfigs(const simplecpp::TokenList &tokens, std::set const std::string &last = configs_if.back(); if (last.size() > 2U && last.compare(last.size()-2U,2,"=0") == 0) { std::vector configs(configs_if); - ret.erase(cfg(configs, userDefines)); + ret.remove(cfg(configs, userDefines)); configs[configs.size() - 1U] = last.substr(0,last.size()-2U); if (configs.size() == 1U) - ret.erase(""); + ret.remove(""); if (!elseError.empty()) elseError += ';'; elseError += cfg(configs, userDefines); @@ -651,26 +639,17 @@ static void getConfigs(const simplecpp::TokenList &tokens, std::set } } if (!elseError.empty()) - ret.insert(std::move(elseError)); + insertUniqueCfg(ret, std::move(elseError)); } -std::set Preprocessor::getConfigs(const simplecpp::TokenList &tokens) const +void Preprocessor::getConfigs(const std::string& filename, const simplecpp::TokenList &tokens, std::set& defined, std::list& configs) const { - std::set ret = { "" }; if (!tokens.cfront()) - return ret; - - std::set defined = { "__cplusplus" }; - - ::getConfigs(tokens, defined, mSettings.userDefines, mSettings.userUndefs, ret); - - for (const auto &filedata : mFileCache) { - if (!mSettings.configurationExcluded(filedata->filename)) - ::getConfigs(filedata->tokens, defined, mSettings.userDefines, mSettings.userUndefs, ret); - } + return; - return ret; + if (!mSettings.configurationExcluded(filename)) + ::getConfigs(tokens, defined, mSettings.userDefines, mSettings.userUndefs, configs); } static void splitcfg(const std::string &cfg, std::list &defines, const std::string &defaultValue) @@ -773,6 +752,16 @@ void Preprocessor::handleErrors(const simplecpp::OutputList& outputList, bool th } } +bool Preprocessor::loadFiles(const simplecpp::TokenList &rawtokens, std::vector &files) +{ + const simplecpp::DUI dui = createDUI(mSettings, "", mLang); + + simplecpp::OutputList outputList; + mFileCache = simplecpp::load(rawtokens, files, dui, &outputList); + handleErrors(outputList, false); + return !hasErrors(outputList); +} + void Preprocessor::removeComments(simplecpp::TokenList &tokens) const { tokens.removeComments(); @@ -985,9 +974,6 @@ std::size_t Preprocessor::calculateHash(const simplecpp::TokenList &tokens1, con void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList &tokenList) const { Preprocessor::simplifyPragmaAsmPrivate(tokenList); - for (const auto &filedata : mFileCache) { - Preprocessor::simplifyPragmaAsmPrivate(filedata->tokens); - } } void Preprocessor::simplifyPragmaAsmPrivate(simplecpp::TokenList &tokenList) diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 34ae6dfff72..f7ecb26fa1b 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -114,11 +114,14 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { void inlineSuppressions(const simplecpp::TokenList &tokens, SuppressionList &suppressions); - std::list createDirectives(const simplecpp::TokenList &tokens) const; + void createDirectives(const simplecpp::TokenList &tokens, std::list& directives) const; - std::set getConfigs(const simplecpp::TokenList &tokens) const; + void getConfigs(const std::string& filename, const simplecpp::TokenList& tokens, std::set& defined, std::list& configs) const; std::vector getRemarkComments(const simplecpp::TokenList &tokens) const; + void addRemarkComments(const simplecpp::TokenList& tokens, std::vector& remarkComments) const; + + bool loadFiles(const simplecpp::TokenList& rawtokens, std::vector& files); void removeComments(simplecpp::TokenList &tokens) const; @@ -148,6 +151,10 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { static bool hasErrors(const simplecpp::Output &output); + void setLoadCallback(simplecpp::FileDataCache::callback_type cb) { + mFileCache.set_callback(std::move(cb)); + } + private: void handleErrors(const simplecpp::OutputList &outputList, bool throwError); @@ -168,8 +175,6 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { static bool hasErrors(const simplecpp::OutputList &outputList); - void addRemarkComments(const simplecpp::TokenList &tokens, std::vector &remarkComments) const; - const Settings& mSettings; ErrorLogger &mErrorLogger; diff --git a/test/helpers.cpp b/test/helpers.cpp index 222fc384784..5f92504964b 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -117,7 +117,7 @@ ScopedFile::~ScopedFile() { // TODO: we should be using the actual Preprocessor implementation std::string PreprocessorHelper::getcodeforcfg(const Settings& settings, ErrorLogger& errorlogger, const std::string &filedata, const std::string &cfg, const std::string &filename, SuppressionList *inlineSuppression) { - std::map cfgcode = getcode(settings, errorlogger, filedata.c_str(), std::set{cfg}, filename, inlineSuppression); + std::map cfgcode = getcode(settings, errorlogger, filedata.c_str(), std::list{cfg}, filename, inlineSuppression); const auto it = cfgcode.find(cfg); if (it == cfgcode.end()) return ""; @@ -129,7 +129,7 @@ std::map PreprocessorHelper::getcode(const Settings& s return getcode(settings, errorlogger, code, {}, filename, nullptr); } -std::map PreprocessorHelper::getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::set cfgs, const std::string &filename, SuppressionList *inlineSuppression) +std::map PreprocessorHelper::getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::list cfgs, const std::string &filename, SuppressionList *inlineSuppression) { simplecpp::OutputList outputList; std::vector files; @@ -148,8 +148,10 @@ std::map PreprocessorHelper::getcode(const Settings& s return {}; std::map cfgcode; - if (cfgs.empty()) - cfgs = preprocessor.getConfigs(tokens); + if (cfgs.empty()) { + std::set configDefines = { "__cplusplus" }; + preprocessor.getConfigs(filename, tokens, configDefines, cfgs); + } for (const std::string & config : cfgs) { try { // TODO: also preserve location information when #include exists - enabling that will fail since #line is treated like a regular token @@ -174,7 +176,8 @@ void SimpleTokenizer2::preprocess(const char code[], std::vector &f // Tokenizer.. tokenizer.list.createTokens(std::move(tokens2)); - std::list directives = preprocessor.createDirectives(tokens1); + std::list directives; + preprocessor.createDirectives(tokens1, directives); tokenizer.setDirectives(std::move(directives)); } diff --git a/test/helpers.h b/test/helpers.h index 1b803dcb679..5ed541b5a92 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -177,7 +177,7 @@ class PreprocessorHelper static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], const std::string &filename = "file.c"); private: - static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::set cfgs, const std::string &filename, SuppressionList *inlineSuppression); + static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::list cfgs, const std::string &filename, SuppressionList *inlineSuppression); }; namespace cppcheck { diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 125ed6ebfd0..c4b818b79b9 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -539,6 +539,7 @@ class TestCppcheck : public TestFixture { const simplecpp::TokenList tokens(istr, files, "m1.c"); Preprocessor preprocessor(settings, errorLogger, Standards::Language::C); + ASSERT(preprocessor.loadFiles(tokens, files)); AddonInfo premiumaddon; premiumaddon.name = "premiumaddon.json"; diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index fd290d75c88..97e01cc6711 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -312,7 +312,11 @@ class TestPreprocessor : public TestFixture { simplecpp::TokenList tokens(code, size-1,files); tokens.removeComments(); Preprocessor preprocessor(settings, *this, Standards::Language::C); // TODO: do we need to consider #file? - const std::set configs = preprocessor.getConfigs(tokens); + std::list configs; + { + std::set configDefines = { "__cplusplus" }; + preprocessor.getConfigs("", tokens, configDefines, configs); + } std::string ret; for (const std::string & config : configs) ret += config + '\n'; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 84d94908454..624b543244a 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -570,7 +570,8 @@ class TestTokenizer : public TestFixture { std::vector files; const simplecpp::TokenList tokens1(istr, files, filename, &outputList); Preprocessor preprocessor(settings, *this, Path::identify(tokens1.getFiles()[0], false)); - std::list directives = preprocessor.createDirectives(tokens1); + std::list directives; + preprocessor.createDirectives(tokens1, directives); TokenList tokenlist{settings, Path::identify(filename, false)}; Tokenizer tokenizer(std::move(tokenlist), *this); From 5b6ac46aefc04808c88d1753e6bcf8c8dc7aeb67 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:24:18 +0200 Subject: [PATCH 03/29] Include functional --- externals/simplecpp/simplecpp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 192c99f8a41..d6f48634ebc 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include From 9f9151c4c55d7fe0420dad30addba0121c5a9003 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:30:21 +0200 Subject: [PATCH 04/29] Fix merge conflicts --- test/helpers.cpp | 51 --------------------------------------- test/helpers.h | 21 ---------------- test/testpreprocessor.cpp | 10 +++++--- 3 files changed, 6 insertions(+), 76 deletions(-) diff --git a/test/helpers.cpp b/test/helpers.cpp index d07f9e515c9..036013499ab 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -111,57 +111,6 @@ ScopedFile::~ScopedFile() { } } -// TODO: we should be using the actual Preprocessor implementation -std::string PreprocessorHelper::getcodeforcfg(const Settings& settings, ErrorLogger& errorlogger, const std::string &filedata, const std::string &cfg, const std::string &filename, SuppressionList *inlineSuppression) -{ - std::map cfgcode = getcode(settings, errorlogger, filedata.c_str(), std::list{cfg}, filename, inlineSuppression); - const auto it = cfgcode.find(cfg); - if (it == cfgcode.end()) - return ""; - return it->second; -} - -std::map PreprocessorHelper::getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], const std::string &filename) -{ - return getcode(settings, errorlogger, code, {}, filename, nullptr); -} - -std::map PreprocessorHelper::getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::list cfgs, const std::string &filename, SuppressionList *inlineSuppression) -{ - simplecpp::OutputList outputList; - std::vector files; - - std::istringstream istr(code); - simplecpp::TokenList tokens(istr, files, Path::simplifyPath(filename), &outputList); - Preprocessor preprocessor(settings, errorlogger, Path::identify(tokens.getFiles()[0], false)); - if (inlineSuppression) - preprocessor.inlineSuppressions(tokens, *inlineSuppression); - preprocessor.removeComments(tokens); - preprocessor.simplifyPragmaAsm(tokens); - - preprocessor.reportOutput(outputList, true); - - if (Preprocessor::hasErrors(outputList)) - return {}; - - std::map cfgcode; - if (cfgs.empty()) { - std::set configDefines = { "__cplusplus" }; - preprocessor.getConfigs(filename, tokens, configDefines, cfgs); - } - for (const std::string & config : cfgs) { - try { - // TODO: also preserve location information when #include exists - enabling that will fail since #line is treated like a regular token - cfgcode[config] = preprocessor.getcode(tokens, config, files, std::string(code).find("#file") != std::string::npos); - } catch (const simplecpp::Output &) { - cfgcode[config] = ""; - } - } - - return cfgcode; -} - -void SimpleTokenizer2::preprocess(const char code[], std::vector &files, const std::string& file0, Tokenizer& tokenizer, ErrorLogger& errorlogger) void SimpleTokenizer2::preprocess(const char* code, std::size_t size, std::vector &files, const std::string& file0, Tokenizer& tokenizer, ErrorLogger& errorlogger) { const simplecpp::TokenList tokens1(code, size, files, file0); diff --git a/test/helpers.h b/test/helpers.h index 86e50e464df..bb05598d8ea 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -165,27 +165,6 @@ class ScopedFile { const std::string mFullPath; }; -class PreprocessorHelper -{ -public: - /** - * Get preprocessed code for a given configuration - * - * Note: for testing only. - * - * @param filedata file data including preprocessing 'if', 'define', etc - * @param cfg configuration to read out - * @param filename name of source file - * @param inlineSuppression the inline suppressions - */ - static std::string getcodeforcfg(const Settings& settings, ErrorLogger& errorlogger, const std::string &filedata, const std::string &cfg, const std::string &filename, SuppressionList *inlineSuppression = nullptr); - - static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], const std::string &filename = "file.c"); - -private: - static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::list cfgs, const std::string &filename, SuppressionList *inlineSuppression); -}; - namespace cppcheck { template std::size_t count_all_of(const std::string& str, T sub) { diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 79fa4a9bd27..6521485bccb 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -93,7 +93,7 @@ class TestPreprocessor : public TestFixture { static std::string getcodeforcfg(const Settings& settings, ErrorLogger& errorlogger, const char* code, std::size_t size, const std::string &cfg, const std::string &filename, SuppressionList *inlineSuppression = nullptr) { - std::map cfgcode = getcode(settings, errorlogger, code, size, std::set{cfg}, filename, inlineSuppression); + std::map cfgcode = getcode(settings, errorlogger, code, size, std::list{cfg}, filename, inlineSuppression); const auto it = cfgcode.find(cfg); if (it == cfgcode.end()) return ""; @@ -112,7 +112,7 @@ class TestPreprocessor : public TestFixture { return getcode(settings, errorlogger, code, size-1, {}, filename, nullptr); } - static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char* code, std::size_t size, std::set cfgs, const std::string &filename, SuppressionList *inlineSuppression) + static std::map getcode(const Settings& settings, ErrorLogger& errorlogger, const char* code, std::size_t size, std::list cfgs, const std::string &filename, SuppressionList *inlineSuppression) { simplecpp::OutputList outputList; std::vector files; @@ -131,8 +131,10 @@ class TestPreprocessor : public TestFixture { return {}; std::map cfgcode; - if (cfgs.empty()) - cfgs = preprocessor.getConfigs(tokens); + if (cfgs.empty()) { + std::set configDefines = { "__cplusplus" }; + preprocessor.getConfigs(filename, tokens, configDefines, cfgs); + } for (const std::string & config : cfgs) { try { const bool writeLocations = (strstr(code, "#file") != nullptr) || (strstr(code, "#include") != nullptr); From 41636da982780df32df4364961e257653306f54e Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:33:53 +0200 Subject: [PATCH 05/29] Sort configs in testpreprocessor --- test/testpreprocessor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 6521485bccb..a677556dfa6 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -375,6 +375,7 @@ class TestPreprocessor : public TestFixture { std::set configDefines = { "__cplusplus" }; preprocessor.getConfigs("", tokens, configDefines, configs); } + configs.sort(); std::string ret; for (const std::string & config : configs) ret += config + '\n'; From 1acae0f248cbc23b42123434b332451274d9a98f Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:34:20 +0200 Subject: [PATCH 06/29] Use explicit type in lambda --- lib/cppcheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 4317de48680..a536b29b3f2 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1044,7 +1044,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str std::list configurations; std::set configDefines = { "__cplusplus" }; - preprocessor.setLoadCallback([&](auto& data) { + preprocessor.setLoadCallback([&](simplecpp::FileData& data) { preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); data.tokens.removeComments(); From 8c2c4a7bce106ad55854f2572b09a4d47e1cba40 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:43:16 +0200 Subject: [PATCH 07/29] Add empty config in testpreprocessor --- test/testpreprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index a677556dfa6..b7d49f6dfbd 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -370,7 +370,7 @@ class TestPreprocessor : public TestFixture { simplecpp::TokenList tokens(code,files); tokens.removeComments(); Preprocessor preprocessor(settings, *this, Standards::Language::C); // TODO: do we need to consider #file? - std::list configs; + std::list configs = { "" }; { std::set configDefines = { "__cplusplus" }; preprocessor.getConfigs("", tokens, configDefines, configs); From dae4be476d89bafe9b0ff1a7b70a991e422e73f6 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 20:56:39 +0200 Subject: [PATCH 08/29] Fix unused function errors --- lib/cppcheck.cpp | 5 ----- lib/preprocessor.cpp | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index a536b29b3f2..5e0555b2663 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -104,11 +104,6 @@ class CppCheck::CppCheckLogger : public ErrorLogger return mRemarkComments; } - void setRemarkComments(std::vector remarkComments) - { - mRemarkComments = std::move(remarkComments); - } - void setLocationMacros(const Token* startTok, const std::vector& files) { mLocationMacros.clear(); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 084661ac67f..99425335651 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -312,6 +312,7 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens, Suppre } } +// cppcheck-suppress unusedFunction std::vector Preprocessor::getRemarkComments(const simplecpp::TokenList &tokens) const { std::vector ret; From 423152928072530820a2ef62e52f201cadc345c7 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 21:11:20 +0200 Subject: [PATCH 09/29] Sort configurations in cppcheck --- lib/cppcheck.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 5e0555b2663..7c01c361ddf 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1057,6 +1057,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str configurations = { "" }; preprocessor.getConfigs(file.spath(), tokens1, configDefines, configurations); preprocessor.loadFiles(tokens1, files); + configurations.sort(); }); } else { configurations = { mSettings.userDefines }; From 7e8325c8725e4b9f448de5fe5bd7012d7045b2e0 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 21:11:32 +0200 Subject: [PATCH 10/29] Fix empty configs in testpreprocessor --- test/testpreprocessor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index b7d49f6dfbd..f4666d0de5e 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -132,6 +132,7 @@ class TestPreprocessor : public TestFixture { std::map cfgcode; if (cfgs.empty()) { + cfgs.push_back(""); std::set configDefines = { "__cplusplus" }; preprocessor.getConfigs(filename, tokens, configDefines, cfgs); } From 9ad91441d50f9a01d112099347241418ef7064fd Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 21:13:48 +0200 Subject: [PATCH 11/29] Fix formatting --- lib/cppcheck.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 7c01c361ddf..20a12f56b3c 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1040,14 +1040,14 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str std::set configDefines = { "__cplusplus" }; preprocessor.setLoadCallback([&](simplecpp::FileData& data) { - preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); - preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); - data.tokens.removeComments(); - preprocessor.createDirectives(data.tokens, directives); - preprocessor.simplifyPragmaAsm(data.tokens); - if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) - preprocessor.getConfigs(data.filename, data.tokens, configDefines, configurations); - }); + preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); + preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); + data.tokens.removeComments(); + preprocessor.createDirectives(data.tokens, directives); + preprocessor.simplifyPragmaAsm(data.tokens); + if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) + preprocessor.getConfigs(data.filename, data.tokens, configDefines, configurations); + }); Preprocessor::setPlatformInfo(tokens1, mSettings); From f29cc98190fa90aef7f8866c75e5e132898d5e47 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 21:46:39 +0200 Subject: [PATCH 12/29] Fix clang-tidy issue --- test/testpreprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index f4666d0de5e..c83fc3a73c0 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -132,7 +132,7 @@ class TestPreprocessor : public TestFixture { std::map cfgcode; if (cfgs.empty()) { - cfgs.push_back(""); + cfgs.emplace_back(""); std::set configDefines = { "__cplusplus" }; preprocessor.getConfigs(filename, tokens, configDefines, cfgs); } From c96c859cb546a55a8592bdb700e356d50b6ebf30 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 21:47:24 +0200 Subject: [PATCH 13/29] Fix loadFiles overwriting mFileCache --- lib/preprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 99425335651..6cbe3afecfe 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -759,7 +759,7 @@ bool Preprocessor::loadFiles(const simplecpp::TokenList &rawtokens, std::vector< const simplecpp::DUI dui = createDUI(mSettings, "", mLang); simplecpp::OutputList outputList; - mFileCache = simplecpp::load(rawtokens, files, dui, &outputList); + mFileCache = simplecpp::load(rawtokens, files, dui, &outputList, std::move(mFileCache)); handleErrors(outputList, false); return !hasErrors(outputList); } From 028e360fe485429106518db2644c0d8ca0a051da Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 21:47:40 +0200 Subject: [PATCH 14/29] Add some comments --- lib/cppcheck.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 20a12f56b3c..5af4136a962 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1036,15 +1036,19 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str preprocessor.createDirectives(tokens1, directives); preprocessor.simplifyPragmaAsm(tokens1); + // This needs to be a linked list to allow new configurations to be discovered + // and added while iterating and checking existing configurations std::list configurations; std::set configDefines = { "__cplusplus" }; preprocessor.setLoadCallback([&](simplecpp::FileData& data) { + // Do preprocessing on included file preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); data.tokens.removeComments(); preprocessor.createDirectives(data.tokens, directives); preprocessor.simplifyPragmaAsm(data.tokens); + // Discover new configurations from included file if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) preprocessor.getConfigs(data.filename, data.tokens, configDefines, configurations); }); From 147315dd4b6674c7534af769e5bea3800b57b02d Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 23:16:15 +0200 Subject: [PATCH 15/29] Fix dump and plist --- lib/cppcheck.cpp | 26 ++++++++++---------------- lib/errorlogger.cpp | 9 ++------- lib/errorlogger.h | 20 +++++++++++++++----- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 5af4136a962..e69ade453f5 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -123,16 +123,17 @@ class CppCheck::CppCheckLogger : public ErrorLogger mErrorList.clear(); } - void openPlist(const std::string& filename, const std::vector& files) + void openPlist(const std::string& filename, const std::vector* files) { mPlistFile.open(filename); - mPlistFile << ErrorLogger::plistHeader(version(), files); + mPlistFile << ErrorLogger::plistHeader(version()); + mPlistFilenames = files; } void closePlist() { if (mPlistFile.is_open()) { - mPlistFile << ErrorLogger::plistFooter(); + mPlistFile << ErrorLogger::plistFooter(mPlistFilenames); mPlistFile.close(); } } @@ -275,6 +276,7 @@ class CppCheck::CppCheckLogger : public ErrorLogger using Location = std::pair; std::map> mLocationMacros; // What macros are used on a location? + const std::vector* mPlistFilenames{}; std::ofstream mPlistFile; unsigned int mExitCode{}; @@ -994,22 +996,12 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str filename2 = file.spath(); const std::size_t fileNameHash = std::hash {}(file.spath()); filename2 = mSettings.plistOutput + filename2.substr(0, filename2.find('.')) + "_" + std::to_string(fileNameHash) + ".plist"; - mLogger->openPlist(filename2, files); - } - - std::string dumpProlog; - if (mSettings.dump || !mSettings.addons.empty()) { - dumpProlog += getDumpFileContentsRawTokens(files, tokens1); + mLogger->openPlist(filename2, &files); } // Parse comments and then remove them preprocessor.addRemarkComments(tokens1, mLogger->remarkComments()); preprocessor.inlineSuppressions(tokens1, mSuppressions.nomsg); - if (mSettings.dump || !mSettings.addons.empty()) { - std::ostringstream oss; - mSuppressions.nomsg.dump(oss); - dumpProlog += oss.str(); - } tokens1.removeComments(); if (!mSettings.buildDir.empty()) { @@ -1106,7 +1098,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str createDumpFile(mSettings, file, fileIndex, fdump, dumpFile); if (fdump.is_open()) { fdump << getLibraryDumpData(); - fdump << dumpProlog; if (!mSettings.dump) filesDeleter.addFile(dumpFile); } @@ -1289,8 +1280,11 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str } // TODO: will not be closed if we encountered an exception - // dumped all configs, close root element now if (fdump.is_open()) { + // dump all filenames, raw tokens, suppressions + fdump << getDumpFileContentsRawTokens(files, tokens1); + mSuppressions.nomsg.dump(fdump); + // dumped all configs, close root element now fdump << "" << std::endl; fdump.close(); } diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index 47157f7a504..6992f514add 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -818,7 +818,7 @@ std::string ErrorLogger::toxml(const std::string &str) return xml; } -std::string ErrorLogger::plistHeader(const std::string &version, const std::vector &files) +std::string ErrorLogger::plistHeader(const std::string &version) { std::ostringstream ostr; ostr << "\r\n" @@ -826,12 +826,7 @@ std::string ErrorLogger::plistHeader(const std::string &version, const std::vect << "\r\n" << "\r\n" << " clang_version\r\n" - << "cppcheck version " << version << "\r\n" - << " files\r\n" - << " \r\n"; - for (const std::string & file : files) - ostr << " " << ErrorLogger::toxml(file) << "\r\n"; - ostr << " \r\n" + << " cppcheck version " << version << "\r\n" << " diagnostics\r\n" << " \r\n"; return ostr.str(); diff --git a/lib/errorlogger.h b/lib/errorlogger.h index 5101f765fad..beae28c4851 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -268,12 +269,21 @@ class CPPCHECKLIB ErrorLogger { */ static std::string toxml(const std::string &str); - static std::string plistHeader(const std::string &version, const std::vector &files); + static std::string plistHeader(const std::string &version); static std::string plistData(const ErrorMessage &msg); - static const char *plistFooter() { - return " \r\n" - "\r\n" - ""; + static std::string plistFooter(const std::vector *files) { + std::ostringstream ostr; + ostr << " \r\n" + << " files\r\n" + << " \r\n"; + if (files) { + for (const std::string& file : *files) + ostr << " " << ErrorLogger::toxml(file) << "\r\n"; + } + ostr << " \r\n" + << "\r\n" + << ""; + return ostr.str(); } static bool isCriticalErrorId(const std::string& id) { From a40a3c47754ef77ac157e5b4206c62c0b36c86b0 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 23:41:20 +0200 Subject: [PATCH 16/29] Fix plist filenames --- lib/cppcheck.cpp | 16 ++++++++++++---- lib/errorlogger.h | 12 +++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index e69ade453f5..511375bd55e 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -123,11 +123,15 @@ class CppCheck::CppCheckLogger : public ErrorLogger mErrorList.clear(); } - void openPlist(const std::string& filename, const std::vector* files) + void openPlist(const std::string& filename) { mPlistFile.open(filename); mPlistFile << ErrorLogger::plistHeader(version()); - mPlistFilenames = files; + } + + void setPlistFilenames(std::vector files) + { + mPlistFilenames = std::move(files); } void closePlist() @@ -276,8 +280,8 @@ class CppCheck::CppCheckLogger : public ErrorLogger using Location = std::pair; std::map> mLocationMacros; // What macros are used on a location? - const std::vector* mPlistFilenames{}; std::ofstream mPlistFile; + std::vector mPlistFilenames; unsigned int mExitCode{}; @@ -996,7 +1000,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str filename2 = file.spath(); const std::size_t fileNameHash = std::hash {}(file.spath()); filename2 = mSettings.plistOutput + filename2.substr(0, filename2.find('.')) + "_" + std::to_string(fileNameHash) + ".plist"; - mLogger->openPlist(filename2, &files); + mLogger->openPlist(filename2); } // Parse comments and then remove them @@ -1289,6 +1293,10 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str fdump.close(); } + if (!mSettings.plistOutput.empty()) { + mLogger->setPlistFilenames(std::move(files)); + } + executeAddons(dumpFile, file); } catch (const TerminateException &) { // Analysis is terminated diff --git a/lib/errorlogger.h b/lib/errorlogger.h index beae28c4851..ef3172b7273 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -271,15 +271,13 @@ class CPPCHECKLIB ErrorLogger { static std::string plistHeader(const std::string &version); static std::string plistData(const ErrorMessage &msg); - static std::string plistFooter(const std::vector *files) { + static std::string plistFooter(const std::vector& files) { std::ostringstream ostr; ostr << " \r\n" - << " files\r\n" - << " \r\n"; - if (files) { - for (const std::string& file : *files) - ostr << " " << ErrorLogger::toxml(file) << "\r\n"; - } + << " files\r\n" + << " \r\n"; + for (const std::string& file : files) + ostr << " " << ErrorLogger::toxml(file) << "\r\n"; ostr << " \r\n" << "\r\n" << ""; From 7a455a74ae7e6b924799c2c05389f04a384f9eb5 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 23:47:15 +0200 Subject: [PATCH 17/29] Fix formatting --- lib/errorlogger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/errorlogger.h b/lib/errorlogger.h index ef3172b7273..da02b096e4b 100644 --- a/lib/errorlogger.h +++ b/lib/errorlogger.h @@ -274,8 +274,8 @@ class CPPCHECKLIB ErrorLogger { static std::string plistFooter(const std::vector& files) { std::ostringstream ostr; ostr << " \r\n" - << " files\r\n" - << " \r\n"; + << " files\r\n" + << " \r\n"; for (const std::string& file : files) ostr << " " << ErrorLogger::toxml(file) << "\r\n"; ostr << " \r\n" From e1ac8be051f99d7cb96c6bf9898123c039066028 Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 24 Oct 2025 23:47:36 +0200 Subject: [PATCH 18/29] Clear plistfilenames --- lib/cppcheck.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 511375bd55e..bc9f12b6231 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -131,7 +131,9 @@ class CppCheck::CppCheckLogger : public ErrorLogger void setPlistFilenames(std::vector files) { - mPlistFilenames = std::move(files); + if (mPlistFile.is_open()) { + mPlistFilenames = std::move(files); + } } void closePlist() @@ -139,6 +141,7 @@ class CppCheck::CppCheckLogger : public ErrorLogger if (mPlistFile.is_open()) { mPlistFile << ErrorLogger::plistFooter(mPlistFilenames); mPlistFile.close(); + mPlistFilenames.clear(); } } From 3c3c27b36f1b986beeb60278abe422394d416700 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 00:06:20 +0200 Subject: [PATCH 19/29] Fix clang-tidy issues --- lib/preprocessor.cpp | 2 +- lib/preprocessor.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 6cbe3afecfe..530a5c06c53 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -973,7 +973,7 @@ std::size_t Preprocessor::calculateHash(const simplecpp::TokenList &tokens1, con return (std::hash{})(hashData); } -void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList &tokenList) const +void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList &tokenList) { Preprocessor::simplifyPragmaAsmPrivate(tokenList); } diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 14004a6fc55..e25f276faaf 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -113,7 +113,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { void inlineSuppressions(const simplecpp::TokenList &tokens, SuppressionList &suppressions); - void createDirectives(const simplecpp::TokenList &tokens, std::list& directives) const; + static void createDirectives(const simplecpp::TokenList &tokens, std::list& directives); void getConfigs(const std::string& filename, const simplecpp::TokenList& tokens, std::set& defined, std::list& configs) const; @@ -139,7 +139,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { */ std::size_t calculateHash(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const; - void simplifyPragmaAsm(simplecpp::TokenList &tokenList) const; + static void simplifyPragmaAsm(simplecpp::TokenList &tokenList); static void getErrorMessages(ErrorLogger &errorLogger, const Settings &settings); From 18b2d18ba5c08d80140c6c1e61f5aa517524aa52 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 00:42:35 +0200 Subject: [PATCH 20/29] Fix dump for misra verify --- lib/cppcheck.cpp | 35 +++++++++++++++++++++++++++++++---- lib/cppcheck.h | 3 +++ lib/cppcheck.vcxproj | 8 ++++---- lib/preprocessor.cpp | 2 +- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index bc9f12b6231..3bf386d9a7f 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1006,6 +1006,11 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str mLogger->openPlist(filename2); } + std::string dumpFooter; + if (mSettings.dump || !mSettings.addons.empty()) { + dumpFooter += getDumpFileContentsRawTokensFooter(tokens1); + } + // Parse comments and then remove them preprocessor.addRemarkComments(tokens1, mLogger->remarkComments()); preprocessor.inlineSuppressions(tokens1, mSuppressions.nomsg); @@ -1289,7 +1294,8 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // TODO: will not be closed if we encountered an exception if (fdump.is_open()) { // dump all filenames, raw tokens, suppressions - fdump << getDumpFileContentsRawTokens(files, tokens1); + std::string dumpHeader = getDumpFileContentsRawTokensHeader(files); + fdump << getDumpFileContentsRawTokens(dumpHeader, dumpFooter); mSuppressions.nomsg.dump(fdump); // dumped all configs, close root element now fdump << "" << std::endl; @@ -1974,6 +1980,23 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const { std::string CppCheck::getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const { std::string dumpProlog; dumpProlog += " \n"; + dumpProlog += getDumpFileContentsRawTokensHeader(files); + dumpProlog += getDumpFileContentsRawTokensFooter(tokens1); + dumpProlog += " \n"; + return dumpProlog; +} + +std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const { + std::string dumpProlog; + dumpProlog += " \n"; + dumpProlog += header; + dumpProlog += footer; + dumpProlog += " \n"; + return dumpProlog; +} + +std::string CppCheck::getDumpFileContentsRawTokensHeader(const std::vector& files) const { + std::string dumpProlog; for (unsigned int i = 0; i < files.size(); ++i) { dumpProlog += " \n"; } - for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { + return dumpProlog; +} + +std::string CppCheck::getDumpFileContentsRawTokensFooter(const simplecpp::TokenList& tokens1) const { + std::string dumpProlog; + for (const simplecpp::Token* tok = tokens1.cfront(); tok; tok = tok->next) { dumpProlog += " location.line); dumpProlog += "\" "; - dumpProlog +="column=\""; + dumpProlog += "column=\""; dumpProlog += std::to_string(tok->location.col); dumpProlog += "\" "; @@ -2002,6 +2030,5 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::vector contents, this is only public for testing purposes */ std::string getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const; + std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const; + std::string getDumpFileContentsRawTokensHeader(const std::vector& files) const; + std::string getDumpFileContentsRawTokensFooter(const simplecpp::TokenList& tokens1) const; std::string getLibraryDumpData() const; diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 78e9eaecd69..8c4a6f69dda 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -200,25 +200,25 @@ DynamicLibrary Unicode false - v142 + v143 DynamicLibrary Unicode false - v142 + v143 DynamicLibrary Unicode false - v142 + v143 DynamicLibrary Unicode false - v142 + v143 diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 530a5c06c53..731aefa4ace 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -323,7 +323,7 @@ std::vector Preprocessor::getRemarkComments(const simplecpp::Toke return ret; } -void Preprocessor::createDirectives(const simplecpp::TokenList &tokens, std::list& directives) const +void Preprocessor::createDirectives(const simplecpp::TokenList &tokens, std::list& directives) { for (const simplecpp::Token *tok = tokens.cfront(); tok; tok = tok->next) { if ((tok->op != '#') || (tok->previous && tok->previous->location.line == tok->location.line)) From 54939200ed6d8950a26782d663d9e499bf443937 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 00:45:24 +0200 Subject: [PATCH 21/29] Fix qualification warning --- lib/cppcheck.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 9e4e294bb6b..654a6be9857 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -154,7 +154,7 @@ class CPPCHECKLIB CppCheck { * @brief Get dumpfile contents, this is only public for testing purposes */ std::string getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const; - std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const; + std::string getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const; std::string getDumpFileContentsRawTokensHeader(const std::vector& files) const; std::string getDumpFileContentsRawTokensFooter(const simplecpp::TokenList& tokens1) const; From 58466278f270f729511ad69864cbfd8132aac7e3 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 01:01:51 +0200 Subject: [PATCH 22/29] Fix getDumpFileContentsRawTokens, change Preprocessor::removeComments --- lib/cppcheck.cpp | 13 +++++-------- lib/preprocessor.cpp | 5 +---- lib/preprocessor.h | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 3bf386d9a7f..f4a0bb014e5 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1014,7 +1014,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // Parse comments and then remove them preprocessor.addRemarkComments(tokens1, mLogger->remarkComments()); preprocessor.inlineSuppressions(tokens1, mSuppressions.nomsg); - tokens1.removeComments(); + preprocessor.removeComments(tokens1); if (!mSettings.buildDir.empty()) { analyzerInformation.reset(new AnalyzerInformation); @@ -1049,7 +1049,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // Do preprocessing on included file preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); - data.tokens.removeComments(); + preprocessor.removeComments(data.tokens); preprocessor.createDirectives(data.tokens, directives); preprocessor.simplifyPragmaAsm(data.tokens); // Discover new configurations from included file @@ -1978,12 +1978,9 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const { } std::string CppCheck::getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const { - std::string dumpProlog; - dumpProlog += " \n"; - dumpProlog += getDumpFileContentsRawTokensHeader(files); - dumpProlog += getDumpFileContentsRawTokensFooter(tokens1); - dumpProlog += " \n"; - return dumpProlog; + std::string header = getDumpFileContentsRawTokensHeader(files); + std::string footer = getDumpFileContentsRawTokensFooter(tokens1); + return getDumpFileContentsRawTokens(header, footer); } std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const { diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 731aefa4ace..75eff6f9dfd 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -764,12 +764,9 @@ bool Preprocessor::loadFiles(const simplecpp::TokenList &rawtokens, std::vector< return !hasErrors(outputList); } -void Preprocessor::removeComments(simplecpp::TokenList &tokens) const +void Preprocessor::removeComments(simplecpp::TokenList &tokens) { tokens.removeComments(); - for (const auto &filedata : mFileCache) { - filedata->tokens.removeComments(); - } } void Preprocessor::setPlatformInfo(simplecpp::TokenList &tokens, const Settings& settings) diff --git a/lib/preprocessor.h b/lib/preprocessor.h index e25f276faaf..23dd10ad9e5 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -122,7 +122,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { bool loadFiles(const simplecpp::TokenList& rawtokens, std::vector& files); - void removeComments(simplecpp::TokenList &tokens) const; + static void removeComments(simplecpp::TokenList &tokens); static void setPlatformInfo(simplecpp::TokenList &tokens, const Settings& settings); From 3762b49190635f7f8e65ffca8e2f421e4f215ef0 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 02:22:51 +0200 Subject: [PATCH 23/29] Access removeComments and createDirectives through class --- lib/cppcheck.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index f4a0bb014e5..a36a1a44ffd 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1014,7 +1014,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // Parse comments and then remove them preprocessor.addRemarkComments(tokens1, mLogger->remarkComments()); preprocessor.inlineSuppressions(tokens1, mSuppressions.nomsg); - preprocessor.removeComments(tokens1); + Preprocessor::removeComments(tokens1); if (!mSettings.buildDir.empty()) { analyzerInformation.reset(new AnalyzerInformation); @@ -1037,7 +1037,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // Get directives std::list directives; - preprocessor.createDirectives(tokens1, directives); + Preprocessor::createDirectives(tokens1, directives); preprocessor.simplifyPragmaAsm(tokens1); // This needs to be a linked list to allow new configurations to be discovered @@ -1049,8 +1049,8 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // Do preprocessing on included file preprocessor.addRemarkComments(data.tokens, mLogger->remarkComments()); preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); - preprocessor.removeComments(data.tokens); - preprocessor.createDirectives(data.tokens, directives); + Preprocessor::removeComments(data.tokens); + Preprocessor::createDirectives(data.tokens, directives); preprocessor.simplifyPragmaAsm(data.tokens); // Discover new configurations from included file if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) From 1c54f77a6e1c5f2bbb6994302d070883a26b81ca Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 02:45:33 +0200 Subject: [PATCH 24/29] Access removeComments and createDirectives through class in helpers.cpp --- test/helpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers.cpp b/test/helpers.cpp index 036013499ab..f011cdcf335 100644 --- a/test/helpers.cpp +++ b/test/helpers.cpp @@ -122,7 +122,7 @@ void SimpleTokenizer2::preprocess(const char* code, std::size_t size, std::vecto tokenizer.list.createTokens(std::move(tokens2)); std::list directives; - preprocessor.createDirectives(tokens1, directives); + Preprocessor::createDirectives(tokens1, directives); tokenizer.setDirectives(std::move(directives)); } From cb350c02a7ae406615a97f50096c1729fa55484a Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 03:03:10 +0200 Subject: [PATCH 25/29] Fix clang-tidy issues --- test/testpreprocessor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index c83fc3a73c0..2c36c9718c8 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -122,7 +122,7 @@ class TestPreprocessor : public TestFixture { Preprocessor preprocessor(settings, errorlogger, Path::identify(tokens.getFiles()[0], false)); if (inlineSuppression) preprocessor.inlineSuppressions(tokens, *inlineSuppression); - preprocessor.removeComments(tokens); + Preprocessor::removeComments(tokens); preprocessor.simplifyPragmaAsm(tokens); preprocessor.reportOutput(outputList, true); @@ -369,7 +369,7 @@ class TestPreprocessor : public TestFixture { std::vector files; // TODO: this adds an empty filename simplecpp::TokenList tokens(code,files); - tokens.removeComments(); + Preprocessor::removeComments(tokens); Preprocessor preprocessor(settings, *this, Standards::Language::C); // TODO: do we need to consider #file? std::list configs = { "" }; { @@ -388,7 +388,7 @@ class TestPreprocessor : public TestFixture { std::vector files; // TODO: this adds an empty filename simplecpp::TokenList tokens(code,files); - tokens.removeComments(); + Preprocessor::removeComments(tokens); Preprocessor preprocessor(settingsDefault, *this, Standards::Language::C); // TODO: do we need to consider #file? return preprocessor.calculateHash(tokens, ""); } From 1ba4b705bd9b4412d67b616e80e1e2371dbf55e9 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 03:50:35 +0200 Subject: [PATCH 26/29] Fix clang-tidy issues --- lib/cppcheck.cpp | 4 ++-- lib/preprocessor.cpp | 5 ----- lib/preprocessor.h | 2 -- test/testpreprocessor.cpp | 2 +- 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index a36a1a44ffd..de7888d9712 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1038,7 +1038,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str // Get directives std::list directives; Preprocessor::createDirectives(tokens1, directives); - preprocessor.simplifyPragmaAsm(tokens1); + Preprocessor::simplifyPragmaAsm(tokens1); // This needs to be a linked list to allow new configurations to be discovered // and added while iterating and checking existing configurations @@ -1051,7 +1051,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str preprocessor.inlineSuppressions(data.tokens, mSuppressions.nomsg); Preprocessor::removeComments(data.tokens); Preprocessor::createDirectives(data.tokens, directives); - preprocessor.simplifyPragmaAsm(data.tokens); + Preprocessor::simplifyPragmaAsm(data.tokens); // Discover new configurations from included file if ((mSettings.checkAllConfigurations && mSettings.userDefines.empty()) || mSettings.force) preprocessor.getConfigs(data.filename, data.tokens, configDefines, configurations); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 75eff6f9dfd..34baa084f04 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -971,11 +971,6 @@ std::size_t Preprocessor::calculateHash(const simplecpp::TokenList &tokens1, con } void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList &tokenList) -{ - Preprocessor::simplifyPragmaAsmPrivate(tokenList); -} - -void Preprocessor::simplifyPragmaAsmPrivate(simplecpp::TokenList &tokenList) { // assembler code.. for (simplecpp::Token *tok = tokenList.front(); tok; tok = tok->next) { diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 23dd10ad9e5..7d015a3b347 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -159,8 +159,6 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor { void reportOutput(const simplecpp::OutputList &outputList, bool showerror); - static void simplifyPragmaAsmPrivate(simplecpp::TokenList &tokenList); - /** * Include file types. */ diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 2c36c9718c8..00dd8be473b 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -123,7 +123,7 @@ class TestPreprocessor : public TestFixture { if (inlineSuppression) preprocessor.inlineSuppressions(tokens, *inlineSuppression); Preprocessor::removeComments(tokens); - preprocessor.simplifyPragmaAsm(tokens); + Preprocessor::simplifyPragmaAsm(tokens); preprocessor.reportOutput(outputList, true); From 71bec71b7d5aa4adf26a94eb2655fe610cec6343 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 04:28:16 +0200 Subject: [PATCH 27/29] Fix clang-tidy issues --- lib/cppcheck.cpp | 12 ++++++++---- lib/cppcheck.h | 4 ++-- test/testtokenize.cpp | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index de7888d9712..acd8a6e3271 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -1977,13 +1977,15 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const { return false; } -std::string CppCheck::getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const { +std::string CppCheck::getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const +{ std::string header = getDumpFileContentsRawTokensHeader(files); std::string footer = getDumpFileContentsRawTokensFooter(tokens1); return getDumpFileContentsRawTokens(header, footer); } -std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const { +std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) +{ std::string dumpProlog; dumpProlog += " \n"; dumpProlog += header; @@ -1992,7 +1994,8 @@ std::string CppCheck::getDumpFileContentsRawTokens(const std::string& header, co return dumpProlog; } -std::string CppCheck::getDumpFileContentsRawTokensHeader(const std::vector& files) const { +std::string CppCheck::getDumpFileContentsRawTokensHeader(const std::vector& files) const +{ std::string dumpProlog; for (unsigned int i = 0; i < files.size(); ++i) { dumpProlog += " next) { dumpProlog += " contents, this is only public for testing purposes */ std::string getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const; - std::string getDumpFileContentsRawTokens(const std::string& header, const std::string& footer) const; + static std::string getDumpFileContentsRawTokens(const std::string& header, const std::string& footer); std::string getDumpFileContentsRawTokensHeader(const std::vector& files) const; - std::string getDumpFileContentsRawTokensFooter(const simplecpp::TokenList& tokens1) const; + static std::string getDumpFileContentsRawTokensFooter(const simplecpp::TokenList& tokens1); std::string getLibraryDumpData() const; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index e7ba152b10e..f7d215dde97 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -583,7 +583,7 @@ class TestTokenizer : public TestFixture { const simplecpp::TokenList tokens1(code, files, filename, &outputList); Preprocessor preprocessor(settings, *this, Path::identify(tokens1.getFiles()[0], false)); std::list directives; - preprocessor.createDirectives(tokens1, directives); + Preprocessor::createDirectives(tokens1, directives); TokenList tokenlist{settings, Path::identify(filename, false)}; Tokenizer tokenizer(std::move(tokenlist), *this); From beed6999c6ea296f6dabfbc3f1689eb10cf69051 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 04:30:08 +0200 Subject: [PATCH 28/29] Add comment on unused function --- lib/preprocessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 34baa084f04..1a3d08904dd 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -312,7 +312,7 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens, Suppre } } -// cppcheck-suppress unusedFunction +// cppcheck-suppress unusedFunction - only used in tests std::vector Preprocessor::getRemarkComments(const simplecpp::TokenList &tokens) const { std::vector ret; From dc4cbe32c6aaf55d42b9f119811b4995804c11d6 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 25 Oct 2025 04:31:37 +0200 Subject: [PATCH 29/29] Remove unused preprocessor instance --- test/testtokenize.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f7d215dde97..8d386191ef5 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -581,7 +581,6 @@ class TestTokenizer : public TestFixture { simplecpp::OutputList outputList; std::vector files; const simplecpp::TokenList tokens1(code, files, filename, &outputList); - Preprocessor preprocessor(settings, *this, Path::identify(tokens1.getFiles()[0], false)); std::list directives; Preprocessor::createDirectives(tokens1, directives);