summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorBen Langmuir <blangmuir@apple.com>2015-12-10 23:41:39 +0000
committerBen Langmuir <blangmuir@apple.com>2015-12-10 23:41:39 +0000
commitf13302e63ff0c858ecac7cc30ea2201c523a43ba (patch)
tree368c35038f8ff52ee23b47dbcfc79dcae74cc226 /clang
parent83760378617dfa9670ce9439e9bfdcf2a5c81b90 (diff)
downloadbcm5719-llvm-f13302e63ff0c858ecac7cc30ea2201c523a43ba.tar.gz
bcm5719-llvm-f13302e63ff0c858ecac7cc30ea2201c523a43ba.zip
[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
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Basic/VirtualFileSystem.cpp50
-rw-r--r--clang/test/VFS/Inputs/public_header.h1
-rw-r--r--clang/test/VFS/Inputs/public_header3.h1
-rw-r--r--clang/test/VFS/Inputs/vfsoverlay.yaml4
-rw-r--r--clang/test/VFS/real-path-found-first.m1
-rw-r--r--clang/unittests/Basic/VirtualFileSystemTest.cpp27
6 files changed, 60 insertions, 24 deletions
diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp
index 501a5ddb849..cf5a8d681ea 100644
--- a/clang/lib/Basic/VirtualFileSystem.cpp
+++ b/clang/lib/Basic/VirtualFileSystem.cpp
@@ -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)) {}
-
- 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>>
+ FileWithFixedStatus(std::unique_ptr<File> InnerFile, Status S)
+ : InnerFile(std::move(InnerFile)), S(S) {}
+
+ 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>
diff --git a/clang/test/VFS/Inputs/public_header.h b/clang/test/VFS/Inputs/public_header.h
index 09d9969d319..cc7bcb57eea 100644
--- a/clang/test/VFS/Inputs/public_header.h
+++ b/clang/test/VFS/Inputs/public_header.h
@@ -1,2 +1,3 @@
#import <SomeFramework/public_header2.h>
+#import "public_header3.h" // includer-relative
void from_framework(void);
diff --git a/clang/test/VFS/Inputs/public_header3.h b/clang/test/VFS/Inputs/public_header3.h
new file mode 100644
index 00000000000..ac9deac6ab3
--- /dev/null
+++ b/clang/test/VFS/Inputs/public_header3.h
@@ -0,0 +1 @@
+// public_header3.h
diff --git a/clang/test/VFS/Inputs/vfsoverlay.yaml b/clang/test/VFS/Inputs/vfsoverlay.yaml
index f395d45ee3b..504a1530d3c 100644
--- a/clang/test/VFS/Inputs/vfsoverlay.yaml
+++ b/clang/test/VFS/Inputs/vfsoverlay.yaml
@@ -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' }
]
}
]
diff --git a/clang/test/VFS/real-path-found-first.m b/clang/test/VFS/real-path-found-first.m
index 3b37a644bcb..5838aa36c45 100644
--- a/clang/test/VFS/real-path-found-first.m
+++ b/clang/test/VFS/real-path-found-first.m
@@ -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
diff --git a/clang/unittests/Basic/VirtualFileSystemTest.cpp b/clang/unittests/Basic/VirtualFileSystemTest.cpp
index 96b8295acdb..ac07035d3e1 100644
--- a/clang/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/clang/unittests/Basic/VirtualFileSystemTest.cpp
@@ -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/");
OpenPOWER on IntegriCloud