diff --git a/clang-tools-extra/clangd/CompileCommands.h b/clang-tools-extra/clangd/CompileCommands.h --- a/clang-tools-extra/clangd/CompileCommands.h +++ b/clang-tools-extra/clangd/CompileCommands.h @@ -25,6 +25,10 @@ // - 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 ClangPath; diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -12,6 +12,8 @@ #include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Tooling/ArgumentsAdjusters.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Option/Option.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" @@ -20,6 +22,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include #include #include @@ -202,14 +205,9 @@ return false; }; - // clangd should not write files to disk, including dependency files - // requested on the command line. - Cmd = tooling::getClangStripDependencyFileAdjuster()(Cmd, ""); - // Strip plugin related command line arguments. Clangd does - // not support plugins currently. Therefore it breaks if - // compiler tries to load plugins. - Cmd = tooling::getStripPluginsAdjuster()(Cmd, ""); - Cmd = tooling::getClangSyntaxOnlyAdjuster()(Cmd, ""); + llvm::erase_if(Cmd, [](llvm::StringRef Elem) { + return Elem.startswith("--save-temps") || Elem.startswith("-save-temps"); + }); std::vector ToAppend; if (ResourceDir && !Has("-resource-dir")) @@ -223,8 +221,8 @@ } if (!ToAppend.empty()) { - Cmd = tooling::getInsertArgumentAdjuster( - std::move(ToAppend), tooling::ArgumentInsertPosition::END)(Cmd, ""); + Cmd.insert(llvm::find(Cmd, "--"), std::make_move_iterator(ToAppend.begin()), + std::make_move_iterator(ToAppend.end())); } if (!Cmd.empty()) { diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp --- a/clang-tools-extra/clangd/Compiler.cpp +++ b/clang-tools-extra/clangd/Compiler.cpp @@ -64,6 +64,7 @@ // 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. @@ -90,6 +91,12 @@ 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(); + return CI; } diff --git a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp --- a/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -41,11 +41,9 @@ Mangler.ClangPath = testPath("fake/clang"); Mangler.ResourceDir = testPath("fake/resources"); Mangler.Sysroot = testPath("fake/sysroot"); - std::vector Cmd = {"clang++", "-Xclang", "-load", - "-Xclang", "plugin", "-MF", - "dep", "--", "foo.cc"}; + std::vector Cmd = {"clang++", "--", "foo.cc"}; Mangler.adjust(Cmd); - EXPECT_THAT(Cmd, ElementsAre(testPath("fake/clang++"), "-fsyntax-only", + EXPECT_THAT(Cmd, ElementsAre(testPath("fake/clang++"), "-resource-dir=" + testPath("fake/resources"), "-isysroot", testPath("fake/sysroot"), "--", "foo.cc")); @@ -69,38 +67,6 @@ HasSubstr("-isysroot " + testPath("fake/sysroot"))); } -TEST(CommandMangler, StripPlugins) { - auto Mangler = CommandMangler::forTests(); - std::vector Cmd = {"clang++", "-Xclang", "-load", - "-Xclang", "plugin", "foo.cc"}; - Mangler.adjust(Cmd); - for (const char* Stripped : {"-Xclang", "-load", "plugin"}) - EXPECT_THAT(Cmd, Not(Contains(Stripped))); -} - -TEST(CommandMangler, StripOutput) { - auto Mangler = CommandMangler::forTests(); - std::vector Cmd = {"clang++", "-MF", "dependency", "-c", - "foo.cc"}; - Mangler.adjust(Cmd); - for (const char* Stripped : {"-MF", "dependency"}) - EXPECT_THAT(Cmd, Not(Contains(Stripped))); -} - -TEST(CommandMangler, StripShowIncludes) { - auto Mangler = CommandMangler::forTests(); - std::vector Cmd = {"clang-cl", "/showIncludes", "foo.cc"}; - Mangler.adjust(Cmd); - EXPECT_THAT(Cmd, Not(Contains("/showIncludes"))); -} - -TEST(CommandMangler, StripShowIncludesUser) { - auto Mangler = CommandMangler::forTests(); - std::vector Cmd = {"clang-cl", "/showIncludes:user", "foo.cc"}; - Mangler.adjust(Cmd); - EXPECT_THAT(Cmd, Not(Contains("/showIncludes:user"))); -} - TEST(CommandMangler, ClangPath) { auto Mangler = CommandMangler::forTests(); Mangler.ClangPath = testPath("fake/clang"); @@ -205,7 +171,7 @@ Mangler.adjust(Cmd); } // Edits are applied in given order and before other mangling. - EXPECT_THAT(Cmd, ElementsAre(_, "FOO.CC", "--hello", "-fsyntax-only")); + EXPECT_THAT(Cmd, ElementsAre(_, "FOO.CC", "--hello")); } static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) { diff --git a/clang-tools-extra/clangd/unittests/CompilerTests.cpp b/clang-tools-extra/clangd/unittests/CompilerTests.cpp --- a/clang-tools-extra/clangd/unittests/CompilerTests.cpp +++ b/clang-tools-extra/clangd/unittests/CompilerTests.cpp @@ -8,6 +8,8 @@ #include "Compiler.h" #include "TestTU.h" +#include "clang/Frontend/DependencyOutputOptions.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/PreprocessorOptions.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -56,6 +58,50 @@ TU.build(); // no-crash } +TEST(BuildCompilerInvocation, DropsShowIncludes) { + MockFS FS; + IgnoreDiagnostics Diags; + TestTU TU; + + TU.ExtraArgs = {"-Xclang", "--show-includes"}; + EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags) + ->getDependencyOutputOpts() + .ShowIncludesDest, + ShowIncludesDestination::None); + + TU.ExtraArgs = {"/showIncludes", "--driver-mode=cl"}; + EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags) + ->getDependencyOutputOpts() + .ShowIncludesDest, + ShowIncludesDestination::None); + + TU.ExtraArgs = {"/showIncludes:user", "--driver-mode=cl"}; + EXPECT_THAT(buildCompilerInvocation(TU.inputs(FS), Diags) + ->getDependencyOutputOpts() + .ShowIncludesDest, + ShowIncludesDestination::None); +} + +TEST(BuildCompilerInvocation, DropsPlugins) { + MockFS FS; + IgnoreDiagnostics Diags; + TestTU TU; + + TU.ExtraArgs = {"-Xclang", "-load", + "-Xclang", "plugins.so", + "-Xclang", "-plugin", + "-Xclang", "my_plugin", + "-Xclang", "-plugin-arg-my_plugin", + "-Xclang", "foo=bar", + "-Xclang", "-add-plugin", + "-Xclang", "my_plugin2"}; + auto &Opts = buildCompilerInvocation(TU.inputs(FS), Diags)->getFrontendOpts(); + EXPECT_THAT(Opts.Plugins, IsEmpty()); + EXPECT_THAT(Opts.PluginArgs, IsEmpty()); + EXPECT_THAT(Opts.AddPluginActions, IsEmpty()); + EXPECT_EQ(Opts.ProgramAction, frontend::ActionKind::ParseSyntaxOnly); + EXPECT_TRUE(Opts.ActionName.empty()); +} } // namespace } // namespace clangd } // namespace clang