lh123 updated this revision to Diff 231217.
lh123 set the repository for this revision to rG LLVM Github Monorepo.
lh123 added a comment.
rebase to D70769 <https://reviews.llvm.org/D70769>
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D70222/new/
https://reviews.llvm.org/D70222
Files:
clang/include/clang/Tooling/CompilationDatabase.h
clang/lib/Tooling/CMakeLists.txt
clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
clang/lib/Tooling/JSONCompilationDatabase.cpp
clang/unittests/Tooling/CompilationDatabaseTest.cpp
Index: clang/unittests/Tooling/CompilationDatabaseTest.cpp
===================================================================
--- clang/unittests/Tooling/CompilationDatabaseTest.cpp
+++ clang/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -859,5 +859,64 @@
"clang++ --driver-mode=g++ bar.cpp -D bar.cpp");
}
+class ExpandResponseFilesTest : public MemDBTest {
+protected:
+ void SetUp() override {
+ FS = new llvm::vfs::InMemoryFileSystem;
+
+ InnerDir = path(StringRef("inner"));
+
+ llvm::sys::path::append(RspFileName1, InnerDir, "rsp1.rsp");
+ addFile(RspFileName1, "-Dflag1");
+
+ RspFileName2 = path(StringRef("rsp2.rsp"));
+ addFile(RspFileName2, "-Dflag2 @rsp3.rsp");
+
+ RspFileName3 = path(StringRef("rsp3.rsp"));
+ addFile(RspFileName3, "-Dflag3");
+
+ RspFileName4 = path(StringRef("rsp4.rsp"));
+ addFile(RspFileName4, "-Dflag4 @rsp4.rsp");
+
+ llvm::sys::path::append(RspFileName5, InnerDir, "rsp5.rsp");
+ addFile(RspFileName5, "-Dflag5 @inner/rsp1.rsp");
+ }
+
+ void addFile(StringRef File, StringRef Context) {
+ ASSERT_TRUE(FS->addFile(File, 0, llvm::MemoryBuffer::getMemBufferCopy(Context)));
+ }
+
+ std::string getCommand(llvm::StringRef F) {
+ auto Results = expandResponseFiles(std::make_unique<MemCDB>(Entries),
+ FS)
+ ->getCompileCommands(path(F));
+ if (Results.empty()) {
+ return "none";
+ }
+ return llvm::join(Results[0].CommandLine, " ");
+ }
+
+ SmallString<128> InnerDir;
+ SmallString<128> RspFileName1;
+ SmallString<128> RspFileName2;
+ SmallString<128> RspFileName3;
+ SmallString<128> RspFileName4;
+ SmallString<128> RspFileName5;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS;
+
+};
+
+TEST_F(ExpandResponseFilesTest, ExpandResponseFiles) {
+ // clang-format off
+ add("foo.cpp", "clang",
+ ("@inner/rsp1.rsp @rsp2.rsp @rsp4.rsp "
+ "@" + RspFileName1 + " @inner/rsp5.rsp @rsp6.rsp")
+ .str());
+ // clang-format on
+ EXPECT_EQ(getCommand("foo.cpp"), "clang foo.cpp -D foo.cpp -Dflag1 -Dflag2 "
+ "-Dflag3 -Dflag4 @rsp4.rsp -Dflag1 "
+ "-Dflag5 -Dflag1 @rsp6.rsp");
+}
+
} // end namespace tooling
} // end namespace clang
Index: clang/lib/Tooling/JSONCompilationDatabase.cpp
===================================================================
--- clang/lib/Tooling/JSONCompilationDatabase.cpp
+++ clang/lib/Tooling/JSONCompilationDatabase.cpp
@@ -168,7 +168,8 @@
auto Base = JSONCompilationDatabase::loadFromFile(
JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect);
return Base ? inferTargetAndDriverMode(
- inferMissingCompileCommands(std::move(Base)))
+ inferMissingCompileCommands(expandResponseFiles(
+ std::move(Base), llvm::vfs::getRealFileSystem())))
: nullptr;
}
};
Index: clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
===================================================================
--- /dev/null
+++ clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
@@ -0,0 +1,92 @@
+//===- ExpandResponseFileCompilationDataBase.cpp --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace clang {
+namespace tooling {
+namespace {
+
+class ExpandResponseFilesDatabase : public CompilationDatabase {
+public:
+ ExpandResponseFilesDatabase(
+ std::unique_ptr<CompilationDatabase> Base,
+ llvm::cl::TokenizerCallback Tokenizer,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
+ : Base(std::move(Base)), Tokenizer(Tokenizer), FS(FS) {
+ assert(this->Base != nullptr);
+ assert(this->Tokenizer != nullptr);
+ assert(this->FS != nullptr);
+ }
+
+ std::vector<std::string> getAllFiles() const override {
+ return Base->getAllFiles();
+ }
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override {
+ return expand(Base->getCompileCommands(FilePath));
+ }
+
+ std::vector<CompileCommand> getAllCompileCommands() const override {
+ return expand(Base->getAllCompileCommands());
+ }
+
+private:
+ std::vector<CompileCommand> expand(std::vector<CompileCommand> Cmds) const {
+ llvm::ErrorOr<std::string> PreWorkingDirectory =
+ FS->getCurrentWorkingDirectory();
+ 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());
+ SeenRSPFile |= Arg.front() == '@';
+ }
+ if (!SeenRSPFile)
+ continue;
+ if (FS->setCurrentWorkingDirectory(Cmd.Directory))
+ continue;
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Saver(Alloc);
+ llvm::cl::ExpandResponseFiles(Saver, Tokenizer, *FS, Argv);
+ Cmd.CommandLine.assign(Argv.begin(), Argv.end());
+ }
+ if (PreWorkingDirectory)
+ FS->setCurrentWorkingDirectory(*PreWorkingDirectory);
+ return Cmds;
+ }
+
+private:
+ std::unique_ptr<CompilationDatabase> Base;
+ llvm::cl::TokenizerCallback Tokenizer;
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
+};
+
+} // namespace
+
+std::unique_ptr<CompilationDatabase>
+expandResponseFiles(std::unique_ptr<CompilationDatabase> Base,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
+ auto Tokenizer = llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows()
+ ? llvm::cl::TokenizeWindowsCommandLine
+ : llvm::cl::TokenizeGNUCommandLine;
+ return std::make_unique<ExpandResponseFilesDatabase>(std::move(Base),
+ Tokenizer, FS);
+}
+
+} // namespace tooling
+} // namespace clang
Index: clang/lib/Tooling/CMakeLists.txt
===================================================================
--- clang/lib/Tooling/CMakeLists.txt
+++ clang/lib/Tooling/CMakeLists.txt
@@ -17,6 +17,7 @@
CommonOptionsParser.cpp
CompilationDatabase.cpp
Execution.cpp
+ ExpandResponseFilesCompilationDatabase.cpp
FileMatchTrie.cpp
FixIt.cpp
GuessTargetAndModeCompilationDatabase.cpp
Index: clang/include/clang/Tooling/CompilationDatabase.h
===================================================================
--- clang/include/clang/Tooling/CompilationDatabase.h
+++ clang/include/clang/Tooling/CompilationDatabase.h
@@ -31,6 +31,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <memory>
#include <string>
#include <utility>
@@ -219,6 +220,12 @@
std::unique_ptr<CompilationDatabase>
inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base);
+/// Returns a wrapped CompilationDatabase that will expand all rsp(response)
+/// files on commandline returned by underlying database.
+std::unique_ptr<CompilationDatabase>
+expandResponseFiles(std::unique_ptr<CompilationDatabase> Base,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
+
} // namespace tooling
} // namespace clang
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits