sammccall created this revision. sammccall added a reviewer: kadircet. Herald added a subscriber: arphaman. Herald added a reviewer: njames93. Herald added a project: All. sammccall requested review of this revision. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
This uses the fast-check allowlist added in the previous commit. This is behind a config option to allow users/developers to enable checks we haven't timed yet, and to allow the --check-tidy-time flag to work. https://github.com/clangd/clangd/issues/1337 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D138505 Files: clang-tools-extra/clangd/Config.h clang-tools-extra/clangd/ConfigCompile.cpp clang-tools-extra/clangd/ConfigFragment.h clang-tools-extra/clangd/ConfigYAML.cpp clang-tools-extra/clangd/ParsedAST.cpp clang-tools-extra/clangd/TidyProvider.cpp clang-tools-extra/clangd/TidyProvider.h clang-tools-extra/clangd/tool/Check.cpp
Index: clang-tools-extra/clangd/tool/Check.cpp =================================================================== --- clang-tools-extra/clangd/tool/Check.cpp +++ clang-tools-extra/clangd/tool/Check.cpp @@ -30,6 +30,8 @@ #include "CodeComplete.h" #include "CompileCommands.h" #include "Config.h" +#include "ConfigFragment.h" +#include "ConfigProvider.h" #include "Feature.h" #include "GlobalCompilationDatabase.h" #include "Hover.h" @@ -82,15 +84,19 @@ "check-completion", llvm::cl::desc("Run code-completion at each point (slow)"), llvm::cl::init(false)}; +llvm::cl::opt<bool> CheckWarnings{ + "check-warnings", + llvm::cl::desc("Print warnings as well as errors"), + llvm::cl::init(false)}; // Print (and count) the error-level diagnostics (warnings are ignored). unsigned showErrors(llvm::ArrayRef<Diag> Diags) { unsigned ErrCount = 0; for (const auto &D : Diags) { - if (D.Severity >= DiagnosticsEngine::Error) { + if (D.Severity >= DiagnosticsEngine::Error || CheckWarnings) elog("[{0}] Line {1}: {2}", D.Name, D.Range.start.line + 1, D.Message); + if (D.Severity >= DiagnosticsEngine::Error) ++ErrCount; - } } return ErrCount; } @@ -452,8 +458,23 @@ } log("Testing on source file {0}", File); + class OverrideConfigProvider : public config::Provider { + std::vector<config::CompiledFragment> + getFragments(const config::Params &, + config::DiagnosticCallback Diag) const override { + config::Fragment F; + // If we're timing clang-tidy checks, implicitly disabling the slow ones + // is counterproductive! + if (CheckTidyTime.getNumOccurrences()) + F.Diagnostics.ClangTidy.SlowChecks = true; + return {std::move(F).compile(Diag)}; + } + } OverrideConfig; + auto ConfigProvider = + config::Provider::combine({Opts.ConfigProvider, &OverrideConfig}); + auto ContextProvider = ClangdServer::createConfiguredContextProvider( - Opts.ConfigProvider, nullptr); + ConfigProvider.get(), nullptr); WithContext Ctx(ContextProvider( FakeFile.empty() ? File Index: clang-tools-extra/clangd/TidyProvider.h =================================================================== --- clang-tools-extra/clangd/TidyProvider.h +++ clang-tools-extra/clangd/TidyProvider.h @@ -60,6 +60,10 @@ /// \pre \p must not be empty, must not contain '*' or ',' or start with '-'. bool isRegisteredTidyCheck(llvm::StringRef Check); +/// Returns if \p Check is a known-fast clang-tidy check. +/// By default, only such checks will run in clangd. +bool isFastTidyCheck(llvm::StringRef Check); + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/TidyProvider.cpp =================================================================== --- clang-tools-extra/clangd/TidyProvider.cpp +++ clang-tools-extra/clangd/TidyProvider.cpp @@ -213,13 +213,7 @@ // tries to build an AST. "-bugprone-use-after-move", // Alias for bugprone-use-after-move. - "-hicpp-invalid-access-moved", - - // ----- Performance problems ----- - - // This check runs expensive analysis for each variable. - // It has been observed to increase reparse time by 10x. - "-misc-const-correctness"); + "-hicpp-invalid-access-moved"); size_t Size = BadChecks.size(); for (const std::string &Str : ExtraBadChecks) { @@ -308,5 +302,14 @@ return AllChecks.contains(Check); } + +bool isFastTidyCheck(llvm::StringRef Check) { + static auto &Fast = *new llvm::StringSet<>{ +#define FAST(CHECK, TIME) #CHECK, +#include "TidyFastChecks.inc" + }; + return Fast.contains(Check); +} + } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/ParsedAST.cpp =================================================================== --- clang-tools-extra/clangd/ParsedAST.cpp +++ clang-tools-extra/clangd/ParsedAST.cpp @@ -345,6 +345,7 @@ std::shared_ptr<const PreambleData> Preamble) { trace::Span Tracer("BuildAST"); SPAN_ATTACH(Tracer, "File", Filename); + const Config &Cfg = Config::current(); auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory); if (Preamble && Preamble->StatCache) @@ -476,6 +477,15 @@ tidy::ClangTidyCheckFactories CTFactories; for (const auto &E : tidy::ClangTidyModuleRegistry::entries()) E.instantiate()->addCheckFactories(CTFactories); + if (!Cfg.Diagnostics.ClangTidy.SlowChecks) { + // Can't remove checks from a factories container, so create a new one. + tidy::ClangTidyCheckFactories FastFactories; + for (const auto &Factory : CTFactories) { + if (isFastTidyCheck(Factory.getKey())) + FastFactories.registerCheckFactory(Factory.first(), Factory.second); + } + CTFactories = std::move(FastFactories); + } CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>( tidy::ClangTidyGlobalOptions(), ClangTidyOpts)); CTContext->setDiagnosticsEngine(&Clang->getDiagnostics()); @@ -504,7 +514,6 @@ SourceLocation()); } - const Config &Cfg = Config::current(); ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) { if (Cfg.Diagnostics.SuppressAll || Index: clang-tools-extra/clangd/ConfigYAML.cpp =================================================================== --- clang-tools-extra/clangd/ConfigYAML.cpp +++ clang-tools-extra/clangd/ConfigYAML.cpp @@ -152,6 +152,10 @@ }); CheckOptDict.parse(N); }); + Dict.handle("SlowChecks", [&](Node &N) { + if (auto SlowChecks = boolValue(N, "SlowChecks")) + F.SlowChecks = *SlowChecks; + }); Dict.parse(N); } Index: clang-tools-extra/clangd/ConfigFragment.h =================================================================== --- clang-tools-extra/clangd/ConfigFragment.h +++ clang-tools-extra/clangd/ConfigFragment.h @@ -264,6 +264,11 @@ /// readability-braces-around-statements.ShortStatementLines: 2 std::vector<std::pair<Located<std::string>, Located<std::string>>> CheckOptions; + + /// Whether to run checks that may slow down clangd. + /// By default, only known-fast checks are executed. + /// This may exclude recently-added fast checks we have not timed yet. + llvm::Optional<Located<bool>> SlowChecks; }; ClangTidyBlock ClangTidy; }; Index: clang-tools-extra/clangd/ConfigCompile.cpp =================================================================== --- clang-tools-extra/clangd/ConfigCompile.cpp +++ clang-tools-extra/clangd/ConfigCompile.cpp @@ -514,6 +514,11 @@ StringPair.first, StringPair.second); }); } + + if (F.SlowChecks.has_value()) + Out.Apply.push_back([V = **F.SlowChecks](const Params &, Config &C) { + C.Diagnostics.ClangTidy.SlowChecks = V; + }); } void compile(Fragment::DiagnosticsBlock::IncludesBlock &&F) { Index: clang-tools-extra/clangd/Config.h =================================================================== --- clang-tools-extra/clangd/Config.h +++ clang-tools-extra/clangd/Config.h @@ -99,6 +99,7 @@ // A comma-seperated list of globs specify which clang-tidy checks to run. std::string Checks; llvm::StringMap<std::string> CheckOptions; + bool SlowChecks = false; } ClangTidy; UnusedIncludesPolicy UnusedIncludes = None;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits