[clang] [clang-tools-extra] [Tooling] Preserve backslashes in POSIX source paths (PR #207499)

Zeyi Xu via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 6 18:58:10 PDT 2026


https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/207499

>From 247afadb3971244f036f86c58267c6b158f6644d Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Sat, 4 Jul 2026 16:57:31 +0800
Subject: [PATCH 1/2] [Tooling] Preserve backslashes in POSIX source paths

---
 clang/lib/Tooling/Tooling.cpp           |  2 +-
 clang/unittests/Tooling/ToolingTest.cpp | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 5da9c31ec47ec..71307d1fe7307 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -260,7 +260,7 @@ llvm::Expected<std::string> getAbsolutePath(llvm::vfs::FileSystem &FS,
   SmallString<1024> AbsolutePath = RelativePath;
   if (auto EC = FS.makeAbsolute(AbsolutePath))
     return llvm::errorCodeToError(EC);
-  llvm::sys::path::native(AbsolutePath);
+  llvm::sys::path::make_preferred(AbsolutePath);
   return std::string(AbsolutePath);
 }
 
diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp
index c3b8ffa00924e..aee46dc2e2c63 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -686,6 +686,26 @@ TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
       {"-fcolor-diagnostics"}));
 }
 
+#if !defined(_WIN32)
+TEST(getAbsolutePath, PosixPreservesBackslashes) {
+  auto FS = llvm::vfs::getRealFileSystem();
+  llvm::Expected<std::string> Path = getAbsolutePath(*FS, "a\\b.cc");
+  if (!Path)
+    FAIL() << llvm::toString(Path.takeError());
+
+  llvm::ErrorOr<std::string> CWD = FS->getCurrentWorkingDirectory();
+  ASSERT_TRUE(CWD) << CWD.getError().message();
+
+  SmallString<128> Expected(*CWD);
+  llvm::sys::path::append(Expected, "a\\b.cc");
+  SmallString<128> WithSlash(*CWD);
+  llvm::sys::path::append(WithSlash, "a/b.cc");
+
+  EXPECT_EQ(std::string(Expected), *Path);
+  EXPECT_NE(std::string(WithSlash), *Path);
+}
+#endif
+
 TEST(ClangToolTest, ArgumentAdjusters) {
   FixedCompilationDatabase Compilations("/", std::vector<std::string>());
 

>From 69fe3414afb5df54ca4017ae01c9c335c328c501 Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Tue, 7 Jul 2026 09:57:46 +0800
Subject: [PATCH 2/2] address review feedback

---
 clang-tools-extra/docs/ReleaseNotes.rst |  3 +++
 clang/unittests/Tooling/ToolingTest.cpp | 12 ++++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2a980cc089a65..1df3799039bcb 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -202,6 +202,9 @@ Improvements to clang-tidy
 - Improved :program:`clang-tidy` ``-store-check-profile`` by generating valid
   JSON when the source file path contains characters that require JSON escaping.
 
+- Improved :program:`clang-tidy` by preserving literal backslash characters in
+  POSIX source paths.
+
 - Ensured that :program:`clang-tidy` and the clang compiler uses the same logic
   for the suppression of compiler diagnostics in system headers and expansions
   of macros defined in system headers. Previously the default setting of tidy
diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp
index aee46dc2e2c63..352588fc31a01 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -686,8 +686,7 @@ TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
       {"-fcolor-diagnostics"}));
 }
 
-#if !defined(_WIN32)
-TEST(getAbsolutePath, PosixPreservesBackslashes) {
+TEST(getAbsolutePath, BackslashPath) {
   auto FS = llvm::vfs::getRealFileSystem();
   llvm::Expected<std::string> Path = getAbsolutePath(*FS, "a\\b.cc");
   if (!Path)
@@ -696,15 +695,20 @@ TEST(getAbsolutePath, PosixPreservesBackslashes) {
   llvm::ErrorOr<std::string> CWD = FS->getCurrentWorkingDirectory();
   ASSERT_TRUE(CWD) << CWD.getError().message();
 
+#if defined(_WIN32)
+  SmallString<128> Expected(*CWD);
+  llvm::sys::path::append(Expected, "a", "b.cc");
+  llvm::sys::path::make_preferred(Expected);
+  EXPECT_EQ(std::string(Expected), *Path);
+#else
   SmallString<128> Expected(*CWD);
   llvm::sys::path::append(Expected, "a\\b.cc");
   SmallString<128> WithSlash(*CWD);
   llvm::sys::path::append(WithSlash, "a/b.cc");
-
   EXPECT_EQ(std::string(Expected), *Path);
   EXPECT_NE(std::string(WithSlash), *Path);
-}
 #endif
+}
 
 TEST(ClangToolTest, ArgumentAdjusters) {
   FixedCompilationDatabase Compilations("/", std::vector<std::string>());



More information about the cfe-commits mailing list