Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
VirtualFileSystem.cpp
Go to the documentation of this file.
1//===- VirtualFileSystem.cpp - Virtual File System Layer ------------------===//
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// This file implements the VirtualFileSystem interface.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Support/VirtualFileSystem.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/DenseMap.h"
16#include "llvm/ADT/IntrusiveRefCntPtr.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/StringSet.h"
22#include "llvm/ADT/Twine.h"
23#include "llvm/ADT/iterator_range.h"
24#include "llvm/Config/llvm-config.h"
25#include "llvm/Support/Casting.h"
26#include "llvm/Support/Chrono.h"
27#include "llvm/Support/Compiler.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/Errc.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/ErrorOr.h"
32#include "llvm/Support/FileSystem.h"
33#include "llvm/Support/FileSystem/UniqueID.h"
34#include "llvm/Support/MemoryBuffer.h"
35#include "llvm/Support/Path.h"
36#include "llvm/Support/SMLoc.h"
37#include "llvm/Support/SourceMgr.h"
38#include "llvm/Support/YAMLParser.h"
39#include "llvm/Support/raw_ostream.h"
40#include <atomic>
41#include <cassert>
42#include <cstdint>
43#include <iterator>
44#include <limits>
45#include <map>
46#include <memory>
47#include <optional>
48#include <string>
49#include <system_error>
50#include <utility>
51#include <vector>
52
53using namespacellvm;
54using namespacellvm::vfs;
55
56usingllvm::sys::fs::file_t;
57usingllvm::sys::fs::file_status;
58usingllvm::sys::fs::file_type;
59usingllvm::sys::fs::kInvalidFile;
60usingllvm::sys::fs::perms;
61usingllvm::sys::fs::UniqueID;
62
63Status::Status(constfile_status &Status)
64 : UID(Status.getUniqueID()), MTime(Status.getLastModificationTime()),
65User(Status.getUser()), Group(Status.getGroup()),Size(Status.getSize()),
66Type(Status.type()), Perms(Status.permissions()) {}
67
68Status::Status(constTwine &Name,UniqueID UID,sys::TimePoint<> MTime,
69uint32_tUser,uint32_t Group,uint64_tSize, file_typeType,
70 perms Perms)
71 :Name(Name.str()), UID(UID), MTime(MTime),User(User), Group(Group),
72Size(Size),Type(Type), Perms(Perms) {}
73
74StatusStatus::copyWithNewSize(constStatus &In,uint64_t NewSize) {
75returnStatus(In.getName(), In.getUniqueID(), In.getLastModificationTime(),
76 In.getUser(), In.getGroup(), NewSize, In.getType(),
77 In.getPermissions());
78}
79
80StatusStatus::copyWithNewName(constStatus &In,constTwine &NewName) {
81returnStatus(NewName, In.getUniqueID(), In.getLastModificationTime(),
82 In.getUser(), In.getGroup(), In.getSize(), In.getType(),
83 In.getPermissions());
84}
85
86StatusStatus::copyWithNewName(constfile_status &In,constTwine &NewName) {
87returnStatus(NewName, In.getUniqueID(), In.getLastModificationTime(),
88 In.getUser(), In.getGroup(), In.getSize(), In.type(),
89 In.permissions());
90}
91
92boolStatus::equivalent(constStatus &Other) const{
93assert(isStatusKnown() &&Other.isStatusKnown());
94returngetUniqueID() ==Other.getUniqueID();
95}
96
97boolStatus::isDirectory() const{returnType == file_type::directory_file; }
98
99boolStatus::isRegularFile() const{returnType == file_type::regular_file; }
100
101boolStatus::isOther() const{
102returnexists() && !isRegularFile() && !isDirectory() && !isSymlink();
103}
104
105boolStatus::isSymlink() const{returnType == file_type::symlink_file; }
106
107boolStatus::isStatusKnown() const{returnType != file_type::status_error; }
108
109boolStatus::exists() const{
110returnisStatusKnown() &&Type != file_type::file_not_found;
111}
112
113File::~File() =default;
114
115FileSystem::~FileSystem() =default;
116
117ErrorOr<std::unique_ptr<MemoryBuffer>>
118FileSystem::getBufferForFile(constllvm::Twine &Name, int64_t FileSize,
119bool RequiresNullTerminator,bool IsVolatile,
120bool IsText) {
121autoF = IsText ?openFileForRead(Name) :openFileForReadBinary(Name);
122if (!F)
123returnF.getError();
124
125return (*F)->getBuffer(Name, FileSize, RequiresNullTerminator, IsVolatile);
126}
127
128std::error_codeFileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const{
129if (llvm::sys::path::is_absolute(Path))
130return {};
131
132auto WorkingDir =getCurrentWorkingDirectory();
133if (!WorkingDir)
134return WorkingDir.getError();
135
136llvm::sys::fs::make_absolute(WorkingDir.get(), Path);
137return {};
138}
139
140std::error_codeFileSystem::getRealPath(constTwine &Path,
141SmallVectorImpl<char> &Output) {
142returnerrc::operation_not_permitted;
143}
144
145std::error_codeFileSystem::isLocal(constTwine &Path,bool &Result) {
146returnerrc::operation_not_permitted;
147}
148
149boolFileSystem::exists(constTwine &Path) {
150autoStatus =status(Path);
151returnStatus &&Status->exists();
152}
153
154llvm::ErrorOr<bool>FileSystem::equivalent(constTwine &A,constTwine &B) {
155auto StatusA =status(A);
156if (!StatusA)
157return StatusA.getError();
158auto StatusB =status(B);
159if (!StatusB)
160return StatusB.getError();
161return StatusA->equivalent(*StatusB);
162}
163
164#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
165voidFileSystem::dump() const{print(dbgs(),PrintType::RecursiveContents); }
166#endif
167
168#ifndef NDEBUG
169staticboolisTraversalComponent(StringRef Component) {
170return Component ==".." || Component ==".";
171}
172
173staticboolpathHasTraversal(StringRef Path) {
174using namespacellvm::sys;
175
176for (StringRef Comp :llvm::make_range(path::begin(Path),path::end(Path)))
177if (isTraversalComponent(Comp))
178returntrue;
179returnfalse;
180}
181#endif
182
183//===-----------------------------------------------------------------------===/
184// RealFileSystem implementation
185//===-----------------------------------------------------------------------===/
186
187namespace{
188
189/// Wrapper around a raw file descriptor.
190classRealFile :publicFile {
191friendclassRealFileSystem;
192
193file_t FD;
194Status S;
195 std::string RealName;
196
197 RealFile(file_t RawFD,StringRef NewName,StringRef NewRealPathName)
198 : FD(RawFD), S(NewName, {}, {}, {}, {}, {},
199llvm::sys::fs::file_type::status_error, {}),
200 RealName(NewRealPathName.str()) {
201assert(FD != kInvalidFile &&"Invalid or inactive file descriptor");
202 }
203
204public:
205 ~RealFile()override;
206
207ErrorOr<Status>status()override;
208ErrorOr<std::string>getName()override;
209ErrorOr<std::unique_ptr<MemoryBuffer>> getBuffer(constTwine &Name,
210 int64_t FileSize,
211bool RequiresNullTerminator,
212bool IsVolatile)override;
213 std::error_code close()override;
214void setPath(constTwine &Path)override;
215};
216
217}// namespace
218
219RealFile::~RealFile() { close(); }
220
221ErrorOr<Status> RealFile::status() {
222assert(FD != kInvalidFile &&"cannot stat closed file");
223if (!S.isStatusKnown()) {
224file_status RealStatus;
225if (std::error_code EC =sys::fs::status(FD, RealStatus))
226returnEC;
227 S =Status::copyWithNewName(RealStatus, S.getName());
228 }
229return S;
230}
231
232ErrorOr<std::string> RealFile::getName() {
233return RealName.empty() ? S.getName().str() : RealName;
234}
235
236ErrorOr<std::unique_ptr<MemoryBuffer>>
237RealFile::getBuffer(constTwine &Name, int64_t FileSize,
238bool RequiresNullTerminator,bool IsVolatile) {
239assert(FD != kInvalidFile &&"cannot get buffer for closed file");
240returnMemoryBuffer::getOpenFile(FD,Name, FileSize, RequiresNullTerminator,
241 IsVolatile);
242}
243
244std::error_code RealFile::close() {
245 std::error_codeEC =sys::fs::closeFile(FD);
246 FD =kInvalidFile;
247returnEC;
248}
249
250void RealFile::setPath(constTwine &Path) {
251 RealName =Path.str();
252if (autoStatus =status())
253 S =Status.get().copyWithNewName(Status.get(), Path);
254}
255
256namespace{
257
258/// A file system according to your operating system.
259/// This may be linked to the process's working directory, or maintain its own.
260///
261/// Currently, its own working directory is emulated by storing the path and
262/// sending absolute paths to llvm::sys::fs:: functions.
263/// A more principled approach would be to push this down a level, modelling
264/// the working dir as an llvm::sys::fs::WorkingDir or similar.
265/// This would enable the use of openat()-style functions on some platforms.
266classRealFileSystem :publicFileSystem {
267public:
268explicit RealFileSystem(bool LinkCWDToProcess) {
269if (!LinkCWDToProcess) {
270SmallString<128> PWD, RealPWD;
271if (std::error_code EC =llvm::sys::fs::current_path(PWD))
272 WD =EC;
273elseif (llvm::sys::fs::real_path(PWD, RealPWD))
274 WD = WorkingDirectory{PWD, PWD};
275else
276 WD = WorkingDirectory{PWD, RealPWD};
277 }
278 }
279
280ErrorOr<Status>status(constTwine &Path)override;
281ErrorOr<std::unique_ptr<File>>openFileForRead(constTwine &Path)override;
282ErrorOr<std::unique_ptr<File>>
283 openFileForReadBinary(constTwine &Path)override;
284directory_iterator dir_begin(constTwine &Dir, std::error_code &EC)override;
285
286llvm::ErrorOr<std::string> getCurrentWorkingDirectory()const override;
287 std::error_code setCurrentWorkingDirectory(constTwine &Path)override;
288 std::error_code isLocal(constTwine &Path,bool &Result)override;
289 std::error_code getRealPath(constTwine &Path,
290SmallVectorImpl<char> &Output)override;
291
292protected:
293void printImpl(raw_ostream &OS, PrintTypeType,
294unsigned IndentLevel)const override;
295
296private:
297// If this FS has its own working dir, use it to make Path absolute.
298// The returned twine is safe to use as long as both Storage and Path live.
299Twine adjustPath(constTwine &Path,SmallVectorImpl<char> &Storage) const{
300if (!WD || !*WD)
301returnPath;
302Path.toVector(Storage);
303sys::fs::make_absolute(WD->get().Resolved, Storage);
304return Storage;
305 }
306
307ErrorOr<std::unique_ptr<File>>
308 openFileForReadWithFlags(constTwine &Name,sys::fs::OpenFlags Flags) {
309SmallString<256> RealName, Storage;
310Expected<file_t> FDOrErr =sys::fs::openNativeFileForRead(
311 adjustPath(Name, Storage), Flags, &RealName);
312if (!FDOrErr)
313returnerrorToErrorCode(FDOrErr.takeError());
314return std::unique_ptr<File>(
315new RealFile(*FDOrErr,Name.str(), RealName.str()));
316 }
317
318structWorkingDirectory {
319// The current working directory, without symlinks resolved. (echo $PWD).
320SmallString<128> Specified;
321// The current working directory, with links resolved. (readlink .).
322SmallString<128>Resolved;
323 };
324 std::optional<llvm::ErrorOr<WorkingDirectory>> WD;
325};
326
327}// namespace
328
329ErrorOr<Status> RealFileSystem::status(constTwine &Path) {
330SmallString<256> Storage;
331sys::fs::file_status RealStatus;
332if (std::error_code EC =
333sys::fs::status(adjustPath(Path, Storage), RealStatus))
334returnEC;
335returnStatus::copyWithNewName(RealStatus, Path);
336}
337
338ErrorOr<std::unique_ptr<File>>
339RealFileSystem::openFileForRead(constTwine &Name) {
340return openFileForReadWithFlags(Name,sys::fs::OF_Text);
341}
342
343ErrorOr<std::unique_ptr<File>>
344RealFileSystem::openFileForReadBinary(constTwine &Name) {
345return openFileForReadWithFlags(Name,sys::fs::OF_None);
346}
347
348llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const{
349if (WD && *WD)
350return std::string(WD->get().Specified);
351if (WD)
352return WD->getError();
353
354SmallString<128> Dir;
355if (std::error_code EC =llvm::sys::fs::current_path(Dir))
356returnEC;
357return std::string(Dir);
358}
359
360std::error_code RealFileSystem::setCurrentWorkingDirectory(constTwine &Path) {
361if (!WD)
362returnllvm::sys::fs::set_current_path(Path);
363
364SmallString<128>Absolute,Resolved, Storage;
365 adjustPath(Path, Storage).toVector(Absolute);
366bool IsDir;
367if (auto Err =llvm::sys::fs::is_directory(Absolute, IsDir))
368return Err;
369if (!IsDir)
370return std::make_error_code(std::errc::not_a_directory);
371if (auto Err =llvm::sys::fs::real_path(Absolute, Resolved))
372return Err;
373 WD = WorkingDirectory{Absolute,Resolved};
374return std::error_code();
375}
376
377std::error_code RealFileSystem::isLocal(constTwine &Path,bool &Result) {
378SmallString<256> Storage;
379returnllvm::sys::fs::is_local(adjustPath(Path, Storage), Result);
380}
381
382std::error_code RealFileSystem::getRealPath(constTwine &Path,
383SmallVectorImpl<char> &Output) {
384SmallString<256> Storage;
385returnllvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
386}
387
388void RealFileSystem::printImpl(raw_ostream &OS, PrintTypeType,
389unsigned IndentLevel) const{
390 printIndent(OS, IndentLevel);
391OS <<"RealFileSystem using ";
392if (WD)
393OS <<"own";
394else
395OS <<"process";
396OS <<" CWD\n";
397}
398
399IntrusiveRefCntPtr<FileSystem>vfs::getRealFileSystem() {
400staticIntrusiveRefCntPtr<FileSystem> FS(new RealFileSystem(true));
401return FS;
402}
403
404std::unique_ptr<FileSystem>vfs::createPhysicalFileSystem() {
405return std::make_unique<RealFileSystem>(false);
406}
407
408namespace{
409
410classRealFSDirIter :publicllvm::vfs::detail::DirIterImpl {
411llvm::sys::fs::directory_iterator Iter;
412
413public:
414 RealFSDirIter(constTwine &Path, std::error_code &EC) : Iter(Path, EC) {
415if (Iter !=llvm::sys::fs::directory_iterator())
416 CurrentEntry =directory_entry(Iter->path(), Iter->type());
417 }
418
419 std::error_code increment() override{
420 std::error_code EC;
421 Iter.increment(EC);
422 CurrentEntry = (Iter ==llvm::sys::fs::directory_iterator())
423 ?directory_entry()
424 :directory_entry(Iter->path(), Iter->type());
425return EC;
426 }
427};
428
429}// namespace
430
431directory_iterator RealFileSystem::dir_begin(constTwine &Dir,
432 std::error_code &EC) {
433SmallString<128> Storage;
434returndirectory_iterator(
435 std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
436}
437
438//===-----------------------------------------------------------------------===/
439// OverlayFileSystem implementation
440//===-----------------------------------------------------------------------===/
441
442OverlayFileSystem::OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> BaseFS) {
443 FSList.push_back(std::move(BaseFS));
444}
445
446voidOverlayFileSystem::pushOverlay(IntrusiveRefCntPtr<FileSystem> FS) {
447 FSList.push_back(FS);
448// Synchronize added file systems by duplicating the working directory from
449// the first one in the list.
450 FS->setCurrentWorkingDirectory(getCurrentWorkingDirectory().get());
451}
452
453ErrorOr<Status>OverlayFileSystem::status(constTwine &Path) {
454// FIXME: handle symlinks that cross file systems
455for (iteratorI =overlays_begin(), E =overlays_end();I != E; ++I) {
456ErrorOr<Status>Status = (*I)->status(Path);
457if (Status ||Status.getError() !=llvm::errc::no_such_file_or_directory)
458returnStatus;
459 }
460returnmake_error_code(llvm::errc::no_such_file_or_directory);
461}
462
463boolOverlayFileSystem::exists(constTwine &Path) {
464// FIXME: handle symlinks that cross file systems
465for (iteratorI =overlays_begin(), E =overlays_end();I != E; ++I) {
466if ((*I)->exists(Path))
467returntrue;
468 }
469returnfalse;
470}
471
472ErrorOr<std::unique_ptr<File>>
473OverlayFileSystem::openFileForRead(constllvm::Twine &Path) {
474// FIXME: handle symlinks that cross file systems
475for (iteratorI =overlays_begin(), E =overlays_end();I != E; ++I) {
476auto Result = (*I)->openFileForRead(Path);
477if (Result || Result.getError() !=llvm::errc::no_such_file_or_directory)
478return Result;
479 }
480returnmake_error_code(llvm::errc::no_such_file_or_directory);
481}
482
483llvm::ErrorOr<std::string>
484OverlayFileSystem::getCurrentWorkingDirectory() const{
485// All file systems are synchronized, just take the first working directory.
486return FSList.front()->getCurrentWorkingDirectory();
487}
488
489std::error_code
490OverlayFileSystem::setCurrentWorkingDirectory(constTwine &Path) {
491for (auto &FS : FSList)
492if (std::error_code EC = FS->setCurrentWorkingDirectory(Path))
493return EC;
494return {};
495}
496
497std::error_codeOverlayFileSystem::isLocal(constTwine &Path,bool &Result) {
498for (auto &FS : FSList)
499if (FS->exists(Path))
500return FS->isLocal(Path, Result);
501returnerrc::no_such_file_or_directory;
502}
503
504std::error_codeOverlayFileSystem::getRealPath(constTwine &Path,
505SmallVectorImpl<char> &Output) {
506for (constauto &FS : FSList)
507if (FS->exists(Path))
508return FS->getRealPath(Path, Output);
509returnerrc::no_such_file_or_directory;
510}
511
512voidOverlayFileSystem::visitChildFileSystems(VisitCallbackTy Callback) {
513for (IntrusiveRefCntPtr<FileSystem> FS :overlays_range()) {
514 Callback(*FS);
515 FS->visitChildFileSystems(Callback);
516 }
517}
518
519voidOverlayFileSystem::printImpl(raw_ostream &OS, PrintTypeType,
520unsigned IndentLevel) const{
521 printIndent(OS, IndentLevel);
522OS <<"OverlayFileSystem\n";
523if (Type == PrintType::Summary)
524return;
525
526if (Type == PrintType::Contents)
527Type = PrintType::Summary;
528for (constauto &FS :overlays_range())
529 FS->print(OS,Type, IndentLevel + 1);
530}
531
532llvm::vfs::detail::DirIterImpl::~DirIterImpl() =default;
533
534namespace{
535
536/// Combines and deduplicates directory entries across multiple file systems.
537classCombiningDirIterImpl :publicllvm::vfs::detail::DirIterImpl {
538usingFileSystemPtr =llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>;
539
540 /// Iterators to combine, processed in reverse order.
541SmallVector<directory_iterator, 8> IterList;
542 /// The iterator currently being traversed.
543directory_iterator CurrentDirIter;
544 /// The set of names already returned as entries.
545llvm::StringSet<> SeenNames;
546
547 /// Sets \c CurrentDirIter to the next iterator in the list, or leaves it as
548 /// is (at its end position) if we've already gone through them all.
549 std::error_code incrementIter(bool IsFirstTime) {
550while (!IterList.empty()) {
551 CurrentDirIter = IterList.back();
552 IterList.pop_back();
553if (CurrentDirIter !=directory_iterator())
554break;// found
555 }
556
557if (IsFirstTime && CurrentDirIter ==directory_iterator())
558return errc::no_such_file_or_directory;
559return {};
560 }
561
562 std::error_code incrementDirIter(bool IsFirstTime) {
563assert((IsFirstTime || CurrentDirIter !=directory_iterator()) &&
564"incrementing past end");
565 std::error_codeEC;
566if (!IsFirstTime)
567 CurrentDirIter.increment(EC);
568if (!EC && CurrentDirIter ==directory_iterator())
569EC = incrementIter(IsFirstTime);
570returnEC;
571 }
572
573 std::error_code incrementImpl(bool IsFirstTime) {
574while (true) {
575 std::error_codeEC = incrementDirIter(IsFirstTime);
576if (EC || CurrentDirIter ==directory_iterator()) {
577 CurrentEntry =directory_entry();
578returnEC;
579 }
580 CurrentEntry = *CurrentDirIter;
581StringRefName =llvm::sys::path::filename(CurrentEntry.path());
582if (SeenNames.insert(Name).second)
583returnEC;// name not seen before
584 }
585llvm_unreachable("returned above");
586 }
587
588public:
589 CombiningDirIterImpl(ArrayRef<FileSystemPtr> FileSystems, std::string Dir,
590 std::error_code &EC) {
591for (constauto &FS : FileSystems) {
592 std::error_code FEC;
593directory_iterator Iter =FS->dir_begin(Dir, FEC);
594if (FEC && FEC != errc::no_such_file_or_directory) {
595EC = FEC;
596return;
597 }
598if (!FEC)
599 IterList.push_back(Iter);
600 }
601EC = incrementImpl(true);
602 }
603
604 CombiningDirIterImpl(ArrayRef<directory_iterator> DirIters,
605 std::error_code &EC)
606 : IterList(DirIters) {
607EC = incrementImpl(true);
608 }
609
610 std::error_code increment() override{return incrementImpl(false); }
611};
612
613}// namespace
614
615directory_iteratorOverlayFileSystem::dir_begin(constTwine &Dir,
616 std::error_code &EC) {
617directory_iterator Combined =directory_iterator(
618 std::make_shared<CombiningDirIterImpl>(FSList, Dir.str(), EC));
619if (EC)
620return {};
621return Combined;
622}
623
624void ProxyFileSystem::anchor() {}
625
626namespacellvm {
627namespacevfs {
628
629namespacedetail {
630
631enumInMemoryNodeKind {
632IME_File,
633IME_Directory,
634IME_HardLink,
635IME_SymbolicLink,
636};
637
638/// The in memory file system is a tree of Nodes. Every node can either be a
639/// file, symlink, hardlink or a directory.
640classInMemoryNode {
641InMemoryNodeKind Kind;
642 std::string FileName;
643
644public:
645InMemoryNode(llvm::StringRef FileName,InMemoryNodeKind Kind)
646 : Kind(Kind), FileName(std::string(llvm::sys::path::filename(FileName))) {
647 }
648virtual~InMemoryNode() =default;
649
650 /// Return the \p Status for this node. \p RequestedName should be the name
651 /// through which the caller referred to this node. It will override
652 /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
653virtualStatusgetStatus(constTwine &RequestedName)const = 0;
654
655 /// Get the filename of this node (the name without the directory part).
656StringRefgetFileName() const{return FileName; }
657InMemoryNodeKindgetKind() const{return Kind; }
658virtual std::stringtoString(unsigned Indent)const = 0;
659};
660
661classInMemoryFile :publicInMemoryNode {
662Status Stat;
663 std::unique_ptr<llvm::MemoryBuffer> Buffer;
664
665public:
666InMemoryFile(Status Stat, std::unique_ptr<llvm::MemoryBuffer> Buffer)
667 :InMemoryNode(Stat.getName(),IME_File), Stat(std::move(Stat)),
668 Buffer(std::move(Buffer)) {}
669
670StatusgetStatus(constTwine &RequestedName) const override{
671return Status::copyWithNewName(Stat, RequestedName);
672 }
673llvm::MemoryBuffer *getBuffer() const{return Buffer.get(); }
674
675 std::stringtoString(unsigned Indent) const override{
676return (std::string(Indent,' ') + Stat.getName() +"\n").str();
677 }
678
679staticboolclassof(constInMemoryNode *N) {
680returnN->getKind() ==IME_File;
681 }
682};
683
684namespace{
685
686classInMemoryHardLink :public InMemoryNode {
687const InMemoryFile &ResolvedFile;
688
689public:
690 InMemoryHardLink(StringRef Path,const InMemoryFile &ResolvedFile)
691 : InMemoryNode(Path, IME_HardLink), ResolvedFile(ResolvedFile) {}
692const InMemoryFile &getResolvedFile() const{return ResolvedFile; }
693
694Status getStatus(constTwine &RequestedName) const override{
695return ResolvedFile.getStatus(RequestedName);
696 }
697
698 std::stringtoString(unsigned Indent) const override{
699return std::string(Indent,' ') +"HardLink to -> " +
700 ResolvedFile.toString(0);
701 }
702
703staticbool classof(const InMemoryNode *N) {
704returnN->getKind() ==IME_HardLink;
705 }
706};
707
708classInMemorySymbolicLink :public InMemoryNode {
709 std::string TargetPath;
710Status Stat;
711
712public:
713 InMemorySymbolicLink(StringRef Path,StringRef TargetPath,Status Stat)
714 : InMemoryNode(Path,IME_SymbolicLink), TargetPath(std::move(TargetPath)),
715 Stat(Stat) {}
716
717 std::stringtoString(unsigned Indent) const override{
718return std::string(Indent,' ') +"SymbolicLink to -> " + TargetPath;
719 }
720
721Status getStatus(constTwine &RequestedName) const override{
722return Status::copyWithNewName(Stat, RequestedName);
723 }
724
725StringRef getTargetPath() const{return TargetPath; }
726
727staticbool classof(const InMemoryNode *N) {
728returnN->getKind() ==IME_SymbolicLink;
729 }
730};
731
732/// Adapt a InMemoryFile for VFS' File interface. The goal is to make
733/// \p InMemoryFileAdaptor mimic as much as possible the behavior of
734/// \p RealFile.
735classInMemoryFileAdaptor :publicFile {
736const InMemoryFile &Node;
737 /// The name to use when returning a Status for this file.
738 std::string RequestedName;
739
740public:
741explicit InMemoryFileAdaptor(const InMemoryFile &Node,
742 std::string RequestedName)
743 :Node(Node), RequestedName(std::move(RequestedName)) {}
744
745llvm::ErrorOr<Status>status() override{
746returnNode.getStatus(RequestedName);
747 }
748
749llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
750 getBuffer(constTwine &Name, int64_t FileSize,bool RequiresNullTerminator,
751bool IsVolatile) override{
752llvm::MemoryBuffer *Buf =Node.getBuffer();
753returnllvm::MemoryBuffer::getMemBuffer(
754 Buf->getBuffer(), Buf->getBufferIdentifier(), RequiresNullTerminator);
755 }
756
757 std::error_code close() override{return {}; }
758
759void setPath(constTwine &Path) override{ RequestedName =Path.str(); }
760};
761}// namespace
762
763classInMemoryDirectory :publicInMemoryNode {
764Status Stat;
765 std::map<std::string, std::unique_ptr<InMemoryNode>, std::less<>> Entries;
766
767public:
768InMemoryDirectory(Status Stat)
769 :InMemoryNode(Stat.getName(),IME_Directory), Stat(std::move(Stat)) {}
770
771 /// Return the \p Status for this node. \p RequestedName should be the name
772 /// through which the caller referred to this node. It will override
773 /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
774StatusgetStatus(constTwine &RequestedName) const override{
775return Status::copyWithNewName(Stat, RequestedName);
776 }
777
778UniqueIDgetUniqueID() const{return Stat.getUniqueID(); }
779
780InMemoryNode *getChild(StringRefName) const{
781autoI = Entries.find(Name);
782if (I != Entries.end())
783returnI->second.get();
784returnnullptr;
785 }
786
787InMemoryNode *addChild(StringRefName, std::unique_ptr<InMemoryNode> Child) {
788return Entries.emplace(Name, std::move(Child)).first->second.get();
789 }
790
791usingconst_iterator =decltype(Entries)::const_iterator;
792
793const_iteratorbegin() const{return Entries.begin(); }
794const_iteratorend() const{return Entries.end(); }
795
796 std::stringtoString(unsigned Indent) const override{
797 std::string Result =
798 (std::string(Indent,' ') + Stat.getName() +"\n").str();
799for (constauto &Entry : Entries)
800 Result += Entry.second->toString(Indent + 2);
801return Result;
802 }
803
804staticboolclassof(constInMemoryNode *N) {
805returnN->getKind() ==IME_Directory;
806 }
807};
808
809}// namespace detail
810
811// The UniqueID of in-memory files is derived from path and content.
812// This avoids difficulties in creating exactly equivalent in-memory FSes,
813// as often needed in multithreaded programs.
814staticsys::fs::UniqueIDgetUniqueID(hash_code Hash) {
815returnsys::fs::UniqueID(std::numeric_limits<uint64_t>::max(),
816uint64_t(size_t(Hash)));
817}
818staticsys::fs::UniqueIDgetFileID(sys::fs::UniqueID Parent,
819llvm::StringRefName,
820llvm::StringRef Contents) {
821returngetUniqueID(llvm::hash_combine(Parent.getFile(),Name, Contents));
822}
823staticsys::fs::UniqueIDgetDirectoryID(sys::fs::UniqueID Parent,
824llvm::StringRefName) {
825returngetUniqueID(llvm::hash_combine(Parent.getFile(),Name));
826}
827
828Statusdetail::NewInMemoryNodeInfo::makeStatus() const{
829UniqueID UID =
830 (Type == sys::fs::file_type::directory_file)
831 ?getDirectoryID(DirUID,Name)
832 :getFileID(DirUID,Name, Buffer ? Buffer->getBuffer() :"");
833
834returnStatus(Path, UID,llvm::sys::toTimePoint(ModificationTime),User,
835 Group, Buffer ? Buffer->getBufferSize() : 0,Type, Perms);
836}
837
838InMemoryFileSystem::InMemoryFileSystem(bool UseNormalizedPaths)
839 : Root(newdetail::InMemoryDirectory(
840Status("",getDirectoryID(llvm::sys::fs::UniqueID(),""),
841llvm::sys::TimePoint<>(), 0, 0, 0,
842llvm::sys::fs::file_type::directory_file,
843llvm::sys::fs::perms::all_all))),
844 UseNormalizedPaths(UseNormalizedPaths) {}
845
846InMemoryFileSystem::~InMemoryFileSystem() =default;
847
848std::stringInMemoryFileSystem::toString() const{
849return Root->toString(/*Indent=*/0);
850}
851
852bool InMemoryFileSystem::addFile(constTwine &P, time_t ModificationTime,
853 std::unique_ptr<llvm::MemoryBuffer> Buffer,
854 std::optional<uint32_t>User,
855 std::optional<uint32_t> Group,
856 std::optional<llvm::sys::fs::file_type>Type,
857 std::optional<llvm::sys::fs::perms> Perms,
858 MakeNodeFn MakeNode) {
859SmallString<128> Path;
860P.toVector(Path);
861
862// Fix up relative paths. This just prepends the current working directory.
863 std::error_code EC =makeAbsolute(Path);
864assert(!EC);
865 (void)EC;
866
867if (useNormalizedPaths())
868llvm::sys::path::remove_dots(Path,/*remove_dot_dot=*/true);
869
870if (Path.empty())
871returnfalse;
872
873detail::InMemoryDirectory *Dir = Root.get();
874autoI =llvm::sys::path::begin(Path), E =sys::path::end(Path);
875constauto ResolvedUser =User.value_or(0);
876constauto ResolvedGroup = Group.value_or(0);
877constauto ResolvedType =Type.value_or(sys::fs::file_type::regular_file);
878constauto ResolvedPerms = Perms.value_or(sys::fs::all_all);
879// Any intermediate directories we create should be accessible by
880// the owner, even if Perms says otherwise for the final path.
881constauto NewDirectoryPerms = ResolvedPerms |sys::fs::owner_all;
882
883StringRefName = *I;
884while (true) {
885Name = *I;
886 ++I;
887if (I == E)
888break;
889detail::InMemoryNode *Node = Dir->getChild(Name);
890if (!Node) {
891// This isn't the last element, so we create a new directory.
892Status Stat(
893StringRef(Path.str().begin(),Name.end() - Path.str().begin()),
894getDirectoryID(Dir->getUniqueID(),Name),
895llvm::sys::toTimePoint(ModificationTime), ResolvedUser, ResolvedGroup,
896 0,sys::fs::file_type::directory_file, NewDirectoryPerms);
897 Dir = cast<detail::InMemoryDirectory>(Dir->addChild(
898Name, std::make_unique<detail::InMemoryDirectory>(std::move(Stat))));
899continue;
900 }
901// Creating file under another file.
902if (!isa<detail::InMemoryDirectory>(Node))
903returnfalse;
904 Dir = cast<detail::InMemoryDirectory>(Node);
905 }
906detail::InMemoryNode *Node = Dir->getChild(Name);
907if (!Node) {
908 Dir->addChild(Name,
909 MakeNode({Dir->getUniqueID(), Path,Name, ModificationTime,
910 std::move(Buffer), ResolvedUser, ResolvedGroup,
911 ResolvedType, ResolvedPerms}));
912returntrue;
913 }
914if (isa<detail::InMemoryDirectory>(Node))
915return ResolvedType ==sys::fs::file_type::directory_file;
916
917assert((isa<detail::InMemoryFile>(Node) ||
918 isa<detail::InMemoryHardLink>(Node)) &&
919"Must be either file, hardlink or directory!");
920
921// Return false only if the new file is different from the existing one.
922if (auto *Link = dyn_cast<detail::InMemoryHardLink>(Node)) {
923returnLink->getResolvedFile().getBuffer()->getBuffer() ==
924 Buffer->getBuffer();
925 }
926return cast<detail::InMemoryFile>(Node)->getBuffer()->getBuffer() ==
927 Buffer->getBuffer();
928}
929
930bool InMemoryFileSystem::addFile(constTwine &P, time_t ModificationTime,
931 std::unique_ptr<llvm::MemoryBuffer> Buffer,
932 std::optional<uint32_t>User,
933 std::optional<uint32_t> Group,
934 std::optional<llvm::sys::fs::file_type>Type,
935 std::optional<llvm::sys::fs::perms> Perms) {
936return addFile(P, ModificationTime, std::move(Buffer),User, Group,Type,
937 Perms,
938 [](detail::NewInMemoryNodeInfo NNI)
939 -> std::unique_ptr<detail::InMemoryNode> {
940Status Stat = NNI.makeStatus();
941if (Stat.getType() ==sys::fs::file_type::directory_file)
942return std::make_unique<detail::InMemoryDirectory>(Stat);
943return std::make_unique<detail::InMemoryFile>(
944 Stat, std::move(NNI.Buffer));
945 });
946}
947
948boolInMemoryFileSystem::addFileNoOwn(
949constTwine &P, time_t ModificationTime,
950constllvm::MemoryBufferRef &Buffer, std::optional<uint32_t>User,
951 std::optional<uint32_t> Group, std::optional<llvm::sys::fs::file_type>Type,
952 std::optional<llvm::sys::fs::perms> Perms) {
953return addFile(P, ModificationTime,llvm::MemoryBuffer::getMemBuffer(Buffer),
954 std::move(User), std::move(Group), std::move(Type),
955 std::move(Perms),
956 [](detail::NewInMemoryNodeInfo NNI)
957 -> std::unique_ptr<detail::InMemoryNode> {
958Status Stat = NNI.makeStatus();
959if (Stat.getType() ==sys::fs::file_type::directory_file)
960return std::make_unique<detail::InMemoryDirectory>(Stat);
961return std::make_unique<detail::InMemoryFile>(
962 Stat, std::move(NNI.Buffer));
963 });
964}
965
966detail::NamedNodeOrError
967InMemoryFileSystem::lookupNode(constTwine &P,bool FollowFinalSymlink,
968size_t SymlinkDepth) const{
969SmallString<128> Path;
970P.toVector(Path);
971
972// Fix up relative paths. This just prepends the current working directory.
973 std::error_code EC =makeAbsolute(Path);
974assert(!EC);
975 (void)EC;
976
977if (useNormalizedPaths())
978llvm::sys::path::remove_dots(Path,/*remove_dot_dot=*/true);
979
980constdetail::InMemoryDirectory *Dir = Root.get();
981if (Path.empty())
982returndetail::NamedNodeOrError(Path, Dir);
983
984autoI =llvm::sys::path::begin(Path), E =llvm::sys::path::end(Path);
985while (true) {
986detail::InMemoryNode *Node = Dir->getChild(*I);
987 ++I;
988if (!Node)
989returnerrc::no_such_file_or_directory;
990
991if (auto Symlink = dyn_cast<detail::InMemorySymbolicLink>(Node)) {
992// If we're at the end of the path, and we're not following through
993// terminal symlinks, then we're done.
994if (I == E && !FollowFinalSymlink)
995returndetail::NamedNodeOrError(Path, Symlink);
996
997if (SymlinkDepth >InMemoryFileSystem::MaxSymlinkDepth)
998returnerrc::no_such_file_or_directory;
999
1000SmallString<128> TargetPath = Symlink->getTargetPath();
1001if (std::error_code EC =makeAbsolute(TargetPath))
1002return EC;
1003
1004// Keep going with the target. We always want to follow symlinks here
1005// because we're either at the end of a path that we want to follow, or
1006// not at the end of a path, in which case we need to follow the symlink
1007// regardless.
1008autoTarget =
1009 lookupNode(TargetPath,/*FollowFinalSymlink=*/true, SymlinkDepth + 1);
1010if (!Target ||I == E)
1011returnTarget;
1012
1013if (!isa<detail::InMemoryDirectory>(*Target))
1014returnerrc::no_such_file_or_directory;
1015
1016// Otherwise, continue on the search in the symlinked directory.
1017 Dir = cast<detail::InMemoryDirectory>(*Target);
1018continue;
1019 }
1020
1021// Return the file if it's at the end of the path.
1022if (autoFile = dyn_cast<detail::InMemoryFile>(Node)) {
1023if (I == E)
1024returndetail::NamedNodeOrError(Path,File);
1025returnerrc::no_such_file_or_directory;
1026 }
1027
1028// If Node is HardLink then return the resolved file.
1029if (autoFile = dyn_cast<detail::InMemoryHardLink>(Node)) {
1030if (I == E)
1031returndetail::NamedNodeOrError(Path, &File->getResolvedFile());
1032returnerrc::no_such_file_or_directory;
1033 }
1034// Traverse directories.
1035 Dir = cast<detail::InMemoryDirectory>(Node);
1036if (I == E)
1037returndetail::NamedNodeOrError(Path, Dir);
1038 }
1039}
1040
1041boolInMemoryFileSystem::addHardLink(constTwine &NewLink,
1042constTwine &Target) {
1043auto NewLinkNode = lookupNode(NewLink,/*FollowFinalSymlink=*/false);
1044// Whether symlinks in the hardlink target are followed is
1045// implementation-defined in POSIX.
1046// We're following symlinks here to be consistent with macOS.
1047auto TargetNode = lookupNode(Target,/*FollowFinalSymlink=*/true);
1048// FromPath must not have been added before. ToPath must have been added
1049// before. Resolved ToPath must be a File.
1050if (!TargetNode || NewLinkNode || !isa<detail::InMemoryFile>(*TargetNode))
1051returnfalse;
1052return addFile(NewLink, 0,nullptr, std::nullopt, std::nullopt, std::nullopt,
1053 std::nullopt, [&](detail::NewInMemoryNodeInfo NNI) {
1054return std::make_unique<detail::InMemoryHardLink>(
1055 NNI.Path.str(),
1056 *cast<detail::InMemoryFile>(*TargetNode));
1057 });
1058}
1059
1060boolInMemoryFileSystem::addSymbolicLink(
1061constTwine &NewLink,constTwine &Target, time_t ModificationTime,
1062 std::optional<uint32_t>User, std::optional<uint32_t> Group,
1063 std::optional<llvm::sys::fs::perms> Perms) {
1064auto NewLinkNode = lookupNode(NewLink,/*FollowFinalSymlink=*/false);
1065if (NewLinkNode)
1066returnfalse;
1067
1068SmallString<128> NewLinkStr, TargetStr;
1069 NewLink.toVector(NewLinkStr);
1070Target.toVector(TargetStr);
1071
1072return addFile(NewLinkStr, ModificationTime,nullptr,User, Group,
1073sys::fs::file_type::symlink_file, Perms,
1074 [&](detail::NewInMemoryNodeInfo NNI) {
1075return std::make_unique<detail::InMemorySymbolicLink>(
1076 NewLinkStr, TargetStr, NNI.makeStatus());
1077 });
1078}
1079
1080llvm::ErrorOr<Status>InMemoryFileSystem::status(constTwine &Path) {
1081auto Node = lookupNode(Path,/*FollowFinalSymlink=*/true);
1082if (Node)
1083return (*Node)->getStatus(Path);
1084return Node.getError();
1085}
1086
1087llvm::ErrorOr<std::unique_ptr<File>>
1088InMemoryFileSystem::openFileForRead(constTwine &Path) {
1089auto Node = lookupNode(Path,/*FollowFinalSymlink=*/true);
1090if (!Node)
1091return Node.getError();
1092
1093// When we have a file provide a heap-allocated wrapper for the memory buffer
1094// to match the ownership semantics for File.
1095if (auto *F = dyn_cast<detail::InMemoryFile>(*Node))
1096return std::unique_ptr<File>(
1097new detail::InMemoryFileAdaptor(*F, Path.str()));
1098
1099// FIXME: errc::not_a_file?
1100returnmake_error_code(llvm::errc::invalid_argument);
1101}
1102
1103/// Adaptor from InMemoryDir::iterator to directory_iterator.
1104classInMemoryFileSystem::DirIterator :publicllvm::vfs::detail::DirIterImpl {
1105constInMemoryFileSystem *FS;
1106detail::InMemoryDirectory::const_iterator I;
1107detail::InMemoryDirectory::const_iterator E;
1108 std::string RequestedDirName;
1109
1110void setCurrentEntry() {
1111if (I != E) {
1112SmallString<256> Path(RequestedDirName);
1113llvm::sys::path::append(Path,I->second->getFileName());
1114sys::fs::file_typeType =sys::fs::file_type::type_unknown;
1115switch (I->second->getKind()) {
1116casedetail::IME_File:
1117casedetail::IME_HardLink:
1118Type =sys::fs::file_type::regular_file;
1119break;
1120casedetail::IME_Directory:
1121Type =sys::fs::file_type::directory_file;
1122break;
1123casedetail::IME_SymbolicLink:
1124if (auto SymlinkTarget =
1125 FS->lookupNode(Path,/*FollowFinalSymlink=*/true)) {
1126 Path = SymlinkTarget.getName();
1127Type = (*SymlinkTarget)->getStatus(Path).getType();
1128 }
1129break;
1130 }
1131CurrentEntry =directory_entry(std::string(Path),Type);
1132 }else {
1133// When we're at the end, make CurrentEntry invalid and DirIterImpl will
1134// do the rest.
1135CurrentEntry =directory_entry();
1136 }
1137 }
1138
1139public:
1140DirIterator() =default;
1141
1142DirIterator(constInMemoryFileSystem *FS,
1143constdetail::InMemoryDirectory &Dir,
1144 std::string RequestedDirName)
1145 : FS(FS),I(Dir.begin()), E(Dir.end()),
1146 RequestedDirName(std::move(RequestedDirName)) {
1147 setCurrentEntry();
1148 }
1149
1150 std::error_codeincrement() override{
1151 ++I;
1152 setCurrentEntry();
1153return {};
1154 }
1155};
1156
1157directory_iteratorInMemoryFileSystem::dir_begin(constTwine &Dir,
1158 std::error_code &EC) {
1159auto Node = lookupNode(Dir,/*FollowFinalSymlink=*/true);
1160if (!Node) {
1161 EC = Node.getError();
1162returndirectory_iterator(std::make_shared<DirIterator>());
1163 }
1164
1165if (auto *DirNode = dyn_cast<detail::InMemoryDirectory>(*Node))
1166returndirectory_iterator(
1167 std::make_shared<DirIterator>(this, *DirNode, Dir.str()));
1168
1169 EC =make_error_code(llvm::errc::not_a_directory);
1170returndirectory_iterator(std::make_shared<DirIterator>());
1171}
1172
1173std::error_codeInMemoryFileSystem::setCurrentWorkingDirectory(constTwine &P) {
1174SmallString<128> Path;
1175P.toVector(Path);
1176
1177// Fix up relative paths. This just prepends the current working directory.
1178 std::error_code EC =makeAbsolute(Path);
1179assert(!EC);
1180 (void)EC;
1181
1182if (useNormalizedPaths())
1183llvm::sys::path::remove_dots(Path,/*remove_dot_dot=*/true);
1184
1185if (!Path.empty())
1186 WorkingDirectory = std::string(Path);
1187return {};
1188}
1189
1190std::error_codeInMemoryFileSystem::getRealPath(constTwine &Path,
1191SmallVectorImpl<char> &Output) {
1192auto CWD =getCurrentWorkingDirectory();
1193if (!CWD || CWD->empty())
1194returnerrc::operation_not_permitted;
1195 Path.toVector(Output);
1196if (auto EC =makeAbsolute(Output))
1197return EC;
1198llvm::sys::path::remove_dots(Output,/*remove_dot_dot=*/true);
1199return {};
1200}
1201
1202std::error_codeInMemoryFileSystem::isLocal(constTwine &Path,bool &Result) {
1203 Result =false;
1204return {};
1205}
1206
1207voidInMemoryFileSystem::printImpl(raw_ostream &OS, PrintType PrintContents,
1208unsigned IndentLevel) const{
1209 printIndent(OS, IndentLevel);
1210OS <<"InMemoryFileSystem\n";
1211}
1212
1213}// namespace vfs
1214}// namespace llvm
1215
1216//===-----------------------------------------------------------------------===/
1217// RedirectingFileSystem implementation
1218//===-----------------------------------------------------------------------===/
1219
1220namespace{
1221
1222staticllvm::sys::path::Style getExistingStyle(llvm::StringRef Path) {
1223// Detect the path style in use by checking the first separator.
1224llvm::sys::path::Style style =llvm::sys::path::Style::native;
1225constsize_t n = Path.find_first_of("/\\");
1226// Can't distinguish between posix and windows_slash here.
1227if (n !=static_cast<size_t>(-1))
1228 style = (Path[n] =='/') ?llvm::sys::path::Style::posix
1229 :llvm::sys::path::Style::windows_backslash;
1230return style;
1231}
1232
1233/// Removes leading "./" as well as path components like ".." and ".".
1234staticllvm::SmallString<256> canonicalize(llvm::StringRef Path) {
1235// First detect the path style in use by checking the first separator.
1236llvm::sys::path::Style style = getExistingStyle(Path);
1237
1238// Now remove the dots. Explicitly specifying the path style prevents the
1239// direction of the slashes from changing.
1240llvm::SmallString<256> result =
1241llvm::sys::path::remove_leading_dotslash(Path, style);
1242llvm::sys::path::remove_dots(result,/*remove_dot_dot=*/true, style);
1243return result;
1244}
1245
1246/// Whether the error and entry specify a file/directory that was not found.
1247staticbool isFileNotFound(std::error_code EC,
1248RedirectingFileSystem::Entry *E =nullptr) {
1249if (E && !isa<RedirectingFileSystem::DirectoryRemapEntry>(E))
1250returnfalse;
1251returnEC ==llvm::errc::no_such_file_or_directory;
1252}
1253
1254}// anonymous namespace
1255
1256
1257RedirectingFileSystem::RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> FS)
1258 : ExternalFS(std::move(FS)) {
1259if (ExternalFS)
1260if (auto ExternalWorkingDirectory =
1261 ExternalFS->getCurrentWorkingDirectory()) {
1262 WorkingDirectory = *ExternalWorkingDirectory;
1263 }
1264}
1265
1266/// Directory iterator implementation for \c RedirectingFileSystem's
1267/// directory entries.
1268classllvm::vfs::RedirectingFSDirIterImpl
1269 :publicllvm::vfs::detail::DirIterImpl {
1270 std::string Dir;
1271RedirectingFileSystem::DirectoryEntry::iterator Current, End;
1272
1273 std::error_code incrementImpl(bool IsFirstTime) {
1274assert((IsFirstTime || Current !=End) &&"cannot iterate past end");
1275if (!IsFirstTime)
1276 ++Current;
1277if (Current !=End) {
1278SmallString<128> PathStr(Dir);
1279llvm::sys::path::append(PathStr, (*Current)->getName());
1280sys::fs::file_typeType =sys::fs::file_type::type_unknown;
1281switch ((*Current)->getKind()) {
1282caseRedirectingFileSystem::EK_Directory:
1283 [[fallthrough]];
1284caseRedirectingFileSystem::EK_DirectoryRemap:
1285Type =sys::fs::file_type::directory_file;
1286break;
1287caseRedirectingFileSystem::EK_File:
1288Type =sys::fs::file_type::regular_file;
1289break;
1290 }
1291CurrentEntry =directory_entry(std::string(PathStr),Type);
1292 }else {
1293CurrentEntry =directory_entry();
1294 }
1295return {};
1296 };
1297
1298public:
1299RedirectingFSDirIterImpl(
1300constTwine &Path,RedirectingFileSystem::DirectoryEntry::iterator Begin,
1301RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
1302 : Dir(Path.str()), Current(Begin),End(End) {
1303 EC = incrementImpl(/*IsFirstTime=*/true);
1304 }
1305
1306 std::error_codeincrement() override{
1307return incrementImpl(/*IsFirstTime=*/false);
1308 }
1309};
1310
1311namespace{
1312/// Directory iterator implementation for \c RedirectingFileSystem's
1313/// directory remap entries that maps the paths reported by the external
1314/// file system's directory iterator back to the virtual directory's path.
1315classRedirectingFSDirRemapIterImpl :publicllvm::vfs::detail::DirIterImpl {
1316 std::string Dir;
1317llvm::sys::path::Style DirStyle;
1318llvm::vfs::directory_iterator ExternalIter;
1319
1320public:
1321 RedirectingFSDirRemapIterImpl(std::string DirPath,
1322llvm::vfs::directory_iterator ExtIter)
1323 : Dir(std::move(DirPath)), DirStyle(getExistingStyle(Dir)),
1324 ExternalIter(ExtIter) {
1325if (ExternalIter !=llvm::vfs::directory_iterator())
1326 setCurrentEntry();
1327 }
1328
1329void setCurrentEntry() {
1330StringRef ExternalPath = ExternalIter->path();
1331llvm::sys::path::Style ExternalStyle = getExistingStyle(ExternalPath);
1332StringRefFile =llvm::sys::path::filename(ExternalPath, ExternalStyle);
1333
1334SmallString<128> NewPath(Dir);
1335llvm::sys::path::append(NewPath, DirStyle,File);
1336
1337 CurrentEntry =directory_entry(std::string(NewPath), ExternalIter->type());
1338 }
1339
1340 std::error_code increment() override{
1341 std::error_codeEC;
1342 ExternalIter.increment(EC);
1343if (!EC && ExternalIter !=llvm::vfs::directory_iterator())
1344 setCurrentEntry();
1345else
1346 CurrentEntry =directory_entry();
1347returnEC;
1348 }
1349};
1350}// namespace
1351
1352llvm::ErrorOr<std::string>
1353RedirectingFileSystem::getCurrentWorkingDirectory() const{
1354return WorkingDirectory;
1355}
1356
1357std::error_code
1358RedirectingFileSystem::setCurrentWorkingDirectory(constTwine &Path) {
1359// Don't change the working directory if the path doesn't exist.
1360if (!exists(Path))
1361returnerrc::no_such_file_or_directory;
1362
1363SmallString<128> AbsolutePath;
1364 Path.toVector(AbsolutePath);
1365if (std::error_code EC = makeAbsolute(AbsolutePath))
1366return EC;
1367 WorkingDirectory = std::string(AbsolutePath);
1368return {};
1369}
1370
1371std::error_codeRedirectingFileSystem::isLocal(constTwine &Path_,
1372bool &Result) {
1373SmallString<256> Path;
1374 Path_.toVector(Path);
1375
1376if (makeAbsolute(Path))
1377return {};
1378
1379return ExternalFS->isLocal(Path, Result);
1380}
1381
1382std::error_code RedirectingFileSystem::makeAbsolute(SmallVectorImpl<char> &Path) const{
1383// is_absolute(..., Style::windows_*) accepts paths with both slash types.
1384if (llvm::sys::path::is_absolute(Path,llvm::sys::path::Style::posix) ||
1385llvm::sys::path::is_absolute(Path,
1386llvm::sys::path::Style::windows_backslash))
1387// This covers windows absolute path with forward slash as well, as the
1388// forward slashes are treated as path separation in llvm::path
1389// regardless of what path::Style is used.
1390return {};
1391
1392auto WorkingDir =getCurrentWorkingDirectory();
1393if (!WorkingDir)
1394return WorkingDir.getError();
1395
1396return makeAbsolute(WorkingDir.get(), Path);
1397}
1398
1399std::error_code
1400RedirectingFileSystem::makeAbsolute(StringRef WorkingDir,
1401SmallVectorImpl<char> &Path) const{
1402// We can't use sys::fs::make_absolute because that assumes the path style
1403// is native and there is no way to override that. Since we know WorkingDir
1404// is absolute, we can use it to determine which style we actually have and
1405// append Path ourselves.
1406if (!WorkingDir.empty() &&
1407 !sys::path::is_absolute(WorkingDir,sys::path::Style::posix) &&
1408 !sys::path::is_absolute(WorkingDir,
1409sys::path::Style::windows_backslash)) {
1410return std::error_code();
1411 }
1412sys::path::Style style =sys::path::Style::windows_backslash;
1413if (sys::path::is_absolute(WorkingDir,sys::path::Style::posix)) {
1414 style =sys::path::Style::posix;
1415 }else {
1416// Distinguish between windows_backslash and windows_slash; getExistingStyle
1417// returns posix for a path with windows_slash.
1418if (getExistingStyle(WorkingDir) !=sys::path::Style::windows_backslash)
1419 style =sys::path::Style::windows_slash;
1420 }
1421
1422 std::stringResult = std::string(WorkingDir);
1423StringRef Dir(Result);
1424if (!Dir.ends_with(sys::path::get_separator(style))) {
1425Result +=sys::path::get_separator(style);
1426 }
1427// backslashes '\' are legit path charactors under POSIX. Windows APIs
1428// like CreateFile accepts forward slashes '/' as path
1429// separator (even when mixed with backslashes). Therefore,
1430// `Path` should be directly appended to `WorkingDir` without converting
1431// path separator.
1432Result.append(Path.data(),Path.size());
1433Path.assign(Result.begin(),Result.end());
1434
1435return {};
1436}
1437
1438directory_iteratorRedirectingFileSystem::dir_begin(constTwine &Dir,
1439 std::error_code &EC) {
1440SmallString<256> Path;
1441 Dir.toVector(Path);
1442
1443 EC = makeAbsolute(Path);
1444if (EC)
1445return {};
1446
1447ErrorOr<RedirectingFileSystem::LookupResult> Result =lookupPath(Path);
1448if (!Result) {
1449if (Redirection !=RedirectKind::RedirectOnly &&
1450 isFileNotFound(Result.getError()))
1451return ExternalFS->dir_begin(Path, EC);
1452
1453 EC = Result.getError();
1454return {};
1455 }
1456
1457// Use status to make sure the path exists and refers to a directory.
1458ErrorOr<Status> S = status(Path, Dir, *Result);
1459if (!S) {
1460if (Redirection !=RedirectKind::RedirectOnly &&
1461 isFileNotFound(S.getError(), Result->E))
1462return ExternalFS->dir_begin(Dir, EC);
1463
1464 EC = S.getError();
1465return {};
1466 }
1467
1468if (!S->isDirectory()) {
1469 EC =errc::not_a_directory;
1470return {};
1471 }
1472
1473// Create the appropriate directory iterator based on whether we found a
1474// DirectoryRemapEntry or DirectoryEntry.
1475directory_iterator RedirectIter;
1476 std::error_code RedirectEC;
1477if (auto ExtRedirect = Result->getExternalRedirect()) {
1478auto RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
1479 RedirectIter = ExternalFS->dir_begin(*ExtRedirect, RedirectEC);
1480
1481if (!RE->useExternalName(UseExternalNames)) {
1482// Update the paths in the results to use the virtual directory's path.
1483 RedirectIter =
1484directory_iterator(std::make_shared<RedirectingFSDirRemapIterImpl>(
1485 std::string(Path), RedirectIter));
1486 }
1487 }else {
1488auto DE = cast<DirectoryEntry>(Result->E);
1489 RedirectIter =
1490directory_iterator(std::make_shared<RedirectingFSDirIterImpl>(
1491 Path, DE->contents_begin(), DE->contents_end(), RedirectEC));
1492 }
1493
1494if (RedirectEC) {
1495if (RedirectEC !=errc::no_such_file_or_directory) {
1496 EC = RedirectEC;
1497return {};
1498 }
1499 RedirectIter = {};
1500 }
1501
1502if (Redirection ==RedirectKind::RedirectOnly) {
1503 EC = RedirectEC;
1504return RedirectIter;
1505 }
1506
1507 std::error_code ExternalEC;
1508directory_iterator ExternalIter = ExternalFS->dir_begin(Path, ExternalEC);
1509if (ExternalEC) {
1510if (ExternalEC !=errc::no_such_file_or_directory) {
1511 EC = ExternalEC;
1512return {};
1513 }
1514 ExternalIter = {};
1515 }
1516
1517SmallVector<directory_iterator, 2> Iters;
1518switch (Redirection) {
1519caseRedirectKind::Fallthrough:
1520 Iters.push_back(ExternalIter);
1521 Iters.push_back(RedirectIter);
1522break;
1523caseRedirectKind::Fallback:
1524 Iters.push_back(RedirectIter);
1525 Iters.push_back(ExternalIter);
1526break;
1527default:
1528llvm_unreachable("unhandled RedirectKind");
1529 }
1530
1531directory_iterator Combined{
1532 std::make_shared<CombiningDirIterImpl>(Iters, EC)};
1533if (EC)
1534return {};
1535return Combined;
1536}
1537
1538voidRedirectingFileSystem::setOverlayFileDir(StringRef Dir) {
1539 OverlayFileDir = Dir.str();
1540}
1541
1542StringRefRedirectingFileSystem::getOverlayFileDir() const{
1543return OverlayFileDir;
1544}
1545
1546voidRedirectingFileSystem::setFallthrough(bool Fallthrough) {
1547if (Fallthrough) {
1548 Redirection =RedirectingFileSystem::RedirectKind::Fallthrough;
1549 }else {
1550 Redirection =RedirectingFileSystem::RedirectKind::RedirectOnly;
1551 }
1552}
1553
1554voidRedirectingFileSystem::setRedirection(
1555RedirectingFileSystem::RedirectKind Kind) {
1556 Redirection = Kind;
1557}
1558
1559std::vector<StringRef>RedirectingFileSystem::getRoots() const{
1560 std::vector<StringRef> R;
1561 R.reserve(Roots.size());
1562for (constauto &Root : Roots)
1563 R.push_back(Root->getName());
1564return R;
1565}
1566
1567voidRedirectingFileSystem::printImpl(raw_ostream &OS,PrintTypeType,
1568unsigned IndentLevel) const{
1569printIndent(OS, IndentLevel);
1570OS <<"RedirectingFileSystem (UseExternalNames: "
1571 << (UseExternalNames ?"true" :"false") <<")\n";
1572if (Type ==PrintType::Summary)
1573return;
1574
1575for (constauto &Root : Roots)
1576printEntry(OS, Root.get(), IndentLevel);
1577
1578printIndent(OS, IndentLevel);
1579OS <<"ExternalFS:\n";
1580 ExternalFS->print(OS,Type ==PrintType::Contents ?PrintType::Summary :Type,
1581 IndentLevel + 1);
1582}
1583
1584voidRedirectingFileSystem::printEntry(raw_ostream &OS,
1585RedirectingFileSystem::Entry *E,
1586unsigned IndentLevel) const{
1587printIndent(OS, IndentLevel);
1588OS <<"'" << E->getName() <<"'";
1589
1590switch (E->getKind()) {
1591caseEK_Directory: {
1592auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(E);
1593
1594OS <<"\n";
1595for (std::unique_ptr<Entry> &SubEntry :
1596llvm::make_range(DE->contents_begin(), DE->contents_end()))
1597printEntry(OS, SubEntry.get(), IndentLevel + 1);
1598break;
1599 }
1600caseEK_DirectoryRemap:
1601caseEK_File: {
1602auto *RE = cast<RedirectingFileSystem::RemapEntry>(E);
1603OS <<" -> '" << RE->getExternalContentsPath() <<"'";
1604switch (RE->getUseName()) {
1605caseNK_NotSet:
1606break;
1607caseNK_External:
1608OS <<" (UseExternalName: true)";
1609break;
1610caseNK_Virtual:
1611OS <<" (UseExternalName: false)";
1612break;
1613 }
1614OS <<"\n";
1615break;
1616 }
1617 }
1618}
1619
1620voidRedirectingFileSystem::visitChildFileSystems(VisitCallbackTy Callback) {
1621if (ExternalFS) {
1622 Callback(*ExternalFS);
1623 ExternalFS->visitChildFileSystems(Callback);
1624 }
1625}
1626
1627/// A helper class to hold the common YAML parsing state.
1628classllvm::vfs::RedirectingFileSystemParser {
1629yaml::Stream &Stream;
1630
1631voiderror(yaml::Node *N,constTwine &Msg) { Stream.printError(N, Msg); }
1632
1633// false on error
1634bool parseScalarString(yaml::Node *N,StringRef &Result,
1635SmallVectorImpl<char> &Storage) {
1636constauto *S = dyn_cast<yaml::ScalarNode>(N);
1637
1638if (!S) {
1639error(N,"expected string");
1640returnfalse;
1641 }
1642 Result = S->getValue(Storage);
1643returntrue;
1644 }
1645
1646// false on error
1647bool parseScalarBool(yaml::Node *N,bool &Result) {
1648SmallString<5> Storage;
1649StringRefValue;
1650if (!parseScalarString(N,Value, Storage))
1651returnfalse;
1652
1653if (Value.equals_insensitive("true") ||Value.equals_insensitive("on") ||
1654Value.equals_insensitive("yes") ||Value =="1") {
1655 Result =true;
1656returntrue;
1657 }elseif (Value.equals_insensitive("false") ||
1658Value.equals_insensitive("off") ||
1659Value.equals_insensitive("no") ||Value =="0") {
1660 Result =false;
1661returntrue;
1662 }
1663
1664error(N,"expected boolean value");
1665returnfalse;
1666 }
1667
1668 std::optional<RedirectingFileSystem::RedirectKind>
1669 parseRedirectKind(yaml::Node *N) {
1670SmallString<12> Storage;
1671StringRefValue;
1672if (!parseScalarString(N,Value, Storage))
1673return std::nullopt;
1674
1675if (Value.equals_insensitive("fallthrough")) {
1676returnRedirectingFileSystem::RedirectKind::Fallthrough;
1677 }elseif (Value.equals_insensitive("fallback")) {
1678returnRedirectingFileSystem::RedirectKind::Fallback;
1679 }elseif (Value.equals_insensitive("redirect-only")) {
1680returnRedirectingFileSystem::RedirectKind::RedirectOnly;
1681 }
1682return std::nullopt;
1683 }
1684
1685 std::optional<RedirectingFileSystem::RootRelativeKind>
1686 parseRootRelativeKind(yaml::Node *N) {
1687SmallString<12> Storage;
1688StringRefValue;
1689if (!parseScalarString(N,Value, Storage))
1690return std::nullopt;
1691if (Value.equals_insensitive("cwd")) {
1692returnRedirectingFileSystem::RootRelativeKind::CWD;
1693 }elseif (Value.equals_insensitive("overlay-dir")) {
1694returnRedirectingFileSystem::RootRelativeKind::OverlayDir;
1695 }
1696return std::nullopt;
1697 }
1698
1699structKeyStatus {
1700bool Required;
1701bool Seen =false;
1702
1703 KeyStatus(bool Required =false) : Required(Required) {}
1704 };
1705
1706usingKeyStatusPair = std::pair<StringRef, KeyStatus>;
1707
1708// false on error
1709bool checkDuplicateOrUnknownKey(yaml::Node *KeyNode,StringRef Key,
1710DenseMap<StringRef, KeyStatus> &Keys) {
1711auto It = Keys.find(Key);
1712if (It == Keys.end()) {
1713error(KeyNode,"unknown key");
1714returnfalse;
1715 }
1716 KeyStatus &S = It->second;
1717if (S.Seen) {
1718error(KeyNode,Twine("duplicate key '") + Key +"'");
1719returnfalse;
1720 }
1721 S.Seen =true;
1722returntrue;
1723 }
1724
1725// false on error
1726bool checkMissingKeys(yaml::Node *Obj,DenseMap<StringRef, KeyStatus> &Keys) {
1727for (constauto &I : Keys) {
1728if (I.second.Required && !I.second.Seen) {
1729error(Obj,Twine("missing key '") +I.first +"'");
1730returnfalse;
1731 }
1732 }
1733returntrue;
1734 }
1735
1736public:
1737staticRedirectingFileSystem::Entry *
1738lookupOrCreateEntry(RedirectingFileSystem *FS,StringRefName,
1739RedirectingFileSystem::Entry *ParentEntry =nullptr) {
1740if (!ParentEntry) {// Look for a existent root
1741for (constauto &Root : FS->Roots) {
1742if (Name == Root->getName()) {
1743 ParentEntry = Root.get();
1744return ParentEntry;
1745 }
1746 }
1747 }else {// Advance to the next component
1748auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1749for (std::unique_ptr<RedirectingFileSystem::Entry> &Content :
1750llvm::make_range(DE->contents_begin(), DE->contents_end())) {
1751auto *DirContent =
1752 dyn_cast<RedirectingFileSystem::DirectoryEntry>(Content.get());
1753if (DirContent &&Name ==Content->getName())
1754return DirContent;
1755 }
1756 }
1757
1758// ... or create a new one
1759 std::unique_ptr<RedirectingFileSystem::Entry> E =
1760 std::make_unique<RedirectingFileSystem::DirectoryEntry>(
1761Name,Status("",getNextVirtualUniqueID(),
1762 std::chrono::system_clock::now(), 0, 0, 0,
1763 file_type::directory_file,sys::fs::all_all));
1764
1765if (!ParentEntry) {// Add a new root to the overlay
1766 FS->Roots.push_back(std::move(E));
1767 ParentEntry = FS->Roots.back().get();
1768return ParentEntry;
1769 }
1770
1771auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(ParentEntry);
1772 DE->addContent(std::move(E));
1773return DE->getLastContent();
1774 }
1775
1776private:
1777void uniqueOverlayTree(RedirectingFileSystem *FS,
1778RedirectingFileSystem::Entry *SrcE,
1779RedirectingFileSystem::Entry *NewParentE =nullptr) {
1780StringRefName = SrcE->getName();
1781switch (SrcE->getKind()) {
1782caseRedirectingFileSystem::EK_Directory: {
1783auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
1784// Empty directories could be present in the YAML as a way to
1785// describe a file for a current directory after some of its subdir
1786// is parsed. This only leads to redundant walks, ignore it.
1787if (!Name.empty())
1788 NewParentE =lookupOrCreateEntry(FS,Name, NewParentE);
1789for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
1790llvm::make_range(DE->contents_begin(), DE->contents_end()))
1791 uniqueOverlayTree(FS, SubEntry.get(), NewParentE);
1792break;
1793 }
1794caseRedirectingFileSystem::EK_DirectoryRemap: {
1795assert(NewParentE &&"Parent entry must exist");
1796auto *DR = cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
1797auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1798 DE->addContent(
1799 std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
1800Name, DR->getExternalContentsPath(), DR->getUseName()));
1801break;
1802 }
1803caseRedirectingFileSystem::EK_File: {
1804assert(NewParentE &&"Parent entry must exist");
1805auto *FE = cast<RedirectingFileSystem::FileEntry>(SrcE);
1806auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(NewParentE);
1807 DE->addContent(std::make_unique<RedirectingFileSystem::FileEntry>(
1808Name, FE->getExternalContentsPath(), FE->getUseName()));
1809break;
1810 }
1811 }
1812 }
1813
1814 std::unique_ptr<RedirectingFileSystem::Entry>
1815 parseEntry(yaml::Node *N,RedirectingFileSystem *FS,bool IsRootEntry) {
1816auto *M = dyn_cast<yaml::MappingNode>(N);
1817if (!M) {
1818error(N,"expected mapping node for file or directory entry");
1819returnnullptr;
1820 }
1821
1822 KeyStatusPair Fields[] = {
1823 KeyStatusPair("name",true),
1824 KeyStatusPair("type",true),
1825 KeyStatusPair("contents",false),
1826 KeyStatusPair("external-contents",false),
1827 KeyStatusPair("use-external-name",false),
1828 };
1829
1830DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
1831
1832enum { CF_NotSet, CF_List, CF_External } ContentsField = CF_NotSet;
1833 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>>
1834 EntryArrayContents;
1835SmallString<256> ExternalContentsPath;
1836SmallString<256>Name;
1837yaml::Node *NameValueNode =nullptr;
1838auto UseExternalName =RedirectingFileSystem::NK_NotSet;
1839RedirectingFileSystem::EntryKindKind;
1840
1841for (auto &I : *M) {
1842StringRefKey;
1843// Reuse the buffer for key and value, since we don't look at key after
1844// parsing value.
1845SmallString<256> Buffer;
1846if (!parseScalarString(I.getKey(), Key, Buffer))
1847returnnullptr;
1848
1849if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
1850returnnullptr;
1851
1852StringRefValue;
1853if (Key =="name") {
1854if (!parseScalarString(I.getValue(),Value, Buffer))
1855returnnullptr;
1856
1857 NameValueNode =I.getValue();
1858// Guarantee that old YAML files containing paths with ".." and "."
1859// are properly canonicalized before read into the VFS.
1860Name = canonicalize(Value).str();
1861 }elseif (Key =="type") {
1862if (!parseScalarString(I.getValue(),Value, Buffer))
1863returnnullptr;
1864if (Value =="file")
1865Kind =RedirectingFileSystem::EK_File;
1866elseif (Value =="directory")
1867Kind =RedirectingFileSystem::EK_Directory;
1868elseif (Value =="directory-remap")
1869Kind =RedirectingFileSystem::EK_DirectoryRemap;
1870else {
1871error(I.getValue(),"unknown value for 'type'");
1872returnnullptr;
1873 }
1874 }elseif (Key =="contents") {
1875if (ContentsField != CF_NotSet) {
1876error(I.getKey(),
1877"entry already has 'contents' or 'external-contents'");
1878returnnullptr;
1879 }
1880 ContentsField = CF_List;
1881auto *Contents = dyn_cast<yaml::SequenceNode>(I.getValue());
1882if (!Contents) {
1883// FIXME: this is only for directories, what about files?
1884error(I.getValue(),"expected array");
1885returnnullptr;
1886 }
1887
1888for (auto &I : *Contents) {
1889if (std::unique_ptr<RedirectingFileSystem::Entry> E =
1890 parseEntry(&I, FS,/*IsRootEntry*/false))
1891 EntryArrayContents.push_back(std::move(E));
1892else
1893returnnullptr;
1894 }
1895 }elseif (Key =="external-contents") {
1896if (ContentsField != CF_NotSet) {
1897error(I.getKey(),
1898"entry already has 'contents' or 'external-contents'");
1899returnnullptr;
1900 }
1901 ContentsField = CF_External;
1902if (!parseScalarString(I.getValue(),Value, Buffer))
1903returnnullptr;
1904
1905SmallString<256> FullPath;
1906if (FS->IsRelativeOverlay) {
1907 FullPath =FS->getOverlayFileDir();
1908assert(!FullPath.empty() &&
1909"External contents prefix directory must exist");
1910llvm::sys::path::append(FullPath,Value);
1911 }else {
1912 FullPath =Value;
1913 }
1914
1915// Guarantee that old YAML files containing paths with ".." and "."
1916// are properly canonicalized before read into the VFS.
1917 FullPath = canonicalize(FullPath);
1918 ExternalContentsPath = FullPath.str();
1919 }elseif (Key =="use-external-name") {
1920bool Val;
1921if (!parseScalarBool(I.getValue(), Val))
1922returnnullptr;
1923 UseExternalName = Val ?RedirectingFileSystem::NK_External
1924 :RedirectingFileSystem::NK_Virtual;
1925 }else {
1926llvm_unreachable("key missing from Keys");
1927 }
1928 }
1929
1930if (Stream.failed())
1931returnnullptr;
1932
1933// check for missing keys
1934if (ContentsField == CF_NotSet) {
1935error(N,"missing key 'contents' or 'external-contents'");
1936returnnullptr;
1937 }
1938if (!checkMissingKeys(N, Keys))
1939returnnullptr;
1940
1941// check invalid configuration
1942if (Kind ==RedirectingFileSystem::EK_Directory &&
1943 UseExternalName !=RedirectingFileSystem::NK_NotSet) {
1944error(N,"'use-external-name' is not supported for 'directory' entries");
1945returnnullptr;
1946 }
1947
1948if (Kind ==RedirectingFileSystem::EK_DirectoryRemap &&
1949 ContentsField == CF_List) {
1950error(N,"'contents' is not supported for 'directory-remap' entries");
1951returnnullptr;
1952 }
1953
1954sys::path::Style path_style =sys::path::Style::native;
1955if (IsRootEntry) {
1956// VFS root entries may be in either Posix or Windows style. Figure out
1957// which style we have, and use it consistently.
1958if (sys::path::is_absolute(Name,sys::path::Style::posix)) {
1959 path_style =sys::path::Style::posix;
1960 }elseif (sys::path::is_absolute(Name,
1961sys::path::Style::windows_backslash)) {
1962 path_style =sys::path::Style::windows_backslash;
1963 }else {
1964// Relative VFS root entries are made absolute to either the overlay
1965// directory, or the current working directory, then we can determine
1966// the path style from that.
1967 std::error_codeEC;
1968if (FS->RootRelative ==
1969RedirectingFileSystem::RootRelativeKind::OverlayDir) {
1970StringRef FullPath =FS->getOverlayFileDir();
1971assert(!FullPath.empty() &&"Overlay file directory must exist");
1972EC =FS->makeAbsolute(FullPath,Name);
1973Name = canonicalize(Name);
1974 }else {
1975EC =sys::fs::make_absolute(Name);
1976 }
1977if (EC) {
1978assert(NameValueNode &&"Name presence should be checked earlier");
1979error(
1980 NameValueNode,
1981"entry with relative path at the root level is not discoverable");
1982returnnullptr;
1983 }
1984 path_style =sys::path::is_absolute(Name,sys::path::Style::posix)
1985 ?sys::path::Style::posix
1986 :sys::path::Style::windows_backslash;
1987 }
1988// is::path::is_absolute(Name, sys::path::Style::windows_backslash) will
1989// return true even if `Name` is using forward slashes. Distinguish
1990// between windows_backslash and windows_slash.
1991if (path_style ==sys::path::Style::windows_backslash &&
1992 getExistingStyle(Name) !=sys::path::Style::windows_backslash)
1993 path_style =sys::path::Style::windows_slash;
1994 }
1995
1996// Remove trailing slash(es), being careful not to remove the root path
1997StringRef Trimmed =Name;
1998size_t RootPathLen =sys::path::root_path(Trimmed, path_style).size();
1999while (Trimmed.size() > RootPathLen &&
2000sys::path::is_separator(Trimmed.back(), path_style))
2001 Trimmed = Trimmed.slice(0, Trimmed.size() - 1);
2002
2003// Get the last component
2004StringRef LastComponent =sys::path::filename(Trimmed, path_style);
2005
2006 std::unique_ptr<RedirectingFileSystem::Entry>Result;
2007switch (Kind) {
2008caseRedirectingFileSystem::EK_File:
2009Result = std::make_unique<RedirectingFileSystem::FileEntry>(
2010 LastComponent, std::move(ExternalContentsPath), UseExternalName);
2011break;
2012caseRedirectingFileSystem::EK_DirectoryRemap:
2013Result = std::make_unique<RedirectingFileSystem::DirectoryRemapEntry>(
2014 LastComponent, std::move(ExternalContentsPath), UseExternalName);
2015break;
2016caseRedirectingFileSystem::EK_Directory:
2017Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
2018 LastComponent, std::move(EntryArrayContents),
2019Status("",getNextVirtualUniqueID(), std::chrono::system_clock::now(),
2020 0, 0, 0, file_type::directory_file,sys::fs::all_all));
2021break;
2022 }
2023
2024StringRef Parent =sys::path::parent_path(Trimmed, path_style);
2025if (Parent.empty())
2026returnResult;
2027
2028// if 'name' contains multiple components, create implicit directory entries
2029for (sys::path::reverse_iteratorI =sys::path::rbegin(Parent, path_style),
2030 E =sys::path::rend(Parent);
2031I != E; ++I) {
2032 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> Entries;
2033 Entries.push_back(std::move(Result));
2034Result = std::make_unique<RedirectingFileSystem::DirectoryEntry>(
2035 *I, std::move(Entries),
2036Status("",getNextVirtualUniqueID(), std::chrono::system_clock::now(),
2037 0, 0, 0, file_type::directory_file,sys::fs::all_all));
2038 }
2039returnResult;
2040 }
2041
2042public:
2043RedirectingFileSystemParser(yaml::Stream &S) : Stream(S) {}
2044
2045// false on error
2046boolparse(yaml::Node *Root,RedirectingFileSystem *FS) {
2047auto *Top = dyn_cast<yaml::MappingNode>(Root);
2048if (!Top) {
2049error(Root,"expected mapping node");
2050returnfalse;
2051 }
2052
2053 KeyStatusPair Fields[] = {
2054 KeyStatusPair("version",true),
2055 KeyStatusPair("case-sensitive",false),
2056 KeyStatusPair("use-external-names",false),
2057 KeyStatusPair("root-relative",false),
2058 KeyStatusPair("overlay-relative",false),
2059 KeyStatusPair("fallthrough",false),
2060 KeyStatusPair("redirecting-with",false),
2061 KeyStatusPair("roots",true),
2062 };
2063
2064DenseMap<StringRef, KeyStatus> Keys(std::begin(Fields), std::end(Fields));
2065 std::vector<std::unique_ptr<RedirectingFileSystem::Entry>> RootEntries;
2066
2067// Parse configuration and 'roots'
2068for (auto &I : *Top) {
2069SmallString<10> KeyBuffer;
2070StringRef Key;
2071if (!parseScalarString(I.getKey(), Key, KeyBuffer))
2072returnfalse;
2073
2074if (!checkDuplicateOrUnknownKey(I.getKey(), Key, Keys))
2075returnfalse;
2076
2077if (Key =="roots") {
2078auto *Roots = dyn_cast<yaml::SequenceNode>(I.getValue());
2079if (!Roots) {
2080error(I.getValue(),"expected array");
2081returnfalse;
2082 }
2083
2084for (auto &I : *Roots) {
2085if (std::unique_ptr<RedirectingFileSystem::Entry> E =
2086 parseEntry(&I, FS,/*IsRootEntry*/true))
2087 RootEntries.push_back(std::move(E));
2088else
2089returnfalse;
2090 }
2091 }elseif (Key =="version") {
2092StringRef VersionString;
2093SmallString<4> Storage;
2094if (!parseScalarString(I.getValue(), VersionString, Storage))
2095returnfalse;
2096intVersion;
2097if (VersionString.getAsInteger<int>(10,Version)) {
2098error(I.getValue(),"expected integer");
2099returnfalse;
2100 }
2101if (Version < 0) {
2102error(I.getValue(),"invalid version number");
2103returnfalse;
2104 }
2105if (Version != 0) {
2106error(I.getValue(),"version mismatch, expected 0");
2107returnfalse;
2108 }
2109 }elseif (Key =="case-sensitive") {
2110if (!parseScalarBool(I.getValue(), FS->CaseSensitive))
2111returnfalse;
2112 }elseif (Key =="overlay-relative") {
2113if (!parseScalarBool(I.getValue(), FS->IsRelativeOverlay))
2114returnfalse;
2115 }elseif (Key =="use-external-names") {
2116if (!parseScalarBool(I.getValue(), FS->UseExternalNames))
2117returnfalse;
2118 }elseif (Key =="fallthrough") {
2119if (Keys["redirecting-with"].Seen) {
2120error(I.getValue(),
2121"'fallthrough' and 'redirecting-with' are mutually exclusive");
2122returnfalse;
2123 }
2124
2125bool ShouldFallthrough =false;
2126if (!parseScalarBool(I.getValue(), ShouldFallthrough))
2127returnfalse;
2128
2129if (ShouldFallthrough) {
2130 FS->Redirection =RedirectingFileSystem::RedirectKind::Fallthrough;
2131 }else {
2132 FS->Redirection =RedirectingFileSystem::RedirectKind::RedirectOnly;
2133 }
2134 }elseif (Key =="redirecting-with") {
2135if (Keys["fallthrough"].Seen) {
2136error(I.getValue(),
2137"'fallthrough' and 'redirecting-with' are mutually exclusive");
2138returnfalse;
2139 }
2140
2141if (auto Kind = parseRedirectKind(I.getValue())) {
2142 FS->Redirection = *Kind;
2143 }else {
2144error(I.getValue(),"expected valid redirect kind");
2145returnfalse;
2146 }
2147 }elseif (Key =="root-relative") {
2148if (auto Kind = parseRootRelativeKind(I.getValue())) {
2149 FS->RootRelative = *Kind;
2150 }else {
2151error(I.getValue(),"expected valid root-relative kind");
2152returnfalse;
2153 }
2154 }else {
2155llvm_unreachable("key missing from Keys");
2156 }
2157 }
2158
2159if (Stream.failed())
2160returnfalse;
2161
2162if (!checkMissingKeys(Top, Keys))
2163returnfalse;
2164
2165// Now that we sucessefully parsed the YAML file, canonicalize the internal
2166// representation to a proper directory tree so that we can search faster
2167// inside the VFS.
2168for (auto &E : RootEntries)
2169 uniqueOverlayTree(FS, E.get());
2170
2171returntrue;
2172 }
2173};
2174
2175std::unique_ptr<RedirectingFileSystem>
2176RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer,
2177SourceMgr::DiagHandlerTyDiagHandler,
2178StringRef YAMLFilePath,void *DiagContext,
2179IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2180SourceMgr SM;
2181yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
2182
2183 SM.setDiagHandler(DiagHandler, DiagContext);
2184yaml::document_iterator DI = Stream.begin();
2185yaml::Node *Root = DI->getRoot();
2186if (DI == Stream.end() || !Root) {
2187 SM.PrintMessage(SMLoc(),SourceMgr::DK_Error,"expected root node");
2188returnnullptr;
2189 }
2190
2191RedirectingFileSystemParserP(Stream);
2192
2193 std::unique_ptr<RedirectingFileSystem> FS(
2194newRedirectingFileSystem(ExternalFS));
2195
2196if (!YAMLFilePath.empty()) {
2197// Use the YAML path from -ivfsoverlay to compute the dir to be prefixed
2198// to each 'external-contents' path.
2199//
2200// Example:
2201// -ivfsoverlay dummy.cache/vfs/vfs.yaml
2202// yields:
2203// FS->OverlayFileDir => /<absolute_path_to>/dummy.cache/vfs
2204//
2205SmallString<256> OverlayAbsDir =sys::path::parent_path(YAMLFilePath);
2206 std::error_code EC =llvm::sys::fs::make_absolute(OverlayAbsDir);
2207assert(!EC &&"Overlay dir final path must be absolute");
2208 (void)EC;
2209 FS->setOverlayFileDir(OverlayAbsDir);
2210 }
2211
2212if (!P.parse(Root, FS.get()))
2213returnnullptr;
2214
2215return FS;
2216}
2217
2218std::unique_ptr<RedirectingFileSystem>RedirectingFileSystem::create(
2219ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
2220bool UseExternalNames,FileSystem &ExternalFS) {
2221 std::unique_ptr<RedirectingFileSystem> FS(
2222newRedirectingFileSystem(&ExternalFS));
2223 FS->UseExternalNames = UseExternalNames;
2224
2225StringMap<RedirectingFileSystem::Entry *> Entries;
2226
2227for (auto &Mapping :llvm::reverse(RemappedFiles)) {
2228SmallString<128>From =StringRef(Mapping.first);
2229SmallString<128> To =StringRef(Mapping.second);
2230 {
2231auto EC = ExternalFS.makeAbsolute(From);
2232 (void)EC;
2233assert(!EC &&"Could not make absolute path");
2234 }
2235
2236// Check if we've already mapped this file. The first one we see (in the
2237// reverse iteration) wins.
2238RedirectingFileSystem::Entry *&ToEntry = Entries[From];
2239if (ToEntry)
2240continue;
2241
2242// Add parent directories.
2243RedirectingFileSystem::Entry *Parent =nullptr;
2244StringRef FromDirectory =llvm::sys::path::parent_path(From);
2245for (autoI =llvm::sys::path::begin(FromDirectory),
2246 E =llvm::sys::path::end(FromDirectory);
2247I != E; ++I) {
2248 Parent =RedirectingFileSystemParser::lookupOrCreateEntry(FS.get(), *I,
2249 Parent);
2250 }
2251assert(Parent &&"File without a directory?");
2252 {
2253auto EC = ExternalFS.makeAbsolute(To);
2254 (void)EC;
2255assert(!EC &&"Could not make absolute path");
2256 }
2257
2258// Add the file.
2259auto NewFile = std::make_unique<RedirectingFileSystem::FileEntry>(
2260llvm::sys::path::filename(From), To,
2261 UseExternalNames ?RedirectingFileSystem::NK_External
2262 :RedirectingFileSystem::NK_Virtual);
2263 ToEntry = NewFile.get();
2264 cast<RedirectingFileSystem::DirectoryEntry>(Parent)->addContent(
2265 std::move(NewFile));
2266 }
2267
2268return FS;
2269}
2270
2271RedirectingFileSystem::LookupResult::LookupResult(
2272Entry *E,sys::path::const_iterator Start,sys::path::const_iteratorEnd)
2273 : E(E) {
2274assert(E !=nullptr);
2275// If the matched entry is a DirectoryRemapEntry, set ExternalRedirect to the
2276// path of the directory it maps to in the external file system plus any
2277// remaining path components in the provided iterator.
2278if (auto *DRE = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(E)) {
2279SmallString<256> Redirect(DRE->getExternalContentsPath());
2280sys::path::append(Redirect, Start,End,
2281 getExistingStyle(DRE->getExternalContentsPath()));
2282 ExternalRedirect = std::string(Redirect);
2283 }
2284}
2285
2286voidRedirectingFileSystem::LookupResult::getPath(
2287llvm::SmallVectorImpl<char> &Result) const{
2288 Result.clear();
2289for (Entry *Parent : Parents)
2290llvm::sys::path::append(Result, Parent->getName());
2291llvm::sys::path::append(Result, E->getName());
2292}
2293
2294std::error_code RedirectingFileSystem::makeCanonicalForLookup(
2295SmallVectorImpl<char> &Path) const{
2296if (std::error_code EC = makeAbsolute(Path))
2297return EC;
2298
2299llvm::SmallString<256> CanonicalPath =
2300 canonicalize(StringRef(Path.data(), Path.size()));
2301if (CanonicalPath.empty())
2302returnmake_error_code(llvm::errc::invalid_argument);
2303
2304 Path.assign(CanonicalPath.begin(), CanonicalPath.end());
2305return {};
2306}
2307
2308ErrorOr<RedirectingFileSystem::LookupResult>
2309RedirectingFileSystem::lookupPath(StringRef Path) const{
2310llvm::SmallString<128> CanonicalPath(Path);
2311if (std::error_code EC = makeCanonicalForLookup(CanonicalPath))
2312return EC;
2313
2314// RedirectOnly means the VFS is always used.
2315if (UsageTrackingActive && Redirection ==RedirectKind::RedirectOnly)
2316 HasBeenUsed =true;
2317
2318sys::path::const_iterator Start =sys::path::begin(CanonicalPath);
2319sys::path::const_iteratorEnd =sys::path::end(CanonicalPath);
2320llvm::SmallVector<Entry *, 32> Entries;
2321for (constauto &Root : Roots) {
2322ErrorOr<RedirectingFileSystem::LookupResult> Result =
2323 lookupPathImpl(Start,End, Root.get(), Entries);
2324if (UsageTrackingActive && Result && isa<RemapEntry>(Result->E))
2325 HasBeenUsed =true;
2326if (Result || Result.getError() !=llvm::errc::no_such_file_or_directory) {
2327 Result->Parents = std::move(Entries);
2328return Result;
2329 }
2330 }
2331returnmake_error_code(llvm::errc::no_such_file_or_directory);
2332}
2333
2334ErrorOr<RedirectingFileSystem::LookupResult>
2335RedirectingFileSystem::lookupPathImpl(
2336sys::path::const_iterator Start,sys::path::const_iteratorEnd,
2337RedirectingFileSystem::Entry *From,
2338llvm::SmallVectorImpl<Entry *> &Entries) const{
2339assert(!isTraversalComponent(*Start) &&
2340 !isTraversalComponent(From->getName()) &&
2341"Paths should not contain traversal components");
2342
2343StringRef FromName =From->getName();
2344
2345// Forward the search to the next component in case this is an empty one.
2346if (!FromName.empty()) {
2347if (!pathComponentMatches(*Start, FromName))
2348returnmake_error_code(llvm::errc::no_such_file_or_directory);
2349
2350 ++Start;
2351
2352if (Start ==End) {
2353// Match!
2354return LookupResult(From, Start,End);
2355 }
2356 }
2357
2358if (isa<RedirectingFileSystem::FileEntry>(From))
2359returnmake_error_code(llvm::errc::not_a_directory);
2360
2361if (isa<RedirectingFileSystem::DirectoryRemapEntry>(From))
2362return LookupResult(From, Start,End);
2363
2364auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(From);
2365for (const std::unique_ptr<RedirectingFileSystem::Entry> &DirEntry :
2366llvm::make_range(DE->contents_begin(), DE->contents_end())) {
2367 Entries.push_back(From);
2368ErrorOr<RedirectingFileSystem::LookupResult> Result =
2369 lookupPathImpl(Start,End, DirEntry.get(), Entries);
2370if (Result || Result.getError() !=llvm::errc::no_such_file_or_directory)
2371return Result;
2372 Entries.pop_back();
2373 }
2374
2375returnmake_error_code(llvm::errc::no_such_file_or_directory);
2376}
2377
2378staticStatusgetRedirectedFileStatus(constTwine &OriginalPath,
2379bool UseExternalNames,
2380Status ExternalStatus) {
2381// The path has been mapped by some nested VFS and exposes an external path,
2382// don't override it with the original path.
2383if (ExternalStatus.ExposesExternalVFSPath)
2384return ExternalStatus;
2385
2386Status S = ExternalStatus;
2387if (!UseExternalNames)
2388 S =Status::copyWithNewName(S, OriginalPath);
2389else
2390 S.ExposesExternalVFSPath =true;
2391return S;
2392}
2393
2394ErrorOr<Status> RedirectingFileSystem::status(
2395constTwine &LookupPath,constTwine &OriginalPath,
2396constRedirectingFileSystem::LookupResult &Result) {
2397if (std::optional<StringRef> ExtRedirect =Result.getExternalRedirect()) {
2398SmallString<256> RemappedPath((*ExtRedirect).str());
2399if (std::error_code EC = makeAbsolute(RemappedPath))
2400returnEC;
2401
2402ErrorOr<Status> S = ExternalFS->status(RemappedPath);
2403if (!S)
2404return S;
2405 S =Status::copyWithNewName(*S, *ExtRedirect);
2406auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result.E);
2407returngetRedirectedFileStatus(OriginalPath,
2408 RE->useExternalName(UseExternalNames), *S);
2409 }
2410
2411auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(Result.E);
2412returnStatus::copyWithNewName(DE->getStatus(), LookupPath);
2413}
2414
2415ErrorOr<Status>
2416RedirectingFileSystem::getExternalStatus(constTwine &LookupPath,
2417constTwine &OriginalPath) const{
2418autoResult = ExternalFS->status(LookupPath);
2419
2420// The path has been mapped by some nested VFS, don't override it with the
2421// original path.
2422if (!Result ||Result->ExposesExternalVFSPath)
2423returnResult;
2424returnStatus::copyWithNewName(Result.get(), OriginalPath);
2425}
2426
2427ErrorOr<Status> RedirectingFileSystem::status(constTwine &OriginalPath) {
2428SmallString<256> Path;
2429 OriginalPath.toVector(Path);
2430
2431if (std::error_code EC = makeAbsolute(Path))
2432return EC;
2433
2434if (Redirection ==RedirectKind::Fallback) {
2435// Attempt to find the original file first, only falling back to the
2436// mapped file if that fails.
2437ErrorOr<Status> S = getExternalStatus(Path, OriginalPath);
2438if (S)
2439return S;
2440 }
2441
2442ErrorOr<RedirectingFileSystem::LookupResult> Result =lookupPath(Path);
2443if (!Result) {
2444// Was not able to map file, fallthrough to using the original path if
2445// that was the specified redirection type.
2446if (Redirection ==RedirectKind::Fallthrough &&
2447 isFileNotFound(Result.getError()))
2448return getExternalStatus(Path, OriginalPath);
2449return Result.getError();
2450 }
2451
2452ErrorOr<Status> S = status(Path, OriginalPath, *Result);
2453if (!S && Redirection ==RedirectKind::Fallthrough &&
2454 isFileNotFound(S.getError(), Result->E)) {
2455// Mapped the file but it wasn't found in the underlying filesystem,
2456// fallthrough to using the original path if that was the specified
2457// redirection type.
2458return getExternalStatus(Path, OriginalPath);
2459 }
2460
2461return S;
2462}
2463
2464boolRedirectingFileSystem::exists(constTwine &OriginalPath) {
2465SmallString<256> Path;
2466 OriginalPath.toVector(Path);
2467
2468if (makeAbsolute(Path))
2469returnfalse;
2470
2471if (Redirection ==RedirectKind::Fallback) {
2472// Attempt to find the original file first, only falling back to the
2473// mapped file if that fails.
2474if (ExternalFS->exists(Path))
2475returntrue;
2476 }
2477
2478ErrorOr<RedirectingFileSystem::LookupResult> Result =lookupPath(Path);
2479if (!Result) {
2480// Was not able to map file, fallthrough to using the original path if
2481// that was the specified redirection type.
2482if (Redirection ==RedirectKind::Fallthrough &&
2483 isFileNotFound(Result.getError()))
2484return ExternalFS->exists(Path);
2485returnfalse;
2486 }
2487
2488 std::optional<StringRef> ExtRedirect = Result->getExternalRedirect();
2489if (!ExtRedirect) {
2490assert(isa<RedirectingFileSystem::DirectoryEntry>(Result->E));
2491returntrue;
2492 }
2493
2494SmallString<256> RemappedPath((*ExtRedirect).str());
2495if (makeAbsolute(RemappedPath))
2496returnfalse;
2497
2498if (ExternalFS->exists(RemappedPath))
2499returntrue;
2500
2501if (Redirection ==RedirectKind::Fallthrough) {
2502// Mapped the file but it wasn't found in the underlying filesystem,
2503// fallthrough to using the original path if that was the specified
2504// redirection type.
2505return ExternalFS->exists(Path);
2506 }
2507
2508returnfalse;
2509}
2510
2511namespace{
2512
2513/// Provide a file wrapper with an overriden status.
2514classFileWithFixedStatus :publicFile {
2515 std::unique_ptr<File> InnerFile;
2516Status S;
2517
2518public:
2519 FileWithFixedStatus(std::unique_ptr<File> InnerFile,Status S)
2520 : InnerFile(std::move(InnerFile)), S(std::move(S)) {}
2521
2522ErrorOr<Status> status() override{return S; }
2523ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
2524
2525 getBuffer(constTwine &Name, int64_t FileSize,bool RequiresNullTerminator,
2526bool IsVolatile) override{
2527return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
2528 IsVolatile);
2529 }
2530
2531 std::error_code close() override{return InnerFile->close(); }
2532
2533void setPath(constTwine &Path) override{ S = S.copyWithNewName(S, Path); }
2534};
2535
2536}// namespace
2537
2538ErrorOr<std::unique_ptr<File>>
2539File::getWithPath(ErrorOr<std::unique_ptr<File>> Result,constTwine &P) {
2540// See \c getRedirectedFileStatus - don't update path if it's exposing an
2541// external path.
2542if (!Result || (*Result)->status()->ExposesExternalVFSPath)
2543return Result;
2544
2545ErrorOr<std::unique_ptr<File>>F = std::move(*Result);
2546autoName =F->get()->getName();
2547if (Name &&Name.get() !=P.str())
2548F->get()->setPath(P);
2549returnF;
2550}
2551
2552ErrorOr<std::unique_ptr<File>>
2553RedirectingFileSystem::openFileForRead(constTwine &OriginalPath) {
2554SmallString<256> Path;
2555 OriginalPath.toVector(Path);
2556
2557if (std::error_code EC = makeAbsolute(Path))
2558return EC;
2559
2560if (Redirection ==RedirectKind::Fallback) {
2561// Attempt to find the original file first, only falling back to the
2562// mapped file if that fails.
2563autoF =File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
2564if (F)
2565returnF;
2566 }
2567
2568ErrorOr<RedirectingFileSystem::LookupResult> Result =lookupPath(Path);
2569if (!Result) {
2570// Was not able to map file, fallthrough to using the original path if
2571// that was the specified redirection type.
2572if (Redirection ==RedirectKind::Fallthrough &&
2573 isFileNotFound(Result.getError()))
2574returnFile::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
2575return Result.getError();
2576 }
2577
2578if (!Result->getExternalRedirect())// FIXME: errc::not_a_file?
2579returnmake_error_code(llvm::errc::invalid_argument);
2580
2581StringRef ExtRedirect = *Result->getExternalRedirect();
2582SmallString<256> RemappedPath(ExtRedirect.str());
2583if (std::error_code EC = makeAbsolute(RemappedPath))
2584return EC;
2585
2586auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E);
2587
2588auto ExternalFile =
2589File::getWithPath(ExternalFS->openFileForRead(RemappedPath), ExtRedirect);
2590if (!ExternalFile) {
2591if (Redirection ==RedirectKind::Fallthrough &&
2592 isFileNotFound(ExternalFile.getError(), Result->E)) {
2593// Mapped the file but it wasn't found in the underlying filesystem,
2594// fallthrough to using the original path if that was the specified
2595// redirection type.
2596returnFile::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath);
2597 }
2598return ExternalFile;
2599 }
2600
2601auto ExternalStatus = (*ExternalFile)->status();
2602if (!ExternalStatus)
2603return ExternalStatus.getError();
2604
2605// Otherwise, the file was successfully remapped. Mark it as such. Also
2606// replace the underlying path if the external name is being used.
2607Status S =getRedirectedFileStatus(
2608 OriginalPath, RE->useExternalName(UseExternalNames), *ExternalStatus);
2609return std::unique_ptr<File>(
2610 std::make_unique<FileWithFixedStatus>(std::move(*ExternalFile), S));
2611}
2612
2613std::error_code
2614RedirectingFileSystem::getRealPath(constTwine &OriginalPath,
2615SmallVectorImpl<char> &Output) {
2616SmallString<256> Path;
2617 OriginalPath.toVector(Path);
2618
2619if (std::error_code EC = makeAbsolute(Path))
2620return EC;
2621
2622if (Redirection ==RedirectKind::Fallback) {
2623// Attempt to find the original file first, only falling back to the
2624// mapped file if that fails.
2625 std::error_code EC = ExternalFS->getRealPath(Path, Output);
2626if (!EC)
2627return EC;
2628 }
2629
2630ErrorOr<RedirectingFileSystem::LookupResult> Result =lookupPath(Path);
2631if (!Result) {
2632// Was not able to map file, fallthrough to using the original path if
2633// that was the specified redirection type.
2634if (Redirection ==RedirectKind::Fallthrough &&
2635 isFileNotFound(Result.getError()))
2636return ExternalFS->getRealPath(Path, Output);
2637return Result.getError();
2638 }
2639
2640// If we found FileEntry or DirectoryRemapEntry, look up the mapped
2641// path in the external file system.
2642if (auto ExtRedirect = Result->getExternalRedirect()) {
2643autoP = ExternalFS->getRealPath(*ExtRedirect, Output);
2644if (P && Redirection ==RedirectKind::Fallthrough &&
2645 isFileNotFound(P, Result->E)) {
2646// Mapped the file but it wasn't found in the underlying filesystem,
2647// fallthrough to using the original path if that was the specified
2648// redirection type.
2649return ExternalFS->getRealPath(Path, Output);
2650 }
2651returnP;
2652 }
2653
2654// We found a DirectoryEntry, which does not have a single external contents
2655// path. Use the canonical virtual path.
2656if (Redirection ==RedirectKind::Fallthrough) {
2657 Result->getPath(Output);
2658return {};
2659 }
2660returnllvm::errc::invalid_argument;
2661}
2662
2663std::unique_ptr<FileSystem>
2664vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
2665SourceMgr::DiagHandlerTyDiagHandler,
2666StringRef YAMLFilePath,void *DiagContext,
2667IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2668returnRedirectingFileSystem::create(std::move(Buffer),DiagHandler,
2669 YAMLFilePath, DiagContext,
2670 std::move(ExternalFS));
2671}
2672
2673staticvoidgetVFSEntries(RedirectingFileSystem::Entry *SrcE,
2674SmallVectorImpl<StringRef> &Path,
2675SmallVectorImpl<YAMLVFSEntry> &Entries) {
2676auto Kind = SrcE->getKind();
2677if (Kind ==RedirectingFileSystem::EK_Directory) {
2678auto *DE = dyn_cast<RedirectingFileSystem::DirectoryEntry>(SrcE);
2679assert(DE &&"Must be a directory");
2680for (std::unique_ptr<RedirectingFileSystem::Entry> &SubEntry :
2681llvm::make_range(DE->contents_begin(), DE->contents_end())) {
2682 Path.push_back(SubEntry->getName());
2683getVFSEntries(SubEntry.get(), Path, Entries);
2684 Path.pop_back();
2685 }
2686return;
2687 }
2688
2689if (Kind ==RedirectingFileSystem::EK_DirectoryRemap) {
2690auto *DR = dyn_cast<RedirectingFileSystem::DirectoryRemapEntry>(SrcE);
2691assert(DR &&"Must be a directory remap");
2692SmallString<128> VPath;
2693for (auto &Comp : Path)
2694llvm::sys::path::append(VPath, Comp);
2695 Entries.push_back(
2696YAMLVFSEntry(VPath.c_str(), DR->getExternalContentsPath()));
2697return;
2698 }
2699
2700assert(Kind ==RedirectingFileSystem::EK_File &&"Must be a EK_File");
2701auto *FE = dyn_cast<RedirectingFileSystem::FileEntry>(SrcE);
2702assert(FE &&"Must be a file");
2703SmallString<128> VPath;
2704for (auto &Comp : Path)
2705llvm::sys::path::append(VPath, Comp);
2706 Entries.push_back(YAMLVFSEntry(VPath.c_str(), FE->getExternalContentsPath()));
2707}
2708
2709voidvfs::collectVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer,
2710SourceMgr::DiagHandlerTyDiagHandler,
2711StringRef YAMLFilePath,
2712SmallVectorImpl<YAMLVFSEntry> &CollectedEntries,
2713void *DiagContext,
2714IntrusiveRefCntPtr<FileSystem> ExternalFS) {
2715 std::unique_ptr<RedirectingFileSystem> VFS =RedirectingFileSystem::create(
2716 std::move(Buffer),DiagHandler, YAMLFilePath, DiagContext,
2717 std::move(ExternalFS));
2718if (!VFS)
2719return;
2720ErrorOr<RedirectingFileSystem::LookupResult> RootResult =
2721 VFS->lookupPath("/");
2722if (!RootResult)
2723return;
2724SmallVector<StringRef, 8> Components;
2725 Components.push_back("/");
2726getVFSEntries(RootResult->E, Components, CollectedEntries);
2727}
2728
2729UniqueIDvfs::getNextVirtualUniqueID() {
2730static std::atomic<unsigned> UID;
2731unsignedID = ++UID;
2732// The following assumes that uint64_t max will never collide with a real
2733// dev_t value from the OS.
2734returnUniqueID(std::numeric_limits<uint64_t>::max(),ID);
2735}
2736
2737void YAMLVFSWriter::addEntry(StringRef VirtualPath,StringRef RealPath,
2738bool IsDirectory) {
2739assert(sys::path::is_absolute(VirtualPath) &&"virtual path not absolute");
2740assert(sys::path::is_absolute(RealPath) &&"real path not absolute");
2741assert(!pathHasTraversal(VirtualPath) &&"path traversal is not supported");
2742 Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
2743}
2744
2745voidYAMLVFSWriter::addFileMapping(StringRef VirtualPath,StringRef RealPath) {
2746 addEntry(VirtualPath, RealPath,/*IsDirectory=*/false);
2747}
2748
2749voidYAMLVFSWriter::addDirectoryMapping(StringRef VirtualPath,
2750StringRef RealPath) {
2751 addEntry(VirtualPath, RealPath,/*IsDirectory=*/true);
2752}
2753
2754namespace{
2755
2756classJSONWriter {
2757llvm::raw_ostream &OS;
2758SmallVector<StringRef, 16> DirStack;
2759
2760unsigned getDirIndent() {return 4 * DirStack.size(); }
2761unsigned getFileIndent() {return 4 * (DirStack.size() + 1); }
2762bool containedIn(StringRef Parent,StringRef Path);
2763StringRef containedPart(StringRef Parent,StringRef Path);
2764void startDirectory(StringRef Path);
2765void endDirectory();
2766void writeEntry(StringRef VPath,StringRef RPath);
2767
2768public:
2769 JSONWriter(llvm::raw_ostream &OS) :OS(OS) {}
2770
2771voidwrite(ArrayRef<YAMLVFSEntry> Entries,
2772 std::optional<bool> UseExternalNames,
2773 std::optional<bool> IsCaseSensitive,
2774 std::optional<bool> IsOverlayRelative,StringRef OverlayDir);
2775};
2776
2777}// namespace
2778
2779bool JSONWriter::containedIn(StringRef Parent,StringRef Path) {
2780using namespacellvm::sys;
2781
2782// Compare each path component.
2783auto IParent =path::begin(Parent), EParent =path::end(Parent);
2784for (auto IChild =path::begin(Path), EChild =path::end(Path);
2785 IParent != EParent && IChild != EChild; ++IParent, ++IChild) {
2786if (*IParent != *IChild)
2787returnfalse;
2788 }
2789// Have we exhausted the parent path?
2790return IParent == EParent;
2791}
2792
2793StringRef JSONWriter::containedPart(StringRef Parent,StringRef Path) {
2794assert(!Parent.empty());
2795assert(containedIn(Parent, Path));
2796returnPath.substr(Parent.size() + 1);
2797}
2798
2799void JSONWriter::startDirectory(StringRef Path) {
2800StringRefName =
2801 DirStack.empty() ?Path : containedPart(DirStack.back(), Path);
2802 DirStack.push_back(Path);
2803unsigned Indent = getDirIndent();
2804OS.indent(Indent) <<"{\n";
2805OS.indent(Indent + 2) <<"'type': 'directory',\n";
2806OS.indent(Indent + 2) <<"'name': \"" <<llvm::yaml::escape(Name) <<"\",\n";
2807OS.indent(Indent + 2) <<"'contents': [\n";
2808}
2809
2810void JSONWriter::endDirectory() {
2811unsigned Indent = getDirIndent();
2812OS.indent(Indent + 2) <<"]\n";
2813OS.indent(Indent) <<"}";
2814
2815 DirStack.pop_back();
2816}
2817
2818void JSONWriter::writeEntry(StringRef VPath,StringRef RPath) {
2819unsigned Indent = getFileIndent();
2820OS.indent(Indent) <<"{\n";
2821OS.indent(Indent + 2) <<"'type': 'file',\n";
2822OS.indent(Indent + 2) <<"'name': \"" <<llvm::yaml::escape(VPath) <<"\",\n";
2823OS.indent(Indent + 2) <<"'external-contents': \""
2824 <<llvm::yaml::escape(RPath) <<"\"\n";
2825OS.indent(Indent) <<"}";
2826}
2827
2828void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries,
2829 std::optional<bool> UseExternalNames,
2830 std::optional<bool> IsCaseSensitive,
2831 std::optional<bool> IsOverlayRelative,
2832StringRefOverlayDir) {
2833using namespacellvm::sys;
2834
2835OS <<"{\n"
2836" 'version': 0,\n";
2837if (IsCaseSensitive)
2838OS <<" 'case-sensitive': '" << (*IsCaseSensitive ?"true" :"false")
2839 <<"',\n";
2840if (UseExternalNames)
2841OS <<" 'use-external-names': '" << (*UseExternalNames ?"true" :"false")
2842 <<"',\n";
2843bool UseOverlayRelative =false;
2844if (IsOverlayRelative) {
2845 UseOverlayRelative = *IsOverlayRelative;
2846OS <<" 'overlay-relative': '" << (UseOverlayRelative ?"true" :"false")
2847 <<"',\n";
2848 }
2849OS <<" 'roots': [\n";
2850
2851if (!Entries.empty()) {
2852constYAMLVFSEntry &Entry = Entries.front();
2853
2854 startDirectory(
2855Entry.IsDirectory ?Entry.VPath :path::parent_path(Entry.VPath)
2856 );
2857
2858StringRef RPath =Entry.RPath;
2859if (UseOverlayRelative) {
2860assert(RPath.starts_with(OverlayDir) &&
2861"Overlay dir must be contained in RPath");
2862 RPath = RPath.substr(OverlayDir.size());
2863 }
2864
2865bool IsCurrentDirEmpty =true;
2866if (!Entry.IsDirectory) {
2867 writeEntry(path::filename(Entry.VPath), RPath);
2868 IsCurrentDirEmpty =false;
2869 }
2870
2871for (constauto &Entry : Entries.slice(1)) {
2872StringRef Dir =
2873Entry.IsDirectory ?Entry.VPath :path::parent_path(Entry.VPath);
2874if (Dir == DirStack.back()) {
2875if (!IsCurrentDirEmpty) {
2876OS <<",\n";
2877 }
2878 }else {
2879bool IsDirPoppedFromStack =false;
2880while (!DirStack.empty() && !containedIn(DirStack.back(), Dir)) {
2881OS <<"\n";
2882 endDirectory();
2883 IsDirPoppedFromStack =true;
2884 }
2885if (IsDirPoppedFromStack || !IsCurrentDirEmpty) {
2886OS <<",\n";
2887 }
2888 startDirectory(Dir);
2889 IsCurrentDirEmpty =true;
2890 }
2891StringRef RPath =Entry.RPath;
2892if (UseOverlayRelative) {
2893assert(RPath.starts_with(OverlayDir) &&
2894"Overlay dir must be contained in RPath");
2895 RPath = RPath.substr(OverlayDir.size());
2896 }
2897if (!Entry.IsDirectory) {
2898 writeEntry(path::filename(Entry.VPath), RPath);
2899 IsCurrentDirEmpty =false;
2900 }
2901 }
2902
2903while (!DirStack.empty()) {
2904OS <<"\n";
2905 endDirectory();
2906 }
2907OS <<"\n";
2908 }
2909
2910OS <<" ]\n"
2911 <<"}\n";
2912}
2913
2914voidYAMLVFSWriter::write(llvm::raw_ostream &OS) {
2915llvm::sort(Mappings, [](constYAMLVFSEntry &LHS,constYAMLVFSEntry &RHS) {
2916returnLHS.VPath <RHS.VPath;
2917 });
2918
2919 JSONWriter(OS).write(Mappings, UseExternalNames, IsCaseSensitive,
2920 IsOverlayRelative,OverlayDir);
2921}
2922
2923vfs::recursive_directory_iterator::recursive_directory_iterator(
2924FileSystem &FS_,constTwine &Path, std::error_code &EC)
2925 : FS(&FS_) {
2926directory_iteratorI = FS->dir_begin(Path, EC);
2927if (I !=directory_iterator()) {
2928 State = std::make_shared<detail::RecDirIterState>();
2929 State->Stack.push_back(I);
2930 }
2931}
2932
2933vfs::recursive_directory_iterator &
2934recursive_directory_iterator::increment(std::error_code &EC) {
2935assert(FS && State && !State->Stack.empty() &&"incrementing past end");
2936assert(!State->Stack.back()->path().empty() &&"non-canonical end iterator");
2937vfs::directory_iteratorEnd;
2938
2939if (State->HasNoPushRequest)
2940 State->HasNoPushRequest =false;
2941else {
2942if (State->Stack.back()->type() ==sys::fs::file_type::directory_file) {
2943vfs::directory_iteratorI =
2944 FS->dir_begin(State->Stack.back()->path(), EC);
2945if (I !=End) {
2946 State->Stack.push_back(I);
2947return *this;
2948 }
2949 }
2950 }
2951
2952while (!State->Stack.empty() && State->Stack.back().increment(EC) ==End)
2953 State->Stack.pop_back();
2954
2955if (State->Stack.empty())
2956 State.reset();// end iterator
2957
2958return *this;
2959}
2960
2961voidTracingFileSystem::printImpl(raw_ostream &OS, PrintTypeType,
2962unsigned IndentLevel) const{
2963 printIndent(OS, IndentLevel);
2964OS <<"TracingFileSystem\n";
2965if (Type == PrintType::Summary)
2966return;
2967
2968 printIndent(OS, IndentLevel);
2969OS <<"NumStatusCalls=" <<NumStatusCalls <<"\n";
2970 printIndent(OS, IndentLevel);
2971OS <<"NumOpenFileForReadCalls=" <<NumOpenFileForReadCalls <<"\n";
2972 printIndent(OS, IndentLevel);
2973OS <<"NumDirBeginCalls=" <<NumDirBeginCalls <<"\n";
2974 printIndent(OS, IndentLevel);
2975OS <<"NumGetRealPathCalls=" <<NumGetRealPathCalls <<"\n";
2976 printIndent(OS, IndentLevel);
2977OS <<"NumExistsCalls=" <<NumExistsCalls <<"\n";
2978 printIndent(OS, IndentLevel);
2979OS <<"NumIsLocalCalls=" <<NumIsLocalCalls <<"\n";
2980
2981if (Type == PrintType::Contents)
2982Type = PrintType::Summary;
2983 getUnderlyingFS().print(OS,Type, IndentLevel + 1);
2984}
2985
2986constcharFileSystem::ID = 0;
2987constcharOverlayFileSystem::ID = 0;
2988constcharProxyFileSystem::ID = 0;
2989constcharInMemoryFileSystem::ID = 0;
2990constcharRedirectingFileSystem::ID = 0;
2991constcharTracingFileSystem::ID = 0;
ArrayRef.h
From
BlockVerifier::State From
Definition:BlockVerifier.cpp:57
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Casting.h
Chrono.h
Compiler.h
Debug.h
DenseMap.h
This file defines the DenseMap class.
Content
T Content
Definition:ELFObjHandler.cpp:89
Name
std::string Name
Definition:ELFObjHandler.cpp:77
Size
uint64_t Size
Definition:ELFObjHandler.cpp:81
End
bool End
Definition:ELF_riscv.cpp:480
Errc.h
ErrorOr.h
Provides ErrorOr<T> smart pointer.
makeAbsolute
static void makeAbsolute(SmallVectorImpl< char > &Path)
Make Path absolute.
Definition:FileCollector.cpp:91
FileSystem.h
IntrusiveRefCntPtr.h
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
SpecialSubKind::string
@ string
F
#define F(x, y, z)
Definition:MD5.cpp:55
I
#define I(x, y, z)
Definition:MD5.cpp:58
MemoryBuffer.h
P
#define P(N)
Path.h
getName
static StringRef getName(Value *V)
Definition:ProvenanceAnalysisEvaluator.cpp:20
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SMLoc.h
STLExtras.h
This file contains some templates that are useful if you are working with the STL at all.
OS
raw_pwrite_stream & OS
Definition:SampleProfWriter.cpp:51
SmallString.h
This file defines the SmallString class.
SmallVector.h
This file defines the SmallVector class.
StringRef.h
StringSet.h
StringSet - A set-like wrapper for the StringMap.
SourceMgr.h
error
#define error(X)
Definition:SymbolRecordMapping.cpp:14
DiagHandler
static void DiagHandler(const SMDiagnostic &Diag, void *Context)
Definition:TextStub.cpp:1060
Twine.h
UniqueID.h
getVFSEntries
static void getVFSEntries(RedirectingFileSystem::Entry *SrcE, SmallVectorImpl< StringRef > &Path, SmallVectorImpl< YAMLVFSEntry > &Entries)
Definition:VirtualFileSystem.cpp:2673
getRedirectedFileStatus
static Status getRedirectedFileStatus(const Twine &OriginalPath, bool UseExternalNames, Status ExternalStatus)
Definition:VirtualFileSystem.cpp:2378
pathHasTraversal
static bool pathHasTraversal(StringRef Path)
Definition:VirtualFileSystem.cpp:173
isTraversalComponent
static bool isTraversalComponent(StringRef Component)
Definition:VirtualFileSystem.cpp:169
VirtualFileSystem.h
Defines the virtual file system interface vfs::FileSystem.
RHS
Value * RHS
Definition:X86PartialReduction.cpp:74
LHS
Value * LHS
Definition:X86PartialReduction.cpp:73
getSize
static unsigned getSize(unsigned Kind)
Definition:XtensaAsmBackend.cpp:134
YAMLParser.h
Node
Definition:ItaniumDemangle.h:163
const_iterator
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition:ArrayRef.h:41
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition:DenseMap.h:156
llvm::DenseMapBase::end
iterator end()
Definition:DenseMap.h:84
llvm::DenseMap
Definition:DenseMap.h:727
llvm::ErrorOr
Represents either an error or a value T.
Definition:ErrorOr.h:56
llvm::ErrorOr::getError
std::error_code getError() const
Definition:ErrorOr.h:152
llvm::Expected
Tagged union holding either a T or a Error.
Definition:Error.h:481
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition:Error.h:608
llvm::IntrusiveRefCntPtr
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
Definition:IntrusiveRefCntPtr.h:173
llvm::MemoryBufferRef
Definition:MemoryBufferRef.h:22
llvm::MemoryBuffer
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition:MemoryBuffer.h:51
llvm::MemoryBuffer::getOpenFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Given an already-open file descriptor, read the file and return a MemoryBuffer.
Definition:MemoryBuffer.cpp:550
llvm::MemoryBuffer::getMemBuffer
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Definition:MemoryBuffer.cpp:129
llvm::MemoryBuffer::getBufferIdentifier
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Definition:MemoryBuffer.h:76
llvm::MemoryBuffer::getBuffer
StringRef getBuffer() const
Definition:MemoryBuffer.h:70
llvm::SMLoc
Represents a location in source code.
Definition:SMLoc.h:23
llvm::SmallString
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition:SmallString.h:26
llvm::SmallString::c_str
const char * c_str()
Definition:SmallString.h:259
llvm::SmallString::str
StringRef str() const
Explicit conversion to StringRef.
Definition:SmallString.h:254
llvm::SmallVectorBase::empty
bool empty() const
Definition:SmallVector.h:81
llvm::SmallVectorBase::size
size_t size() const
Definition:SmallVector.h:78
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition:SmallVector.h:573
llvm::SmallVectorTemplateBase::pop_back
void pop_back()
Definition:SmallVector.h:425
llvm::SmallVectorTemplateBase::push_back
void push_back(const T &Elt)
Definition:SmallVector.h:413
llvm::SmallVectorTemplateCommon::end
iterator end()
Definition:SmallVector.h:269
llvm::SmallVectorTemplateCommon::front
reference front()
Definition:SmallVector.h:299
llvm::SmallVectorTemplateCommon::begin
iterator begin()
Definition:SmallVector.h:267
llvm::SmallVectorTemplateCommon::back
reference back()
Definition:SmallVector.h:308
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::SourceMgr
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition:SourceMgr.h:31
llvm::SourceMgr::DK_Error
@ DK_Error
Definition:SourceMgr.h:34
llvm::SourceMgr::PrintMessage
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
Definition:SourceMgr.cpp:352
llvm::SourceMgr::DiagHandlerTy
void(*)(const SMDiagnostic &, void *Context) DiagHandlerTy
Clients that want to handle their own diagnostics in a custom way can register a function pointer+con...
Definition:SourceMgr.h:43
llvm::SourceMgr::setDiagHandler
void setDiagHandler(DiagHandlerTy DH, void *Ctx=nullptr)
Specify a diagnostic handler to be invoked every time PrintMessage is called.
Definition:SourceMgr.h:112
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition:StringMap.h:128
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition:StringRef.h:51
llvm::StringRef::getAsInteger
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition:StringRef.h:470
llvm::StringRef::str
std::string str() const
str - Get the contents as an std::string.
Definition:StringRef.h:229
llvm::StringRef::substr
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition:StringRef.h:571
llvm::StringRef::starts_with
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition:StringRef.h:265
llvm::StringRef::empty
constexpr bool empty() const
empty - Check if the string is empty.
Definition:StringRef.h:147
llvm::StringRef::back
char back() const
back - Get the last character in the string.
Definition:StringRef.h:159
llvm::StringRef::slice
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition:StringRef.h:684
llvm::StringRef::size
constexpr size_t size() const
size - Get the string size.
Definition:StringRef.h:150
llvm::StringSet
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition:StringSet.h:23
llvm::StringSet::insert
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition:StringSet.h:38
llvm::Target
Target - Wrapper for Target specific information.
Definition:TargetRegistry.h:144
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition:Twine.h:81
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition:Twine.cpp:17
llvm::Twine::toVector
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
Definition:Twine.cpp:32
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition:Type.h:45
llvm::Type::print
void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
llvm::User
Definition:User.h:44
llvm::Value
LLVM Value Representation.
Definition:Value.h:74
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition:STLFunctionalExtras.h:37
llvm::hash_code
An opaque object representing a hash code.
Definition:Hashing.h:75
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition:raw_ostream.h:52
llvm::raw_ostream::indent
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
Definition:raw_ostream.cpp:495
llvm::sys::fs::UniqueID
Definition:UniqueID.h:26
llvm::sys::fs::UniqueID::getFile
uint64_t getFile() const
Definition:UniqueID.h:48
llvm::sys::fs::directory_entry::type
file_type type() const
Definition:FileSystem.h:1378
llvm::sys::fs::directory_entry::path
const std::string & path() const
Definition:FileSystem.h:1370
llvm::sys::fs::directory_iterator
directory_iterator - Iterates through the entries in path.
Definition:FileSystem.h:1416
llvm::sys::fs::directory_iterator::increment
directory_iterator & increment(std::error_code &ec)
Definition:FileSystem.h:1442
llvm::sys::fs::file_status
Represents the result of a call to sys::fs::status().
Definition:FileSystem.h:221
llvm::sys::path::const_iterator
Path iterator.
Definition:Path.h:75
llvm::sys::path::reverse_iterator
Reverse path iterator.
Definition:Path.h:101
llvm::vfs::FileSystem
The virtual file system interface.
Definition:VirtualFileSystem.h:266
llvm::vfs::FileSystem::getCurrentWorkingDirectory
virtual llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const =0
Get the working directory of this file system.
llvm::vfs::FileSystem::exists
virtual bool exists(const Twine &Path)
Check whether Path exists.
Definition:VirtualFileSystem.cpp:149
llvm::vfs::FileSystem::openFileForReadBinary
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForReadBinary(const Twine &Path)
Get a File object for the binary file at Path, if one exists.
Definition:VirtualFileSystem.h:284
llvm::vfs::FileSystem::PrintType
PrintType
Definition:VirtualFileSystem.h:339
llvm::vfs::FileSystem::PrintType::Summary
@ Summary
llvm::vfs::FileSystem::PrintType::RecursiveContents
@ RecursiveContents
llvm::vfs::FileSystem::PrintType::Contents
@ Contents
llvm::vfs::FileSystem::makeAbsolute
virtual std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
Definition:VirtualFileSystem.cpp:128
llvm::vfs::FileSystem::ID
static const char ID
Definition:VirtualFileSystem.h:268
llvm::vfs::FileSystem::openFileForRead
virtual llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path)=0
Get a File object for the text file at Path, if one exists.
llvm::vfs::FileSystem::getRealPath
virtual std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output)
Gets real path of Path e.g.
Definition:VirtualFileSystem.cpp:140
llvm::vfs::FileSystem::printIndent
void printIndent(raw_ostream &OS, unsigned IndentLevel) const
Definition:VirtualFileSystem.h:363
llvm::vfs::FileSystem::~FileSystem
virtual ~FileSystem()
llvm::vfs::FileSystem::dump
LLVM_DUMP_METHOD void dump() const
Definition:VirtualFileSystem.cpp:165
llvm::vfs::FileSystem::print
void print(raw_ostream &OS, PrintType Type=PrintType::Contents, unsigned IndentLevel=0) const
Definition:VirtualFileSystem.h:340
llvm::vfs::FileSystem::getBufferForFile
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
Definition:VirtualFileSystem.cpp:118
llvm::vfs::FileSystem::equivalent
llvm::ErrorOr< bool > equivalent(const Twine &A, const Twine &B)
Definition:VirtualFileSystem.cpp:154
llvm::vfs::FileSystem::isLocal
virtual std::error_code isLocal(const Twine &Path, bool &Result)
Is the file mounted on a local filesystem?
Definition:VirtualFileSystem.cpp:145
llvm::vfs::FileSystem::status
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
llvm::vfs::File
Represents an open file.
Definition:VirtualFileSystem.h:111
llvm::vfs::File::getWithPath
static ErrorOr< std::unique_ptr< File > > getWithPath(ErrorOr< std::unique_ptr< File > > Result, const Twine &P)
Definition:VirtualFileSystem.cpp:2539
llvm::vfs::File::~File
virtual ~File()
Destroy the file after closing it (if open).
llvm::vfs::InMemoryFileSystem::DirIterator
Adaptor from InMemoryDir::iterator to directory_iterator.
Definition:VirtualFileSystem.cpp:1104
llvm::vfs::InMemoryFileSystem::DirIterator::DirIterator
DirIterator(const InMemoryFileSystem *FS, const detail::InMemoryDirectory &Dir, std::string RequestedDirName)
Definition:VirtualFileSystem.cpp:1142
llvm::vfs::InMemoryFileSystem::DirIterator::increment
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
Definition:VirtualFileSystem.cpp:1150
llvm::vfs::InMemoryFileSystem::DirIterator::DirIterator
DirIterator()=default
llvm::vfs::InMemoryFileSystem
An in-memory file system.
Definition:VirtualFileSystem.h:537
llvm::vfs::InMemoryFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Definition:VirtualFileSystem.cpp:1202
llvm::vfs::InMemoryFileSystem::dir_begin
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Definition:VirtualFileSystem.cpp:1157
llvm::vfs::InMemoryFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Canonicalizes Path by combining with the current working directory and normalizing the path (e....
Definition:VirtualFileSystem.cpp:1190
llvm::vfs::InMemoryFileSystem::~InMemoryFileSystem
~InMemoryFileSystem() override
llvm::vfs::InMemoryFileSystem::ID
static const char ID
Definition:VirtualFileSystem.h:543
llvm::vfs::InMemoryFileSystem::MaxSymlinkDepth
static constexpr size_t MaxSymlinkDepth
Arbitrary max depth to search through symlinks.
Definition:VirtualFileSystem.h:599
llvm::vfs::InMemoryFileSystem::InMemoryFileSystem
InMemoryFileSystem(bool UseNormalizedPaths=true)
Definition:VirtualFileSystem.cpp:838
llvm::vfs::InMemoryFileSystem::useNormalizedPaths
bool useNormalizedPaths() const
Return true if this file system normalizes . and .. in paths.
Definition:VirtualFileSystem.h:627
llvm::vfs::InMemoryFileSystem::printImpl
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition:VirtualFileSystem.cpp:1207
llvm::vfs::InMemoryFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Definition:VirtualFileSystem.h:634
llvm::vfs::InMemoryFileSystem::addHardLink
bool addHardLink(const Twine &NewLink, const Twine &Target)
Add a hard link to a file.
Definition:VirtualFileSystem.cpp:1041
llvm::vfs::InMemoryFileSystem::toString
std::string toString() const
Definition:VirtualFileSystem.cpp:848
llvm::vfs::InMemoryFileSystem::addFileNoOwn
bool addFileNoOwn(const Twine &Path, time_t ModificationTime, const llvm::MemoryBufferRef &Buffer, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::file_type > Type=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)
Add a buffer to the VFS with a path.
Definition:VirtualFileSystem.cpp:948
llvm::vfs::InMemoryFileSystem::addSymbolicLink
bool addSymbolicLink(const Twine &NewLink, const Twine &Target, time_t ModificationTime, std::optional< uint32_t > User=std::nullopt, std::optional< uint32_t > Group=std::nullopt, std::optional< llvm::sys::fs::perms > Perms=std::nullopt)
Add a symbolic link.
Definition:VirtualFileSystem.cpp:1060
llvm::vfs::InMemoryFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Definition:VirtualFileSystem.cpp:1173
llvm::vfs::InMemoryFileSystem::status
llvm::ErrorOr< Status > status(const Twine &Path) override
Definition:VirtualFileSystem.cpp:1080
llvm::vfs::InMemoryFileSystem::openFileForRead
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Definition:VirtualFileSystem.cpp:1088
llvm::vfs::OverlayFileSystem::dir_begin
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Definition:VirtualFileSystem.cpp:615
llvm::vfs::OverlayFileSystem::visitChildFileSystems
void visitChildFileSystems(VisitCallbackTy Callback) override
Definition:VirtualFileSystem.cpp:512
llvm::vfs::OverlayFileSystem::openFileForRead
llvm::ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Definition:VirtualFileSystem.cpp:473
llvm::vfs::OverlayFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Definition:VirtualFileSystem.cpp:504
llvm::vfs::OverlayFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Definition:VirtualFileSystem.cpp:490
llvm::vfs::OverlayFileSystem::pushOverlay
void pushOverlay(IntrusiveRefCntPtr< FileSystem > FS)
Pushes a file system on top of the stack.
Definition:VirtualFileSystem.cpp:446
llvm::vfs::OverlayFileSystem::OverlayFileSystem
OverlayFileSystem(IntrusiveRefCntPtr< FileSystem > Base)
Definition:VirtualFileSystem.cpp:442
llvm::vfs::OverlayFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Definition:VirtualFileSystem.cpp:484
llvm::vfs::OverlayFileSystem::overlays_end
iterator overlays_end()
Get an iterator pointing one-past the least recently added file system.
Definition:VirtualFileSystem.h:428
llvm::vfs::OverlayFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Definition:VirtualFileSystem.cpp:497
llvm::vfs::OverlayFileSystem::overlays_range
range overlays_range()
Definition:VirtualFileSystem.h:439
llvm::vfs::OverlayFileSystem::exists
bool exists(const Twine &Path) override
Definition:VirtualFileSystem.cpp:463
llvm::vfs::OverlayFileSystem::status
llvm::ErrorOr< Status > status(const Twine &Path) override
Definition:VirtualFileSystem.cpp:453
llvm::vfs::OverlayFileSystem::overlays_begin
iterator overlays_begin()
Get an iterator pointing to the most recently added file system.
Definition:VirtualFileSystem.h:424
llvm::vfs::OverlayFileSystem::ID
static const char ID
Definition:VirtualFileSystem.h:399
llvm::vfs::OverlayFileSystem::iterator
FileSystemList::reverse_iterator iterator
Definition:VirtualFileSystem.h:416
llvm::vfs::OverlayFileSystem::printImpl
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition:VirtualFileSystem.cpp:519
llvm::vfs::ProxyFileSystem::ID
static const char ID
Definition:VirtualFileSystem.h:453
llvm::vfs::RedirectingFSDirIterImpl
Directory iterator implementation for RedirectingFileSystem's directory entries.
Definition:VirtualFileSystem.cpp:1269
llvm::vfs::RedirectingFSDirIterImpl::increment
std::error_code increment() override
Sets CurrentEntry to the next entry in the directory on success, to directory_entry() at end,...
Definition:VirtualFileSystem.cpp:1306
llvm::vfs::RedirectingFSDirIterImpl::RedirectingFSDirIterImpl
RedirectingFSDirIterImpl(const Twine &Path, RedirectingFileSystem::DirectoryEntry::iterator Begin, RedirectingFileSystem::DirectoryEntry::iterator End, std::error_code &EC)
Definition:VirtualFileSystem.cpp:1299
llvm::vfs::RedirectingFileSystemParser
A helper class to hold the common YAML parsing state.
Definition:VirtualFileSystem.cpp:1628
llvm::vfs::RedirectingFileSystemParser::RedirectingFileSystemParser
RedirectingFileSystemParser(yaml::Stream &S)
Definition:VirtualFileSystem.cpp:2043
llvm::vfs::RedirectingFileSystemParser::lookupOrCreateEntry
static RedirectingFileSystem::Entry * lookupOrCreateEntry(RedirectingFileSystem *FS, StringRef Name, RedirectingFileSystem::Entry *ParentEntry=nullptr)
Definition:VirtualFileSystem.cpp:1738
llvm::vfs::RedirectingFileSystemParser::parse
bool parse(yaml::Node *Root, RedirectingFileSystem *FS)
Definition:VirtualFileSystem.cpp:2046
llvm::vfs::RedirectingFileSystem::DirectoryEntry::iterator
decltype(Contents)::iterator iterator
Definition:VirtualFileSystem.h:844
llvm::vfs::RedirectingFileSystem::Entry
A single file or directory in the VFS.
Definition:VirtualFileSystem.h:808
llvm::vfs::RedirectingFileSystem::Entry::getName
StringRef getName() const
Definition:VirtualFileSystem.h:816
llvm::vfs::RedirectingFileSystem::Entry::getKind
EntryKind getKind() const
Definition:VirtualFileSystem.h:817
llvm::vfs::RedirectingFileSystem
A virtual file system parsed from a YAML file.
Definition:VirtualFileSystem.h:778
llvm::vfs::RedirectingFileSystem::RootRelativeKind::OverlayDir
@ OverlayDir
The roots are relative to the directory where the Overlay YAML file.
llvm::vfs::RedirectingFileSystem::RootRelativeKind::CWD
@ CWD
The roots are relative to the current working directory.
llvm::vfs::RedirectingFileSystem::exists
bool exists(const Twine &Path) override
Check whether Path exists.
Definition:VirtualFileSystem.cpp:2464
llvm::vfs::RedirectingFileSystem::printImpl
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition:VirtualFileSystem.cpp:1567
llvm::vfs::RedirectingFileSystem::getRoots
std::vector< llvm::StringRef > getRoots() const
Definition:VirtualFileSystem.cpp:1559
llvm::vfs::RedirectingFileSystem::dir_begin
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override
Get a directory_iterator for Dir.
Definition:VirtualFileSystem.cpp:1438
llvm::vfs::RedirectingFileSystem::lookupPath
ErrorOr< LookupResult > lookupPath(StringRef Path) const
Looks up Path in Roots and returns a LookupResult giving the matched entry and, if the entry was a Fi...
Definition:VirtualFileSystem.cpp:2309
llvm::vfs::RedirectingFileSystem::RedirectKind
RedirectKind
The type of redirection to perform.
Definition:VirtualFileSystem.h:785
llvm::vfs::RedirectingFileSystem::RedirectKind::Fallthrough
@ Fallthrough
Lookup the redirected path first (ie.
llvm::vfs::RedirectingFileSystem::RedirectKind::Fallback
@ Fallback
Lookup the provided path first and if that fails, "fallback" to a lookup of the redirected path.
llvm::vfs::RedirectingFileSystem::RedirectKind::RedirectOnly
@ RedirectOnly
Only lookup the redirected path, do not lookup the originally provided path.
llvm::vfs::RedirectingFileSystem::setFallthrough
void setFallthrough(bool Fallthrough)
Sets the redirection kind to Fallthrough if true or RedirectOnly otherwise.
Definition:VirtualFileSystem.cpp:1546
llvm::vfs::RedirectingFileSystem::visitChildFileSystems
void visitChildFileSystems(VisitCallbackTy Callback) override
Definition:VirtualFileSystem.cpp:1620
llvm::vfs::RedirectingFileSystem::getRealPath
std::error_code getRealPath(const Twine &Path, SmallVectorImpl< char > &Output) override
Gets real path of Path e.g.
Definition:VirtualFileSystem.cpp:2614
llvm::vfs::RedirectingFileSystem::openFileForRead
ErrorOr< std::unique_ptr< File > > openFileForRead(const Twine &Path) override
Get a File object for the text file at Path, if one exists.
Definition:VirtualFileSystem.cpp:2553
llvm::vfs::RedirectingFileSystem::setOverlayFileDir
void setOverlayFileDir(StringRef PrefixDir)
Definition:VirtualFileSystem.cpp:1538
llvm::vfs::RedirectingFileSystem::getCurrentWorkingDirectory
llvm::ErrorOr< std::string > getCurrentWorkingDirectory() const override
Get the working directory of this file system.
Definition:VirtualFileSystem.cpp:1353
llvm::vfs::RedirectingFileSystem::NK_Virtual
@ NK_Virtual
Definition:VirtualFileSystem.h:782
llvm::vfs::RedirectingFileSystem::NK_External
@ NK_External
Definition:VirtualFileSystem.h:782
llvm::vfs::RedirectingFileSystem::NK_NotSet
@ NK_NotSet
Definition:VirtualFileSystem.h:782
llvm::vfs::RedirectingFileSystem::setRedirection
void setRedirection(RedirectingFileSystem::RedirectKind Kind)
Definition:VirtualFileSystem.cpp:1554
llvm::vfs::RedirectingFileSystem::isLocal
std::error_code isLocal(const Twine &Path, bool &Result) override
Is the file mounted on a local filesystem?
Definition:VirtualFileSystem.cpp:1371
llvm::vfs::RedirectingFileSystem::EntryKind
EntryKind
Definition:VirtualFileSystem.h:781
llvm::vfs::RedirectingFileSystem::EK_File
@ EK_File
Definition:VirtualFileSystem.h:781
llvm::vfs::RedirectingFileSystem::EK_DirectoryRemap
@ EK_DirectoryRemap
Definition:VirtualFileSystem.h:781
llvm::vfs::RedirectingFileSystem::EK_Directory
@ EK_Directory
Definition:VirtualFileSystem.h:781
llvm::vfs::RedirectingFileSystem::create
static std::unique_ptr< RedirectingFileSystem > create(std::unique_ptr< MemoryBuffer > Buffer, SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext, IntrusiveRefCntPtr< FileSystem > ExternalFS)
Parses Buffer, which is expected to be in YAML format and returns a virtual file system representing ...
Definition:VirtualFileSystem.cpp:2176
llvm::vfs::RedirectingFileSystem::ID
static const char ID
Definition:VirtualFileSystem.h:780
llvm::vfs::RedirectingFileSystem::setCurrentWorkingDirectory
std::error_code setCurrentWorkingDirectory(const Twine &Path) override
Set the working directory.
Definition:VirtualFileSystem.cpp:1358
llvm::vfs::RedirectingFileSystem::getOverlayFileDir
StringRef getOverlayFileDir() const
Definition:VirtualFileSystem.cpp:1542
llvm::vfs::RedirectingFileSystem::printEntry
void printEntry(raw_ostream &OS, Entry *E, unsigned IndentLevel=0) const
Definition:VirtualFileSystem.cpp:1584
llvm::vfs::Status
The result of a status operation.
Definition:VirtualFileSystem.h:48
llvm::vfs::Status::getUniqueID
llvm::sys::fs::UniqueID getUniqueID() const
Definition:VirtualFileSystem.h:92
llvm::vfs::Status::equivalent
bool equivalent(const Status &Other) const
Definition:VirtualFileSystem.cpp:92
llvm::vfs::Status::copyWithNewName
static Status copyWithNewName(const Status &In, const Twine &NewName)
Get a copy of a Status with a different name.
Definition:VirtualFileSystem.cpp:80
llvm::vfs::Status::isStatusKnown
bool isStatusKnown() const
Definition:VirtualFileSystem.cpp:107
llvm::vfs::Status::exists
bool exists() const
Definition:VirtualFileSystem.cpp:109
llvm::vfs::Status::ExposesExternalVFSPath
bool ExposesExternalVFSPath
Whether this entity has an external path different from the virtual path, and the external path is ex...
Definition:VirtualFileSystem.h:68
llvm::vfs::Status::copyWithNewSize
static Status copyWithNewSize(const Status &In, uint64_t NewSize)
Get a copy of a Status with a different size.
Definition:VirtualFileSystem.cpp:74
llvm::vfs::Status::isOther
bool isOther() const
Definition:VirtualFileSystem.cpp:101
llvm::vfs::Status::isSymlink
bool isSymlink() const
Definition:VirtualFileSystem.cpp:105
llvm::vfs::Status::getType
llvm::sys::fs::file_type getType() const
Definition:VirtualFileSystem.h:89
llvm::vfs::Status::isRegularFile
bool isRegularFile() const
Definition:VirtualFileSystem.cpp:99
llvm::vfs::Status::isDirectory
bool isDirectory() const
Definition:VirtualFileSystem.cpp:97
llvm::vfs::Status::getName
StringRef getName() const
Returns the name that should be used for this file or directory.
Definition:VirtualFileSystem.h:85
llvm::vfs::Status::Status
Status()=default
llvm::vfs::TracingFileSystem::ID
static const char ID
Definition:VirtualFileSystem.h:1154
llvm::vfs::TracingFileSystem::NumOpenFileForReadCalls
std::size_t NumOpenFileForReadCalls
Definition:VirtualFileSystem.h:1157
llvm::vfs::TracingFileSystem::NumIsLocalCalls
std::size_t NumIsLocalCalls
Definition:VirtualFileSystem.h:1161
llvm::vfs::TracingFileSystem::NumExistsCalls
std::size_t NumExistsCalls
Definition:VirtualFileSystem.h:1160
llvm::vfs::TracingFileSystem::printImpl
void printImpl(raw_ostream &OS, PrintType Type, unsigned IndentLevel) const override
Definition:VirtualFileSystem.cpp:2961
llvm::vfs::TracingFileSystem::NumDirBeginCalls
std::size_t NumDirBeginCalls
Definition:VirtualFileSystem.h:1158
llvm::vfs::TracingFileSystem::NumGetRealPathCalls
std::size_t NumGetRealPathCalls
Definition:VirtualFileSystem.h:1159
llvm::vfs::TracingFileSystem::NumStatusCalls
std::size_t NumStatusCalls
Definition:VirtualFileSystem.h:1156
llvm::vfs::YAMLVFSWriter::addFileMapping
void addFileMapping(StringRef VirtualPath, StringRef RealPath)
Definition:VirtualFileSystem.cpp:2745
llvm::vfs::YAMLVFSWriter::write
void write(llvm::raw_ostream &OS)
Definition:VirtualFileSystem.cpp:2914
llvm::vfs::YAMLVFSWriter::addDirectoryMapping
void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath)
Definition:VirtualFileSystem.cpp:2749
llvm::vfs::detail::InMemoryDirectory
Definition:VirtualFileSystem.cpp:763
llvm::vfs::detail::InMemoryDirectory::InMemoryDirectory
InMemoryDirectory(Status Stat)
Definition:VirtualFileSystem.cpp:768
llvm::vfs::detail::InMemoryDirectory::addChild
InMemoryNode * addChild(StringRef Name, std::unique_ptr< InMemoryNode > Child)
Definition:VirtualFileSystem.cpp:787
llvm::vfs::detail::InMemoryDirectory::getStatus
Status getStatus(const Twine &RequestedName) const override
Return the Status for this node.
Definition:VirtualFileSystem.cpp:774
llvm::vfs::detail::InMemoryDirectory::end
const_iterator end() const
Definition:VirtualFileSystem.cpp:794
llvm::vfs::detail::InMemoryDirectory::classof
static bool classof(const InMemoryNode *N)
Definition:VirtualFileSystem.cpp:804
llvm::vfs::detail::InMemoryDirectory::getChild
InMemoryNode * getChild(StringRef Name) const
Definition:VirtualFileSystem.cpp:780
llvm::vfs::detail::InMemoryDirectory::begin
const_iterator begin() const
Definition:VirtualFileSystem.cpp:793
llvm::vfs::detail::InMemoryDirectory::getUniqueID
UniqueID getUniqueID() const
Definition:VirtualFileSystem.cpp:778
llvm::vfs::detail::InMemoryDirectory::const_iterator
decltype(Entries)::const_iterator const_iterator
Definition:VirtualFileSystem.cpp:791
llvm::vfs::detail::InMemoryDirectory::toString
std::string toString(unsigned Indent) const override
Definition:VirtualFileSystem.cpp:796
llvm::vfs::detail::InMemoryFile
Definition:VirtualFileSystem.cpp:661
llvm::vfs::detail::InMemoryFile::getStatus
Status getStatus(const Twine &RequestedName) const override
Return the Status for this node.
Definition:VirtualFileSystem.cpp:670
llvm::vfs::detail::InMemoryFile::toString
std::string toString(unsigned Indent) const override
Definition:VirtualFileSystem.cpp:675
llvm::vfs::detail::InMemoryFile::InMemoryFile
InMemoryFile(Status Stat, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Definition:VirtualFileSystem.cpp:666
llvm::vfs::detail::InMemoryFile::classof
static bool classof(const InMemoryNode *N)
Definition:VirtualFileSystem.cpp:679
llvm::vfs::detail::InMemoryFile::getBuffer
llvm::MemoryBuffer * getBuffer() const
Definition:VirtualFileSystem.cpp:673
llvm::vfs::detail::InMemoryNode
The in memory file system is a tree of Nodes.
Definition:VirtualFileSystem.cpp:640
llvm::vfs::detail::InMemoryNode::getFileName
StringRef getFileName() const
Get the filename of this node (the name without the directory part).
Definition:VirtualFileSystem.cpp:656
llvm::vfs::detail::InMemoryNode::getKind
InMemoryNodeKind getKind() const
Definition:VirtualFileSystem.cpp:657
llvm::vfs::detail::InMemoryNode::~InMemoryNode
virtual ~InMemoryNode()=default
llvm::vfs::detail::InMemoryNode::InMemoryNode
InMemoryNode(llvm::StringRef FileName, InMemoryNodeKind Kind)
Definition:VirtualFileSystem.cpp:645
llvm::vfs::detail::InMemoryNode::toString
virtual std::string toString(unsigned Indent) const =0
llvm::vfs::detail::InMemoryNode::getStatus
virtual Status getStatus(const Twine &RequestedName) const =0
Return the Status for this node.
llvm::vfs::detail::NamedNodeOrError
Definition:VirtualFileSystem.h:516
llvm::vfs::directory_entry
A member of a directory, yielded by a directory_iterator.
Definition:VirtualFileSystem.h:148
llvm::vfs::directory_entry::path
llvm::StringRef path() const
Definition:VirtualFileSystem.h:157
llvm::vfs::directory_entry::type
llvm::sys::fs::file_type type() const
Definition:VirtualFileSystem.h:158
llvm::vfs::directory_iterator
An input iterator over the entries in a virtual path, similar to llvm::sys::fs::directory_iterator.
Definition:VirtualFileSystem.h:179
llvm::vfs::directory_iterator::increment
directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Definition:VirtualFileSystem.h:194
llvm::vfs::recursive_directory_iterator
An input iterator over the recursive contents of a virtual path, similar to llvm::sys::fs::recursive_...
Definition:VirtualFileSystem.h:229
llvm::vfs::recursive_directory_iterator::recursive_directory_iterator
recursive_directory_iterator()=default
Construct an 'end' iterator.
llvm::vfs::recursive_directory_iterator::increment
recursive_directory_iterator & increment(std::error_code &EC)
Equivalent to operator++, with an error code.
Definition:VirtualFileSystem.cpp:2934
llvm::yaml::Node
Abstract base class for all Nodes.
Definition:YAMLParser.h:119
llvm::yaml::Stream
This class represents a YAML stream potentially containing multiple documents.
Definition:YAMLParser.h:86
llvm::yaml::Stream::end
document_iterator end()
Definition:YAMLParser.cpp:1946
llvm::yaml::Stream::begin
document_iterator begin()
Definition:YAMLParser.cpp:1935
llvm::yaml::Stream::failed
bool failed()
Definition:YAMLParser.cpp:1924
llvm::yaml::Stream::printError
void printError(Node *N, const Twine &Msg, SourceMgr::DiagKind Kind=SourceMgr::DK_Error)
Definition:YAMLParser.cpp:1926
llvm::yaml::document_iterator
Iterator abstraction for Documents over a Stream.
Definition:YAMLParser.h:593
uint32_t
uint64_t
unsigned
iterator_range.h
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
ErrorHandling.h
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition:ErrorHandling.h:143
detail
Definition:ClauseT.h:112
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition:AMDGPUMetadata.h:487
llvm::ARM::ProfileKind::M
@ M
llvm::COFF::Entry
@ Entry
Definition:COFF.h:844
llvm::HexagonII::Absolute
@ Absolute
Definition:HexagonBaseInfo.h:32
llvm::X86AS::FS
@ FS
Definition:X86.h:211
llvm::codeview::CompileSym2Flags::EC
@ EC
llvm::codeview::Link
@ Link
Definition:CodeView.h:154
llvm::lltok::Kind
Kind
Definition:LLToken.h:18
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::orc::SymbolState::Resolved
@ Resolved
Queried, materialization begun.
llvm::pdb::PDB_ColorItem::Path
@ Path
llvm::sys::fs::make_absolute
void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
Definition:Path.cpp:906
llvm::sys::fs::kInvalidFile
const file_t kInvalidFile
llvm::sys::fs::real_path
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
llvm::sys::fs::file_t
int file_t
Definition:FileSystem.h:55
llvm::sys::fs::closeFile
std::error_code closeFile(file_t &F)
Close the file object.
llvm::sys::fs::openFileForRead
std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
llvm::sys::fs::status
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
llvm::sys::fs::OpenFlags
OpenFlags
Definition:FileSystem.h:749
llvm::sys::fs::OF_Text
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
Definition:FileSystem.h:754
llvm::sys::fs::OF_None
@ OF_None
Definition:FileSystem.h:750
llvm::sys::fs::file_type
file_type
An enumeration for the file system's view of the type.
Definition:FileSystem.h:61
llvm::sys::fs::file_type::directory_file
@ directory_file
llvm::sys::fs::file_type::status_error
@ status_error
llvm::sys::fs::file_type::type_unknown
@ type_unknown
llvm::sys::fs::file_type::regular_file
@ regular_file
llvm::sys::fs::file_type::symlink_file
@ symlink_file
llvm::sys::fs::set_current_path
std::error_code set_current_path(const Twine &path)
Set the current path.
llvm::sys::fs::is_local
std::error_code is_local(const Twine &path, bool &result)
Is the file mounted on a local filesystem?
llvm::sys::fs::perms
perms
Definition:FileSystem.h:81
llvm::sys::fs::owner_all
@ owner_all
Definition:FileSystem.h:86
llvm::sys::fs::all_all
@ all_all
Definition:FileSystem.h:98
llvm::sys::fs::openNativeFileForRead
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
llvm::sys::fs::current_path
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
llvm::sys::fs::is_directory
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition:Path.cpp:1092
llvm::sys::path::get_separator
StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
Definition:Path.cpp:609
llvm::sys::path::root_path
StringRef root_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get root path.
Definition:Path.cpp:348
llvm::sys::path::begin
const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
Definition:Path.cpp:226
llvm::sys::path::rend
reverse_iterator rend(StringRef path LLVM_LIFETIME_BOUND)
Get reverse end iterator over path.
llvm::sys::path::remove_dots
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition:Path.cpp:715
llvm::sys::path::parent_path
StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
Definition:Path.cpp:467
llvm::sys::path::Style
Style
Definition:Path.h:27
llvm::sys::path::Style::windows_backslash
@ windows_backslash
llvm::sys::path::Style::native
@ native
llvm::sys::path::Style::posix
@ posix
llvm::sys::path::Style::windows_slash
@ windows_slash
llvm::sys::path::remove_leading_dotslash
StringRef remove_leading_dotslash(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
llvm::sys::path::filename
StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition:Path.cpp:577
llvm::sys::path::is_absolute
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition:Path.cpp:671
llvm::sys::path::append
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition:Path.cpp:456
llvm::sys::path::rbegin
reverse_iterator rbegin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get reverse begin iterator over path.
llvm::sys::path::end
const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
Definition:Path.cpp:235
llvm::sys::path::is_separator
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition:Path.cpp:601
llvm::sys
Definition:Atomic.h:28
llvm::sys::TimePoint
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition:Chrono.h:34
llvm::sys::toTimePoint
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
Definition:Chrono.h:65
llvm::vfs::detail::InMemoryNodeKind
InMemoryNodeKind
Definition:VirtualFileSystem.cpp:631
llvm::vfs::detail::IME_File
@ IME_File
Definition:VirtualFileSystem.cpp:632
llvm::vfs::detail::IME_HardLink
@ IME_HardLink
Definition:VirtualFileSystem.cpp:634
llvm::vfs::detail::IME_Directory
@ IME_Directory
Definition:VirtualFileSystem.cpp:633
llvm::vfs::detail::IME_SymbolicLink
@ IME_SymbolicLink
Definition:VirtualFileSystem.cpp:635
llvm::vfs
Definition:MIRSampleProfile.h:30
llvm::vfs::collectVFSFromYAML
void collectVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, SmallVectorImpl< YAMLVFSEntry > &CollectedEntries, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Collect all pairs of <virtual path, real path> entries from the YAMLFilePath.
llvm::vfs::getVFSFromYAML
std::unique_ptr< FileSystem > getVFSFromYAML(std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, void *DiagContext=nullptr, IntrusiveRefCntPtr< FileSystem > ExternalFS=getRealFileSystem())
Gets a FileSystem for a virtual file system described in YAML format.
llvm::vfs::createPhysicalFileSystem
std::unique_ptr< FileSystem > createPhysicalFileSystem()
Create an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition:VirtualFileSystem.cpp:404
llvm::vfs::getFileID
static sys::fs::UniqueID getFileID(sys::fs::UniqueID Parent, llvm::StringRef Name, llvm::StringRef Contents)
Definition:VirtualFileSystem.cpp:818
llvm::vfs::getNextVirtualUniqueID
llvm::sys::fs::UniqueID getNextVirtualUniqueID()
Get a globally unique ID for a virtual file or directory.
Definition:VirtualFileSystem.cpp:2729
llvm::vfs::getUniqueID
static sys::fs::UniqueID getUniqueID(hash_code Hash)
Definition:VirtualFileSystem.cpp:814
llvm::vfs::getRealFileSystem
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
Definition:VirtualFileSystem.cpp:399
llvm::vfs::getDirectoryID
static sys::fs::UniqueID getDirectoryID(sys::fs::UniqueID Parent, llvm::StringRef Name)
Definition:VirtualFileSystem.cpp:823
llvm::yaml::escape
std::string escape(StringRef Input, bool EscapePrintable=true)
Escape Input for a double quoted scalar; if EscapePrintable is true, all UTF8 sequences will be escap...
Definition:YAMLParser.cpp:704
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition:BitcodeReader.h:310
llvm::make_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Definition:iterator_range.h:77
llvm::errc::not_a_directory
@ not_a_directory
llvm::errc::no_such_file_or_directory
@ no_such_file_or_directory
llvm::errc::operation_not_permitted
@ operation_not_permitted
llvm::errc::invalid_argument
@ invalid_argument
llvm::reverse
auto reverse(ContainerTy &&C)
Definition:STLExtras.h:420
llvm::get
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
Definition:PointerIntPair.h:270
llvm::write
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
Definition:DWP.cpp:625
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition:STLExtras.h:1664
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition:Debug.cpp:163
llvm::IRMemLocation::Other
@ Other
Any other memory.
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition:STLExtras.h:1873
llvm::toString
const char * toString(DWARFSectionKind Kind)
Definition:DWARFUnitIndex.h:67
llvm::hash_combine
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition:Hashing.h:590
llvm::errorToErrorCode
std::error_code errorToErrorCode(Error Err)
Helper for converting an ECError to a std::error_code.
Definition:Error.cpp:117
llvm::Version
@ Version
Definition:PGOCtxProfWriter.h:22
std
Implement std::hash so that hash_code can be used in STL containers.
Definition:BitVector.h:858
raw_ostream.h
N
#define N
Status::Status
Status()=default
llvm::vfs::RedirectingFileSystem::LookupResult
Represents the result of a path lookup into the RedirectingFileSystem.
Definition:VirtualFileSystem.h:911
llvm::vfs::RedirectingFileSystem::LookupResult::E
Entry * E
The entry the looked-up path corresponds to.
Definition:VirtualFileSystem.h:916
llvm::vfs::RedirectingFileSystem::LookupResult::LookupResult
LookupResult(Entry *E, sys::path::const_iterator Start, sys::path::const_iterator End)
Definition:VirtualFileSystem.cpp:2271
llvm::vfs::RedirectingFileSystem::LookupResult::getPath
void getPath(llvm::SmallVectorImpl< char > &Path) const
Get the (canonical) path of the found entry.
Definition:VirtualFileSystem.cpp:2286
llvm::vfs::YAMLVFSEntry
Definition:VirtualFileSystem.h:664
llvm::vfs::detail::DirIterImpl
An interface for virtual file systems to provide an iterator over the (non-recursive) contents of a d...
Definition:VirtualFileSystem.h:165
llvm::vfs::detail::DirIterImpl::~DirIterImpl
virtual ~DirIterImpl()
llvm::vfs::detail::DirIterImpl::CurrentEntry
directory_entry CurrentEntry
Definition:VirtualFileSystem.h:172
llvm::vfs::detail::NewInMemoryNodeInfo
Definition:VirtualFileSystem.h:502
llvm::vfs::detail::NewInMemoryNodeInfo::makeStatus
Status makeStatus() const
Definition:VirtualFileSystem.cpp:828
llvm::vfs::detail::NewInMemoryNodeInfo::Buffer
std::unique_ptr< llvm::MemoryBuffer > Buffer
Definition:VirtualFileSystem.h:507
llvm::vfs::detail::NewInMemoryNodeInfo::Path
StringRef Path
Definition:VirtualFileSystem.h:504

Generated on Fri Jul 18 2025 12:55:48 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp