1356843Sdim//===- ExpandResponseFileCompilationDataBase.cpp --------------------------===// 2356843Sdim// 3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4356843Sdim// See https://llvm.org/LICENSE.txt for license information. 5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6356843Sdim// 7356843Sdim//===----------------------------------------------------------------------===// 8356843Sdim 9356843Sdim#include "clang/Tooling/CompilationDatabase.h" 10356843Sdim#include "llvm/ADT/StringRef.h" 11356843Sdim#include "llvm/ADT/Triple.h" 12356843Sdim#include "llvm/Support/CommandLine.h" 13356843Sdim#include "llvm/Support/ConvertUTF.h" 14356843Sdim#include "llvm/Support/ErrorOr.h" 15356843Sdim#include "llvm/Support/MemoryBuffer.h" 16356843Sdim#include "llvm/Support/Path.h" 17356843Sdim#include "llvm/Support/StringSaver.h" 18356843Sdim 19356843Sdimnamespace clang { 20356843Sdimnamespace tooling { 21356843Sdimnamespace { 22356843Sdim 23356843Sdimclass ExpandResponseFilesDatabase : public CompilationDatabase { 24356843Sdimpublic: 25356843Sdim ExpandResponseFilesDatabase( 26356843Sdim std::unique_ptr<CompilationDatabase> Base, 27356843Sdim llvm::cl::TokenizerCallback Tokenizer, 28356843Sdim llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) 29356843Sdim : Base(std::move(Base)), Tokenizer(Tokenizer), FS(std::move(FS)) { 30356843Sdim assert(this->Base != nullptr); 31356843Sdim assert(this->Tokenizer != nullptr); 32356843Sdim assert(this->FS != nullptr); 33356843Sdim } 34356843Sdim 35356843Sdim std::vector<std::string> getAllFiles() const override { 36356843Sdim return Base->getAllFiles(); 37356843Sdim } 38356843Sdim 39356843Sdim std::vector<CompileCommand> 40356843Sdim getCompileCommands(StringRef FilePath) const override { 41356843Sdim return expand(Base->getCompileCommands(FilePath)); 42356843Sdim } 43356843Sdim 44356843Sdim std::vector<CompileCommand> getAllCompileCommands() const override { 45356843Sdim return expand(Base->getAllCompileCommands()); 46356843Sdim } 47356843Sdim 48356843Sdimprivate: 49356843Sdim std::vector<CompileCommand> expand(std::vector<CompileCommand> Cmds) const { 50356843Sdim for (auto &Cmd : Cmds) { 51356843Sdim bool SeenRSPFile = false; 52356843Sdim llvm::SmallVector<const char *, 20> Argv; 53356843Sdim Argv.reserve(Cmd.CommandLine.size()); 54356843Sdim for (auto &Arg : Cmd.CommandLine) { 55356843Sdim Argv.push_back(Arg.c_str()); 56356843Sdim SeenRSPFile |= Arg.front() == '@'; 57356843Sdim } 58356843Sdim if (!SeenRSPFile) 59356843Sdim continue; 60356843Sdim llvm::BumpPtrAllocator Alloc; 61356843Sdim llvm::StringSaver Saver(Alloc); 62356843Sdim llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, *FS, 63356843Sdim llvm::StringRef(Cmd.Directory)); 64356843Sdim // Don't assign directly, Argv aliases CommandLine. 65356843Sdim std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end()); 66356843Sdim Cmd.CommandLine = std::move(ExpandedArgv); 67356843Sdim } 68356843Sdim return Cmds; 69356843Sdim } 70356843Sdim 71356843Sdimprivate: 72356843Sdim std::unique_ptr<CompilationDatabase> Base; 73356843Sdim llvm::cl::TokenizerCallback Tokenizer; 74356843Sdim llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; 75356843Sdim}; 76356843Sdim 77356843Sdim} // namespace 78356843Sdim 79356843Sdimstd::unique_ptr<CompilationDatabase> 80356843SdimexpandResponseFiles(std::unique_ptr<CompilationDatabase> Base, 81356843Sdim llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { 82356843Sdim auto Tokenizer = llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows() 83356843Sdim ? llvm::cl::TokenizeWindowsCommandLine 84356843Sdim : llvm::cl::TokenizeGNUCommandLine; 85356843Sdim return std::make_unique<ExpandResponseFilesDatabase>( 86356843Sdim std::move(Base), Tokenizer, std::move(FS)); 87356843Sdim} 88356843Sdim 89356843Sdim} // namespace tooling 90356843Sdim} // namespace clang 91