simark created this revision.
Herald added a subscriber: cfe-commits.

I noticed that when getVirtualFile is called for a file, subsequent
calls to getFile will return a FileEntry without the RealPathName
computed:

  const FileEntry *VFE = Mgr->getVirtualFile("/foo/../bar", ...);
  const FileEntry *FE = Mgr->getFile("/foo/../bar");
  
  FE->tryGetRealPathName() returns an empty string.

This is because getVirtualFile creates a FileEntry without computing the
RealPathName field and stores it in SeenFileEntries.  getFile then
simply retrieves this object and returns it, when asked for the same
file.

I think it's reasonable to try to compute RealPathName in getVirtualFile
too.

There might be a similar issue with the File field.  If you call
getVirtualFile, then call getFile with open=true, you may get a
FileEntry with the File field NULL, which is not what you requested.  I
have not addressed this issue in this patch though.


Repository:
  rC Clang

https://reviews.llvm.org/D49197

Files:
  lib/Basic/FileManager.cpp
  unittests/Basic/FileManagerTest.cpp


Index: unittests/Basic/FileManagerTest.cpp
===================================================================
--- unittests/Basic/FileManagerTest.cpp
+++ unittests/Basic/FileManagerTest.cpp
@@ -322,4 +322,40 @@
   EXPECT_EQ(Path, ExpectedResult);
 }
 
+/// When calling getVirtualFile then getFile for the same file, the real path
+/// should be computed (in other words, getVirtualFile should compute the real
+/// path).
+TEST_F(FileManagerTest, getVirtualFileThenGetFileRealPathName) {
+  SmallString<64> RealPath;
+  SmallString<64> NonRealPath;
+  SmallString<64> WorkingDirectory;
+
+#ifdef _WIN32
+  RealPath = "C:\\a\\b";
+  NonRealPath = "C:\\a\\..\\a\\b";
+  WorkingDirectory = "C:\\";
+#else
+  RealPath = "/a/b";
+  NonRealPath = "/a/../a/b";
+  WorkingDirectory = "/";
+#endif
+
+  auto FS =
+      IntrusiveRefCntPtr<vfs::InMemoryFileSystem>(new vfs::InMemoryFileSystem);
+  ASSERT_TRUE(!FS->setCurrentWorkingDirectory(WorkingDirectory));
+
+  FS->addFile(RealPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
+
+  FileSystemOptions Opts;
+  FileManager Manager(Opts, FS);
+
+  const FileEntry *VFE = Manager.getVirtualFile(NonRealPath, 0, 0);
+  ASSERT_TRUE(VFE != nullptr);
+  EXPECT_EQ(VFE->tryGetRealPathName(), RealPath);
+
+  const FileEntry *FE = Manager.getFile(NonRealPath);
+  ASSERT_TRUE(FE != nullptr);
+  EXPECT_EQ(FE->tryGetRealPathName(), RealPath);
+}
+
 } // anonymous namespace
Index: lib/Basic/FileManager.cpp
===================================================================
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -390,6 +390,11 @@
   UFE->UID     = NextFileUID++;
   UFE->IsValid = true;
   UFE->File.reset();
+
+  SmallString<128> RealPathName;
+  if (!FS->getRealPath(InterndFileName, RealPathName))
+    UFE->RealPathName = RealPathName.str();
+
   return UFE;
 }
 


Index: unittests/Basic/FileManagerTest.cpp
===================================================================
--- unittests/Basic/FileManagerTest.cpp
+++ unittests/Basic/FileManagerTest.cpp
@@ -322,4 +322,40 @@
   EXPECT_EQ(Path, ExpectedResult);
 }
 
+/// When calling getVirtualFile then getFile for the same file, the real path
+/// should be computed (in other words, getVirtualFile should compute the real
+/// path).
+TEST_F(FileManagerTest, getVirtualFileThenGetFileRealPathName) {
+  SmallString<64> RealPath;
+  SmallString<64> NonRealPath;
+  SmallString<64> WorkingDirectory;
+
+#ifdef _WIN32
+  RealPath = "C:\\a\\b";
+  NonRealPath = "C:\\a\\..\\a\\b";
+  WorkingDirectory = "C:\\";
+#else
+  RealPath = "/a/b";
+  NonRealPath = "/a/../a/b";
+  WorkingDirectory = "/";
+#endif
+
+  auto FS =
+      IntrusiveRefCntPtr<vfs::InMemoryFileSystem>(new vfs::InMemoryFileSystem);
+  ASSERT_TRUE(!FS->setCurrentWorkingDirectory(WorkingDirectory));
+
+  FS->addFile(RealPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
+
+  FileSystemOptions Opts;
+  FileManager Manager(Opts, FS);
+
+  const FileEntry *VFE = Manager.getVirtualFile(NonRealPath, 0, 0);
+  ASSERT_TRUE(VFE != nullptr);
+  EXPECT_EQ(VFE->tryGetRealPathName(), RealPath);
+
+  const FileEntry *FE = Manager.getFile(NonRealPath);
+  ASSERT_TRUE(FE != nullptr);
+  EXPECT_EQ(FE->tryGetRealPathName(), RealPath);
+}
+
 } // anonymous namespace
Index: lib/Basic/FileManager.cpp
===================================================================
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -390,6 +390,11 @@
   UFE->UID     = NextFileUID++;
   UFE->IsValid = true;
   UFE->File.reset();
+
+  SmallString<128> RealPathName;
+  if (!FS->getRealPath(InterndFileName, RealPathName))
+    UFE->RealPathName = RealPathName.str();
+
   return UFE;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to