DmitryPolukhin updated this revision to Diff 498878.
DmitryPolukhin added a comment.
Rebase and retest, cannot reproduce test failure locally
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D143436/new/
https://reviews.llvm.org/D143436
Files:
clang-tools-extra/clangd/CompileCommands.cpp
clang-tools-extra/clangd/CompileCommands.h
clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
clang-tools-extra/clangd/test/Inputs/did-change-configuration-params.args
clang-tools-extra/clangd/test/did-change-configuration-params.test
clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
clang/include/clang/Tooling/Tooling.h
clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
clang/lib/Tooling/Tooling.cpp
Index: clang/lib/Tooling/Tooling.cpp
===================================================================
--- clang/lib/Tooling/Tooling.cpp
+++ clang/lib/Tooling/Tooling.cpp
@@ -43,6 +43,7 @@
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
@@ -299,6 +300,31 @@
}
}
+void addExpandedResponseFiles(std::vector<std::string> &CommandLine,
+ llvm::StringRef WorkingDir,
+ llvm::cl::TokenizerCallback Tokenizer,
+ llvm::vfs::FileSystem &FS) {
+ bool SeenRSPFile = false;
+ llvm::SmallVector<const char *, 20> Argv;
+ Argv.reserve(CommandLine.size());
+ for (auto &Arg : CommandLine) {
+ Argv.push_back(Arg.c_str());
+ if (!Arg.empty())
+ SeenRSPFile |= Arg.front() == '@';
+ }
+ if (!SeenRSPFile)
+ return;
+ llvm::BumpPtrAllocator Alloc;
+ llvm::cl::ExpansionContext ECtx(Alloc, Tokenizer);
+ llvm::Error Err =
+ ECtx.setVFS(&FS).setCurrentDir(WorkingDir).expandResponseFiles(Argv);
+ if (Err)
+ llvm::errs() << Err;
+ // Don't assign directly, Argv aliases CommandLine.
+ std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end());
+ CommandLine = std::move(ExpandedArgv);
+}
+
} // namespace tooling
} // namespace clang
@@ -684,7 +710,7 @@
if (!Invocation.run())
return nullptr;
-
+
assert(ASTs.size() == 1);
return std::move(ASTs[0]);
}
Index: clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
===================================================================
--- clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
+++ clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -48,28 +49,9 @@
private:
std::vector<CompileCommand> expand(std::vector<CompileCommand> Cmds) const {
- for (auto &Cmd : Cmds) {
- bool SeenRSPFile = false;
- llvm::SmallVector<const char *, 20> Argv;
- Argv.reserve(Cmd.CommandLine.size());
- for (auto &Arg : Cmd.CommandLine) {
- Argv.push_back(Arg.c_str());
- if (!Arg.empty())
- SeenRSPFile |= Arg.front() == '@';
- }
- if (!SeenRSPFile)
- continue;
- llvm::BumpPtrAllocator Alloc;
- llvm::cl::ExpansionContext ECtx(Alloc, Tokenizer);
- llvm::Error Err = ECtx.setVFS(FS.get())
- .setCurrentDir(Cmd.Directory)
- .expandResponseFiles(Argv);
- if (Err)
- llvm::errs() << Err;
- // Don't assign directly, Argv aliases CommandLine.
- std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end());
- Cmd.CommandLine = std::move(ExpandedArgv);
- }
+ for (auto &Cmd : Cmds)
+ tooling::addExpandedResponseFiles(Cmd.CommandLine, Cmd.Directory,
+ Tokenizer, *FS);
return Cmds;
}
Index: clang/include/clang/Tooling/Tooling.h
===================================================================
--- clang/include/clang/Tooling/Tooling.h
+++ clang/include/clang/Tooling/Tooling.h
@@ -506,6 +506,12 @@
void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
StringRef InvokedAs);
+/// Helper function that expands response files in command line.
+void addExpandedResponseFiles(std::vector<std::string> &CommandLine,
+ llvm::StringRef WorkingDir,
+ llvm::cl::TokenizerCallback Tokenizer,
+ llvm::vfs::FileSystem &FS);
+
/// Creates a \c CompilerInvocation.
CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
ArrayRef<const char *> CC1Args,
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"));
@@ -197,8 +197,10 @@
Mangler(Cmd, "foo.cc");
}
// Edits are applied in given order and before other mangling and they always
- // go before filename.
- EXPECT_THAT(Cmd.CommandLine, ElementsAre(_, "--hello", "--", "FOO.CC"));
+ // go before filename. `--driver-mode=g++` is inserted by mangler and
+ // converted to upper case with other arguments in this test only.
+ EXPECT_THAT(Cmd.CommandLine,
+ ElementsAre(_, "--DRIVER-MODE=G++", "--hello", "--", "FOO.CC"));
}
static std::string strip(llvm::StringRef Arg, llvm::StringRef Argv) {
Index: clang-tools-extra/clangd/test/did-change-configuration-params.test
===================================================================
--- clang-tools-extra/clangd/test/did-change-configuration-params.test
+++ clang-tools-extra/clangd/test/did-change-configuration-params.test
@@ -1,5 +1,10 @@
-# RUN: clangd -compile_args_from=lsp -lit-test < %s 2> %t | FileCheck -strict-whitespace %s
-# RUN: FileCheck --check-prefix=ERR --input-file=%t %s
+# Use a copy of this file because test needs real paths.
+# RUN: rm -rf %/t
+# RUN: mkdir -p %/t
+# RUN: cp %/S/Inputs/did-change-configuration-params.args %/t/args
+# RUN: sed -e "s|DIRECTORY|%/t/|" %/s > %/t/input
+# RUN: clangd -compile_args_from=lsp -lit-test < %/t/input 2> %/t/output | FileCheck -strict-whitespace %/t/input
+# RUN: FileCheck --check-prefix=ERR --input-file=%/t/output %/t/input
# UNSUPPORTED: system-windows
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
---
@@ -45,13 +50,23 @@
# CHECK-NEXT: "uri": "file://{{.*}}/foo.c",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
+---
+{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabaseChanges":{"/clangd-test/foo.c": {"workingDirectory":"/clangd-test2", "compilationCommand": ["riscv64-unknown-elf-gcc", "-c", "foo.c", "-Wall", "-Werror"]}}}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
+---
+{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"compilationDatabaseChanges":{"/clangd-test/foo.c": {"workingDirectory":"DIRECTORY", "compilationCommand": ["g++", "-c", "foo.c", "-Wall", "-Werror", "@args"]}}}}}
+# CHECK: "method": "textDocument/publishDiagnostics",
#
# ERR: ASTWorker building file {{.*}}foo.c version 0 with command
# ERR: [{{.*}}clangd-test2]
# ERR: clang -c -Wall -Werror {{.*}} -- {{.*}}foo.c
+# ERR: ASTWorker building file {{.*}}foo.c version 0 with command
+# ERR: [{{.*}}clangd-test2]
+# ERR: riscv64-unknown-elf-gcc --target=riscv64-unknown-elf -c -Wall -Werror {{.*}} -- {{.*}}foo.c
+# ERR: ASTWorker building file {{.*}}foo.c version 0 with command
+# ERR: [DIRECTORY]
+# ERR: g++ --driver-mode=g++ -c -Wall -Werror -Wpedantic {{.*}} -- {{.*}}foo.c
---
{"jsonrpc":"2.0","id":5,"method":"shutdown"}
---
{"jsonrpc":"2.0","method":"exit"}
-
-
Index: clang-tools-extra/clangd/test/Inputs/did-change-configuration-params.args
===================================================================
--- /dev/null
+++ clang-tools-extra/clangd/test/Inputs/did-change-configuration-params.args
@@ -0,0 +1 @@
+-Wpedantic
Index: clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
===================================================================
--- clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -244,15 +244,7 @@
parseJSON(PathRef Path, llvm::StringRef Data, std::string &Error) {
if (auto CDB = tooling::JSONCompilationDatabase::loadFromBuffer(
Data, Error, tooling::JSONCommandLineSyntax::AutoDetect)) {
- // FS used for expanding response files.
- // FIXME: ExpandResponseFilesDatabase appears not to provide the usual
- // thread-safety guarantees, as the access to FS is not locked!
- // 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(std::move(CDB));
}
return nullptr;
}
Index: clang-tools-extra/clangd/CompileCommands.h
===================================================================
--- clang-tools-extra/clangd/CompileCommands.h
+++ clang-tools-extra/clangd/CompileCommands.h
@@ -12,6 +12,7 @@
#include "support/Threading.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
#include <deque>
#include <optional>
#include <string>
@@ -50,10 +51,12 @@
llvm::StringRef TargetFile) const;
private:
- CommandMangler() = default;
+ CommandMangler();
Memoize<llvm::StringMap<std::string>> ResolvedDrivers;
Memoize<llvm::StringMap<std::string>> ResolvedDriversNoFollow;
+ llvm::cl::TokenizerCallback Tokenizer;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
};
// Removes args from a command-line in a semantically-aware way.
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"
@@ -27,6 +28,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
+#include "llvm/TargetParser/Host.h"
#include <iterator>
#include <optional>
#include <string>
@@ -185,6 +187,18 @@
} // namespace
+CommandMangler::CommandMangler() {
+ Tokenizer = llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows()
+ ? llvm::cl::TokenizeWindowsCommandLine
+ : llvm::cl::TokenizeGNUCommandLine;
+ // FS used for expanding response files.
+ // FIXME: ExpandResponseFiles appears not to provide the usual
+ // thread-safety guarantees, as the access to FS is not locked!
+ // For now, use the real FS, which is known to be threadsafe (if we don't
+ // use/change working directory, which ExpandResponseFiles doesn't).
+ FS = llvm::vfs::getRealFileSystem();
+}
+
CommandMangler CommandMangler::detect() {
CommandMangler Result;
Result.ClangPath = detectClangPath();
@@ -201,9 +215,11 @@
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 the driver is probably rare enough in practice and erroneous.
if (Cmd.empty())
return;
+ tooling::addExpandedResponseFiles(Cmd, Command.Directory, Tokenizer, *FS);
+ tooling::addTargetAndModeForProgramName(Cmd, Cmd.front());
auto &OptTable = clang::driver::getDriverOptTable();
// OriginalArgs needs to outlive ArgList.
llvm::SmallVector<const char *, 16> OriginalArgs;
@@ -212,7 +228,7 @@
OriginalArgs.push_back(S.c_str());
bool IsCLMode = driver::IsClangCL(driver::getDriverMode(
OriginalArgs[0], llvm::ArrayRef(OriginalArgs).slice(1)));
- // ParseArgs propagates missig arg/opt counts on error, but preserves
+ // ParseArgs propagates missing arg/opt counts on error, but preserves
// everything it could parse in ArgList. So we just ignore those counts.
unsigned IgnoredCount;
// Drop the executable name, as ParseArgs doesn't expect it. This means
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits