Index: llvm/trunk/include/llvm/Support/FileSystem.h =================================================================== --- llvm/trunk/include/llvm/Support/FileSystem.h +++ llvm/trunk/include/llvm/Support/FileSystem.h @@ -349,6 +349,12 @@ std::error_code real_path(const Twine &path, SmallVectorImpl &output, bool expand_tilde = false); +/// Expands ~ expressions to the user's home directory. On Unix ~user +/// directories are resolved as well. +/// +/// @param path The path to resolve. +void expand_tilde(const Twine &path, SmallVectorImpl &output); + /// Get the current path. /// /// @param result Holds the current path on return. Index: llvm/trunk/lib/Support/Unix/Path.inc =================================================================== --- llvm/trunk/lib/Support/Unix/Path.inc +++ llvm/trunk/lib/Support/Unix/Path.inc @@ -550,6 +550,18 @@ llvm::sys::path::append(Path, Storage); } + +void expand_tilde(const Twine &path, SmallVectorImpl &dest) { + dest.clear(); + if (path.isTriviallyEmpty()) + return; + + path.toVector(dest); + expandTildeExpr(dest); + + return; +} + static file_type typeForMode(mode_t Mode) { if (S_ISDIR(Mode)) return file_type::directory_file; Index: llvm/trunk/lib/Support/Windows/Path.inc =================================================================== --- llvm/trunk/lib/Support/Windows/Path.inc +++ llvm/trunk/lib/Support/Windows/Path.inc @@ -1253,6 +1253,17 @@ Path.insert(Path.begin() + 1, HomeDir.begin() + 1, HomeDir.end()); } +void expand_tilde(const Twine &path, SmallVectorImpl &dest) { + dest.clear(); + if (path.isTriviallyEmpty()) + return; + + path.toVector(dest); + expandTildeExpr(dest); + + return; +} + std::error_code real_path(const Twine &path, SmallVectorImpl &dest, bool expand_tilde) { dest.clear(); Index: llvm/trunk/unittests/Support/Path.cpp =================================================================== --- llvm/trunk/unittests/Support/Path.cpp +++ llvm/trunk/unittests/Support/Path.cpp @@ -516,6 +516,8 @@ EXPECT_EQ(Expected, Actual); SmallString<64> HomeDir; + + // This can fail if $HOME is not set and getpwuid fails. bool Result = llvm::sys::path::home_directory(HomeDir); if (Result) { ASSERT_NO_ERROR(fs::real_path(HomeDir, Expected)); @@ -528,6 +530,25 @@ ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/test1")); } +TEST_F(FileSystemTest, ExpandTilde) { + SmallString<64> Expected; + SmallString<64> Actual; + SmallString<64> HomeDir; + + // This can fail if $HOME is not set and getpwuid fails. + bool Result = llvm::sys::path::home_directory(HomeDir); + if (Result) { + fs::expand_tilde(HomeDir, Expected); + + fs::expand_tilde("~", Actual); + EXPECT_EQ(Expected, Actual); + + path::append(Expected, "foo"); + fs::expand_tilde("~/foo", Actual); + EXPECT_EQ(Expected, Actual); + } +} + #ifdef LLVM_ON_UNIX TEST_F(FileSystemTest, RealPathNoReadPerm) { SmallString<64> Expanded;