diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -349,37 +349,52 @@ } } -typedef std::vector> CheckersList; +using CheckersList = std::vector>; +using CheckersSet = std::set>; + +static void +addAnalyzerCheckAndDependencies(CheckersSet &Checks, + llvm::StringRef AnalyzerCheckFullName) { + if (!Checks.emplace(AnalyzerCheckFullName.str(), true).second) + return; + +#define GET_CHECKER_WEAK_DEPENDENCIES +#define GET_CHECKER_DEPENDENCIES +#define CHECKER_DEPENDENCY(Parent, Child) \ + if (Parent == AnalyzerCheckFullName) \ + addAnalyzerCheckAndDependencies(Checks, Child); +#define CHECKER_WEAK_DEPENDENCY(Parent, Child) \ + if (Parent == AnalyzerCheckFullName) \ + addAnalyzerCheckAndDependencies(Checks, Child); +#include "clang/StaticAnalyzer/Checkers/Checkers.inc" +#undef CHECKER_WEAK_DEPENDENCY +#undef CHECKER_DEPENDENCY +#undef GET_CHECKER_DEPENDENCIES +#undef GET_CHECKER_WEAK_DEPENDENCIES +} static CheckersList getAnalyzerCheckersAndPackages(ClangTidyContext &Context, bool IncludeExperimental) { - CheckersList List; - - const auto &RegisteredCheckers = - AnalyzerOptions::getRegisteredCheckers(IncludeExperimental); - bool AnalyzerChecksEnabled = false; - for (StringRef CheckName : RegisteredCheckers) { - std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str()); - AnalyzerChecksEnabled |= Context.isCheckEnabled(ClangTidyCheckName); + CheckersSet Checks; + +#define GET_CHECKERS +#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \ + { \ + llvm::StringRef AnalyzerCheckFullName(FULLNAME); \ + if (!AnalyzerCheckFullName.startswith("debug.") && \ + (IncludeExperimental || \ + !AnalyzerCheckFullName.startswith("alpha."))) { \ + std::string ClangTidyCheckName( \ + (AnalyzerCheckNamePrefix + AnalyzerCheckFullName).str()); \ + if (Context.isCheckEnabled(ClangTidyCheckName)) \ + addAnalyzerCheckAndDependencies(Checks, AnalyzerCheckFullName); \ + } \ } +#include "clang/StaticAnalyzer/Checkers/Checkers.inc" +#undef CHECKER +#undef GET_CHECKERS - if (!AnalyzerChecksEnabled) - return List; - - // List all static analyzer checkers that our filter enables. - // - // Always add all core checkers if any other static analyzer check is enabled. - // This is currently necessary, as other path sensitive checks rely on the - // core checkers. - for (StringRef CheckName : RegisteredCheckers) { - std::string ClangTidyCheckName((AnalyzerCheckNamePrefix + CheckName).str()); - - if (CheckName.startswith("core") || - Context.isCheckEnabled(ClangTidyCheckName)) { - List.emplace_back(std::string(CheckName), true); - } - } - return List; + return {Checks.begin(), Checks.end()}; } #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -98,6 +98,9 @@ `ImplementationFileExtensions`, replacing the check-local options of the same name. +- Clang Static Analyzer checks can now be individually enabled or disabled. + Use `--checks="clang-analyzer-core.*"` to preserve the previous behavior. + New checks ^^^^^^^^^^ diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/enable-analyzer-checks.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/enable-analyzer-checks.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/enable-analyzer-checks.cpp @@ -0,0 +1,10 @@ +// REQUIRES: static-analyzer + +// Check if enabling once check will enable only dependences +// RUN: clang-tidy -checks=-*,clang-analyzer-core.CallAndMessage -list-checks | grep 'clang-analyzer-core.CallAndMessageModeling' +// RUN: clang-tidy -checks=-*,clang-analyzer-core.CallAndMessage -list-checks | wc -l | grep -x '4' + +// Check if disabling dependency does nothing if check is enabled +// RUN: clang-tidy -checks=-*,clang-analyzer-core.CallAndMessage,-clang-analyzer-core.clang-analyzer-core.CallAndMessageModeling \ +// RUN: -list-checks | grep 'clang-analyzer-core.CallAndMessageModeling' +