[VFS] Skip non existent files from the VFS tree

When the VFS uses a YAML file, the real file path for a
virtual file is described in the "external-contents" field. Example:

  ...
  {
     'type': 'file',
     'name': 'a.h',
     'external-contents': '/a/b/c/a.h'
  }

Currently, when parsing umbrella directories, we use
vfs::recursive_directory_iterator to gather the header files to generate the
equivalent modules for. If the external contents for a header does not exist,
we currently are unable to build a module, since the VFS
vfs::recursive_directory_iterator will fail when it finds an entry without a
reliable real path.

Since the YAML file could be prepared ahead of time and shared among
different compiler invocations, an entry might not yet have a reliable
path in 'external-contents', breaking the iteration.

Give the VFS the capability to skip such entries whenever
'ignore-non-existent-contents' property is set in the YAML file.

rdar://problem/27531549

llvm-svn: 278457
This commit is contained in:
Bruno Cardoso Lopes
2016-08-12 01:51:04 +00:00
parent b40d8ad225
commit 1dc8a42281
7 changed files with 88 additions and 8 deletions

View File

@@ -1778,29 +1778,47 @@ VFSFromYamlDirIterImpl::VFSFromYamlDirIterImpl(
RedirectingDirectoryEntry::iterator Begin,
RedirectingDirectoryEntry::iterator End, std::error_code &EC)
: Dir(_Path.str()), FS(FS), Current(Begin), End(End) {
if (Current != End) {
while (Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
if (S)
if (S) {
CurrentEntry = *S;
else
return;
}
// Skip entries which do not map to a reliable external content.
if (FS.ignoreNonExistentContents() &&
S.getError() == llvm::errc::no_such_file_or_directory) {
++Current;
continue;
} else {
EC = S.getError();
break;
}
}
}
std::error_code VFSFromYamlDirIterImpl::increment() {
assert(Current != End && "cannot iterate past end");
if (++Current != End) {
while (++Current != End) {
SmallString<128> PathStr(Dir);
llvm::sys::path::append(PathStr, (*Current)->getName());
llvm::ErrorOr<vfs::Status> S = FS.status(PathStr);
if (!S)
return S.getError();
if (!S) {
// Skip entries which do not map to a reliable external content.
if (FS.ignoreNonExistentContents() &&
S.getError() == llvm::errc::no_such_file_or_directory) {
continue;
} else {
return S.getError();
}
}
CurrentEntry = *S;
} else {
CurrentEntry = Status();
break;
}
if (Current == End)
CurrentEntry = Status();
return std::error_code();
}