From c862577c5299e39ce7711ddd83bd44dd2c8a9b59 Mon Sep 17 00:00:00 2001 From: firewave Date: Sun, 3 Dec 2023 13:00:58 +0100 Subject: [PATCH 1/2] CppCheck: extracted clang-specific code from `check(const std::string&)` into separate method --- lib/cppcheck.cpp | 198 ++++++++++++++++++++++++----------------------- lib/cppcheck.h | 2 + 2 files changed, 103 insertions(+), 97 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index b77eb7edc21..c0cf34a5000 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -423,120 +423,124 @@ static bool reportClangErrors(std::istream &is, const std::function&1") : ("2> " + clangStderr); - if (!mSettings.buildDir.empty()) { - std::ofstream fout(clangcmd); - fout << exe << " " << args2 << " " << redirect2 << std::endl; - } else if (mSettings.verbose && !mSettings.quiet) { - mErrorLogger.reportOut(exe + " " + args2); - } + const std::string args2 = "-fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path; + const std::string redirect2 = analyzerInfo.empty() ? std::string("2>&1") : ("2> " + clangStderr); + if (!mSettings.buildDir.empty()) { + std::ofstream fout(clangcmd); + fout << exe << " " << args2 << " " << redirect2 << std::endl; + } else if (mSettings.verbose && !mSettings.quiet) { + mErrorLogger.reportOut(exe + " " + args2); + } - std::string output2; - if (mExecuteCommand(exe,split(args2),redirect2,output2) != EXIT_SUCCESS || output2.find("TranslationUnitDecl") == std::string::npos) { - std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl; + std::string output2; + if (mExecuteCommand(exe,split(args2),redirect2,output2) != EXIT_SUCCESS || output2.find("TranslationUnitDecl") == std::string::npos) { + std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl; + return 0; + } + + // Ensure there are not syntax errors... + std::vector compilerWarnings; + if (!mSettings.buildDir.empty()) { + std::ifstream fin(clangStderr); + auto reportError = [this](const ErrorMessage& errorMessage) { + reportErr(errorMessage); + }; + if (reportClangErrors(fin, reportError, compilerWarnings)) return 0; - } + } else { + std::istringstream istr(output2); + auto reportError = [this](const ErrorMessage& errorMessage) { + reportErr(errorMessage); + }; + if (reportClangErrors(istr, reportError, compilerWarnings)) + return 0; + } - // Ensure there are not syntax errors... - std::vector compilerWarnings; - if (!mSettings.buildDir.empty()) { - std::ifstream fin(clangStderr); - auto reportError = [this](const ErrorMessage& errorMessage) { - reportErr(errorMessage); - }; - if (reportClangErrors(fin, reportError, compilerWarnings)) - return 0; - } else { - std::istringstream istr(output2); - auto reportError = [this](const ErrorMessage& errorMessage) { - reportErr(errorMessage); - }; - if (reportClangErrors(istr, reportError, compilerWarnings)) - return 0; - } + if (!mSettings.buildDir.empty()) { + std::ofstream fout(clangAst); + fout << output2 << std::endl; + } - if (!mSettings.buildDir.empty()) { - std::ofstream fout(clangAst); - fout << output2 << std::endl; + try { + std::istringstream ast(output2); + Tokenizer tokenizer(&mSettings, this); + tokenizer.list.appendFileIfNew(path); + clangimport::parseClangAstDump(&tokenizer, ast); + ValueFlow::setValues(tokenizer.list, + const_cast(*tokenizer.getSymbolDatabase()), + this, + &mSettings, + &s_timerResults); + if (mSettings.debugnormal) + tokenizer.printDebugOutput(1); + checkNormalTokens(tokenizer); + + // create dumpfile + std::ofstream fdump; + std::string dumpFile; + createDumpFile(mSettings, path, fdump, dumpFile); + if (fdump.is_open()) { + fdump << "\n"; + for (const ErrorMessage& errmsg: compilerWarnings) + fdump << " \n"; + fdump << " \n"; + fdump << " \n"; + fdump << " \n"; + fdump << " \n"; + tokenizer.dump(fdump); + fdump << "\n"; + fdump << "\n"; + fdump.close(); } - try { - std::istringstream ast(output2); - Tokenizer tokenizer(&mSettings, this); - tokenizer.list.appendFileIfNew(path); - clangimport::parseClangAstDump(&tokenizer, ast); - ValueFlow::setValues(tokenizer.list, - const_cast(*tokenizer.getSymbolDatabase()), - this, - &mSettings, - &s_timerResults); - if (mSettings.debugnormal) - tokenizer.printDebugOutput(1); - checkNormalTokens(tokenizer); - - // create dumpfile - std::ofstream fdump; - std::string dumpFile; - createDumpFile(mSettings, path, fdump, dumpFile); - if (fdump.is_open()) { - fdump << "\n"; - for (const ErrorMessage& errmsg: compilerWarnings) - fdump << " \n"; - fdump << " \n"; - fdump << " \n"; - fdump << " \n"; - fdump << " \n"; - tokenizer.dump(fdump); - fdump << "\n"; - fdump << "\n"; - fdump.close(); - } - - // run addons - executeAddons(dumpFile, path); - - } catch (const InternalError &e) { - const ErrorMessage errmsg = ErrorMessage::fromInternalError(e, nullptr, path, "Bailing out from analysis: Processing Clang AST dump failed"); - reportErr(errmsg); - } catch (const TerminateException &) { - // Analysis is terminated - return mExitCode; - } catch (const std::exception &e) { - internalError(path, std::string("Processing Clang AST dump failed: ") + e.what()); - } + // run addons + executeAddons(dumpFile, path); + } catch (const InternalError &e) { + const ErrorMessage errmsg = ErrorMessage::fromInternalError(e, nullptr, path, "Bailing out from analysis: Processing Clang AST dump failed"); + reportErr(errmsg); + } catch (const TerminateException &) { + // Analysis is terminated return mExitCode; + } catch (const std::exception &e) { + internalError(path, std::string("Processing Clang AST dump failed: ") + e.what()); } + return mExitCode; +} + +unsigned int CppCheck::check(const std::string &path) +{ + if (mSettings.clang) + return checkClang(path); + return checkFile(Path::simplifyPath(path), emptyString); } diff --git a/lib/cppcheck.h b/lib/cppcheck.h index 8f31d5d75d9..99272e89af1 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -200,6 +200,8 @@ class CPPCHECKLIB CppCheck : ErrorLogger { void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer); #endif + unsigned int checkClang(const std::string &path); + /** * @brief Errors and warnings are directed here. * From 1031e2dc3c18d58a5d6fe9ac867253187b9f8ac9 Mon Sep 17 00:00:00 2001 From: firewave Date: Sun, 3 Dec 2023 13:01:29 +0100 Subject: [PATCH 2/2] added TODOs --- lib/cppcheck.cpp | 3 +++ lib/filesettings.h | 3 +++ lib/importproject.cpp | 1 + 3 files changed, 7 insertions(+) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index c0cf34a5000..521b3f10603 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -428,6 +428,7 @@ unsigned int CppCheck::checkClang(const std::string &path) if (!mSettings.quiet) mErrorLogger.reportOut(std::string("Checking ") + path + " ...", Color::FgGreen); + // TODO: this ignores the configured language const std::string lang = Path::isCPP(path) ? "-x c++" : "-x c"; const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, emptyString); const std::string clangcmd = analyzerInfo + ".clang-cmd"; @@ -442,6 +443,7 @@ unsigned int CppCheck::checkClang(const std::string &path) #endif std::string flags(lang + " "); + // TODO: does not apply C standard if (Path::isCPP(path) && !mSettings.standards.stdValue.empty()) flags += "-std=" + mSettings.standards.stdValue + " "; @@ -507,6 +509,7 @@ unsigned int CppCheck::checkClang(const std::string &path) std::string dumpFile; createDumpFile(mSettings, path, fdump, dumpFile); if (fdump.is_open()) { + // TODO: use tinyxml2 to create XML fdump << "\n"; for (const ErrorMessage& errmsg: compilerWarnings) fdump << " \n"; diff --git a/lib/filesettings.h b/lib/filesettings.h index 911089092f0..ee914dbdcf0 100644 --- a/lib/filesettings.h +++ b/lib/filesettings.h @@ -31,14 +31,17 @@ struct CPPCHECKLIB FileSettings { std::string cfg; std::string filename; std::string defines; + // TODO: handle differently std::string cppcheckDefines() const { return defines + (msc ? ";_MSC_VER=1900" : "") + (useMfc ? ";__AFXWIN_H__=1" : ""); } std::set undefs; std::list includePaths; + // only used by clang mode std::list systemIncludePaths; std::string standard; Platform::Type platformType = Platform::Type::Unspecified; + // TODO: get rid of these bool msc{}; bool useMfc{}; }; diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 54a62e2f6ce..16bcc2e471f 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -757,6 +757,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map