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

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 25 21:38:45 PDT 2024


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

>From 9774e7e97eb01e8b33c1820e9daec3b1fd64dce5 Mon Sep 17 00:00:00 2001
From: RichardLuo <22096448+RichardLuo0 at users.noreply.github.com>
Date: Mon, 22 Jul 2024 13:12:33 +0800
Subject: [PATCH 1/3] [libc++] fix the state when its in root dir in
 lexically_relative

---
 libcxx/src/filesystem/path.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/src/filesystem/path.cpp b/libcxx/src/filesystem/path.cpp
index b2019521377ed..eefd8b22dfd69 100644
--- a/libcxx/src/filesystem/path.cpp
+++ b/libcxx/src/filesystem/path.cpp
@@ -267,7 +267,7 @@ path path::lexically_relative(const path& base) const {
   // Find the first mismatching element
   auto PP     = PathParser::CreateBegin(__pn_);
   auto PPBase = PathParser::CreateBegin(base.__pn_);
-  while (PP && PPBase && PP.State_ == PPBase.State_ && *PP == *PPBase) {
+  while (PP && PPBase && PP.State_ == PPBase.State_ && (*PP == *PPBase || PP.inRootDir())) {
     ++PP;
     ++PPBase;
   }

>From 77beb3514ac12dd284aed5d4d771174b49a1b7f1 Mon Sep 17 00:00:00 2001
From: RichardLuo <22096448+RichardLuo0 at users.noreply.github.com>
Date: Fri, 26 Jul 2024 12:36:46 +0800
Subject: [PATCH 2/3] [libc++] add lexically_relative and _proximate test

---
 .../path.gen/lexically_relative_and_proximate.pass.cpp          | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp
index 42fa813ada4a5..06954fe876e55 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp
@@ -41,9 +41,11 @@ int main(int, char**) {
 #ifdef _WIN32
       {"//net/", "//net", ""},
       {"//net", "//net/", ""},
+      {"C:\\a\\b", "C:/a", "b"},
 #else
       {"//net/", "//net", "."},
       {"//net", "//net/", "."},
+      {"C:\\a\\b", "C:/a", "../../C:\\a\\b"},
 #endif
       {"//base", "a", ""},
       {"a", "a", "."},

>From 9f2b4b6c787e0a143d34fcebae8267617fe9e73b Mon Sep 17 00:00:00 2001
From: RichardLuo <22096448+RichardLuo0 at users.noreply.github.com>
Date: Fri, 26 Jul 2024 12:37:53 +0800
Subject: [PATCH 3/3] [libc++] fix incorrect hash value in root dir

---
 libcxx/src/filesystem/path.cpp                |  3 +-
 .../path.member/path.compare.pass.cpp         | 60 +++++++++++--------
 2 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/libcxx/src/filesystem/path.cpp b/libcxx/src/filesystem/path.cpp
index eefd8b22dfd69..58742442bae6b 100644
--- a/libcxx/src/filesystem/path.cpp
+++ b/libcxx/src/filesystem/path.cpp
@@ -368,7 +368,8 @@ size_t hash_value(const path& __p) noexcept {
   size_t hash_value = 0;
   hash<string_view_t> hasher;
   while (PP) {
-    hash_value = __hash_combine(hash_value, hasher(*PP));
+    string_view_t Part = PP.inRootDir() ? PATHSTR("/") : *PP;
+    hash_value         = __hash_combine(hash_value, hasher(Part));
     ++PP;
   }
   return hash_value;
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp
index 99f55d3b17f1b..3bebf38a2a7c3 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp
@@ -47,13 +47,20 @@ struct PathCompareTest {
   int expect;
 };
 
-#define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-#define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
-#define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
-#define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
-const PathCompareTest CompareTestCases[] =
-{
-    {"", "",  0},
+#define LONGA                                                                                                          \
+  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \
+  "AAAAAAAA"
+#define LONGB                                                                                                          \
+  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" \
+  "BBBBBBBB"
+#define LONGC                                                                                                          \
+  "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" \
+  "CCCCCCCC"
+#define LONGD                                                                                                          \
+  "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" \
+  "DDDDDDDD"
+const PathCompareTest CompareTestCases[] = {
+    {"", "", 0},
     {"a", "", 1},
     {"", "a", -1},
     {"a/b/c", "a/b/c", 0},
@@ -62,14 +69,19 @@ const PathCompareTest CompareTestCases[] =
     {"a/b", "a/b/c", -1},
     {"a/b/c", "a/b", 1},
     {"a/b/", "a/b/.", -1},
-    {"a/b/", "a/b",    1},
+    {"a/b/", "a/b", 1},
     {"a/b//////", "a/b/////.", -1},
     {"a/.././b", "a///..//.////b", 0},
     {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators
-    {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory
-    {"/foo/bar/", "/foo/bar", 1}, // trailing separator
+    {"///foo/bar", "/foo/bar", 0},                 // "///" is not a root directory
+    {"/foo/bar/", "/foo/bar", 1},                  // trailing separator
     {"foo", "/foo", -1}, // if !this->has_root_directory() and p.has_root_directory(), a value less than 0.
-    {"/foo", "foo", 1}, //  if this->has_root_directory() and !p.has_root_directory(), a value greater than 0.
+    {"/foo", "foo", 1},  //  if this->has_root_directory() and !p.has_root_directory(), a value greater than 0.
+#ifdef _WIN32
+    {"C:/a", "C:\\a", 0},
+#else
+    {"C:/a", "C:\\a", -1},
+#endif
     {("//" LONGA "////" LONGB "/" LONGC "///" LONGD), ("//" LONGA "/" LONGB "/" LONGC "/" LONGD), 0},
     {(LONGA "/" LONGB "/" LONGC), (LONGA "/" LONGB "/" LONGB), 1}
 
@@ -79,23 +91,19 @@ const PathCompareTest CompareTestCases[] =
 #undef LONGC
 #undef LONGD
 
-static inline int normalize_ret(int ret)
-{
-  return ret < 0 ? -1 : (ret > 0 ? 1 : 0);
-}
+static inline int normalize_ret(int ret) { return ret < 0 ? -1 : (ret > 0 ? 1 : 0); }
 
-void test_compare_basic()
-{
+void test_compare_basic() {
   using namespace fs;
-  for (auto const & TC : CompareTestCases) {
+  for (auto const& TC : CompareTestCases) {
     const path p1(TC.LHS);
     const path p2(TC.RHS);
     std::string RHS(TC.RHS);
     const path::string_type R(RHS.begin(), RHS.end());
     const std::basic_string_view<path::value_type> RV(R);
-    const path::value_type *Ptr = R.c_str();
-    const int E = TC.expect;
-    { // compare(...) functions
+    const path::value_type* Ptr = R.c_str();
+    const int E                 = TC.expect;
+    {                           // compare(...) functions
       DisableAllocationGuard g; // none of these operations should allocate
 
       // check runtime results
@@ -113,7 +121,7 @@ void test_compare_basic()
       // check signatures
       ASSERT_NOEXCEPT(p1.compare(p2));
     }
-    { // comparison operators
+    {                           // comparison operators
       DisableAllocationGuard g; // none of these operations should allocate
 
       // check signatures
@@ -180,14 +188,14 @@ void test_compare_elements() {
 
   auto BuildPath = [](std::vector<std::string> const& Elems) {
     fs::path p;
-    for (auto &E : Elems)
+    for (auto& E : Elems)
       p /= E;
     return p;
   };
 
-  for (auto &TC : TestCases) {
-    fs::path LHS = BuildPath(TC.LHSElements);
-    fs::path RHS = BuildPath(TC.RHSElements);
+  for (auto& TC : TestCases) {
+    fs::path LHS        = BuildPath(TC.LHSElements);
+    fs::path RHS        = BuildPath(TC.RHSElements);
     const int ExpectCmp = CompareElements(TC.LHSElements, TC.RHSElements);
     assert(ExpectCmp == TC.Expect);
     const int GotCmp = normalize_ret(LHS.compare(RHS));



More information about the libcxx-commits mailing list