Functions that implement expansion of response and config files depend on many options, which are passes as arguments. Extending the expansion requires new options, it in turn causes changing calls in various places making them even more bulky. This change introduces a class ExpansionContext, which represents set of options that control the expansion. Its methods implements expansion of responce files including config files. It makes extending the expansion easier. No functional changes. Differential Revision: https://reviews.llvm.org/D132379
94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
//===- 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/StringRef.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/ConvertUTF.h"
|
|
#include "llvm/Support/ErrorOr.h"
|
|
#include "llvm/Support/Host.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(std::move(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 {
|
|
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());
|
|
if (!Arg.empty())
|
|
SeenRSPFile |= Arg.front() == '@';
|
|
}
|
|
if (!SeenRSPFile)
|
|
continue;
|
|
llvm::BumpPtrAllocator Alloc;
|
|
llvm::cl::ExpansionContext ECtx(Alloc, Tokenizer);
|
|
ECtx.setVFS(FS.get())
|
|
.setCurrentDir(Cmd.Directory)
|
|
.expandResponseFiles(Argv);
|
|
// Don't assign directly, Argv aliases CommandLine.
|
|
std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end());
|
|
Cmd.CommandLine = std::move(ExpandedArgv);
|
|
}
|
|
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, std::move(FS));
|
|
}
|
|
|
|
} // namespace tooling
|
|
} // namespace clang
|