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: 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 3645ef055dSKadir Cetinkaya std::vector<std::string> getAllFiles() const override { 3745ef055dSKadir Cetinkaya return Base->getAllFiles(); 3845ef055dSKadir Cetinkaya } 3945ef055dSKadir Cetinkaya 4045ef055dSKadir Cetinkaya std::vector<CompileCommand> 4145ef055dSKadir Cetinkaya getCompileCommands(StringRef FilePath) const override { 4245ef055dSKadir Cetinkaya return expand(Base->getCompileCommands(FilePath)); 4345ef055dSKadir Cetinkaya } 4445ef055dSKadir Cetinkaya 4545ef055dSKadir Cetinkaya std::vector<CompileCommand> getAllCompileCommands() const override { 4645ef055dSKadir Cetinkaya return expand(Base->getAllCompileCommands()); 4745ef055dSKadir Cetinkaya } 4845ef055dSKadir Cetinkaya 4945ef055dSKadir Cetinkaya private: 5045ef055dSKadir 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()); 57*fceaf862SDmitry 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); 64ba7a92c0SNico Weber llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, 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> 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