From c44d558a045828b23b4c481321c110cc995a3ba4 Mon Sep 17 00:00:00 2001
From: Nico Rieck <nico.rieck@gmail.com>
Date: Sun, 12 Feb 2012 01:48:21 +0100
Subject: [PATCH] Basic: Handle windows drives in FileManager::getDirectory

---
 lib/Basic/FileManager.cpp           |    5 +++--
 unittests/Basic/FileManagerTest.cpp |   21 +++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index fd6d334..768931c 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -267,8 +267,9 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
                                                 bool CacheFailure) {
   // stat doesn't like trailing separators.
   // At least, on Win32 MSVCRT, stat() cannot strip trailing '/'.
-  // (though it can strip '\\')
-  if (DirName.size() > 1 && llvm::sys::path::is_separator(DirName.back()))
+  // (though it can strip '\\') Do not strip it for root paths like 'C:/'.
+  if (DirName.size() > 1 && llvm::sys::path::is_separator(DirName.back())
+      && !llvm::sys::path::is_root_path(DirName))
     DirName = DirName.substr(0, DirName.size()-1);
 
   ++NumDirLookups;
diff --git a/unittests/Basic/FileManagerTest.cpp b/unittests/Basic/FileManagerTest.cpp
index 91998b6..a2f0839 100644
--- a/unittests/Basic/FileManagerTest.cpp
+++ b/unittests/Basic/FileManagerTest.cpp
@@ -218,6 +218,27 @@ TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
   EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
 }
 
+#else
+
+// The following tests apply to Windows only.
+
+// getDirectory() accepts drive names.
+TEST_F(FileManagerTest, getDirectoryAcceptsWindowsDrive) {
+  // Inject two real files with the same inode.
+  FakeStatCache *statCache = new FakeStatCache;
+  // Path separators are not normalized, so both variants could occur.
+  statCache->InjectDirectory("c:\\", 41);
+  statCache->InjectDirectory("d:/", 42);
+  manager.addStatCache(statCache);
+
+  const DirectoryEntry *drive_c = manager.getDirectory("c:\\");
+  const DirectoryEntry *drive_d = manager.getDirectory("d:/");
+  ASSERT_TRUE(drive_c != NULL);
+  ASSERT_TRUE(drive_d != NULL);
+  EXPECT_STREQ("c:\\", drive_c->getName());
+  EXPECT_STREQ("d:/", drive_d->getName());
+}
+
 #endif  // !_WIN32
 
 } // anonymous namespace
-- 
1.7.8.msysgit.0

