[VFS] Fix status() of opened redirected file

Make RedirectedFileSystem::openFilForRead(path)->status() the same as
RedirectedFileSystem::status(path). Previously we would just get the
status of the underlying real file, which would not have the IsVFSMapped
bit set.

This fixes rebuilding a module that has an include that is relative to
the includer where we will lookup the real path of that file before we
lookup the VFS location.

rdar://problem/23640339

llvm-svn: 255312
This commit is contained in:
Ben Langmuir
2015-12-10 23:41:39 +00:00
parent 8376037861
commit f13302e63f
6 changed files with 59 additions and 23 deletions

View File

@@ -1266,20 +1266,27 @@ RedirectingFileSystem::lookupPath(sys::path::const_iterator Start,
return make_error_code(llvm::errc::no_such_file_or_directory);
}
static Status getRedirectedFileStatus(const Twine &Path, bool UseExternalNames,
Status ExternalStatus) {
Status S = ExternalStatus;
if (!UseExternalNames)
S = Status::copyWithNewName(S, Path.str());
S.IsVFSMapped = true;
return S;
}
ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path, Entry *E) {
assert(E != nullptr);
std::string PathStr(Path.str());
if (auto *F = dyn_cast<RedirectingFileEntry>(E)) {
ErrorOr<Status> S = ExternalFS->status(F->getExternalContentsPath());
assert(!S || S->getName() == F->getExternalContentsPath());
if (S && !F->useExternalName(UseExternalNames))
*S = Status::copyWithNewName(*S, PathStr);
if (S)
S->IsVFSMapped = true;
return getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
*S);
return S;
} else { // directory
auto *DE = cast<RedirectingDirectoryEntry>(E);
return Status::copyWithNewName(DE->getStatus(), PathStr);
return Status::copyWithNewName(DE->getStatus(), Path.str());
}
}
@@ -1291,22 +1298,17 @@ ErrorOr<Status> RedirectingFileSystem::status(const Twine &Path) {
}
namespace {
/// Provide a file wrapper that returns the external name when asked.
class NamedFileAdaptor : public File {
/// Provide a file wrapper with an overriden status.
class FileWithFixedStatus : public File {
std::unique_ptr<File> InnerFile;
std::string NewName;
Status S;
public:
NamedFileAdaptor(std::unique_ptr<File> InnerFile, std::string NewName)
: InnerFile(std::move(InnerFile)), NewName(std::move(NewName)) {}
FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
: InnerFile(std::move(InnerFile)), S(S) {}
llvm::ErrorOr<Status> status() override {
auto InnerStatus = InnerFile->status();
if (InnerStatus)
return Status::copyWithNewName(*InnerStatus, NewName);
return InnerStatus.getError();
}
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
ErrorOr<Status> status() override { return S; }
ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile) override {
return InnerFile->getBuffer(Name, FileSize, RequiresNullTerminator,
@@ -1330,11 +1332,15 @@ RedirectingFileSystem::openFileForRead(const Twine &Path) {
if (!Result)
return Result;
if (!F->useExternalName(UseExternalNames))
return std::unique_ptr<File>(
new NamedFileAdaptor(std::move(*Result), Path.str()));
auto ExternalStatus = (*Result)->status();
if (!ExternalStatus)
return ExternalStatus.getError();
return Result;
// FIXME: Update the status with the name and VFSMapped.
Status S = getRedirectedFileStatus(Path, F->useExternalName(UseExternalNames),
*ExternalStatus);
return std::unique_ptr<File>(
llvm::make_unique<FileWithFixedStatus>(std::move(*Result), S));
}
IntrusiveRefCntPtr<FileSystem>