From 44ed53319e97b80a35dcf9ac7692245497149566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Fri, 5 Jan 2024 22:02:37 +0100 Subject: [PATCH] CppCheck: extracted clang-specific code from `check(const std::string&)` into separate method (#5842) --- lib/cppcheck.cpp | 215 ++++++++++++++++++++++-------------------- lib/cppcheck.h | 2 + lib/filesettings.h | 3 + lib/importproject.cpp | 1 + 4 files changed, 117 insertions(+), 104 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index b77eb7edc..521b3f106 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -423,120 +423,127 @@ 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); - } - - 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; - } - - 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(); - } - - // 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; + 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; + 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; + } + + 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()) { + // TODO: use tinyxml2 to create XML + 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()); + } + + 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 8f31d5d75..99272e89a 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -200,6 +200,8 @@ private: void executeRules(const std::string &tokenlist, const Tokenizer &tokenizer); #endif + unsigned int checkClang(const std::string &path); + /** * @brief Errors and warnings are directed here. * diff --git a/lib/filesettings.h b/lib/filesettings.h index 911089092..ee914dbdc 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 54a62e2f6..16bcc2e47 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -757,6 +757,7 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map