forked from OSchip/llvm-project
[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:
parent
8376037861
commit
f13302e63f
|
@ -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>
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
#import <SomeFramework/public_header2.h>
|
||||
#import "public_header3.h" // includer-relative
|
||||
void from_framework(void);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
// public_header3.h
|
|
@ -22,7 +22,9 @@
|
|||
{ 'name': 'public_header.h', 'type': 'file',
|
||||
'external-contents': 'INPUT_DIR/public_header.h' },
|
||||
{ 'name': 'public_header2.h', 'type': 'file',
|
||||
'external-contents': 'INPUT_DIR/public_header2.h' }
|
||||
'external-contents': 'INPUT_DIR/public_header2.h' },
|
||||
{ 'name': 'public_header3.h', 'type': 'file',
|
||||
'external-contents': 'INPUT_DIR/public_header3.h' }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -70,5 +70,6 @@
|
|||
#ifndef WITH_PREFIX
|
||||
#import <SomeFramework/public_header.h> // expected-warning{{treating}}
|
||||
#import <SomeFramework/public_header2.h> // expected-warning{{treating}}
|
||||
#import <SomeFramework/public_header3.h> // expected-warning{{treating}}
|
||||
@import SomeFramework.public_header2;
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,18 @@ using namespace llvm;
|
|||
using llvm::sys::fs::UniqueID;
|
||||
|
||||
namespace {
|
||||
struct DummyFile : public vfs::File {
|
||||
vfs::Status S;
|
||||
explicit DummyFile(vfs::Status S) : S(S) {}
|
||||
llvm::ErrorOr<vfs::Status> status() override { return S; }
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
|
||||
getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
|
||||
bool IsVolatile) override {
|
||||
llvm_unreachable("unimplemented");
|
||||
}
|
||||
virtual std::error_code close() override { return std::error_code(); }
|
||||
};
|
||||
|
||||
class DummyFileSystem : public vfs::FileSystem {
|
||||
int FSID; // used to produce UniqueIDs
|
||||
int FileID; // used to produce UniqueIDs
|
||||
|
@ -42,7 +54,10 @@ public:
|
|||
}
|
||||
ErrorOr<std::unique_ptr<vfs::File>>
|
||||
openFileForRead(const Twine &Path) override {
|
||||
llvm_unreachable("unimplemented");
|
||||
auto S = status(Path);
|
||||
if (S)
|
||||
return std::unique_ptr<vfs::File>(new DummyFile{*S});
|
||||
return S.getError();
|
||||
}
|
||||
llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
|
||||
return std::string();
|
||||
|
@ -718,10 +733,20 @@ TEST_F(VFSFromYAMLTest, MappedFiles) {
|
|||
ErrorOr<vfs::Status> S = O->status("//root/file1");
|
||||
ASSERT_FALSE(S.getError());
|
||||
EXPECT_EQ("//root/foo/bar/a", S->getName());
|
||||
EXPECT_TRUE(S->IsVFSMapped);
|
||||
|
||||
ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
|
||||
EXPECT_EQ("//root/foo/bar/a", SLower->getName());
|
||||
EXPECT_TRUE(S->equivalent(*SLower));
|
||||
EXPECT_FALSE(SLower->IsVFSMapped);
|
||||
|
||||
// file after opening
|
||||
auto OpenedF = O->openFileForRead("//root/file1");
|
||||
ASSERT_FALSE(OpenedF.getError());
|
||||
auto OpenedS = (*OpenedF)->status();
|
||||
ASSERT_FALSE(OpenedS.getError());
|
||||
EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
|
||||
EXPECT_TRUE(OpenedS->IsVFSMapped);
|
||||
|
||||
// directory
|
||||
S = O->status("//root/");
|
||||
|
|
Loading…
Reference in New Issue