ExpandResponseFilesCompilationDatabase.cpp revision 356843
121308Sache//===- ExpandResponseFileCompilationDataBase.cpp --------------------------===//
221308Sache//
321308Sache// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
421308Sache// See https://llvm.org/LICENSE.txt for license information.
521308Sache// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
621308Sache//
721308Sache//===----------------------------------------------------------------------===//
821308Sache
921308Sache#include "clang/Tooling/CompilationDatabase.h"
1058310Sache#include "llvm/ADT/StringRef.h"
1121308Sache#include "llvm/ADT/Triple.h"
1221308Sache#include "llvm/Support/CommandLine.h"
1321308Sache#include "llvm/Support/ConvertUTF.h"
1421308Sache#include "llvm/Support/ErrorOr.h"
1521308Sache#include "llvm/Support/MemoryBuffer.h"
1621308Sache#include "llvm/Support/Path.h"
1721308Sache#include "llvm/Support/StringSaver.h"
1821308Sache
1921308Sachenamespace clang {
2021308Sachenamespace tooling {
2158310Sachenamespace {
2221308Sache
2321308Sacheclass ExpandResponseFilesDatabase : public CompilationDatabase {
2421308Sachepublic:
2521308Sache  ExpandResponseFilesDatabase(
2621308Sache      std::unique_ptr<CompilationDatabase> Base,
2721308Sache      llvm::cl::TokenizerCallback Tokenizer,
2821308Sache      llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
2921308Sache      : Base(std::move(Base)), Tokenizer(Tokenizer), FS(std::move(FS)) {
3021308Sache    assert(this->Base != nullptr);
3121308Sache    assert(this->Tokenizer != nullptr);
3221308Sache    assert(this->FS != nullptr);
3321308Sache  }
3421308Sache
3521308Sache  std::vector<std::string> getAllFiles() const override {
3621308Sache    return Base->getAllFiles();
3721308Sache  }
3821308Sache
3921308Sache  std::vector<CompileCommand>
4021308Sache  getCompileCommands(StringRef FilePath) const override {
4121308Sache    return expand(Base->getCompileCommands(FilePath));
4221308Sache  }
4321308Sache
4421308Sache  std::vector<CompileCommand> getAllCompileCommands() const override {
4521308Sache    return expand(Base->getAllCompileCommands());
4621308Sache  }
4721308Sache
4821308Sacheprivate:
4958310Sache  std::vector<CompileCommand> expand(std::vector<CompileCommand> Cmds) const {
5058310Sache    for (auto &Cmd : Cmds) {
5121308Sache      bool SeenRSPFile = false;
5221308Sache      llvm::SmallVector<const char *, 20> Argv;
5321308Sache      Argv.reserve(Cmd.CommandLine.size());
5421308Sache      for (auto &Arg : Cmd.CommandLine) {
5521308Sache        Argv.push_back(Arg.c_str());
5621308Sache        SeenRSPFile |= Arg.front() == '@';
5721308Sache      }
5821308Sache      if (!SeenRSPFile)
5921308Sache        continue;
6021308Sache      llvm::BumpPtrAllocator Alloc;
6121308Sache      llvm::StringSaver Saver(Alloc);
6221308Sache      llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, *FS,
6321308Sache                                    llvm::StringRef(Cmd.Directory));
6421308Sache      // Don't assign directly, Argv aliases CommandLine.
6521308Sache      std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end());
6621308Sache      Cmd.CommandLine = std::move(ExpandedArgv);
6721308Sache    }
6821308Sache    return Cmds;
6921308Sache  }
7021308Sache
7121308Sacheprivate:
7221308Sache  std::unique_ptr<CompilationDatabase> Base;
73119610Sache  llvm::cl::TokenizerCallback Tokenizer;
74119610Sache  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
75119610Sache};
76119610Sache
77119610Sache} // namespace
7821308Sache
7921308Sachestd::unique_ptr<CompilationDatabase>
8021308SacheexpandResponseFiles(std::unique_ptr<CompilationDatabase> Base,
8121308Sache                    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
8221308Sache  auto Tokenizer = llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows()
8321308Sache                       ? llvm::cl::TokenizeWindowsCommandLine
8421308Sache                       : llvm::cl::TokenizeGNUCommandLine;
8521308Sache  return std::make_unique<ExpandResponseFilesDatabase>(
8621308Sache      std::move(Base), Tokenizer, std::move(FS));
8721308Sache}
8821308Sache
8921308Sache} // namespace tooling
9021308Sache} // namespace clang
9121308Sache