From e9e76079745dc2eb9de11badacaa9665a2c39511 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 9 Jan 2016 16:33:16 +0000 Subject: [PATCH] [vfs] Normalize working directory if requested. FixedCompilationDatabase sets the working dir to "." by default. For chdir(".") this is a noop but this lead to InMemoryFileSystem to create bogus paths. Fixes PR25327. llvm-svn: 257260 --- clang/include/clang/Basic/VirtualFileSystem.h | 5 +---- clang/lib/Basic/VirtualFileSystem.cpp | 17 +++++++++++++++++ clang/unittests/Basic/VirtualFileSystemTest.cpp | 6 ++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/VirtualFileSystem.h b/clang/include/clang/Basic/VirtualFileSystem.h index 1df4947dd7e8..bab88c90b0a8 100644 --- a/clang/include/clang/Basic/VirtualFileSystem.h +++ b/clang/include/clang/Basic/VirtualFileSystem.h @@ -299,10 +299,7 @@ public: llvm::ErrorOr getCurrentWorkingDirectory() const override { return WorkingDirectory; } - std::error_code setCurrentWorkingDirectory(const Twine &Path) override { - WorkingDirectory = Path.str(); - return std::error_code(); - } + std::error_code setCurrentWorkingDirectory(const Twine &Path) override; }; /// \brief Get a globally unique ID for a virtual file or directory. diff --git a/clang/lib/Basic/VirtualFileSystem.cpp b/clang/lib/Basic/VirtualFileSystem.cpp index cf5a8d681eac..6977f400287f 100644 --- a/clang/lib/Basic/VirtualFileSystem.cpp +++ b/clang/lib/Basic/VirtualFileSystem.cpp @@ -658,6 +658,23 @@ directory_iterator InMemoryFileSystem::dir_begin(const Twine &Dir, EC = make_error_code(llvm::errc::not_a_directory); return directory_iterator(std::make_shared()); } + +std::error_code InMemoryFileSystem::setCurrentWorkingDirectory(const Twine &P) { + SmallString<128> Path; + P.toVector(Path); + + // Fix up relative paths. This just prepends the current working directory. + std::error_code EC = makeAbsolute(Path); + assert(!EC); + (void)EC; + + if (useNormalizedPaths()) + llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true); + + if (!Path.empty()) + WorkingDirectory = Path.str(); + return std::error_code(); +} } } diff --git a/clang/unittests/Basic/VirtualFileSystemTest.cpp b/clang/unittests/Basic/VirtualFileSystemTest.cpp index ac07035d3e1f..b72b757b5ffc 100644 --- a/clang/unittests/Basic/VirtualFileSystemTest.cpp +++ b/clang/unittests/Basic/VirtualFileSystemTest.cpp @@ -657,6 +657,12 @@ TEST_F(InMemoryFileSystemTest, WorkingDirectory) { Stat = FS.status("c"); ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString(); + + NormalizedFS.setCurrentWorkingDirectory("/b/c"); + NormalizedFS.setCurrentWorkingDirectory("."); + ASSERT_EQ("/b/c", NormalizedFS.getCurrentWorkingDirectory().get()); + NormalizedFS.setCurrentWorkingDirectory(".."); + ASSERT_EQ("/b", NormalizedFS.getCurrentWorkingDirectory().get()); } // NOTE: in the tests below, we use '//root/' as our root directory, since it is