[llvm] llvm-ar: fix inconsistent case sensitivity for path matching on Windows (PR #196541)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 07:05:41 PDT 2026


https://github.com/0xFE4415 updated https://github.com/llvm/llvm-project/pull/196541

>From ef5eb93be6c57324a338e445ec61bd4c165409ea Mon Sep 17 00:00:00 2001
From: Luna <259395 at student.pwr.edu.pl>
Date: Sat, 2 May 2026 22:43:39 +0200
Subject: [PATCH 1/3] extended test

---
 .../test/tools/llvm-ar/windows-name-case.test | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/llvm/test/tools/llvm-ar/windows-name-case.test b/llvm/test/tools/llvm-ar/windows-name-case.test
index 970a3e616d3c7..4b93e203ca21c 100644
--- a/llvm/test/tools/llvm-ar/windows-name-case.test
+++ b/llvm/test/tools/llvm-ar/windows-name-case.test
@@ -27,3 +27,34 @@
 # RUN: FileCheck %s -input-file=%t/thin-archive.a --check-prefix=EMPTY --implicit-check-not {{.}}
 
 EMPTY: !<thin>
+
+# File instance counting should respect Windows case-insensitive name matching.
+# Otherwise, if you have foo.txt and FOO.TXT, "-N 2 foo.txt" fails with because
+# file is not found.
+
+# RUN: mkdir -p %t/a %t/b
+# RUN: echo first > %t/a/foo.txt
+# RUN: echo second > %t/b/FOO.TXT
+# RUN: llvm-ar rc %t/count-case.a %t/a/foo.txt %t/b/FOO.TXT
+
+# RUN: mkdir -p %t/out1 %t/out2
+# RUN: llvm-ar xN 1 --output %t/out1 %t/count-case.a foo.txt
+# RUN: cat %t/out1/foo.txt | FileCheck %s --check-prefix=EXTRACT-FIRST
+# RUN: llvm-ar xN 2 --output %t/out2 %t/count-case.a foo.txt
+# RUN: cat %t/out2/FOO.TXT | FileCheck %s --check-prefix=EXTRACT-SECOND
+# RUN: not llvm-ar xN 3 --output %t/out2 %t/count-case.a foo.txt 2>&1 | FileCheck %s --check-prefix=EXTRACT-NOT-FOUND
+
+# EXTRACT-FIRST: first
+# EXTRACT-SECOND: second
+# EXTRACT-NOT-FOUND: error: 'foo.txt' was not found
+
+# RUN: rm -f %t/delete-count.a
+# RUN: llvm-ar rc %t/delete-count.a %t/a/foo.txt %t/b/FOO.TXT
+# RUN: llvm-ar dN 2 %t/delete-count.a foo.txt
+# RUN: llvm-ar t %t/delete-count.a | FileCheck %s --check-prefix=DELETE-SECOND
+# RUN: llvm-ar dN 1 %t/delete-count.a FOO.TXT
+# RUN: llvm-ar t %t/delete-count.a | FileCheck %s --check-prefix=DELETE-EMPTY --allow-empty
+
+# DELETE-SECOND: foo.txt
+# DELETE-SECOND-NOT: FOO.TXT
+# DELETE-EMPTY-NOT: foo.txt

>From 8b9e7cdb3ba2dcc1c064033391066f1c1f09464e Mon Sep 17 00:00:00 2001
From: Luna <259395 at student.pwr.edu.pl>
Date: Sat, 2 May 2026 22:43:39 +0200
Subject: [PATCH 2/3] Fix llvm-ar CountParam matching for normalized paths.

---
 llvm/tools/llvm-ar/llvm-ar.cpp | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index 320a903b59e87..7f4ff0c599208 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -713,8 +713,11 @@ static void performReadOperation(ArchiveOperation Operation,
         });
         if (I == Members.end())
           continue;
-        if (CountParam && ++MemberCount[Name] != CountParam)
-          continue;
+        if (CountParam) {
+          std::string CountKey = normalizePath(*I);
+          if (++MemberCount[CountKey] != CountParam)
+            continue;
+        }
         Members.erase(I);
       }
 
@@ -854,14 +857,20 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
   if (Operation == QuickAppend || Members.empty())
     return IA_AddOldMember;
 
-  auto MI = find_if(Members, [Name](StringRef Path) {
+  std::string CountKey;
+  auto MI = find_if(Members, [Name, &CountKey](StringRef Path) {
+    SmallString<128> MatchPath(Path);
     if (Thin && !sys::path::is_absolute(Path)) {
       Expected<std::string> PathOrErr =
           computeArchiveRelativePath(ArchiveName, Path);
-      return comparePaths(Name, PathOrErr ? *PathOrErr : Path);
-    } else {
-      return comparePaths(Name, Path);
+      if (PathOrErr) {
+        MatchPath = *PathOrErr;
+      }
     }
+    if (!comparePaths(Name, MatchPath))
+      return false;
+    CountKey = normalizePath(MatchPath);
+    return true;
   });
 
   if (MI == Members.end())
@@ -870,7 +879,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
   Pos = MI;
 
   if (Operation == Delete) {
-    if (CountParam && ++MemberCount[Name] != CountParam)
+    if (CountParam && ++MemberCount[CountKey] != CountParam)
       return IA_AddOldMember;
     return IA_Delete;
   }

>From 164f55fe13a51e5942737fc7da343c901e1f2408 Mon Sep 17 00:00:00 2001
From: Meow <259395 at student.pwr.edu.pl>
Date: Fri, 8 May 2026 16:05:31 +0200
Subject: [PATCH 3/3] fix typo

---
 llvm/test/tools/llvm-ar/windows-name-case.test | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/tools/llvm-ar/windows-name-case.test b/llvm/test/tools/llvm-ar/windows-name-case.test
index 4b93e203ca21c..e94583dc12eb1 100644
--- a/llvm/test/tools/llvm-ar/windows-name-case.test
+++ b/llvm/test/tools/llvm-ar/windows-name-case.test
@@ -29,7 +29,7 @@
 EMPTY: !<thin>
 
 # File instance counting should respect Windows case-insensitive name matching.
-# Otherwise, if you have foo.txt and FOO.TXT, "-N 2 foo.txt" fails with because
+# Otherwise, if you have foo.txt and FOO.TXT, "-N 2 foo.txt" fails because
 # file is not found.
 
 # RUN: mkdir -p %t/a %t/b



More information about the llvm-commits mailing list