Index: clang-tools-extra/clangd/CompileCommands.cpp =================================================================== --- clang-tools-extra/clangd/CompileCommands.cpp +++ clang-tools-extra/clangd/CompileCommands.cpp @@ -14,6 +14,7 @@ #include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Tooling/CompilationDatabase.h" +#include "clang/Tooling/Tooling.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -201,7 +202,7 @@ trace::Span S("AdjustCompileFlags"); // Most of the modifications below assumes the Cmd starts with a driver name. // We might consider injecting a generic driver name like "cc" or "c++", but - // a Cmd missing the driver is probably rare enough in practice and errnous. + // a Cmd missing a driver is probably rare enough in practice and erroneous. if (Cmd.empty()) return; auto &OptTable = clang::driver::getDriverOptTable(); @@ -307,12 +308,16 @@ // necessary for the system include extractor to identify the file type // - AFTER applying CompileFlags.Edits, because the name of the compiler // that needs to be invoked may come from the CompileFlags->Compiler key + // - BEFORE addTargetAndModeForProgramName(), because gcc doesn't support + // the target flag that might be added. // - BEFORE resolveDriver() because that can mess up the driver path, // e.g. changing gcc to /path/to/clang/bin/gcc if (SystemIncludeExtractor) { SystemIncludeExtractor(Command, File); } + tooling::addTargetAndModeForProgramName(Cmd, Cmd.front()); + // Check whether the flag exists, either as -flag or -flag=* auto Has = [&](llvm::StringRef Flag) { for (llvm::StringRef Arg : Cmd) { Index: clang-tools-extra/clangd/GlobalCompilationDatabase.cpp =================================================================== --- clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -250,9 +250,8 @@ // For now, use the real FS, which is known to be threadsafe (if we don't // use/change working directory, which ExpandResponseFilesDatabase doesn't). auto FS = llvm::vfs::getRealFileSystem(); - return tooling::inferTargetAndDriverMode( - tooling::inferMissingCompileCommands( - expandResponseFiles(std::move(CDB), std::move(FS)))); + return tooling::inferMissingCompileCommands( + expandResponseFiles(std::move(CDB), std::move(FS))); } return nullptr; } @@ -478,7 +477,7 @@ std::optional ActiveTask; std::thread Thread; // Must be last member. - // Thread body: this is just the basic queue procesing boilerplate. + // Thread body: this is just the basic queue processing boilerplate. void run() { std::unique_lock Lock(Mu); while (true) { Index: clang-tools-extra/clangd/SystemIncludeExtractor.cpp =================================================================== --- clang-tools-extra/clangd/SystemIncludeExtractor.cpp +++ clang-tools-extra/clangd/SystemIncludeExtractor.cpp @@ -185,13 +185,18 @@ const llvm::StringRef FlagsToPreserve[] = { "-nostdinc", "--no-standard-includes", "-nostdinc++", "-nobuiltininc"}; // Preserves these flags and their values, either as separate args or with an - // equalsbetween them + // equals between them const llvm::StringRef ArgsToPreserve[] = {"--sysroot", "-isysroot"}; for (size_t I = 0, E = CommandLine.size(); I < E; ++I) { llvm::StringRef Arg = CommandLine[I]; if (llvm::is_contained(FlagsToPreserve, Arg)) { Args.push_back(Arg); + } else if (Arg.startswith("--target=")) { + Args.push_back(Arg); + } else if (I + 1 < E && Arg.equals("-target")) { + Args.push_back(CommandLine[I]); + Args.push_back(CommandLine[++I]); } else { const auto *Found = llvm::find_if(ArgsToPreserve, [&Arg](llvm::StringRef S) { Index: clang-tools-extra/clangd/test/system-include-extractor.test =================================================================== --- clang-tools-extra/clangd/test/system-include-extractor.test +++ clang-tools-extra/clangd/test/system-include-extractor.test @@ -16,6 +16,8 @@ # RUN: echo '[ -z "${args##*"-nostdinc"*}" ] || exit' >> %t.dir/bin/my_driver.sh # RUN: echo '[ -z "${args##*"-isysroot=/isysroot"*}" ] || exit' >> %t.dir/bin/my_driver.sh # RUN: echo '[ -z "${args##*"--sysroot /my/sysroot/path"*}" ] || exit' >> %t.dir/bin/my_driver.sh +# RUN: echo '[ -z "${args##*"-target arm-linux-gnueabi"*}" ] || exit' >> %t.dir/bin/my_driver.sh +# RUN: echo '[ -z "${args##*"--target=arm-linux-gnueabi"*}" ] || exit' >> %t.dir/bin/my_driver.sh # RUN: echo 'echo line to ignore >&2' >> %t.dir/bin/my_driver.sh # RUN: echo 'printf "Target: arm-linux-gnueabihf\r\n" >&2' >> %t.dir/bin/my_driver.sh # RUN: echo 'printf "#include <...> search starts here:\r\n" >&2' >> %t.dir/bin/my_driver.sh @@ -32,7 +34,7 @@ # Generate a compile_commands.json that will query the mock driver we've # created. Which should add a.h and b.h into include search path. -# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json +# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot -target arm-linux-gnueabi --target=arm-linux-gnueabi", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json # RUN: sed -e "s|INPUT_DIR|%/t.dir|g" %s > %t.test.1 # On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..." @@ -70,7 +72,7 @@ {"jsonrpc":"2.0","method":"exit"} # Generate a different compile_commands.json which does not point to the mock driver -# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json +# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot -target arm-linux-gnueabi --target=arm-linux-gnueabi", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json # Generate a clangd config file which points to the mock driver instead # RUN: echo 'CompileFlags:' > %t.dir/.clangd Index: clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp +++ clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp @@ -49,7 +49,7 @@ Cmd.CommandLine = {"clang++", "--", "foo.cc", "bar.cc"}; Mangler(Cmd, "foo.cc"); EXPECT_THAT(Cmd.CommandLine, - ElementsAre(testPath("fake/clang++"), + ElementsAre(testPath("fake/clang++"), "--driver-mode=g++", "-resource-dir=" + testPath("fake/resources"), "-isysroot", testPath("fake/sysroot"), "--", "foo.cc")); @@ -198,7 +198,8 @@ } // Edits are applied in given order and before other mangling and they always // go before filename. - EXPECT_THAT(Cmd.CommandLine, ElementsAre(_, "--hello", "--", "FOO.CC")); + EXPECT_THAT(Cmd.CommandLine, + ElementsAre(_, "--driver-mode=g++", "--hello", "--", "FOO.CC")); } static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) {