ioeric created this revision.
ioeric added a reviewer: bkramer.
Herald added a subscriber: cfe-commits.

Generally, canonical paths are expected to be absolute. This is the
behavior for Windows build. But for unix, it might return relative paths when
failing to resolve real path (e.g. unsupported symlink on VFS).


Repository:
  rC Clang

https://reviews.llvm.org/D46942

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,35 @@
   EXPECT_EQ(Path, ExpectedResult);
 }
 
+TEST_F(FileManagerTest, GetCanonicalNameReturnsAbsolutePathOnVFS) {
+  SmallString<64> CustomWorkingDir;
+#ifdef _WIN32
+  CustomWorkingDir = "C:\\test";
+#else
+  CustomWorkingDir = "/test";
+#endif
+  llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path");
+
+  auto FS =
+      IntrusiveRefCntPtr<vfs::InMemoryFileSystem>(new vfs::InMemoryFileSystem);
+  // setCurrentworkingdirectory must finish without error.
+  ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
+  SmallString<64> FooPath("weird/foo/foo.cpp");
+  FS->addFile(FooPath.str(), 0, llvm::MemoryBuffer::getMemBuffer(""));
+
+  FileSystemOptions Opts;
+  FileManager Manager(Opts, FS);
+
+  // Use relative path to open the directory.
+  const DirectoryEntry *Dir =
+      Manager.getDirectory(llvm::sys::path::parent_path(FooPath.str()));
+  EXPECT_TRUE(Dir != nullptr);
+  EXPECT_FALSE(llvm::sys::path::is_absolute(Dir->getName()));
+
+  SmallString<64> AbsFooPath(CustomWorkingDir);
+  llvm::sys::path::append(AbsFooPath, FooPath);
+  EXPECT_EQ(Manager.getCanonicalName(Dir),
+            llvm::sys::path::parent_path(AbsFooPath.str()));
+}
+
 } // anonymous namespace
Index: lib/Basic/FileManager.cpp
===================================================================
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -532,15 +532,17 @@
   if (Known != CanonicalDirNames.end())
     return Known->second;
 
-  StringRef CanonicalName(Dir->getName());
+  // Canonical name should still be an absolute path even if realpath fails.
+  llvm::SmallString<128> AbsDirPath(Dir->getName());
+  makeAbsolutePath(AbsDirPath);
+  StringRef CanonicalName = AbsDirPath.str().copy(CanonicalNameStorage);
 
 #ifdef LLVM_ON_UNIX
   char CanonicalNameBuf[PATH_MAX];
-  if (realpath(Dir->getName().str().c_str(), CanonicalNameBuf))
+  if (realpath(AbsDirPath.c_str(), CanonicalNameBuf))
     CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
 #else
   SmallString<256> CanonicalNameBuf(CanonicalName);
-  llvm::sys::fs::make_absolute(CanonicalNameBuf);
   llvm::sys::path::native(CanonicalNameBuf);
   // We've run into needing to remove '..' here in the wild though, so
   // remove it.


Index: unittests/Basic/FileManagerTest.cpp
===================================================================
--- unittests/Basic/FileManagerTest.cpp
+++ unittests/Basic/FileManagerTest.cpp
@@ -322,4 +322,35 @@
   EXPECT_EQ(Path, ExpectedResult);
 }
 
+TEST_F(FileManagerTest, GetCanonicalNameReturnsAbsolutePathOnVFS) {
+  SmallString<64> CustomWorkingDir;
+#ifdef _WIN32
+  CustomWorkingDir = "C:\\test";
+#else
+  CustomWorkingDir = "/test";
+#endif
+  llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path");
+
+  auto FS =
+      IntrusiveRefCntPtr<vfs::InMemoryFileSystem>(new vfs::InMemoryFileSystem);
+  // setCurrentworkingdirectory must finish without error.
+  ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
+  SmallString<64> FooPath("weird/foo/foo.cpp");
+  FS->addFile(FooPath.str(), 0, llvm::MemoryBuffer::getMemBuffer(""));
+
+  FileSystemOptions Opts;
+  FileManager Manager(Opts, FS);
+
+  // Use relative path to open the directory.
+  const DirectoryEntry *Dir =
+      Manager.getDirectory(llvm::sys::path::parent_path(FooPath.str()));
+  EXPECT_TRUE(Dir != nullptr);
+  EXPECT_FALSE(llvm::sys::path::is_absolute(Dir->getName()));
+
+  SmallString<64> AbsFooPath(CustomWorkingDir);
+  llvm::sys::path::append(AbsFooPath, FooPath);
+  EXPECT_EQ(Manager.getCanonicalName(Dir),
+            llvm::sys::path::parent_path(AbsFooPath.str()));
+}
+
 } // anonymous namespace
Index: lib/Basic/FileManager.cpp
===================================================================
--- lib/Basic/FileManager.cpp
+++ lib/Basic/FileManager.cpp
@@ -532,15 +532,17 @@
   if (Known != CanonicalDirNames.end())
     return Known->second;
 
-  StringRef CanonicalName(Dir->getName());
+  // Canonical name should still be an absolute path even if realpath fails.
+  llvm::SmallString<128> AbsDirPath(Dir->getName());
+  makeAbsolutePath(AbsDirPath);
+  StringRef CanonicalName = AbsDirPath.str().copy(CanonicalNameStorage);
 
 #ifdef LLVM_ON_UNIX
   char CanonicalNameBuf[PATH_MAX];
-  if (realpath(Dir->getName().str().c_str(), CanonicalNameBuf))
+  if (realpath(AbsDirPath.c_str(), CanonicalNameBuf))
     CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
 #else
   SmallString<256> CanonicalNameBuf(CanonicalName);
-  llvm::sys::fs::make_absolute(CanonicalNameBuf);
   llvm::sys::path::native(CanonicalNameBuf);
   // We've run into needing to remove '..' here in the wild though, so
   // remove it.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to