147c245a5SManuel Klimek //===--- CompilationDatabase.cpp - ----------------------------------------===//
247c245a5SManuel Klimek //
347c245a5SManuel Klimek //                     The LLVM Compiler Infrastructure
447c245a5SManuel Klimek //
547c245a5SManuel Klimek // This file is distributed under the University of Illinois Open Source
647c245a5SManuel Klimek // License. See LICENSE.TXT for details.
747c245a5SManuel Klimek //
847c245a5SManuel Klimek //===----------------------------------------------------------------------===//
947c245a5SManuel Klimek //
106ed1f85cSDaniel Jasper //  This file contains implementations of the CompilationDatabase base class
116ed1f85cSDaniel Jasper //  and the FixedCompilationDatabase.
1247c245a5SManuel Klimek //
1347c245a5SManuel Klimek //===----------------------------------------------------------------------===//
1447c245a5SManuel Klimek 
1547c245a5SManuel Klimek #include "clang/Tooling/CompilationDatabase.h"
16eb56f4feSEdwin Vane #include "clang/Basic/Diagnostic.h"
17f3ca2698SBenjamin Kramer #include "clang/Basic/DiagnosticOptions.h"
18eb56f4feSEdwin Vane #include "clang/Driver/Action.h"
195553d0d4SChandler Carruth #include "clang/Driver/Compilation.h"
20eb56f4feSEdwin Vane #include "clang/Driver/Driver.h"
21eb56f4feSEdwin Vane #include "clang/Driver/DriverDiagnostic.h"
22eb56f4feSEdwin Vane #include "clang/Driver/Job.h"
23eb56f4feSEdwin Vane #include "clang/Frontend/TextDiagnosticPrinter.h"
245553d0d4SChandler Carruth #include "clang/Tooling/CompilationDatabasePluginRegistry.h"
255553d0d4SChandler Carruth #include "clang/Tooling/Tooling.h"
265553d0d4SChandler Carruth #include "llvm/ADT/SmallString.h"
27eb56f4feSEdwin Vane #include "llvm/Option/Arg.h"
285553d0d4SChandler Carruth #include "llvm/Support/Host.h"
295553d0d4SChandler Carruth #include "llvm/Support/Path.h"
30c46064c2SSerge Pavlov #include "llvm/Support/raw_ostream.h"
315553d0d4SChandler Carruth #include <sstream>
328a8e554aSRafael Espindola #include <system_error>
336a1457e6SBenjamin Kramer using namespace clang;
346a1457e6SBenjamin Kramer using namespace tooling;
3547c245a5SManuel Klimek 
364d79ec7fSJohn Brawn LLVM_INSTANTIATE_REGISTRY(CompilationDatabasePluginRegistry)
374d79ec7fSJohn Brawn 
38637d1e66SAngel Garcia Gomez CompilationDatabase::~CompilationDatabase() {}
3947c245a5SManuel Klimek 
40cdba84c0SDavid Blaikie std::unique_ptr<CompilationDatabase>
4147c245a5SManuel Klimek CompilationDatabase::loadFromDirectory(StringRef BuildDirectory,
4247c245a5SManuel Klimek                                        std::string &ErrorMessage) {
432d487db0SMehdi Amini   llvm::raw_string_ostream ErrorStream(ErrorMessage);
446ed1f85cSDaniel Jasper   for (CompilationDatabasePluginRegistry::iterator
456ed1f85cSDaniel Jasper        It = CompilationDatabasePluginRegistry::begin(),
466ed1f85cSDaniel Jasper        Ie = CompilationDatabasePluginRegistry::end();
476ed1f85cSDaniel Jasper        It != Ie; ++It) {
486ed1f85cSDaniel Jasper     std::string DatabaseErrorMessage;
49b8984329SAhmed Charles     std::unique_ptr<CompilationDatabasePlugin> Plugin(It->instantiate());
50cdba84c0SDavid Blaikie     if (std::unique_ptr<CompilationDatabase> DB =
516ed1f85cSDaniel Jasper             Plugin->loadFromDirectory(BuildDirectory, DatabaseErrorMessage))
526ed1f85cSDaniel Jasper       return DB;
532d487db0SMehdi Amini     ErrorStream << It->getName() << ": " << DatabaseErrorMessage << "\n";
5447c245a5SManuel Klimek   }
55ccbc35edSCraig Topper   return nullptr;
5647c245a5SManuel Klimek }
5747c245a5SManuel Klimek 
58cdba84c0SDavid Blaikie static std::unique_ptr<CompilationDatabase>
596ed1f85cSDaniel Jasper findCompilationDatabaseFromDirectory(StringRef Directory,
606ed1f85cSDaniel Jasper                                      std::string &ErrorMessage) {
616ed1f85cSDaniel Jasper   std::stringstream ErrorStream;
6274351ff4SDaniel Jasper   bool HasErrorMessage = false;
63617f5269SArnaud A. de Grandmaison   while (!Directory.empty()) {
64617f5269SArnaud A. de Grandmaison     std::string LoadErrorMessage;
65617f5269SArnaud A. de Grandmaison 
66cdba84c0SDavid Blaikie     if (std::unique_ptr<CompilationDatabase> DB =
67617f5269SArnaud A. de Grandmaison             CompilationDatabase::loadFromDirectory(Directory, LoadErrorMessage))
68617f5269SArnaud A. de Grandmaison       return DB;
6974351ff4SDaniel Jasper 
7074351ff4SDaniel Jasper     if (!HasErrorMessage) {
716ed1f85cSDaniel Jasper       ErrorStream << "No compilation database found in " << Directory.str()
7274351ff4SDaniel Jasper                   << " or any parent directory\n" << LoadErrorMessage;
7374351ff4SDaniel Jasper       HasErrorMessage = true;
7474351ff4SDaniel Jasper     }
75617f5269SArnaud A. de Grandmaison 
76617f5269SArnaud A. de Grandmaison     Directory = llvm::sys::path::parent_path(Directory);
77617f5269SArnaud A. de Grandmaison   }
786ed1f85cSDaniel Jasper   ErrorMessage = ErrorStream.str();
79ccbc35edSCraig Topper   return nullptr;
80617f5269SArnaud A. de Grandmaison }
81617f5269SArnaud A. de Grandmaison 
82cdba84c0SDavid Blaikie std::unique_ptr<CompilationDatabase>
8365fd0e1fSManuel Klimek CompilationDatabase::autoDetectFromSource(StringRef SourceFile,
8465fd0e1fSManuel Klimek                                           std::string &ErrorMessage) {
85f857950dSDmitri Gribenko   SmallString<1024> AbsolutePath(getAbsolutePath(SourceFile));
8665fd0e1fSManuel Klimek   StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
87617f5269SArnaud A. de Grandmaison 
88cdba84c0SDavid Blaikie   std::unique_ptr<CompilationDatabase> DB =
89cdba84c0SDavid Blaikie       findCompilationDatabaseFromDirectory(Directory, ErrorMessage);
90617f5269SArnaud A. de Grandmaison 
91617f5269SArnaud A. de Grandmaison   if (!DB)
9265fd0e1fSManuel Klimek     ErrorMessage = ("Could not auto-detect compilation database for file \"" +
936ed1f85cSDaniel Jasper                    SourceFile + "\"\n" + ErrorMessage).str();
94617f5269SArnaud A. de Grandmaison   return DB;
95617f5269SArnaud A. de Grandmaison }
96617f5269SArnaud A. de Grandmaison 
97cdba84c0SDavid Blaikie std::unique_ptr<CompilationDatabase>
98617f5269SArnaud A. de Grandmaison CompilationDatabase::autoDetectFromDirectory(StringRef SourceDir,
99617f5269SArnaud A. de Grandmaison                                              std::string &ErrorMessage) {
100f857950dSDmitri Gribenko   SmallString<1024> AbsolutePath(getAbsolutePath(SourceDir));
101617f5269SArnaud A. de Grandmaison 
102cdba84c0SDavid Blaikie   std::unique_ptr<CompilationDatabase> DB =
103cdba84c0SDavid Blaikie       findCompilationDatabaseFromDirectory(AbsolutePath, ErrorMessage);
104617f5269SArnaud A. de Grandmaison 
105617f5269SArnaud A. de Grandmaison   if (!DB)
106617f5269SArnaud A. de Grandmaison     ErrorMessage = ("Could not auto-detect compilation database from directory \"" +
1076ed1f85cSDaniel Jasper                    SourceDir + "\"\n" + ErrorMessage).str();
108617f5269SArnaud A. de Grandmaison   return DB;
10965fd0e1fSManuel Klimek }
11065fd0e1fSManuel Klimek 
111637d1e66SAngel Garcia Gomez CompilationDatabasePlugin::~CompilationDatabasePlugin() {}
1126ed1f85cSDaniel Jasper 
1136a1457e6SBenjamin Kramer namespace {
114eb56f4feSEdwin Vane // Helper for recursively searching through a chain of actions and collecting
115eb56f4feSEdwin Vane // all inputs, direct and indirect, of compile jobs.
116eb56f4feSEdwin Vane struct CompileJobAnalyzer {
117eb56f4feSEdwin Vane   void run(const driver::Action *A) {
118eb56f4feSEdwin Vane     runImpl(A, false);
119eb56f4feSEdwin Vane   }
120eb56f4feSEdwin Vane 
121eb56f4feSEdwin Vane   SmallVector<std::string, 2> Inputs;
122eb56f4feSEdwin Vane 
123eb56f4feSEdwin Vane private:
124eb56f4feSEdwin Vane 
125eb56f4feSEdwin Vane   void runImpl(const driver::Action *A, bool Collect) {
126eb56f4feSEdwin Vane     bool CollectChildren = Collect;
127eb56f4feSEdwin Vane     switch (A->getKind()) {
128eb56f4feSEdwin Vane     case driver::Action::CompileJobClass:
129eb56f4feSEdwin Vane       CollectChildren = true;
130eb56f4feSEdwin Vane       break;
131eb56f4feSEdwin Vane 
132eb56f4feSEdwin Vane     case driver::Action::InputClass: {
133eb56f4feSEdwin Vane       if (Collect) {
134eb56f4feSEdwin Vane         const driver::InputAction *IA = cast<driver::InputAction>(A);
135eb56f4feSEdwin Vane         Inputs.push_back(IA->getInputArg().getSpelling());
136eb56f4feSEdwin Vane       }
137eb56f4feSEdwin Vane     } break;
138eb56f4feSEdwin Vane 
139eb56f4feSEdwin Vane     default:
140eb56f4feSEdwin Vane       // Don't care about others
141eb56f4feSEdwin Vane       ;
142eb56f4feSEdwin Vane     }
143eb56f4feSEdwin Vane 
1445a459f82SNico Weber     for (const driver::Action *AI : A->inputs())
1455a459f82SNico Weber       runImpl(AI, CollectChildren);
146eb56f4feSEdwin Vane   }
147eb56f4feSEdwin Vane };
148eb56f4feSEdwin Vane 
149eb56f4feSEdwin Vane // Special DiagnosticConsumer that looks for warn_drv_input_file_unused
150eb56f4feSEdwin Vane // diagnostics from the driver and collects the option strings for those unused
151eb56f4feSEdwin Vane // options.
152eb56f4feSEdwin Vane class UnusedInputDiagConsumer : public DiagnosticConsumer {
153eb56f4feSEdwin Vane public:
154c46064c2SSerge Pavlov   UnusedInputDiagConsumer(DiagnosticConsumer &Other) : Other(Other) {}
155eb56f4feSEdwin Vane 
15634eb2072SAlexander Kornienko   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
157a798a9dbSCraig Topper                         const Diagnostic &Info) override {
158eb56f4feSEdwin Vane     if (Info.getID() == clang::diag::warn_drv_input_file_unused) {
159eb56f4feSEdwin Vane       // Arg 1 for this diagnostic is the option that didn't get used.
160eb56f4feSEdwin Vane       UnusedInputs.push_back(Info.getArgStdStr(0));
161c46064c2SSerge Pavlov     } else if (DiagLevel >= DiagnosticsEngine::Error) {
162c46064c2SSerge Pavlov       // If driver failed to create compilation object, show the diagnostics
163c46064c2SSerge Pavlov       // to user.
164c46064c2SSerge Pavlov       Other.HandleDiagnostic(DiagLevel, Info);
165eb56f4feSEdwin Vane     }
166eb56f4feSEdwin Vane   }
167eb56f4feSEdwin Vane 
168c46064c2SSerge Pavlov   DiagnosticConsumer &Other;
169eb56f4feSEdwin Vane   SmallVector<std::string, 2> UnusedInputs;
170eb56f4feSEdwin Vane };
171eb56f4feSEdwin Vane 
172eb56f4feSEdwin Vane // Unary functor for asking "Given a StringRef S1, does there exist a string
173eb56f4feSEdwin Vane // S2 in Arr where S1 == S2?"
174eb56f4feSEdwin Vane struct MatchesAny {
175eb56f4feSEdwin Vane   MatchesAny(ArrayRef<std::string> Arr) : Arr(Arr) {}
176eb56f4feSEdwin Vane   bool operator() (StringRef S) {
177eb56f4feSEdwin Vane     for (const std::string *I = Arr.begin(), *E = Arr.end(); I != E; ++I)
178eb56f4feSEdwin Vane       if (*I == S)
179eb56f4feSEdwin Vane         return true;
180eb56f4feSEdwin Vane     return false;
181eb56f4feSEdwin Vane   }
182eb56f4feSEdwin Vane private:
183eb56f4feSEdwin Vane   ArrayRef<std::string> Arr;
184eb56f4feSEdwin Vane };
1856a1457e6SBenjamin Kramer } // namespace
186eb56f4feSEdwin Vane 
187eb56f4feSEdwin Vane /// \brief Strips any positional args and possible argv[0] from a command-line
188eb56f4feSEdwin Vane /// provided by the user to construct a FixedCompilationDatabase.
189eb56f4feSEdwin Vane ///
190eb56f4feSEdwin Vane /// FixedCompilationDatabase requires a command line to be in this format as it
191eb56f4feSEdwin Vane /// constructs the command line for each file by appending the name of the file
192eb56f4feSEdwin Vane /// to be compiled. FixedCompilationDatabase also adds its own argv[0] to the
193eb56f4feSEdwin Vane /// start of the command line although its value is not important as it's just
194eb56f4feSEdwin Vane /// ignored by the Driver invoked by the ClangTool using the
195eb56f4feSEdwin Vane /// FixedCompilationDatabase.
196eb56f4feSEdwin Vane ///
197eb56f4feSEdwin Vane /// FIXME: This functionality should probably be made available by
198eb56f4feSEdwin Vane /// clang::driver::Driver although what the interface should look like is not
199eb56f4feSEdwin Vane /// clear.
200eb56f4feSEdwin Vane ///
201eb56f4feSEdwin Vane /// \param[in] Args Args as provided by the user.
2025335cf33SNAKAMURA Takumi /// \return Resulting stripped command line.
2035335cf33SNAKAMURA Takumi ///          \li true if successful.
204eb56f4feSEdwin Vane ///          \li false if \c Args cannot be used for compilation jobs (e.g.
205eb56f4feSEdwin Vane ///          contains an option like -E or -version).
2063a4fe369SArtyom Skrobov static bool stripPositionalArgs(std::vector<const char *> Args,
207c46064c2SSerge Pavlov                                 std::vector<std::string> &Result,
208c46064c2SSerge Pavlov                                 std::string &ErrorMsg) {
209eb56f4feSEdwin Vane   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
210c46064c2SSerge Pavlov   llvm::raw_string_ostream Output(ErrorMsg);
211c46064c2SSerge Pavlov   TextDiagnosticPrinter DiagnosticPrinter(Output, &*DiagOpts);
212c46064c2SSerge Pavlov   UnusedInputDiagConsumer DiagClient(DiagnosticPrinter);
213eb56f4feSEdwin Vane   DiagnosticsEngine Diagnostics(
214eb56f4feSEdwin Vane       IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
215eb56f4feSEdwin Vane       &*DiagOpts, &DiagClient, false);
216eb56f4feSEdwin Vane 
2171761f118SAlp Toker   // The clang executable path isn't required since the jobs the driver builds
2181761f118SAlp Toker   // will not be executed.
219b8984329SAhmed Charles   std::unique_ptr<driver::Driver> NewDriver(new driver::Driver(
220eb56f4feSEdwin Vane       /* ClangExecutable= */ "", llvm::sys::getDefaultTargetTriple(),
2211761f118SAlp Toker       Diagnostics));
222eb56f4feSEdwin Vane   NewDriver->setCheckInputsExist(false);
223eb56f4feSEdwin Vane 
224eb56f4feSEdwin Vane   // This becomes the new argv[0]. The value is actually not important as it
225eb56f4feSEdwin Vane   // isn't used for invoking Tools.
226eb56f4feSEdwin Vane   Args.insert(Args.begin(), "clang-tool");
227eb56f4feSEdwin Vane 
228eb56f4feSEdwin Vane   // By adding -c, we force the driver to treat compilation as the last phase.
229eb56f4feSEdwin Vane   // It will then issue warnings via Diagnostics about un-used options that
230eb56f4feSEdwin Vane   // would have been used for linking. If the user provided a compiler name as
231eb56f4feSEdwin Vane   // the original argv[0], this will be treated as a linker input thanks to
232eb56f4feSEdwin Vane   // insertng a new argv[0] above. All un-used options get collected by
233eb56f4feSEdwin Vane   // UnusedInputdiagConsumer and get stripped out later.
234eb56f4feSEdwin Vane   Args.push_back("-c");
235eb56f4feSEdwin Vane 
236eb56f4feSEdwin Vane   // Put a dummy C++ file on to ensure there's at least one compile job for the
237eb56f4feSEdwin Vane   // driver to construct. If the user specified some other argument that
238eb56f4feSEdwin Vane   // prevents compilation, e.g. -E or something like -version, we may still end
239eb56f4feSEdwin Vane   // up with no jobs but then this is the user's fault.
240eb56f4feSEdwin Vane   Args.push_back("placeholder.cpp");
241eb56f4feSEdwin Vane 
2423a4fe369SArtyom Skrobov   // Remove -no-integrated-as; it's not used for syntax checking,
2433a4fe369SArtyom Skrobov   // and it confuses targets which don't support this option.
244e1265143SArnaud A. de Grandmaison   Args.erase(std::remove_if(Args.begin(), Args.end(),
245e1265143SArnaud A. de Grandmaison                             MatchesAny(std::string("-no-integrated-as"))),
246e1265143SArnaud A. de Grandmaison              Args.end());
2473a4fe369SArtyom Skrobov 
248b8984329SAhmed Charles   const std::unique_ptr<driver::Compilation> Compilation(
249eb56f4feSEdwin Vane       NewDriver->BuildCompilation(Args));
250c46064c2SSerge Pavlov   if (!Compilation)
251c46064c2SSerge Pavlov     return false;
252eb56f4feSEdwin Vane 
253eb56f4feSEdwin Vane   const driver::JobList &Jobs = Compilation->getJobs();
254eb56f4feSEdwin Vane 
255eb56f4feSEdwin Vane   CompileJobAnalyzer CompileAnalyzer;
256eb56f4feSEdwin Vane 
2570cd9248dSJustin Bogner   for (const auto &Cmd : Jobs) {
258e2863ecaSAlex Lorenz     // Collect only for Assemble and Compile jobs. If we do all jobs we get
259e2863ecaSAlex Lorenz     // duplicates since Link jobs point to Assemble jobs as inputs.
260e2863ecaSAlex Lorenz     if (Cmd.getSource().getKind() == driver::Action::AssembleJobClass ||
261e2863ecaSAlex Lorenz         Cmd.getSource().getKind() == driver::Action::CompileJobClass) {
262c11bf802SDavid Blaikie       CompileAnalyzer.run(&Cmd.getSource());
263eb56f4feSEdwin Vane     }
264e2863ecaSAlex Lorenz   }
265eb56f4feSEdwin Vane 
266eb56f4feSEdwin Vane   if (CompileAnalyzer.Inputs.empty()) {
267c46064c2SSerge Pavlov     ErrorMsg = "warning: no compile jobs found\n";
268eb56f4feSEdwin Vane     return false;
269eb56f4feSEdwin Vane   }
270eb56f4feSEdwin Vane 
271eb56f4feSEdwin Vane   // Remove all compilation input files from the command line. This is
272eb56f4feSEdwin Vane   // necessary so that getCompileCommands() can construct a command line for
273eb56f4feSEdwin Vane   // each file.
274eb56f4feSEdwin Vane   std::vector<const char *>::iterator End = std::remove_if(
275eb56f4feSEdwin Vane       Args.begin(), Args.end(), MatchesAny(CompileAnalyzer.Inputs));
276eb56f4feSEdwin Vane 
277eb56f4feSEdwin Vane   // Remove all inputs deemed unused for compilation.
278eb56f4feSEdwin Vane   End = std::remove_if(Args.begin(), End, MatchesAny(DiagClient.UnusedInputs));
279eb56f4feSEdwin Vane 
280eb56f4feSEdwin Vane   // Remove the -c add above as well. It will be at the end right now.
281e99bb4b2SRichard Trieu   assert(strcmp(*(End - 1), "-c") == 0);
282eb56f4feSEdwin Vane   --End;
283eb56f4feSEdwin Vane 
284eb56f4feSEdwin Vane   Result = std::vector<std::string>(Args.begin() + 1, End);
285eb56f4feSEdwin Vane   return true;
286eb56f4feSEdwin Vane }
287eb56f4feSEdwin Vane 
288c46064c2SSerge Pavlov std::unique_ptr<FixedCompilationDatabase>
289c46064c2SSerge Pavlov FixedCompilationDatabase::loadFromCommandLine(int &Argc,
290c46064c2SSerge Pavlov                                               const char *const *Argv,
291c46064c2SSerge Pavlov                                               std::string &ErrorMsg,
292*41a9ee98SZachary Turner                                               Twine Directory) {
293c46064c2SSerge Pavlov   ErrorMsg.clear();
294c46064c2SSerge Pavlov   if (Argc == 0)
295c46064c2SSerge Pavlov     return nullptr;
296ab8f7d58SDavid Blaikie   const char *const *DoubleDash = std::find(Argv, Argv + Argc, StringRef("--"));
297ff26efceSManuel Klimek   if (DoubleDash == Argv + Argc)
298ccbc35edSCraig Topper     return nullptr;
299eb56f4feSEdwin Vane   std::vector<const char *> CommandLine(DoubleDash + 1, Argv + Argc);
300ff26efceSManuel Klimek   Argc = DoubleDash - Argv;
301eb56f4feSEdwin Vane 
302eb56f4feSEdwin Vane   std::vector<std::string> StrippedArgs;
303c46064c2SSerge Pavlov   if (!stripPositionalArgs(CommandLine, StrippedArgs, ErrorMsg))
304ccbc35edSCraig Topper     return nullptr;
305c46064c2SSerge Pavlov   return std::unique_ptr<FixedCompilationDatabase>(
306c46064c2SSerge Pavlov       new FixedCompilationDatabase(Directory, StrippedArgs));
307ff26efceSManuel Klimek }
308ff26efceSManuel Klimek 
309*41a9ee98SZachary Turner FixedCompilationDatabase::
310*41a9ee98SZachary Turner FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine) {
311ff26efceSManuel Klimek   std::vector<std::string> ToolCommandLine(1, "clang-tool");
312ff26efceSManuel Klimek   ToolCommandLine.insert(ToolCommandLine.end(),
313ff26efceSManuel Klimek                          CommandLine.begin(), CommandLine.end());
31474bcd21eSArgyrios Kyrtzidis   CompileCommands.emplace_back(Directory, StringRef(),
315399aea30SJoerg Sonnenberger                                std::move(ToolCommandLine),
316399aea30SJoerg Sonnenberger                                StringRef());
317ff26efceSManuel Klimek }
318ff26efceSManuel Klimek 
319ff26efceSManuel Klimek std::vector<CompileCommand>
320ff26efceSManuel Klimek FixedCompilationDatabase::getCompileCommands(StringRef FilePath) const {
321ff26efceSManuel Klimek   std::vector<CompileCommand> Result(CompileCommands);
322ff26efceSManuel Klimek   Result[0].CommandLine.push_back(FilePath);
32374bcd21eSArgyrios Kyrtzidis   Result[0].Filename = FilePath;
324ff26efceSManuel Klimek   return Result;
325ff26efceSManuel Klimek }
326ff26efceSManuel Klimek 
32760b80161SManuel Klimek std::vector<std::string>
32860b80161SManuel Klimek FixedCompilationDatabase::getAllFiles() const {
32960b80161SManuel Klimek   return std::vector<std::string>();
33060b80161SManuel Klimek }
33160b80161SManuel Klimek 
332251ad5e0SArgyrios Kyrtzidis std::vector<CompileCommand>
333251ad5e0SArgyrios Kyrtzidis FixedCompilationDatabase::getAllCompileCommands() const {
334251ad5e0SArgyrios Kyrtzidis   return std::vector<CompileCommand>();
335251ad5e0SArgyrios Kyrtzidis }
336251ad5e0SArgyrios Kyrtzidis 
3376a1457e6SBenjamin Kramer namespace clang {
3386a1457e6SBenjamin Kramer namespace tooling {
3396a1457e6SBenjamin Kramer 
3406ed1f85cSDaniel Jasper // This anchor is used to force the linker to link in the generated object file
3416ed1f85cSDaniel Jasper // and thus register the JSONCompilationDatabasePlugin.
3426ed1f85cSDaniel Jasper extern volatile int JSONAnchorSource;
343b7e8c7c7SYaron Keren static int LLVM_ATTRIBUTE_UNUSED JSONAnchorDest = JSONAnchorSource;
34447c245a5SManuel Klimek 
34547c245a5SManuel Klimek } // end namespace tooling
34647c245a5SManuel Klimek } // end namespace clang
347