diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 1ddbd3a61..4c21da846 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -227,8 +227,12 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strcmp(argv[i], "--check-library") == 0) mSettings->checkLibrary = true; - else if (std::strcmp(argv[i], "--clang") == 0) + else if (std::strncmp(argv[i], "--clang", 7) == 0) { mSettings->clang = true; + if (std::strncmp(argv[i], "--clang=", 8) == 0) { + mSettings->clangExecutable = argv[i] + 8; + } + } else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) { mSettings->configExcludePaths.insert(Path::fromNativeSeparators(argv[i] + 17)); @@ -972,11 +976,13 @@ void CmdLineParser::printHelp() " analysis is disabled by this flag.\n" " --check-library Show information messages when library files have\n" " incomplete info.\n" - " --clang Experimental: Use Clang parser instead of the builtin\n" - " Cppcheck parser. Cppcheck executes `clang`. The Clang\n" - " AST is imported and converted into Cppcheck data.\n" - " After that the normal Cppcheck analysis is used. You\n" - " must have `clang` in PATH.\n" + " --clang= Experimental: Use Clang parser instead of the builtin Cppcheck\n" + " parser. Takes the executable as optional parameter and\n" + " defaults to `clang`. Cppcheck will run the given Clang\n" + " executable, import the Clang AST and convert it into\n" + " Cppcheck data. After that the normal Cppcheck analysis is\n" + " used. You must have the executable in PATH if no path is\n" + " given.\n" " --config-exclude=\n" " Path (prefix) to be excluded from configuration\n" " checking. Preprocessor configurations defined in\n" diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index b3491c238..401dc4cdb 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -328,10 +328,12 @@ unsigned int CppCheck::check(const std::string &path) const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, ""); const std::string clangcmd = analyzerInfo + ".clang-cmd"; const std::string clangStderr = analyzerInfo + ".clang-stderr"; + std::string exe = mSettings.clangExecutable; #ifdef _WIN32 - const std::string exe = "clang.exe"; -#else - const std::string exe = "clang"; + // append .exe if it is not a path + if (Path::fromNativeSeparators(mSettings.clangExecutable).find('/') == std::string::npos) { + exe += ".exe"; + } #endif std::string flags(lang + " "); diff --git a/lib/settings.cpp b/lib/settings.cpp index bb725785d..0d8629c7e 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -37,6 +37,7 @@ Settings::Settings() checkLibrary(false), checkUnusedTemplates(false), clang(false), + clangExecutable("clang"), clangTidy(false), daca(false), debugBugHunting(false), diff --git a/lib/settings.h b/lib/settings.h index 170fad833..099ade030 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -115,6 +115,9 @@ public: /** Use Clang */ bool clang; + /** Custom Clang executable */ + std::string clangExecutable; + /** Use clang-tidy */ bool clangTidy; diff --git a/man/manual.md b/man/manual.md index d880c444b..1323a011d 100644 --- a/man/manual.md +++ b/man/manual.md @@ -116,6 +116,8 @@ Install `clang`. Then use Cppcheck option `--clang`. Technically, Cppcheck will execute `clang` with its `-ast-dump` option. The Clang output is then imported and converted into our normal Cppcheck format. And then normal Cppcheck analysis is performed on that. +You can also pass a custom Clang executable to the option by using e.g. `--clang=clang-10`. You can also pass it with a path. On Windows it will append the `.exe` extension unless you use a path. + ## Severities The possible severities for messages are: