]> granicus.if.org Git - clang/commitdiff
Do not resolve directory junctions for `-fdiagnostics-absolute-paths` on Windows.
authorIgor Kudrin <ikudrin@accesssoftek.com>
Fri, 24 May 2019 04:46:22 +0000 (04:46 +0000)
committerIgor Kudrin <ikudrin@accesssoftek.com>
Fri, 24 May 2019 04:46:22 +0000 (04:46 +0000)
If the source file path contains directory junctions, and we resolve them when
printing diagnostic messages, these paths look independent for an IDE.
For example, both Visual Studio and Visual Studio Code open separate editors
for such paths, which is not only inconvenient but might even result in losing
changes made in one of them.

Differential Revision: https://reviews.llvm.org/D59415

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

lib/Frontend/TextDiagnostic.cpp
test/Frontend/absolute-paths-windows.test [new file with mode: 0644]
test/Frontend/lit.local.cfg

index c6ebdcaf9a8fa572bb6f77661fafdfc1aebad5fa..d0c91286250e73860cfbd8de1f369673247bfdaa 100644 (file)
@@ -765,7 +765,28 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) {
     const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
         llvm::sys::path::parent_path(Filename));
     if (Dir) {
+      // We want to print a simplified absolute path, i. e. without "dots".
+      //
+      // The hardest part here are the paths like "<part1>/<link>/../<part2>".
+      // On Unix-like systems, we cannot just collapse "<link>/..", because
+      // paths are resolved sequentially, and, thereby, the path
+      // "<part1>/<part2>" may point to a different location. That is why
+      // we use FileManager::getCanonicalName(), which expands all indirections
+      // with llvm::sys::fs::real_path() and caches the result.
+      //
+      // On the other hand, it would be better to preserve as much of the
+      // original path as possible, because that helps a user to recognize it.
+      // real_path() expands all links, which sometimes too much. Luckily,
+      // on Windows we can just use llvm::sys::path::remove_dots(), because,
+      // on that system, both aforementioned paths point to the same place.
+#ifdef _WIN32
+      SmallString<4096> DirName = Dir->getName();
+      llvm::sys::fs::make_absolute(DirName);
+      llvm::sys::path::native(DirName);
+      llvm::sys::path::remove_dots(DirName, /* remove_dot_dot */ true);
+#else
       StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
+#endif
       llvm::sys::path::append(AbsoluteFilename, DirName,
                               llvm::sys::path::filename(Filename));
       Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size());
diff --git a/test/Frontend/absolute-paths-windows.test b/test/Frontend/absolute-paths-windows.test
new file mode 100644 (file)
index 0000000..10741d5
--- /dev/null
@@ -0,0 +1,9 @@
+// REQUIRES: system-windows
+// RUN: rm -rf %t.dir
+// RUN: mkdir -p %t.dir\real
+// RUN: cmd /c mklink /j %t.dir\junc %t.dir\real
+// RUN: echo "wrong code" > %t.dir\real\foo.cpp
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-absolute-paths %t.dir\junc\foo.cpp 2>&1 | FileCheck %s
+
+// CHECK-NOT: .dir\real\foo.cpp
+// CHECK: .dir\junc\foo.cpp
index 7a05c5dfd25974ac2a9045cbc26a4d608a8083c6..835360be27551adf1444ef6a2eb36f64d4684e21 100644 (file)
@@ -1 +1 @@
-config.suffixes = ['.c', '.cpp', '.m', '.mm', '.ll', '.cl']
+config.suffixes = ['.c', '.cpp', '.m', '.mm', '.ll', '.cl', '.test']