/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Tooling/ExpandResponseFilesCompilationDatabase.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ExpandResponseFileCompilationDataBase.cpp --------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "clang/Tooling/CompilationDatabase.h" |
10 | | #include "llvm/ADT/StringRef.h" |
11 | | #include "llvm/ADT/Triple.h" |
12 | | #include "llvm/Support/CommandLine.h" |
13 | | #include "llvm/Support/ConvertUTF.h" |
14 | | #include "llvm/Support/ErrorOr.h" |
15 | | #include "llvm/Support/Host.h" |
16 | | #include "llvm/Support/MemoryBuffer.h" |
17 | | #include "llvm/Support/Path.h" |
18 | | #include "llvm/Support/StringSaver.h" |
19 | | |
20 | | namespace clang { |
21 | | namespace tooling { |
22 | | namespace { |
23 | | |
24 | | class ExpandResponseFilesDatabase : public CompilationDatabase { |
25 | | public: |
26 | | ExpandResponseFilesDatabase( |
27 | | std::unique_ptr<CompilationDatabase> Base, |
28 | | llvm::cl::TokenizerCallback Tokenizer, |
29 | | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) |
30 | 23 | : Base(std::move(Base)), Tokenizer(Tokenizer), FS(std::move(FS)) { |
31 | 23 | assert(this->Base != nullptr); |
32 | 0 | assert(this->Tokenizer != nullptr); |
33 | 0 | assert(this->FS != nullptr); |
34 | 23 | } |
35 | | |
36 | 20 | std::vector<std::string> getAllFiles() const override { |
37 | 20 | return Base->getAllFiles(); |
38 | 20 | } |
39 | | |
40 | | std::vector<CompileCommand> |
41 | 20 | getCompileCommands(StringRef FilePath) const override { |
42 | 20 | return expand(Base->getCompileCommands(FilePath)); |
43 | 20 | } |
44 | | |
45 | 1 | std::vector<CompileCommand> getAllCompileCommands() const override { |
46 | 1 | return expand(Base->getAllCompileCommands()); |
47 | 1 | } |
48 | | |
49 | | private: |
50 | 21 | std::vector<CompileCommand> expand(std::vector<CompileCommand> Cmds) const { |
51 | 22 | for (auto &Cmd : Cmds) { |
52 | 22 | bool SeenRSPFile = false; |
53 | 22 | llvm::SmallVector<const char *, 20> Argv; |
54 | 22 | Argv.reserve(Cmd.CommandLine.size()); |
55 | 96 | for (auto &Arg : Cmd.CommandLine) { |
56 | 96 | Argv.push_back(Arg.c_str()); |
57 | 96 | if (!Arg.empty()) |
58 | 95 | SeenRSPFile |= Arg.front() == '@'; |
59 | 96 | } |
60 | 22 | if (!SeenRSPFile) |
61 | 20 | continue; |
62 | 2 | llvm::BumpPtrAllocator Alloc; |
63 | 2 | llvm::StringSaver Saver(Alloc); |
64 | 2 | llvm::cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, false, |
65 | 2 | llvm::StringRef(Cmd.Directory), *FS); |
66 | | // Don't assign directly, Argv aliases CommandLine. |
67 | 2 | std::vector<std::string> ExpandedArgv(Argv.begin(), Argv.end()); |
68 | 2 | Cmd.CommandLine = std::move(ExpandedArgv); |
69 | 2 | } |
70 | 21 | return Cmds; |
71 | 21 | } |
72 | | |
73 | | private: |
74 | | std::unique_ptr<CompilationDatabase> Base; |
75 | | llvm::cl::TokenizerCallback Tokenizer; |
76 | | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; |
77 | | }; |
78 | | |
79 | | } // namespace |
80 | | |
81 | | std::unique_ptr<CompilationDatabase> |
82 | | expandResponseFiles(std::unique_ptr<CompilationDatabase> Base, |
83 | 23 | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) { |
84 | 23 | auto Tokenizer = llvm::Triple(llvm::sys::getProcessTriple()).isOSWindows() |
85 | 23 | ? llvm::cl::TokenizeWindowsCommandLine0 |
86 | 23 | : llvm::cl::TokenizeGNUCommandLine; |
87 | 23 | return std::make_unique<ExpandResponseFilesDatabase>( |
88 | 23 | std::move(Base), Tokenizer, std::move(FS)); |
89 | 23 | } |
90 | | |
91 | | } // namespace tooling |
92 | | } // namespace clang |