Hello, this patch fixes loading files on Windows with a path without subdirectories (like 'C:\foo.cpp'). Without the patch, the trailing path separator is stripped and stat() fails for 'C:'.
-- Nico
From c2142af3102060a7105ec9ef9432f12c5308f7dc Mon Sep 17 00:00:00 2001 From: Nico Rieck <[email protected]> Date: Sun, 12 Feb 2012 02:10:30 +0100 Subject: [PATCH] Support/FileSystem: Add path::is_root_path Used by clang to not strip trailing path separators from Windows drives. --- include/llvm/Support/PathV2.h | 6 ++++++ lib/Support/PathV2.cpp | 14 ++++++++++++++ unittests/Support/Path.cpp | 1 + 3 files changed, 21 insertions(+), 0 deletions(-) diff --git a/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h index 6d38c95..78fac8f 100644 --- a/include/llvm/Support/PathV2.h +++ b/include/llvm/Support/PathV2.h @@ -283,6 +283,12 @@ void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result); /// @result True if the path has a root name, false otherwise. bool has_root_name(const Twine &path); +/// @brief Check whether the path is a root path (excludes network paths). +/// +/// @param path Input path. +/// @result True if \a path is a root path, false otherwise. +bool is_root_path(StringRef path); + /// @brief Has root directory? /// /// root_directory != "" diff --git a/lib/Support/PathV2.cpp b/lib/Support/PathV2.cpp index 3ef13e2..0901945 100644 --- a/lib/Support/PathV2.cpp +++ b/lib/Support/PathV2.cpp @@ -519,6 +519,20 @@ void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) { result.append(DefaultResult, DefaultResult + strlen(DefaultResult)); } +bool is_root_path(StringRef path) { + switch (path.size()) { + // POSIX style + case 1: return is_separator(path[0]); +#ifdef LLVM_ON_WIN32 + // C: + case 2: return path.endswith(":"); + // C:/ + case 3: return path[1] == ':' && is_separator(path[2]); +#endif + default: return false; + } +} + bool has_root_name(const Twine &path) { SmallString<128> path_storage; StringRef p = path.toStringRef(path_storage); diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 358dad0..9107bb1 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -108,6 +108,7 @@ TEST(Support, Path) { #endif path::has_root_path(*i); + path::is_root_path(*i); path::root_path(*i); path::has_root_name(*i); path::root_name(*i); -- 1.7.8.msysgit.0
From c44d558a045828b23b4c481321c110cc995a3ba4 Mon Sep 17 00:00:00 2001 From: Nico Rieck <[email protected]> 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
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
