145ef055dSKadir Cetinkaya //===- ExpandResponseFileCompilationDataBase.cpp --------------------------===//
245ef055dSKadir Cetinkaya //
345ef055dSKadir Cetinkaya // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
445ef055dSKadir Cetinkaya // See https://llvm.org/LICENSE.txt for license information.
545ef055dSKadir Cetinkaya // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
645ef055dSKadir Cetinkaya //
745ef055dSKadir Cetinkaya //===----------------------------------------------------------------------===//
845ef055dSKadir Cetinkaya
945ef055dSKadir Cetinkaya #include "clang/Tooling/CompilationDatabase.h"
10b3b37783SKadir Cetinkaya #include "llvm/ADT/StringRef.h"
1145ef055dSKadir Cetinkaya #include "llvm/ADT/Triple.h"
1245ef055dSKadir Cetinkaya #include "llvm/Support/CommandLine.h"
1345ef055dSKadir Cetinkaya #include "llvm/Support/ConvertUTF.h"
1445ef055dSKadir Cetinkaya #include "llvm/Support/ErrorOr.h"
15213aea4cSReid Kleckner #include "llvm/Support/Host.h"
1645ef055dSKadir Cetinkaya #include "llvm/Support/MemoryBuffer.h"
1745ef055dSKadir Cetinkaya #include "llvm/Support/Path.h"
1845ef055dSKadir Cetinkaya #include "llvm/Support/StringSaver.h"
1945ef055dSKadir Cetinkaya
2045ef055dSKadir Cetinkaya namespace clang {
2145ef055dSKadir Cetinkaya namespace tooling {
2245ef055dSKadir Cetinkaya namespace {
2345ef055dSKadir Cetinkaya
2445ef055dSKadir Cetinkaya class ExpandResponseFilesDatabase : public CompilationDatabase {
2545ef055dSKadir Cetinkaya public:
ExpandResponseFilesDatabase(std::unique_ptr<CompilationDatabase> Base,llvm::cl::TokenizerCallback Tokenizer,llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)2645ef055dSKadir Cetinkaya ExpandResponseFilesDatabase(
2745ef055dSKadir Cetinkaya std::unique_ptr<CompilationDatabase> Base,
2845ef055dSKadir Cetinkaya llvm::cl::TokenizerCallback Tokenizer,
2945ef055dSKadir Cetinkaya llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
3045ef055dSKadir Cetinkaya : Base(std::move(Base)), Tokenizer(Tokenizer), FS(std::move(FS)) {
3145ef055dSKadir Cetinkaya assert(this->Base != nullptr);
3245ef055dSKadir Cetinkaya assert(this->Tokenizer != nullptr);
3345ef055dSKadir Cetinkaya assert(this->FS != nullptr);
3445ef055dSKadir Cetinkaya }
3545ef055dSKadir Cetinkaya
getAllFiles() const3645ef055dSKadir Cetinkaya std::vector<std::string> getAllFiles() const override {
3745ef055dSKadir Cetinkaya return Base->getAllFiles();
3845ef055dSKadir Cetinkaya }
3945ef055dSKadir Cetinkaya
4045ef055dSKadir Cetinkaya std::vector<CompileCommand>
getCompileCommands(StringRef FilePath) const4145ef055dSKadir Cetinkaya getCompileCommands(StringRef FilePath) const override {
4245ef055dSKadir Cetinkaya return expand(Base->getCompileCommands(FilePath));
4345ef055dSKadir Cetinkaya }
4445ef055dSKadir Cetinkaya
getAllCompileCommands() const4545ef055dSKadir Cetinkaya std::vector<CompileCommand> getAllCompileCommands() const override {
4645ef055dSKadir Cetinkaya return expand(Base->getAllCompileCommands());
4745ef055dSKadir Cetinkaya }
4845ef055dSKadir Cetinkaya
4945ef055dSKadir Cetinkaya private:
expand(std::vector<CompileCommand> Cmds) const5045ef055dSKadir Cetinkaya std::vector<CompileCommand> expand(std::vector<CompileCommand> Cmds) const {
5145ef055dSKadir Cetinkaya for (auto &Cmd : Cmds) {
5245ef055dSKadir Cetinkaya bool SeenRSPFile = false;
5345ef055dSKadir Cetinkaya llvm::SmallVector<const char *, 20> Argv;
5445ef055dSKadir Cetinkaya Argv.reserve(Cmd.CommandLine.size());
5545ef055dSKadir Cetinkaya for (auto &Arg : Cmd.CommandLine) {
5645ef055dSKadir Cetinkaya Argv.push_back(Arg.c_str());
57fceaf862SDmitry Polukhin if (!Arg.empty())
5845ef055dSKadir Cetinkaya SeenRSPFile |= Arg.front() == '@';
5945ef055dSKadir Cetinkaya }
6045ef055dSKadir Cetinkaya if (!SeenRSPFile)
6145ef055dSKadir Cetinkaya continue;
6245ef055dSKadir Cetinkaya llvm::BumpPtrAllocator Alloc;
6345ef055dSKadir Cetinkaya llvm::StringSaver Saver(Alloc);
64*9d37d0eaSJack Andersen llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, false,
65ba7a92c0SNico Weber llvm::StringRef(Cmd.Directory), *FS);
66966fac19SSam McCall // Don't assign directly, Argv aliases CommandLine.
67966fac19SSam McCall std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end());
68966fac19SSam McCall Cmd.CommandLine = std::move(ExpandedArgv);
6945ef055dSKadir Cetinkaya }
7045ef055dSKadir Cetinkaya return Cmds;
7145ef055dSKadir Cetinkaya }
7245ef055dSKadir Cetinkaya
7345ef055dSKadir Cetinkaya private:
7445ef055dSKadir Cetinkaya std::unique_ptr<CompilationDatabase> Base;
7545ef055dSKadir Cetinkaya llvm::cl::TokenizerCallback Tokenizer;
7645ef055dSKadir Cetinkaya llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
7745ef055dSKadir Cetinkaya };
7845ef055dSKadir Cetinkaya
7945ef055dSKadir Cetinkaya } // namespace
8045ef055dSKadir Cetinkaya
8145ef055dSKadir Cetinkaya std::unique_ptr<CompilationDatabase>
expandResponseFiles(std::unique_ptr<CompilationDatabase> Base,llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)8245ef055dSKadir Cetinkaya expandResponseFiles(std::unique_ptr<CompilationDatabase> Base,
8345ef055dSKadir Cetinkaya llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
8445ef055dSKadir Cetinkaya auto Tokenizer = llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows()
8545ef055dSKadir Cetinkaya ? llvm::cl::TokenizeWindowsCommandLine
8645ef055dSKadir Cetinkaya : llvm::cl::TokenizeGNUCommandLine;
8745ef055dSKadir Cetinkaya return std::make_unique<ExpandResponseFilesDatabase>(
8845ef055dSKadir Cetinkaya std::move(Base), Tokenizer, std::move(FS));
8945ef055dSKadir Cetinkaya }
9045ef055dSKadir Cetinkaya
9145ef055dSKadir Cetinkaya } // namespace tooling
9245ef055dSKadir Cetinkaya } // namespace clang
93