1 //===--- GlobalCompilationDatabase.cpp ---------------------------*- C++-*-===//
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 "GlobalCompilationDatabase.h"
10 #include "FS.h"
11 #include "SourceCode.h"
12 #include "support/Logger.h"
13 #include "support/Path.h"
14 #include "support/ThreadsafeFS.h"
15 #include "clang/Frontend/CompilerInvocation.h"
16 #include "clang/Tooling/ArgumentsAdjusters.h"
17 #include "clang/Tooling/CompilationDatabase.h"
18 #include "clang/Tooling/CompilationDatabasePluginRegistry.h"
19 #include "clang/Tooling/JSONCompilationDatabase.h"
20 #include "llvm/ADT/None.h"
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/ADT/ScopeExit.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/Support/FileSystem.h"
26 #include "llvm/Support/FileUtilities.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/Program.h"
29 #include "llvm/Support/VirtualFileSystem.h"
30 #include <chrono>
31 #include <string>
32 #include <tuple>
33 #include <vector>
34 
35 namespace clang {
36 namespace clangd {
37 namespace {
38 
39 // Variant of parent_path that operates only on absolute paths.
40 PathRef absoluteParent(PathRef Path) {
41   assert(llvm::sys::path::is_absolute(Path));
42 #if defined(_WIN32)
43   // llvm::sys says "C:\" is absolute, and its parent is "C:" which is relative.
44   // This unhelpful behavior seems to have been inherited from boost.
45   if (llvm::sys::path::relative_path(Path).empty()) {
46     return PathRef();
47   }
48 #endif
49   PathRef Result = llvm::sys::path::parent_path(Path);
50   assert(Result.empty() || llvm::sys::path::is_absolute(Result));
51   return Result;
52 }
53 
54 // Runs the given action on all parent directories of filename, starting from
55 // deepest directory and going up to root. Stops whenever action succeeds.
56 void actOnAllParentDirectories(PathRef FileName,
57                                llvm::function_ref<bool(PathRef)> Action) {
58   for (auto Path = absoluteParent(FileName); !Path.empty() && !Action(Path);
59        Path = absoluteParent(Path))
60     ;
61 }
62 
63 } // namespace
64 
65 tooling::CompileCommand
66 GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
67   std::vector<std::string> Argv = {"clang"};
68   // Clang treats .h files as C by default and files without extension as linker
69   // input, resulting in unhelpful diagnostics.
70   // Parsing as Objective C++ is friendly to more cases.
71   auto FileExtension = llvm::sys::path::extension(File);
72   if (FileExtension.empty() || FileExtension == ".h")
73     Argv.push_back("-xobjective-c++-header");
74   Argv.push_back(std::string(File));
75   tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
76                               llvm::sys::path::filename(File), std::move(Argv),
77                               /*Output=*/"");
78   Cmd.Heuristic = "clangd fallback";
79   return Cmd;
80 }
81 
82 // Loads and caches the CDB from a single directory.
83 //
84 // This class is threadsafe, which is to say we have independent locks for each
85 // directory we're searching for a CDB.
86 // Loading is deferred until first access.
87 //
88 // The DirectoryBasedCDB keeps a map from path => DirectoryCache.
89 // Typical usage is to:
90 //  - 1) determine all the paths that might be searched
91 //  - 2) acquire the map lock and get-or-create all the DirectoryCache entries
92 //  - 3) release the map lock and query the caches as desired
93 class DirectoryBasedGlobalCompilationDatabase::DirectoryCache {
94   using stopwatch = std::chrono::steady_clock;
95 
96   // CachedFile is used to read a CDB file on disk (e.g. compile_commands.json).
97   // It specializes in being able to quickly bail out if the file is unchanged,
98   // which is the common case.
99   // Internally, it stores file metadata so a stat() can verify it's unchanged.
100   // We don't actually cache the content as it's not needed - if the file is
101   // unchanged then the previous CDB is valid.
102   struct CachedFile {
103     CachedFile(llvm::StringRef Parent, llvm::StringRef Rel) {
104       llvm::SmallString<256> Path = Parent;
105       llvm::sys::path::append(Path, Rel);
106       this->Path = Path.str().str();
107     }
108     std::string Path;
109     size_t Size = NoFileCached;
110     llvm::sys::TimePoint<> ModifiedTime;
111     FileDigest ContentHash;
112 
113     static constexpr size_t NoFileCached = -1;
114 
115     struct LoadResult {
116       enum {
117         FileNotFound,
118         TransientError,
119         FoundSameData,
120         FoundNewData,
121       } Result;
122       std::unique_ptr<llvm::MemoryBuffer> Buffer; // Set only if FoundNewData
123     };
124 
125     LoadResult load(llvm::vfs::FileSystem &FS, bool HasOldData);
126   };
127 
128   // If we've looked for a CDB here and found none, the time when that happened.
129   // (Atomics make it possible for get() to return without taking a lock)
130   std::atomic<stopwatch::rep> NoCDBAt = {
131       stopwatch::time_point::min().time_since_epoch().count()};
132 
133   // Guards the following cache state.
134   std::mutex Mu;
135   // When was the cache last known to be in sync with disk state?
136   stopwatch::time_point CachePopulatedAt = stopwatch::time_point::min();
137   // Whether a new CDB has been loaded but not broadcast yet.
138   bool NeedsBroadcast = false;
139   // Last loaded CDB, meaningful if CachePopulatedAt was ever set.
140   // shared_ptr so we can overwrite this when callers are still using the CDB.
141   std::shared_ptr<tooling::CompilationDatabase> CDB;
142   // File metadata for the CDB files we support tracking directly.
143   CachedFile CompileCommandsJson;
144   CachedFile BuildCompileCommandsJson;
145   CachedFile CompileFlagsTxt;
146   // CachedFile member corresponding to CDB.
147   //   CDB  | ACF  | Scenario
148   //   null | null | no CDB found, or initial empty cache
149   //   set  | null | CDB was loaded via generic plugin interface
150   //   null | set  | found known CDB file, but parsing it failed
151   //   set  | set  | CDB was parsed from a known file
152   CachedFile *ActiveCachedFile = nullptr;
153 
154 public:
155   DirectoryCache(llvm::StringRef Path)
156       : CompileCommandsJson(Path, "compile_commands.json"),
157         BuildCompileCommandsJson(Path, "build/compile_commands.json"),
158         CompileFlagsTxt(Path, "compile_flags.txt"), Path(Path) {
159     assert(llvm::sys::path::is_absolute(Path));
160   }
161 
162   // Absolute canonical path that we're the cache for. (Not case-folded).
163   const std::string Path;
164 
165   // Get the CDB associated with this directory.
166   // ShouldBroadcast:
167   //  - as input, signals whether the caller is willing to broadcast a
168   //    newly-discovered CDB. (e.g. to trigger background indexing)
169   //  - as output, signals whether the caller should do so.
170   // (If a new CDB is discovered and ShouldBroadcast is false, we mark the
171   // CDB as needing broadcast, and broadcast it next time we can).
172   std::shared_ptr<const tooling::CompilationDatabase>
173   get(const ThreadsafeFS &TFS, bool &ShouldBroadcast,
174       stopwatch::time_point FreshTime, stopwatch::time_point FreshTimeMissing) {
175     // Fast path for common case without taking lock.
176     if (stopwatch::time_point(stopwatch::duration(NoCDBAt.load())) >
177         FreshTimeMissing) {
178       ShouldBroadcast = false;
179       return nullptr;
180     }
181 
182     std::lock_guard<std::mutex> Lock(Mu);
183     auto RequestBroadcast = llvm::make_scope_exit([&, OldCDB(CDB.get())] {
184       // If we loaded a new CDB, it should be broadcast at some point.
185       if (CDB != nullptr && CDB.get() != OldCDB)
186         NeedsBroadcast = true;
187       else if (CDB == nullptr) // nothing to broadcast anymore!
188         NeedsBroadcast = false;
189       // If we have something to broadcast, then do so iff allowed.
190       if (!ShouldBroadcast)
191         return;
192       ShouldBroadcast = NeedsBroadcast;
193       NeedsBroadcast = false;
194     });
195 
196     // If our cache is valid, serve from it.
197     if (CachePopulatedAt > FreshTime)
198       return CDB;
199 
200     if (/*MayCache=*/load(*TFS.view(/*CWD=*/llvm::None))) {
201       // Use new timestamp, as loading may be slow.
202       CachePopulatedAt = stopwatch::now();
203       NoCDBAt.store((CDB ? stopwatch::time_point::min() : CachePopulatedAt)
204                         .time_since_epoch()
205                         .count());
206     }
207 
208     return CDB;
209   }
210 
211 private:
212   // Updates `CDB` from disk state. Returns false on failure.
213   bool load(llvm::vfs::FileSystem &FS);
214 };
215 
216 DirectoryBasedGlobalCompilationDatabase::DirectoryCache::CachedFile::LoadResult
217 DirectoryBasedGlobalCompilationDatabase::DirectoryCache::CachedFile::load(
218     llvm::vfs::FileSystem &FS, bool HasOldData) {
219   auto Stat = FS.status(Path);
220   if (!Stat || !Stat->isRegularFile()) {
221     Size = NoFileCached;
222     ContentHash = {};
223     return {LoadResult::FileNotFound, nullptr};
224   }
225   // If both the size and mtime match, presume unchanged without reading.
226   if (HasOldData && Stat->getLastModificationTime() == ModifiedTime &&
227       Stat->getSize() == Size)
228     return {LoadResult::FoundSameData, nullptr};
229   auto Buf = FS.getBufferForFile(Path);
230   if (!Buf || (*Buf)->getBufferSize() != Stat->getSize()) {
231     // Don't clear the cache - possible we're seeing inconsistent size as the
232     // file is being recreated. If it ends up identical later, great!
233     //
234     // This isn't a complete solution: if we see a partial file but stat/read
235     // agree on its size, we're ultimately going to have spurious CDB reloads.
236     // May be worth fixing if generators don't write atomically (CMake does).
237     elog("Failed to read {0}: {1}", Path,
238          Buf ? "size changed" : Buf.getError().message());
239     return {LoadResult::TransientError, nullptr};
240   }
241 
242   FileDigest NewContentHash = digest((*Buf)->getBuffer());
243   if (HasOldData && NewContentHash == ContentHash) {
244     // mtime changed but data is the same: avoid rebuilding the CDB.
245     ModifiedTime = Stat->getLastModificationTime();
246     return {LoadResult::FoundSameData, nullptr};
247   }
248 
249   Size = (*Buf)->getBufferSize();
250   ModifiedTime = Stat->getLastModificationTime();
251   ContentHash = NewContentHash;
252   return {LoadResult::FoundNewData, std::move(*Buf)};
253 }
254 
255 // Adapt CDB-loading functions to a common interface for DirectoryCache::load().
256 static std::unique_ptr<tooling::CompilationDatabase>
257 parseJSON(PathRef Path, llvm::StringRef Data, std::string &Error) {
258   if (auto CDB = tooling::JSONCompilationDatabase::loadFromBuffer(
259           Data, Error, tooling::JSONCommandLineSyntax::AutoDetect)) {
260     // FS used for expanding response files.
261     // FIXME: ExpandResponseFilesDatabase appears not to provide the usual
262     // thread-safety guarantees, as the access to FS is not locked!
263     // For now, use the real FS, which is known to be threadsafe (if we don't
264     // use/change working directory, which ExpandResponseFilesDatabase doesn't).
265     auto FS = llvm::vfs::getRealFileSystem();
266     return tooling::inferTargetAndDriverMode(
267         tooling::inferMissingCompileCommands(
268             expandResponseFiles(std::move(CDB), std::move(FS))));
269   }
270   return nullptr;
271 }
272 static std::unique_ptr<tooling::CompilationDatabase>
273 parseFixed(PathRef Path, llvm::StringRef Data, std::string &Error) {
274   return tooling::FixedCompilationDatabase::loadFromBuffer(
275       llvm::sys::path::parent_path(Path), Data, Error);
276 }
277 
278 bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load(
279     llvm::vfs::FileSystem &FS) {
280   dlog("Probing directory {0}", Path);
281   std::string Error;
282 
283   // Load from the specially-supported compilation databases (JSON + Fixed).
284   // For these, we know the files they read and cache their metadata so we can
285   // cheaply validate whether they've changed, and hot-reload if they have.
286   // (As a bonus, these are also VFS-clean)!
287   struct CDBFile {
288     CachedFile *File;
289     // Wrapper for {Fixed,JSON}CompilationDatabase::loadFromBuffer.
290     llvm::function_ref<std::unique_ptr<tooling::CompilationDatabase>(
291         PathRef,
292         /*Data*/ llvm::StringRef,
293         /*ErrorMsg*/ std::string &)>
294         Parser;
295   };
296   for (const auto &Entry : {CDBFile{&CompileCommandsJson, parseJSON},
297                             CDBFile{&BuildCompileCommandsJson, parseJSON},
298                             CDBFile{&CompileFlagsTxt, parseFixed}}) {
299     bool Active = ActiveCachedFile == Entry.File;
300     auto Loaded = Entry.File->load(FS, Active);
301     switch (Loaded.Result) {
302     case CachedFile::LoadResult::FileNotFound:
303       if (Active) {
304         log("Unloaded compilation database from {0}", Entry.File->Path);
305         ActiveCachedFile = nullptr;
306         CDB = nullptr;
307       }
308       // Continue looking at other candidates.
309       break;
310     case CachedFile::LoadResult::TransientError:
311       // File existed but we couldn't read it. Reuse the cache, retry later.
312       return false; // Load again next time.
313     case CachedFile::LoadResult::FoundSameData:
314       assert(Active && "CachedFile may not return 'same data' if !HasOldData");
315       // This is the critical file, and it hasn't changed.
316       return true;
317     case CachedFile::LoadResult::FoundNewData:
318       // We have a new CDB!
319       CDB = Entry.Parser(Entry.File->Path, Loaded.Buffer->getBuffer(), Error);
320       if (CDB)
321         log("{0} compilation database from {1}", Active ? "Reloaded" : "Loaded",
322             Entry.File->Path);
323       else
324         elog("Failed to load compilation database from {0}: {1}",
325              Entry.File->Path, Error);
326       ActiveCachedFile = Entry.File;
327       return true;
328     }
329   }
330 
331   // Fall back to generic handling of compilation databases.
332   // We don't know what files they read, so can't efficiently check whether
333   // they need to be reloaded. So we never do that.
334   // FIXME: the interface doesn't provide a way to virtualize FS access.
335 
336   // Don't try these more than once. If we've scanned before, we're done.
337   if (CachePopulatedAt > stopwatch::time_point::min())
338     return true;
339   for (const auto &Entry :
340        tooling::CompilationDatabasePluginRegistry::entries()) {
341     // Avoid duplicating the special cases handled above.
342     if (Entry.getName() == "fixed-compilation-database" ||
343         Entry.getName() == "json-compilation-database")
344       continue;
345     auto Plugin = Entry.instantiate();
346     if (auto CDB = Plugin->loadFromDirectory(Path, Error)) {
347       log("Loaded compilation database from {0} with plugin {1}", Path,
348           Entry.getName());
349       this->CDB = std::move(CDB);
350       return true;
351     }
352     // Don't log Error here, it's usually just "couldn't find <file>".
353   }
354   dlog("No compilation database at {0}", Path);
355   return true;
356 }
357 
358 DirectoryBasedGlobalCompilationDatabase::
359     DirectoryBasedGlobalCompilationDatabase(const Options &Opts)
360     : Opts(Opts) {
361   if (Opts.CompileCommandsDir)
362     OnlyDirCache = std::make_unique<DirectoryCache>(*Opts.CompileCommandsDir);
363 }
364 
365 DirectoryBasedGlobalCompilationDatabase::
366     ~DirectoryBasedGlobalCompilationDatabase() = default;
367 
368 llvm::Optional<tooling::CompileCommand>
369 DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
370   CDBLookupRequest Req;
371   Req.FileName = File;
372   Req.ShouldBroadcast = true;
373   auto Now = std::chrono::steady_clock::now();
374   Req.FreshTime = Now - Opts.RevalidateAfter;
375   Req.FreshTimeMissing = Now - Opts.RevalidateMissingAfter;
376 
377   auto Res = lookupCDB(Req);
378   if (!Res) {
379     log("Failed to find compilation database for {0}", File);
380     return llvm::None;
381   }
382 
383   auto Candidates = Res->CDB->getCompileCommands(File);
384   if (!Candidates.empty())
385     return std::move(Candidates.front());
386 
387   return None;
388 }
389 
390 // For platforms where paths are case-insensitive (but case-preserving),
391 // we need to do case-insensitive comparisons and use lowercase keys.
392 // FIXME: Make Path a real class with desired semantics instead.
393 //        This class is not the only place this problem exists.
394 // FIXME: Mac filesystems default to case-insensitive, but may be sensitive.
395 
396 static std::string maybeCaseFoldPath(PathRef Path) {
397 #if defined(_WIN32) || defined(__APPLE__)
398   return Path.lower();
399 #else
400   return std::string(Path);
401 #endif
402 }
403 
404 static bool pathEqual(PathRef A, PathRef B) {
405 #if defined(_WIN32) || defined(__APPLE__)
406   return A.equals_lower(B);
407 #else
408   return A == B;
409 #endif
410 }
411 
412 std::vector<DirectoryBasedGlobalCompilationDatabase::DirectoryCache *>
413 DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches(
414     llvm::ArrayRef<llvm::StringRef> Dirs) const {
415   std::vector<std::string> FoldedDirs;
416   FoldedDirs.reserve(Dirs.size());
417   for (const auto &Dir : Dirs) {
418 #ifndef NDEBUG
419     if (!llvm::sys::path::is_absolute(Dir))
420       elog("Trying to cache CDB for relative {0}");
421 #endif
422     FoldedDirs.push_back(maybeCaseFoldPath(Dir));
423   }
424 
425   std::vector<DirectoryCache *> Ret;
426   Ret.reserve(Dirs.size());
427 
428   std::lock_guard<std::mutex> Lock(DirCachesMutex);
429   for (unsigned I = 0; I < Dirs.size(); ++I)
430     Ret.push_back(&DirCaches.try_emplace(FoldedDirs[I], Dirs[I]).first->second);
431   return Ret;
432 }
433 
434 llvm::Optional<DirectoryBasedGlobalCompilationDatabase::CDBLookupResult>
435 DirectoryBasedGlobalCompilationDatabase::lookupCDB(
436     CDBLookupRequest Request) const {
437   assert(llvm::sys::path::is_absolute(Request.FileName) &&
438          "path must be absolute");
439 
440   bool ShouldBroadcast = false;
441   DirectoryCache *DirCache = nullptr;
442   std::shared_ptr<const tooling::CompilationDatabase> CDB = nullptr;
443   if (OnlyDirCache) {
444     DirCache = OnlyDirCache.get();
445     ShouldBroadcast = Request.ShouldBroadcast;
446     CDB = DirCache->get(Opts.TFS, ShouldBroadcast, Request.FreshTime,
447                         Request.FreshTimeMissing);
448   } else {
449     // Traverse the canonical version to prevent false positives. i.e.:
450     // src/build/../a.cc can detect a CDB in /src/build if not canonicalized.
451     std::string CanonicalPath = removeDots(Request.FileName);
452     std::vector<llvm::StringRef> SearchDirs;
453     actOnAllParentDirectories(CanonicalPath, [&](PathRef Path) {
454       SearchDirs.push_back(Path);
455       return false;
456     });
457     for (DirectoryCache *Candidate : getDirectoryCaches(SearchDirs)) {
458       bool CandidateShouldBroadcast = Request.ShouldBroadcast;
459       if ((CDB = Candidate->get(Opts.TFS, CandidateShouldBroadcast,
460                                 Request.FreshTime, Request.FreshTimeMissing))) {
461         DirCache = Candidate;
462         ShouldBroadcast = CandidateShouldBroadcast;
463         break;
464       }
465     }
466   }
467 
468   if (!CDB)
469     return llvm::None;
470 
471   CDBLookupResult Result;
472   Result.CDB = std::move(CDB);
473   Result.PI.SourceRoot = DirCache->Path;
474 
475   // FIXME: Maybe make the following part async, since this can block
476   // retrieval of compile commands.
477   if (ShouldBroadcast)
478     broadcastCDB(Result);
479   return Result;
480 }
481 
482 void DirectoryBasedGlobalCompilationDatabase::broadcastCDB(
483     CDBLookupResult Result) const {
484   vlog("Broadcasting compilation database from {0}", Result.PI.SourceRoot);
485   assert(Result.CDB && "Trying to broadcast an invalid CDB!");
486 
487   std::vector<std::string> AllFiles = Result.CDB->getAllFiles();
488   // We assume CDB in CompileCommandsDir owns all of its entries, since we don't
489   // perform any search in parent paths whenever it is set.
490   if (OnlyDirCache) {
491     assert(OnlyDirCache->Path == Result.PI.SourceRoot &&
492            "Trying to broadcast a CDB outside of CompileCommandsDir!");
493     OnCommandChanged.broadcast(std::move(AllFiles));
494     return;
495   }
496 
497   // Uniquify all parent directories of all files.
498   llvm::StringMap<bool> DirectoryHasCDB;
499   std::vector<llvm::StringRef> FileAncestors;
500   for (llvm::StringRef File : AllFiles) {
501     actOnAllParentDirectories(File, [&](PathRef Path) {
502       auto It = DirectoryHasCDB.try_emplace(Path);
503       // Already seen this path, and all of its parents.
504       if (!It.second)
505         return true;
506 
507       FileAncestors.push_back(It.first->getKey());
508       return pathEqual(Path, Result.PI.SourceRoot);
509     });
510   }
511   // Work out which ones have CDBs in them.
512   // Given that we know that CDBs have been moved/generated, don't trust caches.
513   // (This should be rare, so it's OK to add a little latency).
514   constexpr auto IgnoreCache = std::chrono::steady_clock::time_point::max();
515   auto DirectoryCaches = getDirectoryCaches(FileAncestors);
516   assert(DirectoryCaches.size() == FileAncestors.size());
517   for (unsigned I = 0; I < DirectoryCaches.size(); ++I) {
518     bool ShouldBroadcast = false;
519     if (DirectoryCaches[I]->get(Opts.TFS, ShouldBroadcast,
520                                 /*FreshTime=*/IgnoreCache,
521                                 /*FreshTimeMissing=*/IgnoreCache))
522       DirectoryHasCDB.find(FileAncestors[I])->setValue(true);
523   }
524 
525   std::vector<std::string> GovernedFiles;
526   for (llvm::StringRef File : AllFiles) {
527     // A file is governed by this CDB if lookup for the file would find it.
528     // Independent of whether it has an entry for that file or not.
529     actOnAllParentDirectories(File, [&](PathRef Path) {
530       if (DirectoryHasCDB.lookup(Path)) {
531         if (pathEqual(Path, Result.PI.SourceRoot))
532           // Make sure listeners always get a canonical path for the file.
533           GovernedFiles.push_back(removeDots(File));
534         // Stop as soon as we hit a CDB.
535         return true;
536       }
537       return false;
538     });
539   }
540 
541   OnCommandChanged.broadcast(std::move(GovernedFiles));
542 }
543 
544 llvm::Optional<ProjectInfo>
545 DirectoryBasedGlobalCompilationDatabase::getProjectInfo(PathRef File) const {
546   CDBLookupRequest Req;
547   Req.FileName = File;
548   Req.ShouldBroadcast = false;
549   Req.FreshTime = Req.FreshTimeMissing =
550       std::chrono::steady_clock::time_point::min();
551   auto Res = lookupCDB(Req);
552   if (!Res)
553     return llvm::None;
554   return Res->PI;
555 }
556 
557 OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base,
558                        std::vector<std::string> FallbackFlags,
559                        tooling::ArgumentsAdjuster Adjuster)
560     : DelegatingCDB(Base), ArgsAdjuster(std::move(Adjuster)),
561       FallbackFlags(std::move(FallbackFlags)) {}
562 
563 llvm::Optional<tooling::CompileCommand>
564 OverlayCDB::getCompileCommand(PathRef File) const {
565   llvm::Optional<tooling::CompileCommand> Cmd;
566   {
567     std::lock_guard<std::mutex> Lock(Mutex);
568     auto It = Commands.find(removeDots(File));
569     if (It != Commands.end())
570       Cmd = It->second;
571   }
572   if (!Cmd)
573     Cmd = DelegatingCDB::getCompileCommand(File);
574   if (!Cmd)
575     return llvm::None;
576   if (ArgsAdjuster)
577     Cmd->CommandLine = ArgsAdjuster(Cmd->CommandLine, Cmd->Filename);
578   return Cmd;
579 }
580 
581 tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
582   auto Cmd = DelegatingCDB::getFallbackCommand(File);
583   std::lock_guard<std::mutex> Lock(Mutex);
584   Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
585                          FallbackFlags.end());
586   if (ArgsAdjuster)
587     Cmd.CommandLine = ArgsAdjuster(Cmd.CommandLine, Cmd.Filename);
588   return Cmd;
589 }
590 
591 void OverlayCDB::setCompileCommand(
592     PathRef File, llvm::Optional<tooling::CompileCommand> Cmd) {
593   // We store a canonical version internally to prevent mismatches between set
594   // and get compile commands. Also it assures clients listening to broadcasts
595   // doesn't receive different names for the same file.
596   std::string CanonPath = removeDots(File);
597   {
598     std::unique_lock<std::mutex> Lock(Mutex);
599     if (Cmd)
600       Commands[CanonPath] = std::move(*Cmd);
601     else
602       Commands.erase(CanonPath);
603   }
604   OnCommandChanged.broadcast({CanonPath});
605 }
606 
607 DelegatingCDB::DelegatingCDB(const GlobalCompilationDatabase *Base)
608     : Base(Base) {
609   if (Base)
610     BaseChanged = Base->watch([this](const std::vector<std::string> Changes) {
611       OnCommandChanged.broadcast(Changes);
612     });
613 }
614 
615 DelegatingCDB::DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base)
616     : DelegatingCDB(Base.get()) {
617   BaseOwner = std::move(Base);
618 }
619 
620 llvm::Optional<tooling::CompileCommand>
621 DelegatingCDB::getCompileCommand(PathRef File) const {
622   if (!Base)
623     return llvm::None;
624   return Base->getCompileCommand(File);
625 }
626 
627 llvm::Optional<ProjectInfo> DelegatingCDB::getProjectInfo(PathRef File) const {
628   if (!Base)
629     return llvm::None;
630   return Base->getProjectInfo(File);
631 }
632 
633 tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
634   if (!Base)
635     return GlobalCompilationDatabase::getFallbackCommand(File);
636   return Base->getFallbackCommand(File);
637 }
638 
639 } // namespace clangd
640 } // namespace clang
641