diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/VirtualFileSystem.cpp | 117 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/ModuleDependencyCollector.cpp | 4 |
3 files changed, 104 insertions, 21 deletions
diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp index 68ad428ec7e..cfe61dc428a 100644 --- a/clang/lib/Basic/VirtualFileSystem.cpp +++ b/clang/lib/Basic/VirtualFileSystem.cpp @@ -790,6 +790,7 @@ public: /// All configuration options are optional. /// 'case-sensitive': <boolean, default=true> /// 'use-external-names': <boolean, default=true> +/// 'overlay-relative': <boolean, default=false> /// /// Virtual directories are represented as /// \verbatim @@ -832,6 +833,10 @@ class RedirectingFileSystem : public vfs::FileSystem { std::vector<std::unique_ptr<Entry>> Roots; /// \brief The file system to use for external references. IntrusiveRefCntPtr<FileSystem> ExternalFS; + /// If IsRelativeOverlay is set, this represents the directory + /// path that should be prefixed to each 'external-contents' entry + /// when reading from YAML files. + std::string ExternalContentsPrefixDir; /// @name Configuration /// @{ @@ -841,6 +846,10 @@ class RedirectingFileSystem : public vfs::FileSystem { /// Currently, case-insensitive matching only works correctly with ASCII. bool CaseSensitive; + /// IsRelativeOverlay marks whether a IsExternalContentsPrefixDir path must + /// be prefixed in every 'external-contents' when reading from YAML files. + bool IsRelativeOverlay = false; + /// \brief Whether to use to use the value of 'external-contents' for the /// names of files. This global value is overridable on a per-file basis. bool UseExternalNames; @@ -868,8 +877,8 @@ public: /// returns a virtual file system representing its contents. static RedirectingFileSystem * create(std::unique_ptr<MemoryBuffer> Buffer, - SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext, - IntrusiveRefCntPtr<FileSystem> ExternalFS); + SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath, + void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS); ErrorOr<Status> status(const Twine &Path) override; ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; @@ -902,6 +911,15 @@ public: return directory_iterator(std::make_shared<VFSFromYamlDirIterImpl>(Dir, *this, D->contents_begin(), D->contents_end(), EC)); } + + void setExternalContentsPrefixDir(StringRef PrefixDir) { + ExternalContentsPrefixDir = PrefixDir.str(); + } + + StringRef getExternalContentsPrefixDir() const { + return ExternalContentsPrefixDir; + } + }; /// \brief A helper class to hold the common YAML parsing state. @@ -981,7 +999,7 @@ class RedirectingFileSystemParser { return true; } - std::unique_ptr<Entry> parseEntry(yaml::Node *N) { + std::unique_ptr<Entry> parseEntry(yaml::Node *N, RedirectingFileSystem *FS) { yaml::MappingNode *M = dyn_cast<yaml::MappingNode>(N); if (!M) { error(N, "expected mapping node for file or directory entry"); @@ -1057,7 +1075,7 @@ class RedirectingFileSystemParser { for (yaml::SequenceNode::iterator I = Contents->begin(), E = Contents->end(); I != E; ++I) { - if (std::unique_ptr<Entry> E = parseEntry(&*I)) + if (std::unique_ptr<Entry> E = parseEntry(&*I, FS)) EntryArrayContents.push_back(std::move(E)); else return nullptr; @@ -1071,12 +1089,22 @@ class RedirectingFileSystemParser { HasContents = true; if (!parseScalarString(I->getValue(), Value, Buffer)) return nullptr; - SmallString<256> Path(Value); + + SmallString<128> FullPath; + if (FS->IsRelativeOverlay) { + FullPath = FS->getExternalContentsPrefixDir(); + assert(!FullPath.empty() && + "External contents prefix directory must exist"); + llvm::sys::path::append(FullPath, Value); + } else { + FullPath = Value; + } + // Guarantee that old YAML files containing paths with ".." and "." are // properly canonicalized before read into the VFS. - Path = sys::path::remove_leading_dotslash(Path); - sys::path::remove_dots(Path, /*remove_dot_dot=*/true); - ExternalContentsPath = Path.str(); + FullPath = sys::path::remove_leading_dotslash(FullPath); + sys::path::remove_dots(FullPath, /*remove_dot_dot=*/true); + ExternalContentsPath = FullPath.str(); } else if (Key == "use-external-name") { bool Val; if (!parseScalarBool(I->getValue(), Val)) @@ -1162,6 +1190,7 @@ public: KeyStatusPair("version", true), KeyStatusPair("case-sensitive", false), KeyStatusPair("use-external-names", false), + KeyStatusPair("overlay-relative", false), KeyStatusPair("roots", true), }; @@ -1187,7 +1216,7 @@ public: for (yaml::SequenceNode::iterator I = Roots->begin(), E = Roots->end(); I != E; ++I) { - if (std::unique_ptr<Entry> E = parseEntry(&*I)) + if (std::unique_ptr<Entry> E = parseEntry(&*I, FS)) FS->Roots.push_back(std::move(E)); else return false; @@ -1213,6 +1242,9 @@ public: } else if (Key == "case-sensitive") { if (!parseScalarBool(I->getValue(), FS->CaseSensitive)) return false; + } else if (Key == "overlay-relative") { + if (!parseScalarBool(I->getValue(), FS->IsRelativeOverlay)) + return false; } else if (Key == "use-external-names") { if (!parseScalarBool(I->getValue(), FS->UseExternalNames)) return false; @@ -1233,9 +1265,11 @@ public: Entry::~Entry() = default; -RedirectingFileSystem *RedirectingFileSystem::create( - std::unique_ptr<MemoryBuffer> Buffer, SourceMgr::DiagHandlerTy DiagHandler, - void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS) { +RedirectingFileSystem * +RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer, + SourceMgr::DiagHandlerTy DiagHandler, + StringRef YAMLFilePath, void *DiagContext, + IntrusiveRefCntPtr<FileSystem> ExternalFS) { SourceMgr SM; yaml::Stream Stream(Buffer->getMemBufferRef(), SM); @@ -1252,6 +1286,23 @@ RedirectingFileSystem *RedirectingFileSystem::create( std::unique_ptr<RedirectingFileSystem> FS( new RedirectingFileSystem(ExternalFS)); + + if (!YAMLFilePath.empty()) { + // Use the YAML path from -ivfsoverlay to compute the dir to be prefixed + // to each 'external-contents' path. + // + // Example: + // -ivfsoverlay dummy.cache/vfs/vfs.yaml + // yields: + // FS->ExternalContentsPrefixDir => /<absolute_path_to>/dummy.cache/vfs + // + SmallString<256> OverlayAbsDir = sys::path::parent_path(YAMLFilePath); + std::error_code EC = llvm::sys::fs::make_absolute(OverlayAbsDir); + assert(!EC && "Overlay dir final path must be absolute"); + (void)EC; + FS->setExternalContentsPrefixDir(OverlayAbsDir); + } + if (!P.parse(Root, FS.get())) return nullptr; @@ -1396,10 +1447,12 @@ RedirectingFileSystem::openFileForRead(const Twine &Path) { IntrusiveRefCntPtr<FileSystem> vfs::getVFSFromYAML(std::unique_ptr<MemoryBuffer> Buffer, - SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext, + SourceMgr::DiagHandlerTy DiagHandler, + StringRef YAMLFilePath, + void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS) { return RedirectingFileSystem::create(std::move(Buffer), DiagHandler, - DiagContext, ExternalFS); + YAMLFilePath, DiagContext, ExternalFS); } UniqueID vfs::getNextVirtualUniqueID() { @@ -1431,7 +1484,8 @@ class JSONWriter { public: JSONWriter(llvm::raw_ostream &OS) : OS(OS) {} - void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> IsCaseSensitive); + void write(ArrayRef<YAMLVFSEntry> Entries, Optional<bool> IsCaseSensitive, + Optional<bool> IsOverlayRelative, StringRef OverlayDir); }; } @@ -1484,7 +1538,9 @@ void JSONWriter::writeEntry(StringRef VPath, StringRef RPath) { } void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, - Optional<bool> IsCaseSensitive) { + Optional<bool> IsCaseSensitive, + Optional<bool> IsOverlayRelative, + StringRef OverlayDir) { using namespace llvm::sys; OS << "{\n" @@ -1492,12 +1548,27 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, if (IsCaseSensitive.hasValue()) OS << " 'case-sensitive': '" << (IsCaseSensitive.getValue() ? "true" : "false") << "',\n"; + bool UseOverlayRelative = false; + if (IsOverlayRelative.hasValue()) { + UseOverlayRelative = IsOverlayRelative.getValue(); + OS << " 'overlay-relative': '" + << (UseOverlayRelative ? "true" : "false") << "',\n"; + } OS << " 'roots': [\n"; if (!Entries.empty()) { const YAMLVFSEntry &Entry = Entries.front(); startDirectory(path::parent_path(Entry.VPath)); - writeEntry(path::filename(Entry.VPath), Entry.RPath); + + StringRef RPath = Entry.RPath; + if (UseOverlayRelative) { + unsigned OverlayDirLen = OverlayDir.size(); + assert(RPath.substr(0, OverlayDirLen) == OverlayDir && + "Overlay dir must be contained in RPath"); + RPath = RPath.slice(OverlayDirLen, RPath.size()); + } + + writeEntry(path::filename(Entry.VPath), RPath); for (const auto &Entry : Entries.slice(1)) { StringRef Dir = path::parent_path(Entry.VPath); @@ -1511,7 +1582,14 @@ void JSONWriter::write(ArrayRef<YAMLVFSEntry> Entries, OS << ",\n"; startDirectory(Dir); } - writeEntry(path::filename(Entry.VPath), Entry.RPath); + StringRef RPath = Entry.RPath; + if (UseOverlayRelative) { + unsigned OverlayDirLen = OverlayDir.size(); + assert(RPath.substr(0, OverlayDirLen) == OverlayDir && + "Overlay dir must be contained in RPath"); + RPath = RPath.slice(OverlayDirLen, RPath.size()); + } + writeEntry(path::filename(Entry.VPath), RPath); } while (!DirStack.empty()) { @@ -1531,7 +1609,8 @@ void YAMLVFSWriter::write(llvm::raw_ostream &OS) { return LHS.VPath < RHS.VPath; }); - JSONWriter(OS).write(Mappings, IsCaseSensitive); + JSONWriter(OS).write(Mappings, IsCaseSensitive, IsOverlayRelative, + OverlayDir); } VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl( diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index cf4b5cf20a1..feace7ec770 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2344,8 +2344,8 @@ createVFSFromCompilerInvocation(const CompilerInvocation &CI, return IntrusiveRefCntPtr<vfs::FileSystem>(); } - IntrusiveRefCntPtr<vfs::FileSystem> FS = - vfs::getVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr); + IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML( + std::move(Buffer.get()), /*DiagHandler*/ nullptr, File); if (!FS.get()) { Diags.Report(diag::err_invalid_vfs_overlay) << File; return IntrusiveRefCntPtr<vfs::FileSystem>(); diff --git a/clang/lib/Frontend/ModuleDependencyCollector.cpp b/clang/lib/Frontend/ModuleDependencyCollector.cpp index df5e19df91d..7ba04645590 100644 --- a/clang/lib/Frontend/ModuleDependencyCollector.cpp +++ b/clang/lib/Frontend/ModuleDependencyCollector.cpp @@ -51,6 +51,10 @@ void ModuleDependencyCollector::writeFileMap() { SmallString<256> Dest = getDest(); llvm::sys::path::append(Dest, "vfs.yaml"); + // Default to use relative overlay directories in the VFS yaml file. This + // allows crash reproducer scripts to work across machines. + VFSWriter.setOverlayDir(getDest()); + std::error_code EC; llvm::raw_fd_ostream OS(Dest, EC, llvm::sys::fs::F_Text); if (EC) { |