Author: Kadir Cetinkaya Date: 2021-07-30T15:22:51+02:00 New Revision: 41e24222861fb5394ab4c7e892a7d7f2914b533e
URL: https://github.com/llvm/llvm-project/commit/41e24222861fb5394ab4c7e892a7d7f2914b533e DIFF: https://github.com/llvm/llvm-project/commit/41e24222861fb5394ab4c7e892a7d7f2914b533e.diff LOG: [clangd] Unify compiler invocation creation Background-indexing is fine, because it uses GlobalCompilationDatabase to fetch the compile commands (hence uses CommandMangler), and creates invocation through buildCompilerInvocation. Depends on D106639. Differential Revision: https://reviews.llvm.org/D106669 Added: clang-tools-extra/clangd/test/indexer.test Modified: clang-tools-extra/clangd/CompileCommands.h clang-tools-extra/clangd/Compiler.cpp clang-tools-extra/clangd/Compiler.h clang-tools-extra/clangd/indexer/IndexerMain.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/CompileCommands.h b/clang-tools-extra/clangd/CompileCommands.h index 50c1a3571ec42..c6b338297385f 100644 --- a/clang-tools-extra/clangd/CompileCommands.h +++ b/clang-tools-extra/clangd/CompileCommands.h @@ -26,10 +26,6 @@ namespace clangd { // - forcing the use of clangd's builtin headers rather than clang's // - resolving argv0 as cc1 expects // - injecting -isysroot flags on mac as the system clang does -// FIXME: This is currently not used in all code paths that create invocations. -// Make use of these adjusters and buildCompilerInvocation in clangd-indexer as -// well. It should be possible to hook it up by overriding RunInvocation in -// FrontendActionFactory. struct CommandMangler { // Absolute path to clang. llvm::Optional<std::string> ClangPath; diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp index f2fb4489f105a..44a1b1a77db56 100644 --- a/clang-tools-extra/clangd/Compiler.cpp +++ b/clang-tools-extra/clangd/Compiler.cpp @@ -9,6 +9,7 @@ #include "Compiler.h" #include "support/Logger.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/CompilerInvocation.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/PCHContainerOperations.h" #include "llvm/ADT/StringRef.h" @@ -41,6 +42,44 @@ void IgnoreDiagnostics::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, IgnoreDiagnostics::log(DiagLevel, Info); } +void disableUnsupportedOptions(CompilerInvocation &CI) { + // Disable "clang -verify" diagnostics, they are rarely useful in clangd, and + // our compiler invocation set-up doesn't seem to work with it (leading + // assertions in VerifyDiagnosticConsumer). + CI.getDiagnosticOpts().VerifyDiagnostics = false; + CI.getDiagnosticOpts().ShowColors = false; + + // Disable any dependency outputting, we don't want to generate files or write + // to stdout/stderr. + CI.getDependencyOutputOpts().ShowIncludesDest = ShowIncludesDestination::None; + CI.getDependencyOutputOpts().OutputFile.clear(); + CI.getDependencyOutputOpts().HeaderIncludeOutputFile.clear(); + CI.getDependencyOutputOpts().DOTOutputFile.clear(); + CI.getDependencyOutputOpts().ModuleDependencyOutputDir.clear(); + + // Disable any pch generation/usage operations. Since serialized preamble + // format is unstable, using an incompatible one might result in unexpected + // behaviours, including crashes. + CI.getPreprocessorOpts().ImplicitPCHInclude.clear(); + CI.getPreprocessorOpts().PrecompiledPreambleBytes = {0, false}; + CI.getPreprocessorOpts().PCHThroughHeader.clear(); + CI.getPreprocessorOpts().PCHWithHdrStop = false; + CI.getPreprocessorOpts().PCHWithHdrStopCreate = false; + // Don't crash on `#pragma clang __debug parser_crash` + CI.getPreprocessorOpts().DisablePragmaDebugCrash = true; + + // Always default to raw container format as clangd doesn't registry any other + // and clang dies when faced with unknown formats. + CI.getHeaderSearchOpts().ModuleFormat = + PCHContainerOperations().getRawReader().getFormat().str(); + + CI.getFrontendOpts().Plugins.clear(); + CI.getFrontendOpts().AddPluginActions.clear(); + CI.getFrontendOpts().PluginArgs.clear(); + CI.getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; + CI.getFrontendOpts().ActionName.clear(); +} + std::unique_ptr<CompilerInvocation> buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector<std::string> *CC1Args) { @@ -60,43 +99,8 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, CI->getFrontendOpts().DisableFree = false; CI->getLangOpts()->CommentOpts.ParseAllComments = true; CI->getLangOpts()->RetainCommentsFromSystemHeaders = true; - // Disable "clang -verify" diagnostics, they are rarely useful in clangd, and - // our compiler invocation set-up doesn't seem to work with it (leading - // assertions in VerifyDiagnosticConsumer). - CI->getDiagnosticOpts().VerifyDiagnostics = false; - CI->getDiagnosticOpts().ShowColors = false; - - // Disable any dependency outputting, we don't want to generate files or write - // to stdout/stderr. - CI->getDependencyOutputOpts().ShowIncludesDest = - ShowIncludesDestination::None; - CI->getDependencyOutputOpts().OutputFile.clear(); - CI->getDependencyOutputOpts().HeaderIncludeOutputFile.clear(); - CI->getDependencyOutputOpts().DOTOutputFile.clear(); - CI->getDependencyOutputOpts().ModuleDependencyOutputDir.clear(); - - // Disable any pch generation/usage operations. Since serialized preamble - // format is unstable, using an incompatible one might result in unexpected - // behaviours, including crashes. - CI->getPreprocessorOpts().ImplicitPCHInclude.clear(); - CI->getPreprocessorOpts().PrecompiledPreambleBytes = {0, false}; - CI->getPreprocessorOpts().PCHThroughHeader.clear(); - CI->getPreprocessorOpts().PCHWithHdrStop = false; - CI->getPreprocessorOpts().PCHWithHdrStopCreate = false; - // Don't crash on `#pragma clang __debug parser_crash` - CI->getPreprocessorOpts().DisablePragmaDebugCrash = true; - - // Always default to raw container format as clangd doesn't registry any other - // and clang dies when faced with unknown formats. - CI->getHeaderSearchOpts().ModuleFormat = - PCHContainerOperations().getRawReader().getFormat().str(); - - CI->getFrontendOpts().Plugins.clear(); - CI->getFrontendOpts().AddPluginActions.clear(); - CI->getFrontendOpts().PluginArgs.clear(); - CI->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; - CI->getFrontendOpts().ActionName.clear(); + disableUnsupportedOptions(*CI); return CI; } diff --git a/clang-tools-extra/clangd/Compiler.h b/clang-tools-extra/clangd/Compiler.h index 0351069683155..b46765f6813ad 100644 --- a/clang-tools-extra/clangd/Compiler.h +++ b/clang-tools-extra/clangd/Compiler.h @@ -61,6 +61,12 @@ struct ParseInputs { FeatureModuleSet *FeatureModules = nullptr; }; +/// Clears \p CI from options that are not supported by clangd, like codegen or +/// plugins. This should be combined with CommandMangler::adjust, which provides +/// similar functionality for options that needs to be stripped from compile +/// flags. +void disableUnsupportedOptions(CompilerInvocation &CI); + /// Builds compiler invocation that could be used to build AST or preamble. std::unique_ptr<CompilerInvocation> buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp b/clang-tools-extra/clangd/indexer/IndexerMain.cpp index 533334fcc1f28..2b3de014f8f7b 100644 --- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp +++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp @@ -10,6 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "CompileCommands.h" +#include "Compiler.h" #include "index/IndexAction.h" #include "index/Merge.h" #include "index/Ref.h" @@ -23,6 +25,7 @@ #include "clang/Tooling/Tooling.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Signals.h" +#include <utility> namespace clang { namespace clangd { @@ -82,6 +85,15 @@ class IndexActionFactory : public tooling::FrontendActionFactory { /*IncludeGraphCallback=*/nullptr); } + bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation, + FileManager *Files, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, + DiagnosticConsumer *DiagConsumer) override { + disableUnsupportedOptions(*Invocation); + return tooling::FrontendActionFactory::runInvocation( + std::move(Invocation), Files, std::move(PCHContainerOps), DiagConsumer); + } + // Awkward: we write the result in the destructor, because the executor // takes ownership so it's the easiest way to get our data back out. ~IndexActionFactory() { @@ -135,7 +147,8 @@ int main(int argc, const char **argv) { clang::clangd::IndexFileIn Data; auto Err = Executor->get()->execute( std::make_unique<clang::clangd::IndexActionFactory>(Data), - clang::tooling::getStripPluginsAdjuster()); + clang::tooling::ArgumentsAdjuster( + clang::clangd::CommandMangler::detect())); if (Err) { clang::clangd::elog("{0}", std::move(Err)); } diff --git a/clang-tools-extra/clangd/test/indexer.test b/clang-tools-extra/clangd/test/indexer.test new file mode 100644 index 0000000000000..2f01f6c557a7d --- /dev/null +++ b/clang-tools-extra/clangd/test/indexer.test @@ -0,0 +1,9 @@ +# RUN: rm -rf %t.cpp +# RUN: touch %t.cpp +# +# Make sure compile flags are adjusted for clangd. `--save-temps` creates a +# `.ii` file and `-verify` triggers extra diagnostics generation. Clangd should +# strip those. +# RUN: clangd-indexer %t.cpp -- -Xclang -verify --save-temps -- 2>&1 | FileCheck %s +# CHECK-NOT: error: no expected directives found: consider use of 'expected-no-diagnostics' +# RUN: not ls %t.ii _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits