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(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