]> granicus.if.org Git - clang/commitdiff
Fix handling of "clang c:foo"
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 29 Jul 2013 15:47:24 +0000 (15:47 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 29 Jul 2013 15:47:24 +0000 (15:47 +0000)
On windows, c:foo is a valid file path, but stat fails on just "c:". This
causes a problem for clang since its file manager wants to cache data about
the parent directory.

There are refactorings to be done in here, but this gives clang the correct
behavior and testing first.

Patch by Yunzhong Gao!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187359 91177308-0d34-0410-b5e6-96231b3b80d8

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

index d8deac72c4672c795c2b04b574905ceb8e16899c..651a7a430a36b71288be8dc4e5984ed0a53984ab 100644 (file)
@@ -292,6 +292,16 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
       DirName != llvm::sys::path::root_path(DirName) &&
       llvm::sys::path::is_separator(DirName.back()))
     DirName = DirName.substr(0, DirName.size()-1);
+#ifdef LLVM_ON_WIN32
+  // Fixing a problem with "clang C:test.c" on Windows.
+  // Stat("C:") does not recognize "C:" as a valid directory
+  std::string DirNameStr;
+  if (DirName.size() > 1 && DirName.back() == ':' &&
+      DirName.equals_lower(llvm::sys::path::root_name(DirName))) {
+    DirNameStr = DirName.str() + '.';
+    DirName = DirNameStr;
+  }
+#endif
 
   ++NumDirLookups;
   llvm::StringMapEntry<DirectoryEntry *> &NamedDirEnt =
index a55fcbf76cf8e0f6796e6096b3cd7afd9e194202..d86c96f5a2ce02bfd630677ab4cc6064d834048a 100644 (file)
@@ -125,6 +125,14 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
   FakeStatCache *statCache = new FakeStatCache;
   statCache->InjectDirectory("/tmp", 42);
   statCache->InjectFile("/tmp/test", 43);
+
+#ifdef _WIN32
+  const char *DirName = "C:.";
+  const char *FileName = "C:test";
+  statCache->InjectDirectory(DirName, 44);
+  statCache->InjectFile(FileName, 45);
+#endif
+
   manager.addStatCache(statCache);
 
   const FileEntry *file = manager.getFile("/tmp/test");
@@ -134,6 +142,15 @@ TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
   const DirectoryEntry *dir = file->getDir();
   ASSERT_TRUE(dir != NULL);
   EXPECT_STREQ("/tmp", dir->getName());
+
+#ifdef _WIN32
+  file = manager.getFile(FileName);
+  ASSERT_TRUE(file != NULL);
+
+  dir = file->getDir();
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ(DirName, dir->getName());
+#endif
 }
 
 // getFile() returns non-NULL if a virtual file exists at the given path.