r255312 - [VFS] Fix status() of opened redirected file

Ben Langmuir via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 10 15:41:40 PST 2015


Author: benlangmuir
Date: Thu Dec 10 17:41:39 2015
New Revision: 255312

URL: http://llvm.org/viewvc/llvm-project?rev=255312&view=rev
Log:
[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

Added:
    cfe/trunk/test/VFS/Inputs/public_header3.h
Modified:
    cfe/trunk/lib/Basic/VirtualFileSystem.cpp
    cfe/trunk/test/VFS/Inputs/public_header.h
    cfe/trunk/test/VFS/Inputs/vfsoverlay.yaml
    cfe/trunk/test/VFS/real-path-found-first.m
    cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp

Modified: cfe/trunk/lib/Basic/VirtualFileSystem.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/VirtualFileSystem.cpp?rev=255312&r1=255311&r2=255312&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/VirtualFileSystem.cpp (original)
+++ cfe/trunk/lib/Basic/VirtualFileSystem.cpp Thu Dec 10 17:41:39 2015
@@ -1266,20 +1266,27 @@ RedirectingFileSystem::lookupPath(sys::p
   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::s
 }
 
 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(c
   if (!Result)
     return Result;
 
-  if (!F->useExternalName(UseExternalNames))
-    return std::unique_ptr<File>(
-        new NamedFileAdaptor(std::move(*Result), Path.str()));
-
-  return Result;
+  auto ExternalStatus = (*Result)->status();
+  if (!ExternalStatus)
+    return ExternalStatus.getError();
+
+  // 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>

Modified: cfe/trunk/test/VFS/Inputs/public_header.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/VFS/Inputs/public_header.h?rev=255312&r1=255311&r2=255312&view=diff
==============================================================================
--- cfe/trunk/test/VFS/Inputs/public_header.h (original)
+++ cfe/trunk/test/VFS/Inputs/public_header.h Thu Dec 10 17:41:39 2015
@@ -1,2 +1,3 @@
 #import <SomeFramework/public_header2.h>
+#import "public_header3.h" // includer-relative
 void from_framework(void);

Added: cfe/trunk/test/VFS/Inputs/public_header3.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/VFS/Inputs/public_header3.h?rev=255312&view=auto
==============================================================================
--- cfe/trunk/test/VFS/Inputs/public_header3.h (added)
+++ cfe/trunk/test/VFS/Inputs/public_header3.h Thu Dec 10 17:41:39 2015
@@ -0,0 +1 @@
+// public_header3.h

Modified: cfe/trunk/test/VFS/Inputs/vfsoverlay.yaml
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/VFS/Inputs/vfsoverlay.yaml?rev=255312&r1=255311&r2=255312&view=diff
==============================================================================
--- cfe/trunk/test/VFS/Inputs/vfsoverlay.yaml (original)
+++ cfe/trunk/test/VFS/Inputs/vfsoverlay.yaml Thu Dec 10 17:41:39 2015
@@ -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' }
               ]
             }
           ]

Modified: cfe/trunk/test/VFS/real-path-found-first.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/VFS/real-path-found-first.m?rev=255312&r1=255311&r2=255312&view=diff
==============================================================================
--- cfe/trunk/test/VFS/real-path-found-first.m (original)
+++ cfe/trunk/test/VFS/real-path-found-first.m Thu Dec 10 17:41:39 2015
@@ -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

Modified: cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp?rev=255312&r1=255311&r2=255312&view=diff
==============================================================================
--- cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp (original)
+++ cfe/trunk/unittests/Basic/VirtualFileSystemTest.cpp Thu Dec 10 17:41:39 2015
@@ -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/");




More information about the cfe-commits mailing list