[libcxx-commits] [libcxx] [libc++] Fix different slashes confuses lexically_proximate and lexically_relative (PR #99780)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jul 20 12:36:52 PDT 2024


https://github.com/RichardLuo0 created https://github.com/llvm/llvm-project/pull/99780

```cpp
#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;
using path = fs::path;

int main() {
  path p("C:/Users/xxx/program/something.json");
  for (const auto &f : p)
    std::cout << f << std::endl;
  std::cout << p << std::endl;
  path p2("C:\\Users\\xxx\\program");
  for (const auto &f : p2)
    std::cout << f << std::endl;
  std::cout << p.lexically_proximate(p2) << std::endl;
  std::cout << p.make_preferred().lexically_proximate(p2) << std::endl;
}
```
The above code produces the following result on Windows:
```
"C:"
"/"
"Users"
"xxx"
"program"
"something.json"
"C:/Users/xxx/program/something.json"
"C:"
"\\"
"Users"
"xxx"
"program"
"/Users\\xxx\\program\\something.json"
"something.json"
```

lexically_proximate thinks that the second folder (the root) is different. However, they are seen as the same thing on windows.
This also raises another issue: lexically_proximate returns an absolute path when it should return a relative one.

I think we have two solutions:
1. As my PR proposed, make PS_InRootDir always return "/". If you look at https://en.cppreference.com/w/cpp/filesystem/path/begin. Their example has the same behavior. It also prevents other potential issues and saves users time in dealing with different slashes for root dir. But I don't know if this is standard or if this causes other issues.
2. Change the implementation of lexically_relative(). Take special care of the PS_InRootDir state.

>From 6e40c544bfa33923c766ff7459af3e377b79cbf9 Mon Sep 17 00:00:00 2001
From: RichardLuo <22096448+RichardLuo0 at users.noreply.github.com>
Date: Sun, 21 Jul 2024 03:12:56 +0800
Subject: [PATCH] [libc++] Use forward slash for root dir to fix
 lexically_relative on windows

---
 libcxx/src/filesystem/path_parser.h | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/libcxx/src/filesystem/path_parser.h b/libcxx/src/filesystem/path_parser.h
index 06623696452da..b38df13a3f7df 100644
--- a/libcxx/src/filesystem/path_parser.h
+++ b/libcxx/src/filesystem/path_parser.h
@@ -174,10 +174,7 @@ struct PathParser {
     case PS_AtEnd:
       return PATHSTR("");
     case PS_InRootDir:
-      if (RawEntry[0] == '\\')
-        return PATHSTR("\\");
-      else
-        return PATHSTR("/");
+      return PATHSTR("/");
     case PS_InTrailingSep:
       return PATHSTR("");
     case PS_InRootName:



More information about the libcxx-commits mailing list